Author: adrianc
Date: Mon Sep 15 16:40:31 2008 New Revision: 695688 URL: http://svn.apache.org/viewvc?rev=695688&view=rev Log: Temporal expression recurring event framework. Based upon a design by Martin Fowler, and discussed in https://issues.apache.org/jira/browse/OFBIZ-1956. Added: ofbiz/trunk/framework/service/data/ServiceDemoData.xml (with props) ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java (with props) ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java (with props) ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java (with props) ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java (with props) ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java (with props) Modified: ofbiz/trunk/framework/service/entitydef/entitymodel.xml ofbiz/trunk/framework/service/ofbiz-component.xml Added: ofbiz/trunk/framework/service/data/ServiceDemoData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/data/ServiceDemoData.xml?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/data/ServiceDemoData.xml (added) +++ ofbiz/trunk/framework/service/data/ServiceDemoData.xml Mon Sep 15 16:40:31 2008 @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<entity-engine-xml> + <!-- Temporal Expression demo data --> + + <!-- Pre-define all days of the week (Sunday -> Saturday) --> + <TemporalExpression tempExprId="DAYOFWEEK_01" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="1" integer2="1"/> + <TemporalExpression tempExprId="DAYOFWEEK_02" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="2" integer2="2"/> + <TemporalExpression tempExprId="DAYOFWEEK_03" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="3" integer2="3"/> + <TemporalExpression tempExprId="DAYOFWEEK_04" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="4" integer2="4"/> + <TemporalExpression tempExprId="DAYOFWEEK_05" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="5" integer2="5"/> + <TemporalExpression tempExprId="DAYOFWEEK_06" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="6" integer2="6"/> + <TemporalExpression tempExprId="DAYOFWEEK_07" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="7" integer2="7"/> + + <!-- Pre-define some day of the week ranges --> + <TemporalExpression tempExprId="MON_TO_FRI" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="2" integer2="6"/> + <TemporalExpression tempExprId="SAT_TO_SUN" tempExprTypeId="DAY_OF_WEEK_RANGE" integer1="7" integer2="1"/> + + <!-- Pre-define all 13 months (January -> Undecimber) --> + <TemporalExpression tempExprId="MONTH_RANGE_01" tempExprTypeId="MONTH_RANGE" integer1="0" integer2="0"/> + <TemporalExpression tempExprId="MONTH_RANGE_02" tempExprTypeId="MONTH_RANGE" integer1="1" integer2="1"/> + <TemporalExpression tempExprId="MONTH_RANGE_03" tempExprTypeId="MONTH_RANGE" integer1="2" integer2="2"/> + <TemporalExpression tempExprId="MONTH_RANGE_04" tempExprTypeId="MONTH_RANGE" integer1="3" integer2="3"/> + <TemporalExpression tempExprId="MONTH_RANGE_05" tempExprTypeId="MONTH_RANGE" integer1="4" integer2="4"/> + <TemporalExpression tempExprId="MONTH_RANGE_06" tempExprTypeId="MONTH_RANGE" integer1="5" integer2="5"/> + <TemporalExpression tempExprId="MONTH_RANGE_07" tempExprTypeId="MONTH_RANGE" integer1="6" integer2="6"/> + <TemporalExpression tempExprId="MONTH_RANGE_08" tempExprTypeId="MONTH_RANGE" integer1="7" integer2="7"/> + <TemporalExpression tempExprId="MONTH_RANGE_09" tempExprTypeId="MONTH_RANGE" integer1="8" integer2="8"/> + <TemporalExpression tempExprId="MONTH_RANGE_10" tempExprTypeId="MONTH_RANGE" integer1="9" integer2="9"/> + <TemporalExpression tempExprId="MONTH_RANGE_11" tempExprTypeId="MONTH_RANGE" integer1="10" integer2="10"/> + <TemporalExpression tempExprId="MONTH_RANGE_12" tempExprTypeId="MONTH_RANGE" integer1="11" integer2="11"/> + <TemporalExpression tempExprId="MONTH_RANGE_13" tempExprTypeId="MONTH_RANGE" integer1="12" integer2="12"/> + + <!-- Pre-define all 31 days of the month --> + <TemporalExpression tempExprId="DAYOFMONTH_01" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="1" integer2="1"/> + <TemporalExpression tempExprId="DAYOFMONTH_02" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="2" integer2="2"/> + <TemporalExpression tempExprId="DAYOFMONTH_03" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="3" integer2="3"/> + <TemporalExpression tempExprId="DAYOFMONTH_04" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="4" integer2="4"/> + <TemporalExpression tempExprId="DAYOFMONTH_05" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="5" integer2="5"/> + <TemporalExpression tempExprId="DAYOFMONTH_06" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="6" integer2="6"/> + <TemporalExpression tempExprId="DAYOFMONTH_07" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="7" integer2="7"/> + <TemporalExpression tempExprId="DAYOFMONTH_08" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="8" integer2="8"/> + <TemporalExpression tempExprId="DAYOFMONTH_09" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="9" integer2="9"/> + <TemporalExpression tempExprId="DAYOFMONTH_10" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="10" integer2="10"/> + <TemporalExpression tempExprId="DAYOFMONTH_11" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="11" integer2="11"/> + <TemporalExpression tempExprId="DAYOFMONTH_12" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="12" integer2="12"/> + <TemporalExpression tempExprId="DAYOFMONTH_13" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="13" integer2="13"/> + <TemporalExpression tempExprId="DAYOFMONTH_14" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="14" integer2="14"/> + <TemporalExpression tempExprId="DAYOFMONTH_15" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="15" integer2="15"/> + <TemporalExpression tempExprId="DAYOFMONTH_16" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="16" integer2="16"/> + <TemporalExpression tempExprId="DAYOFMONTH_17" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="17" integer2="17"/> + <TemporalExpression tempExprId="DAYOFMONTH_18" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="18" integer2="18"/> + <TemporalExpression tempExprId="DAYOFMONTH_19" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="19" integer2="19"/> + <TemporalExpression tempExprId="DAYOFMONTH_20" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="20" integer2="20"/> + <TemporalExpression tempExprId="DAYOFMONTH_21" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="21" integer2="21"/> + <TemporalExpression tempExprId="DAYOFMONTH_22" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="22" integer2="22"/> + <TemporalExpression tempExprId="DAYOFMONTH_23" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="23" integer2="23"/> + <TemporalExpression tempExprId="DAYOFMONTH_24" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="24" integer2="24"/> + <TemporalExpression tempExprId="DAYOFMONTH_25" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="25" integer2="25"/> + <TemporalExpression tempExprId="DAYOFMONTH_26" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="26" integer2="26"/> + <TemporalExpression tempExprId="DAYOFMONTH_27" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="27" integer2="27"/> + <TemporalExpression tempExprId="DAYOFMONTH_28" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="28" integer2="28"/> + <TemporalExpression tempExprId="DAYOFMONTH_29" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="29" integer2="29"/> + <TemporalExpression tempExprId="DAYOFMONTH_30" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="30" integer2="30"/> + <TemporalExpression tempExprId="DAYOFMONTH_31" tempExprTypeId="DAY_OF_MONTH_RANGE" integer1="31" integer2="31"/> + + <!-- Pre-define nth Monday of the month - many US observances occur on a Monday --> + <TemporalExpression tempExprId="1ST_MONDAY_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="2" integer2="1"/> + <TemporalExpression tempExprId="2ND_MONDAY_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="2" integer2="2"/> + <TemporalExpression tempExprId="3RD_MONDAY_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="2" integer2="3"/> + <TemporalExpression tempExprId="4TH_MONDAY_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="2" integer2="4"/> + <TemporalExpression tempExprId="LAST_MONDAY_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="2" integer2="-1"/> + + <!-- A US federal holiday schedule --> + <TemporalExpression tempExprId="US_FED_HOLIDAYS" tempExprTypeId="UNION"/> + <!-- New Years Day --> + <TemporalExpression tempExprId="JANUARY_FIRST" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="JANUARY_FIRST" toTempExprId="MONTH_RANGE_01"/> + <TemporalExpressionAssoc fromTempExprId="JANUARY_FIRST" toTempExprId="DAYOFMONTH_01"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="JANUARY_FIRST"/> + <!-- Martin Luther King Day --> + <TemporalExpression tempExprId="MLK_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="MLK_DAY" toTempExprId="MONTH_RANGE_01"/> + <TemporalExpressionAssoc fromTempExprId="MLK_DAY" toTempExprId="3RD_MONDAY_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="MLK_DAY"/> + <!-- Presidents Day --> + <TemporalExpression tempExprId="PRESIDENTS_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="PRESIDENTS_DAY" toTempExprId="MONTH_RANGE_02"/> + <TemporalExpressionAssoc fromTempExprId="PRESIDENTS_DAY" toTempExprId="3RD_MONDAY_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="PRESIDENTS_DAY"/> + <!-- Memorial Day --> + <TemporalExpression tempExprId="MEMORIAL_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="MEMORIAL_DAY" toTempExprId="MONTH_RANGE_05"/> + <TemporalExpressionAssoc fromTempExprId="MEMORIAL_DAY" toTempExprId="LAST_MONDAY_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="MEMORIAL_DAY"/> + <!-- Independence Day --> + <TemporalExpression tempExprId="INDEPENDENCE_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="INDEPENDENCE_DAY" toTempExprId="MONTH_RANGE_07"/> + <TemporalExpressionAssoc fromTempExprId="INDEPENDENCE_DAY" toTempExprId="DAYOFMONTH_04"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="INDEPENDENCE_DAY"/> + <!-- Labor Day --> + <TemporalExpression tempExprId="LABOR_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="LABOR_DAY" toTempExprId="MONTH_RANGE_09"/> + <TemporalExpressionAssoc fromTempExprId="LABOR_DAY" toTempExprId="1ST_MONDAY_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="LABOR_DAY"/> + <!-- Columbus Day --> + <TemporalExpression tempExprId="COLUMBUS_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="COLUMBUS_DAY" toTempExprId="MONTH_RANGE_10"/> + <TemporalExpressionAssoc fromTempExprId="COLUMBUS_DAY" toTempExprId="2ND_MONDAY_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="COLUMBUS_DAY"/> + <!-- Veterans Day --> + <TemporalExpression tempExprId="VETERANS_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="VETERANS_DAY" toTempExprId="MONTH_RANGE_11"/> + <TemporalExpressionAssoc fromTempExprId="VETERANS_DAY" toTempExprId="DAYOFMONTH_11"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="VETERANS_DAY"/> + <!-- Thanksgiving Day --> + <TemporalExpression tempExprId="THANKSGIVING_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpression tempExprId="4TH_THURS_IN_MONTH" tempExprTypeId="DAY_IN_MONTH" integer1="5" integer2="4"/> + <TemporalExpressionAssoc fromTempExprId="THANKSGIVING_DAY" toTempExprId="MONTH_RANGE_11"/> + <TemporalExpressionAssoc fromTempExprId="THANKSGIVING_DAY" toTempExprId="4TH_THURS_IN_MONTH"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="THANKSGIVING_DAY"/> + <!-- Christmas Day --> + <TemporalExpression tempExprId="CHRISTMAS_DAY" tempExprTypeId="INTERSECTION"/> + <TemporalExpressionAssoc fromTempExprId="CHRISTMAS_DAY" toTempExprId="MONTH_RANGE_12"/> + <TemporalExpressionAssoc fromTempExprId="CHRISTMAS_DAY" toTempExprId="DAYOFMONTH_25"/> + <TemporalExpressionAssoc fromTempExprId="US_FED_HOLIDAYS" toTempExprId="CHRISTMAS_DAY"/> + + <!-- A semi-monthly expression -> 1st and 15th of the month --> + <TemporalExpression tempExprId="1ST_AND_15TH_MONTH" tempExprTypeId="UNION"/> + <TemporalExpressionAssoc fromTempExprId="1ST_AND_15TH_MONTH" toTempExprId="DAYOFMONTH_01"/> + <TemporalExpressionAssoc fromTempExprId="1ST_AND_15TH_MONTH" toTempExprId="DAYOFMONTH_15"/> + + <!-- A Mon-Fri expression that excludes US federal holidays --> + <TemporalExpression tempExprId="GOVT_WORK_SCHED" tempExprTypeId="DIFFERENCE"/> + <TemporalExpressionAssoc fromTempExprId="GOVT_WORK_SCHED" toTempExprId="MON_TO_FRI" exprAssocType="INCLUDE"/> + <TemporalExpressionAssoc fromTempExprId="GOVT_WORK_SCHED" toTempExprId="US_FED_HOLIDAYS" exprAssocType="EXCLUDE"/> + + <!-- An 8am-5pm Mon-Fri expression that excludes US federal holidays --> + <TemporalExpression tempExprId="DAILY_GRIND" tempExprTypeId="INTERSECTION"/> + <TemporalExpression tempExprId="8AM_TO_5PM" tempExprTypeId="TIME_OF_DAY_RANGE" string1="08:00" string2="17:00"/> + <TemporalExpressionAssoc fromTempExprId="DAILY_GRIND" toTempExprId="8AM_TO_5PM"/> + <TemporalExpressionAssoc fromTempExprId="DAILY_GRIND" toTempExprId="GOVT_WORK_SCHED"/> + + <!-- An every-other-Monday at 5pm expression --> + <TemporalExpression tempExprId="5PM_BIMONDAY" tempExprTypeId="FREQUENCY" date1="2000-01-03 17:00:00.000" integer1="5" integer2="14"/> + + <!-- TemporalExpression field details... --> + + <!-- The TemporalExpression field meanings depend upon what type of expression it is. The integer + values are typically obtained from the java.util.Calendar field constants. For more + information, see the org.ofbiz.service.calendar.TemporalExpressions.java file. + + tempExprTypeId integer1 integer2 date1 date2 string1 string2 + ==================== ============== =============== ====== ====== ========== ======== + DATE_RANGE start end + TIME_OF_DAY_RANGE start [1] end [1] + DAY_OF_WEEK_RANGE start [2] end [2] + MONTH_RANGE start [3] end [3] + DAY_OF_MONTH_RANGE start [4] end [4] + DAY_IN_MONTH day [2] occurrence [5] + FREQUENCY freq type [6] freq count [7] start + + [1] hh:mm:ss.sss + [2] Day of week: 1 = Sunday, 7 = Saturday + [3] Month: January = 0, Undecimber = 12 + [4] Day of month: 1 to 31 + [5] Integer: -5 to +5, zero excluded + [6] Second = 13, Minute = 12, Hour = 11, Day = 5, Month = 2, Year = 1 + [7] Positive integer, zero excluded + --> + +</entity-engine-xml> Propchange: ofbiz/trunk/framework/service/data/ServiceDemoData.xml ------------------------------------------------------------------------------ svn:eol-style = native Modified: ofbiz/trunk/framework/service/entitydef/entitymodel.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/entitydef/entitymodel.xml?rev=695688&r1=695687&r2=695688&view=diff ============================================================================== --- ofbiz/trunk/framework/service/entitydef/entitymodel.xml (original) +++ ofbiz/trunk/framework/service/entitydef/entitymodel.xml Mon Sep 15 16:40:31 2008 @@ -128,6 +128,39 @@ <prim-key field="runtimeDataId"/> </entity> + <!-- Note: TemporalExpression values should be treated as immutable. + In other words, they should be created once and left unmodified by user + interaction. --> + <entity entity-name="TemporalExpression" + package-name="org.ofbiz.service.schedule" + title="Temporal Expression"> + <field name="tempExprId" type="id-ne"></field> + <field name="tempExprTypeId" type="id-ne"></field> + <field name="date1" type="date-time"></field> + <field name="date2" type="date-time"></field> + <field name="integer1" type="numeric"></field> + <field name="integer2" type="numeric"></field> + <field name="string1" type="id"></field> + <field name="string2" type="id"></field> + <prim-key field="tempExprId"/> + </entity> + + <entity entity-name="TemporalExpressionAssoc" + package-name="org.ofbiz.service.schedule" + title="Temporal Expression Association"> + <field name="fromTempExprId" type="id-ne"><description>The "parent" expression</description></field> + <field name="toTempExprId" type="id-ne"><description>The "child" expression</description></field> + <field name="exprAssocType" type="id"><description>Expression association type, applies to DIFFERENCE expression types only. Valid values are INCLUDED or EXCLUDED.</description></field> + <prim-key field="fromTempExprId"/> + <prim-key field="toTempExprId"/> + <relation type="one" fk-name="TEMP_EXPR_FROM" rel-entity-name="TemporalExpression" title="From"> + <key-map field-name="fromTempExprId" rel-field-name="tempExprId"/> + </relation> + <relation type="one" fk-name="TEMP_EXPR_TO" rel-entity-name="TemporalExpression" title="To"> + <key-map field-name="toTempExprId" rel-field-name="tempExprId"/> + </relation> + </entity> + <!-- ========================================================= --> <!-- org.ofbiz.service.semaphore --> <!-- ========================================================= --> Modified: ofbiz/trunk/framework/service/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/ofbiz-component.xml?rev=695688&r1=695687&r2=695688&view=diff ============================================================================== --- ofbiz/trunk/framework/service/ofbiz-component.xml (original) +++ ofbiz/trunk/framework/service/ofbiz-component.xml Mon Sep 15 16:40:31 2008 @@ -31,6 +31,7 @@ <entity-resource type="data" reader-name="seed" loader="main" location="data/ScheduledServiceData.xml"/> <entity-resource type="data" reader-name="seed-initial" loader="main" location="data/ScheduledServices.xml"/> <entity-resource type="data" reader-name="seed" loader="main" location="data/ServiceSecurityData.xml"/> + <entity-resource type="data" reader-name="demo" loader="main" location="data/ServiceDemoData.xml"/> <service-resource type="model" loader="main" location="servicedef/services.xml"/> <service-resource type="model" loader="main" location="servicedef/services_test_se.xml"/> Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java Mon Sep 15 16:40:31 2008 @@ -0,0 +1,115 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.service.calendar; + +import java.io.Serializable; +import java.util.Date; + +/** An immutable range of dates. + */ +@SuppressWarnings("serial") +public class DateRange implements Serializable { + public static final Date MIN_DATE = new Date(Long.MIN_VALUE); + public static final Date MAX_DATE = new Date(Long.MAX_VALUE); + public static final DateRange FullRange = new DateRange(); + + protected Date start = MIN_DATE; + protected Date end = MAX_DATE; + + protected DateRange() {} + + public DateRange(Date start, Date end) { + if (start != null) { + this.start = start; + } + if (end != null) { + this.end = end; + } + } + + public long durationInMillis() { + if (this.end.after(this.start)) { + return this.end.getTime() - this.start.getTime(); + } else { + return this.start.getTime() - this.end.getTime(); + } + } + + public boolean equals(Object obj) { + return obj instanceof DateRange && ((DateRange)obj).start.equals(this.start) && ((DateRange)obj).end.equals(this.end); + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", end = " + this.end; + } + + public Date start() { + return (Date) this.start.clone(); + } + + public Date end() { + return (Date) this.end.clone(); + } + + public boolean isAscending() { + return this.end.after(this.start) && !this.end.equals(this.start); + } + + public boolean isPoint() { + return this.end.equals(this.start); + } + + public boolean includesDate(Date date) { + if (isPoint()) { + return date.equals(this.start); + } + if (isAscending()) { + return (this.start.equals(date) || date.after(this.start)) && (this.end.equals(date) || date.before(this.end)); + } else { + return (this.start.equals(date) || date.before(this.start)) && (this.end.equals(date) || date.after(this.end)); + } + } + + public boolean intersectsRange(DateRange dateRange) { + return intersectsRange(dateRange.start, dateRange.end); + } + + public boolean intersectsRange(Date start, Date end) { + if (start == null) { + throw new IllegalArgumentException("start argument cannot be null"); + } + if (end == null) { + throw new IllegalArgumentException("end argument cannot be null"); + } + if (isPoint()) { + return end.equals(start) && this.start.equals(start); + } + if (isAscending()) { + if (start.after(end)) { + return false; + } + return (this.end.equals(start) || start.before(this.end)) && (this.start.equals(end) || end.after(this.start)); + } else { + if (end.after(start)) { + return false; + } + return (this.end.equals(start) || start.after(this.end)) && (this.start.equals(end) || end.before(this.start)); + } + } +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/DateRange.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java Mon Sep 15 16:40:31 2008 @@ -0,0 +1,106 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.service.calendar; + +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; +import java.util.Set; +import java.util.TreeSet; + +/** Temporal expression abstract class. */ +public abstract class TemporalExpression implements Serializable, Comparable<TemporalExpression> { + protected TemporalExpression() {} + + /** Field used to sort expressions. Expression evaluation depends + * on correct ordering. Expressions are evaluated from lowest value + * to highest value. */ + protected int sequence = Integer.MAX_VALUE; + + /** Field used to sort expressions. Expression evaluation depends + * on correct ordering. Expressions are evaluated from lowest value + * to highest value. */ + protected int subSequence = Integer.MAX_VALUE; + + /** Returns true if this expression includes the specified date. + * @param cal A date to evaluate + * @return true if this expression includes the date represented by + * <code>cal</code> + */ + public abstract boolean includesDate(Calendar cal); + + /** Returns a date representing the first occurrence of this expression + * on or after a specified date. Returns <code>null</code> if there + * is no matching date. + * @param cal A date to evaluate + * @return A Calendar instance representing the first matching date, + * or <code>null</code> if no matching date is found + */ + public abstract Calendar first(Calendar cal); + + /** Returns a date representing the next occurrence of this expression + * after a specified date. Returns <code>null</code> if there + * is no matching date. + * @param cal A date to evaluate + * @return A Calendar instance representing the first matching date, + * or <code>null</code> if no matching date is found + */ + public abstract Calendar next(Calendar cal); + + public int compareTo(TemporalExpression obj) { + if (this.equals(obj)) { + return 0; + } + if (obj.sequence < this.sequence) { + return 1; + } else if (obj.sequence > this.sequence) { + return -1; + } + return obj.subSequence < this.subSequence ? 1 : -1; + } + + /** Returns a range of dates matching this expression. Returns an + * empty Set if no dates are found. + * @param range The range of dates to evaluate + * @param cal The starting date + * @return A Set of matching <code>Date</code> objects + */ + public Set<Date> getRange(org.ofbiz.service.calendar.DateRange range, Calendar cal) { + Set<Date> set = new TreeSet<Date>(); + Date last = range.start(); + Calendar next = first(cal); + while (next != null && range.includesDate(next.getTime())) { + last = next.getTime(); + set.add(last); + next = next(next); + if (next != null && last.equals(next.getTime())) { + break; + } + } + return set; + } + + protected Calendar setStartOfDay(Calendar cal) { + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal; + } +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpression.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java Mon Sep 15 16:40:31 2008 @@ -0,0 +1,118 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.service.calendar; + +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.entity.GenericDelegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityCondition; +import org.ofbiz.entity.util.EntityUtil; + +/** Schedule and TemporalExpression persistence worker. + */ +public class TemporalExpressionWorker { + + // Temporal expression constants + public final static String DateRange = "DATE_RANGE"; + public final static String DayInMonth = "DAY_IN_MONTH"; + public final static String DayOfMonthRange = "DAY_OF_MONTH_RANGE"; + public final static String DayOfWeekRange = "DAY_OF_WEEK_RANGE"; + public final static String Difference = "DIFFERENCE"; + public final static String Frequency = "FREQUENCY"; + public final static String Intersection = "INTERSECTION"; + public final static String MonthRange = "MONTH_RANGE"; + public final static String TimeOfDayRange = "TIME_OF_DAY_RANGE"; + public final static String Union = "UNION"; + public final static String ExpressionTypeList[] = {DateRange, DayInMonth, DayOfMonthRange, DayOfWeekRange, + Difference, Frequency, Intersection, MonthRange, TimeOfDayRange, Union}; + + /** Get a <code>TemporalExpression</code> from persistent storage. + * @param delegator + * @param tempExprId + * @return + * @throws GenericEntityException + */ + public static TemporalExpression getTemporalExpression(GenericDelegator delegator, String tempExprId) throws GenericEntityException { + if (UtilValidate.isEmpty(tempExprId)) { + throw new IllegalArgumentException("tempExprId argument cannot be empty"); + } + GenericValue exprValue = delegator.findOne("TemporalExpression", UtilMisc.toMap("tempExprId", tempExprId), true); + if (UtilValidate.isEmpty(exprValue)) { + throw new IllegalArgumentException("tempExprId argument invalid - expression not found"); + } + return makeTemporalExpression(delegator, exprValue); + } + + /** Create a <code>TemporalExpression</code> instance from a TemporalExpression + * GenericValue.<p>This method makes recursive calls, so care must be taken to + * avoid endless loops.</p> + * @param delegator + * @param exprValue + * @return + * @throws GenericEntityException + */ + public static TemporalExpression makeTemporalExpression(GenericDelegator delegator, GenericValue exprValue) throws GenericEntityException { + String tempExprId = exprValue.getString("tempExprId"); + String tempExprTypeId = exprValue.getString("tempExprTypeId"); + if (DateRange.equals(tempExprTypeId)) { + return new TemporalExpressions.DateRange(exprValue.getTimestamp("date1"), exprValue.getTimestamp("date2")); + } else if (DayInMonth.equals(tempExprTypeId)) { + return new TemporalExpressions.DayInMonth(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()); + } else if (DayOfMonthRange.equals(tempExprTypeId)) { + return new TemporalExpressions.DayOfMonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()); + } else if (DayOfWeekRange.equals(tempExprTypeId)) { + return new TemporalExpressions.DayOfWeekRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()); + } else if (Difference.equals(tempExprTypeId)) { + GenericValue inclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "INCLUDE")), null, null, null, true)); + GenericValue exclAssoc = EntityUtil.getFirst(delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition(EntityCondition.makeCondition("fromTempExprId", tempExprId), EntityCondition.makeCondition("exprAssocType", "EXCLUDE")), null, null, null, true)); + if (inclAssoc != null && exclAssoc != null) { + return new TemporalExpressions.Difference(getTemporalExpression(delegator, inclAssoc.getString("toTempExprId")), getTemporalExpression(delegator, exclAssoc.getString("toTempExprId"))); + } + } else if (Frequency.equals(tempExprTypeId)) { + return new TemporalExpressions.Frequency(exprValue.getTimestamp("date1"), exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()); + } else if (Intersection.equals(tempExprTypeId)) { + return new TemporalExpressions.Intersection(getChildExpressions(delegator, tempExprId)); + } else if (MonthRange.equals(tempExprTypeId)) { + return new TemporalExpressions.MonthRange(exprValue.getLong("integer1").intValue(), exprValue.getLong("integer2").intValue()); + } else if (TimeOfDayRange.equals(tempExprTypeId)) { + return new TemporalExpressions.TimeOfDayRange(exprValue.getString("string1"), exprValue.getString("string2")); + } else if (Union.equals(tempExprTypeId)) { + return new TemporalExpressions.Union(getChildExpressions(delegator, tempExprId)); + } + return TemporalExpressions.NullExpression; + } + + protected static Set<TemporalExpression> getChildExpressions(GenericDelegator delegator, String tempExprId) throws GenericEntityException { + List<GenericValue> valueList = delegator.findList("TemporalExpressionAssoc", EntityCondition.makeCondition("fromTempExprId", tempExprId), null, null, null, true); + if (UtilValidate.isEmpty(valueList)) { + throw new IllegalArgumentException("tempExprId argument invalid - no child expressions found"); + } + Set<TemporalExpression> exprList = new TreeSet<TemporalExpression>(); + for (GenericValue value : valueList) { + exprList.add(makeTemporalExpression(delegator, value.getRelatedOne("ToTemporalExpression"))); + } + return exprList; + } +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressionWorker.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java Mon Sep 15 16:40:31 2008 @@ -0,0 +1,861 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.service.calendar; + +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; +import java.util.Set; +import java.util.TreeSet; +import org.ofbiz.base.util.Debug; + +/** A collection of TemporalExpression classes. */ +@SuppressWarnings("serial") +public class TemporalExpressions implements Serializable { + public static final String module = TemporalExpressions.class.getName(); + public static final TemporalExpression NullExpression = new Null(); + + /** This class represents a null expression. */ + protected static class Null extends TemporalExpression { + public Calendar first(Calendar cal) { + return null; + } + public boolean includesDate(Calendar cal) { + return false; + } + public Calendar next(Calendar cal) { + return null; + } + public Calendar previous(Calendar cal) { + return null; + } + } + + /** This class represents a mathematical union of all of its + * member expressions. */ + public static class Union extends TemporalExpression { + protected Set<TemporalExpression> expressionSet = null; + + protected Union() {} + + public Union(Set<TemporalExpression> expressionSet) { + if (expressionSet == null) { + throw new IllegalArgumentException("expressionSet argument cannot be null"); + } + this.expressionSet = expressionSet; + if (this.expressionSet.size() > 0) { + TemporalExpression that = this.expressionSet.iterator().next(); + if (this.compareTo(that) > 0) { + this.sequence = that.sequence; + this.subSequence = that.subSequence; + } + } + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + return this.expressionSet.equals(((Union) obj).expressionSet); + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", size = " + this.expressionSet.size(); + } + + public boolean includesDate(Calendar cal) { + for (TemporalExpression expression : this.expressionSet) { + if (expression.includesDate(cal)) { + return true; + } + } + return false; + } + + public Calendar first(Calendar cal) { + for (TemporalExpression expression : this.expressionSet) { + Calendar first = expression.first(cal); + if (first != null && includesDate(first)) { + return first; + } + } + return null; + } + + public Calendar next(Calendar cal) { + for (TemporalExpression expression : this.expressionSet) { + Calendar next = expression.next(cal); + if (next != null && includesDate(next)) { + return next; + } + } + return null; + } + + public Set<Date> getRange(org.ofbiz.service.calendar.DateRange range, Calendar cal) { + Set<Date> rawSet = new TreeSet<Date>(); + Set<Date> finalSet = new TreeSet<Date>(); + for (TemporalExpression expression : this.expressionSet) { + rawSet.addAll(expression.getRange(range, cal)); + } + Calendar checkCal = (Calendar) cal.clone(); + for (Date date : rawSet) { + checkCal.setTime(date); + if (includesDate(checkCal)) { + finalSet.add(date); + } + } + return finalSet; + } + } + + /** This class represents a mathematical intersection of all of its + * member expressions. */ + public static class Intersection extends TemporalExpression { + protected Set<TemporalExpression> expressionSet = null; + + protected Intersection() {} + + public Intersection(Set<TemporalExpression> expressionSet) { + if (expressionSet == null) { + throw new IllegalArgumentException("expressionSet argument cannot be null"); + } + this.expressionSet = expressionSet; + if (this.expressionSet.size() > 0) { + TemporalExpression that = this.expressionSet.iterator().next(); + if (this.compareTo(that) > 0) { + this.sequence = that.sequence; + this.subSequence = that.subSequence; + } + } + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + return this.expressionSet.equals(((Intersection) obj).expressionSet); + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", size = " + this.expressionSet.size(); + } + + public void add(TemporalExpression expr) { + this.expressionSet.add(expr); + if (this.compareTo(expr) > 0) { + this.sequence = expr.sequence; + this.subSequence = expr.subSequence; + } + } + + public boolean includesDate(Calendar cal) { + for (TemporalExpression expression : this.expressionSet) { + if (!expression.includesDate(cal)) { + return false; + } + } + return true; + } + + public Calendar first(Calendar cal) { + Calendar first = (Calendar) cal.clone(); + for (TemporalExpression expression : this.expressionSet) { + first = expression.first(first); + if (first == null) { + return null; + } + } + if (includesDate(first)) { + return first; + } else { + return null; + } + } + + public Calendar next(Calendar cal) { + Calendar next = (Calendar) cal.clone(); + for (TemporalExpression expression : this.expressionSet) { + next = expression.next(next); + if (next == null) { + return null; + } + } + if (includesDate(next)) { + return next; + } else { + return null; + } + } + + public Set<Date> getRange(org.ofbiz.service.calendar.DateRange range, Calendar cal) { + Set<Date> finalSet = new TreeSet<Date>(); + Set<Date> rawSet = new TreeSet<Date>(); + Date last = range.start(); + Calendar next = first(cal); + while (next != null && range.includesDate(next.getTime())) { + last = next.getTime(); + rawSet.add(last); + next = next(next); + if (next != null && last.equals(next.getTime())) { + break; + } + } + Calendar checkCal = (Calendar) cal.clone(); + for (Date date : rawSet) { + checkCal.setTime(date); + if (includesDate(checkCal)) { + finalSet.add(date); + } + } + return finalSet; + } + } + + /** This class represents a difference of two temporal expressions. */ + public static class Difference extends TemporalExpression { + protected TemporalExpression included = null; + protected TemporalExpression excluded = null; + + public Difference(TemporalExpression included, TemporalExpression excluded) { + if (included == null) { + throw new IllegalArgumentException("included argument cannot be null"); + } + if (excluded == null) { + throw new IllegalArgumentException("excluded argument cannot be null"); + } + this.included = included; + this.excluded = excluded; + if (this.compareTo(included) > 0) { + this.sequence = included.sequence; + this.subSequence = included.subSequence; + } + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + Difference that = (Difference) obj; + return this.included.equals(that.included) && this.excluded.equals(that.excluded); + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", included = " + this.included + ", excluded = " + this.excluded; + } + + public boolean includesDate(Calendar cal) { + return this.included.includesDate(cal) && !this.excluded.includesDate(cal); + } + + public Calendar first(Calendar cal) { + Calendar first = this.included.first(cal); + while (first != null && this.excluded.includesDate(first)) { + first = this.included.next(first); + } + return first; + } + + public Calendar next(Calendar cal) { + Calendar next = this.included.next(cal); + while (next != null && this.excluded.includesDate(next)) { + next = this.included.next(next); + } + return next; + } + + public Set<Date> getRange(org.ofbiz.service.calendar.DateRange range, Calendar cal) { + Set<Date> finalSet = new TreeSet<Date>(); + Set<Date> rawSet = this.included.getRange(range, cal); + Calendar checkCal = (Calendar) cal.clone(); + for (Date date : rawSet) { + checkCal.setTime(date); + if (!this.excluded.includesDate(checkCal)) { + finalSet.add(date); + } + } + return finalSet; + } + } + + /** A temporal expression that represents a range of dates. */ + public static class DateRange extends TemporalExpression { + protected org.ofbiz.service.calendar.DateRange range = null; + + public DateRange(Date start, Date end) { + this.sequence = 1000; + this.range = new org.ofbiz.service.calendar.DateRange(start, end); + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + return this.range.equals(((DateRange) obj).range); + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.range.start() + ", end = " + this.range.end(); + } + + public boolean includesDate(Calendar cal) { + return this.range.includesDate(cal.getTime()); + } + + public Calendar first(Calendar cal) { + return includesDate(cal) ? cal : null; + } + + public Calendar next(Calendar cal) { + return includesDate(cal) ? cal : null; + } + } + + /** A temporal expression that represents a time of day range. */ + public static class TimeOfDayRange extends TemporalExpression { + protected int start = 0; + protected int end = 0; + + /** + * @param start A time String in the form of hh:mm:ss.sss (24 hr clock) + * @param end A time String in the form of hh:mm:ss.sss (24 hr clock) + */ + public TimeOfDayRange(String start, String end) { + if (start == null || start.length() == 0) { + throw new IllegalArgumentException("start argument cannot be null or empty"); + } + if (end == null || end.length() == 0) { + throw new IllegalArgumentException("end argument cannot be null or empty"); + } + this.start = strToMillis(start); + this.end = strToMillis(end); + this.sequence = 600; + this.subSequence = this.start; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + TimeOfDayRange that = (TimeOfDayRange) obj; + return this.start == that.start && this.end == that.end; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", end = " + this.end; + } + + public boolean includesDate(Calendar cal) { + int millis = calToMillis(cal); + if (this.start <= this.end) { + return millis >= this.start && millis <= this.end; + } else { + return millis <= this.start && millis >= this.end; + } + } + + public Calendar first(Calendar cal) { + if (includesDate(cal)) { + return cal; + } + Calendar first = (Calendar) cal.clone(); + if (calToMillis(cal) > this.end) { + first.add(Calendar.DAY_OF_MONTH, 1); + } + int start = this.start; + int hour = start / 3600000; + start -= hour * 3600000; + int minute = start / 60000; + start -= minute * 60000; + int second = start / 1000; + int millis = start - (second * 1000); + first.set(Calendar.HOUR_OF_DAY, hour); + first.set(Calendar.MINUTE, minute); + first.set(Calendar.SECOND, second); + first.set(Calendar.MILLISECOND, millis); + return first; + } + + public Calendar next(Calendar cal) { + return first(cal); + } + + protected int strToMillis(String str) { + int result = 0; + String strArray[] = str.split(":"); + if (strArray.length == 0 || strArray.length > 3) { + throw new IllegalArgumentException("Invalid time argument"); + } + result = Integer.valueOf(strArray[0]) * 3600000; + if (strArray.length > 1) { + result += (Integer.valueOf(strArray[1]) * 60000); + } + if (strArray.length > 2) { + float val = Float.valueOf(strArray[2]); + result += (int)(val * 1000); + } + return result; + } + + protected int calToMillis(Calendar cal) { + return (cal.get(Calendar.HOUR_OF_DAY) * 3600000) + + (cal.get(Calendar.MINUTE) * 60000) + + (cal.get(Calendar.SECOND) * 1000) + + (cal.get(Calendar.MILLISECOND)); + } + } + + /** A temporal expression that represents a day of week range. */ + public static class DayOfWeekRange extends TemporalExpression { + protected int start; + protected int end; + + /** + * @param start An integer in the range of <code>Calendar.SUNDAY</code> + * to <code>Calendar.SATURDAY</code> + * @param end An integer in the range of <code>Calendar.SUNDAY</code> + * to <code>Calendar.SATURDAY</code> + */ + public DayOfWeekRange(int start, int end) { + if (start < Calendar.SUNDAY || start > Calendar.SATURDAY) { + throw new IllegalArgumentException("Invalid start argument"); + } + if (end < Calendar.SUNDAY || end > Calendar.SATURDAY) { + throw new IllegalArgumentException("Invalid end argument"); + } + this.sequence = 500; + this.subSequence = start; + this.start = start; + this.end = end; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + DayOfWeekRange that = (DayOfWeekRange) obj; + return this.start == that.start && this.end == that.end; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", end = " + this.end; + } + + public boolean includesDate(Calendar cal) { + int dow = cal.get(Calendar.DAY_OF_WEEK); + if (dow == this.start || dow == this.end) { + return true; + } + Calendar compareCal = (Calendar) cal.clone(); + while (compareCal.get(Calendar.DAY_OF_WEEK) != this.start) { + compareCal.add(Calendar.DAY_OF_MONTH, 1); + } + while (compareCal.get(Calendar.DAY_OF_WEEK) != this.end) { + if (compareCal.get(Calendar.DAY_OF_WEEK) == dow) { + return true; + } + compareCal.add(Calendar.DAY_OF_MONTH, 1); + } + return false; + } + + public Calendar first(Calendar cal) { + Calendar first = (Calendar) cal.clone(); + while (!includesDate(first)) { + first.add(Calendar.DAY_OF_MONTH, 1); + } + return setStartOfDay(first); + } + + public Calendar next(Calendar cal) { + Calendar next = (Calendar) cal.clone(); + next.add(Calendar.DAY_OF_MONTH, 1); + while (!includesDate(next)) { + next.add(Calendar.DAY_OF_MONTH, 1); + } + return setStartOfDay(next); + } + } + + /** A temporal expression that represents a month range. */ + public static class MonthRange extends TemporalExpression { + protected int start; + protected int end; + + /** + * @param start An integer in the range of <code>Calendar.JANUARY</code> + * to <code>Calendar.UNDECIMBER</code> + * @param end An integer in the range of <code>Calendar.JANUARY</code> + * to <code>Calendar.UNDECIMBER</code> + */ + public MonthRange(int start, int end) { + if (start < Calendar.JANUARY || start > Calendar.UNDECIMBER) { + throw new IllegalArgumentException("Invalid start argument"); + } + if (end < Calendar.JANUARY || end > Calendar.UNDECIMBER) { + throw new IllegalArgumentException("Invalid end argument"); + } + this.sequence = 200; + this.subSequence = start; + this.start = start; + this.end = end; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + MonthRange that = (MonthRange) obj; + return this.start == that.start && this.end == that.end; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", end = " + this.end; + } + + public boolean includesDate(Calendar cal) { + int month = cal.get(Calendar.MONTH); + if (month == this.start || month == this.end) { + return true; + } + Calendar compareCal = (Calendar) cal.clone(); + while (compareCal.get(Calendar.MONTH) != this.start) { + compareCal.add(Calendar.MONTH, 1); + } + while (compareCal.get(Calendar.MONTH) != this.end) { + if (compareCal.get(Calendar.MONTH) == month) { + return true; + } + compareCal.add(Calendar.MONTH, 1); + } + return false; + } + + public Calendar first(Calendar cal) { + Calendar first = (Calendar) cal.clone(); + first.set(Calendar.DAY_OF_MONTH, 1); + while (!includesDate(first)) { + first.add(Calendar.MONTH, 1); + } + return first; + } + + public Calendar next(Calendar cal) { + Calendar next = (Calendar) cal.clone(); + next.set(Calendar.DAY_OF_MONTH, 1); + next.add(Calendar.MONTH, 1); + while (!includesDate(next)) { + next.add(Calendar.MONTH, 1); + } + return next; + } + } + + /** A temporal expression that represents a day of month range. */ + public static class DayOfMonthRange extends TemporalExpression { + protected int start; + protected int end; + + /** + * @param start An integer in the range of 1 to 31 + * @param end An integer in the range of 1 to 31 + */ + public DayOfMonthRange(int start, int end) { + if (start < 1 || start > end) { + throw new IllegalArgumentException("Invalid start argument"); + } + if (end < 1 || end > 31) { + throw new IllegalArgumentException("Invalid end argument"); + } + this.sequence = 300; + this.subSequence = start; + this.start = start; + this.end = end; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + DayOfMonthRange that = (DayOfMonthRange) obj; + return this.start == that.start && this.end == that.end; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", end = " + this.end; + } + + public boolean includesDate(Calendar cal) { + int dom = cal.get(Calendar.DAY_OF_MONTH); + int end = this.end; + if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) < end) { + end = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + } + return dom >= this.start && dom <= end; + } + + public Calendar first(Calendar cal) { + int month = cal.get(Calendar.MONTH); + Calendar first = (Calendar) cal.clone(); + if (first.get(Calendar.DAY_OF_MONTH) > first.getActualMaximum(Calendar.DAY_OF_MONTH)) { + first.set(Calendar.DAY_OF_MONTH, first.getActualMaximum(Calendar.DAY_OF_MONTH)); + } + setStartOfDay(first); + while (!includesDate(first)) { + first.add(Calendar.DAY_OF_MONTH, 1); + if (first.get(Calendar.MONTH) != month) { + first.set(Calendar.MONTH, month); + first.set(Calendar.DAY_OF_MONTH, 1); + } + } + return first; + } + + public Calendar next(Calendar cal) { + Calendar next = (Calendar) cal.clone(); + setStartOfDay(next); + next.add(Calendar.DAY_OF_MONTH, 1); + while (!includesDate(next)) { + next.add(Calendar.DAY_OF_MONTH, 1); + } + return next; + } + } + + /** A temporal expression that represents a day in the month. */ + public static class DayInMonth extends TemporalExpression { + protected int dayOfWeek; + protected int occurrence; + + /** + * @param start An integer in the range of <code>Calendar.SUNDAY</code> + * to <code>Calendar.SATURDAY</code> + * @param end An integer in the range of -5 to 5, excluding zero + */ + public DayInMonth(int dayOfWeek, int occurrence) { + if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException("Invalid day argument"); + } + if (occurrence < -5 || occurrence == 0 || occurrence > 5) { + throw new IllegalArgumentException("Invalid occurrence argument"); + } + this.sequence = 400; + this.subSequence = dayOfWeek; + this.dayOfWeek = dayOfWeek; + this.occurrence = occurrence; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + DayInMonth that = (DayInMonth) obj; + return this.dayOfWeek == that.dayOfWeek && this.occurrence == that.occurrence; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", dayOfWeek = " + this.dayOfWeek + ", occurrence = " + this.occurrence; + } + + public boolean includesDate(Calendar cal) { + if (cal.get(Calendar.DAY_OF_WEEK) != this.dayOfWeek) { + return false; + } + int month = cal.get(Calendar.MONTH); + int dom = cal.get(Calendar.DAY_OF_MONTH); + Calendar next = (Calendar) cal.clone(); + alignDayOfWeek(next); + return dom == next.get(Calendar.DAY_OF_MONTH) && next.get(Calendar.MONTH) == month; + } + + public Calendar first(Calendar cal) { + int month = cal.get(Calendar.MONTH); + Calendar first = (Calendar) cal.clone(); + alignDayOfWeek(first); + setStartOfDay(first); + if (first.before(cal)) { + first.set(Calendar.DAY_OF_MONTH, 1); + if (first.get(Calendar.MONTH) == month) { + first.add(Calendar.MONTH, 1); + } + alignDayOfWeek(first); + } + return first; + } + + public Calendar next(Calendar cal) { + int month = cal.get(Calendar.MONTH); + Calendar next = (Calendar) cal.clone(); + alignDayOfWeek(next); + setStartOfDay(next); + if (next.before(cal) || next.equals(cal)) { + next.set(Calendar.DAY_OF_MONTH, 1); + if (next.get(Calendar.MONTH) == month) { + next.add(Calendar.MONTH, 1); + } + alignDayOfWeek(next); + } + return next; + } + + protected void alignDayOfWeek(Calendar cal) { + cal.set(Calendar.DAY_OF_MONTH, 1); + if (this.occurrence > 0) { + while (cal.get(Calendar.DAY_OF_WEEK) != this.dayOfWeek) { + cal.add(Calendar.DAY_OF_MONTH, 1); + } + cal.add(Calendar.DAY_OF_MONTH, (this.occurrence - 1) * 7); + } else { + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.DAY_OF_MONTH, -1); + while (cal.get(Calendar.DAY_OF_WEEK) != this.dayOfWeek) { + cal.add(Calendar.DAY_OF_MONTH, -1); + } + cal.add(Calendar.DAY_OF_MONTH, (this.occurrence + 1) * 7); + } + } + } + + /** A temporal expression that represents a frequency. */ + public static class Frequency extends TemporalExpression { + protected Date start; + protected int freqType; + protected int freqCount; + + /** + * @param start One of the following integer values: <code>Calendar.SECOND + * Calendar.MINUTE Calendar.HOUR Calendar.DAY_OF_MONTH Calendar.MONTH + * Calendar.YEAR</code> + * @param end An integer in the range of -5 to 5, excluding zero + */ + public Frequency(Date start, int freqType, int freqCount) { + if (start == null) { + throw new IllegalArgumentException("Invalid start argument"); + } + if (freqType != Calendar.SECOND && freqType != Calendar.MINUTE + && freqType != Calendar.HOUR && freqType != Calendar.DAY_OF_MONTH + && freqType != Calendar.MONTH && freqType != Calendar.YEAR) { + throw new IllegalArgumentException("Invalid freqType argument"); + } + if (freqCount < 1) { + throw new IllegalArgumentException("freqCount argument must be a positive integer"); + } + this.sequence = 100; + this.subSequence = freqType; + this.start = start; + this.freqType = freqType; + this.freqCount = freqCount; + if (Debug.verboseOn()) { + Debug.logVerbose("Created " + this, module); + } + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + Frequency that = (Frequency) obj; + return this.start.equals(that.start) && this.freqType == that.freqType && this.freqCount == that.freqCount; + } catch (Exception e) {} + return false; + } + + public String toString() { + return super.toString() + ", start = " + this.start + ", freqType = " + this.freqType + ", freqCount = " + this.freqCount; + } + + public boolean includesDate(Calendar cal) { + Calendar next = first(cal); + return next.equals(cal); + } + + public Calendar first(Calendar cal) { + Calendar first = (Calendar) cal.clone(); + first.setTime(this.start); + while (first.before(cal)) { + first.add(this.freqType, this.freqCount); + } + return first; + } + + public Calendar next(Calendar cal) { + Calendar next = (Calendar) cal.clone(); + next.setTime(this.start); + while (next.before(cal) || next.equals(cal)) { + next.add(this.freqType, this.freqCount); + } + return next; + } + } +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TemporalExpressions.java ------------------------------------------------------------------------------ svn:eol-style = native Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java?rev=695688&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java Mon Sep 15 16:40:31 2008 @@ -0,0 +1,149 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.service.calendar; + +import java.io.Serializable; +import java.util.Calendar; + +import org.ofbiz.entity.GenericValue; + +/** A representation of a period of time. */ +@SuppressWarnings("serial") +public class TimeDuration implements Serializable { + public static final TimeDuration ZeroTimeDuration = new NullDuration(); + + protected int millis = 0; + protected int seconds = 0; + protected int minutes = 0; + protected int hours = 0; + protected int days = 0; + protected int months = 0; + protected int years = 0; + + protected TimeDuration() {} + + public TimeDuration(int millis, int seconds, int minutes, int hours, int days, int months, int years) { + this.millis = millis; + this.seconds = seconds; + this.minutes = minutes; + this.hours = hours; + this.days = days; + this.months = months; + this.years = years; + } + + public long millis() { + return this.millis; + } + + public long seconds() { + return this.seconds; + } + + public long minutes() { + return this.minutes; + } + + public long hours() { + return this.hours; + } + + public long days() { + return this.days; + } + + public long months() { + return this.months; + } + + public long years() { + return this.years; + } + + /** Add this time duration to a Calendar instance. Returns the original + * Calendar instance. + * @param cal + * @return The <code>cal</code> argument + */ + public Calendar addToCalendar(Calendar cal) { + cal.add(Calendar.MILLISECOND, this.millis); + cal.add(Calendar.SECOND, this.seconds); + cal.add(Calendar.MINUTE, this.minutes); + cal.add(Calendar.HOUR, this.hours); + cal.add(Calendar.DAY_OF_MONTH, this.days); + cal.add(Calendar.MONTH, this.months); + cal.add(Calendar.YEAR, this.years); + return cal; + } + + /** Subtract this time duration to a Calendar instance. Returns the original + * Calendar instance. + * @param cal + * @return The <code>cal</code> argument + */ + public Calendar subtractFromCalendar(Calendar cal) { + cal.add(Calendar.MILLISECOND, -this.millis); + cal.add(Calendar.SECOND, -this.seconds); + cal.add(Calendar.MINUTE, -this.minutes); + cal.add(Calendar.HOUR, -this.hours); + cal.add(Calendar.DAY_OF_MONTH, -this.days); + cal.add(Calendar.MONTH, -this.months); + cal.add(Calendar.YEAR, -this.years); + return cal; + } + + /** Get a <code>TimeDuration</code> instance based on duration fields + * in a GenericValue. Returns ZeroTimeDuration if there is no + * information in the duration fields or if the value argument is null. + * <p>The GenericValue <b>must</b> contain the following <code>numeric</code> + * fields:<ul><li>durationMillis</li><li>durationSeconds</li><li>durationMinutes</li> + * <li>durationHours</li><li>durationDays</li><li>durationMonths</li> + * <li>durationYears</li></ul></p> + * @param value + * @return A TimeDuration instance + */ + public static TimeDuration getTimeDuration(GenericValue value) { + if (value != null) { + int millis = safeLongToInt(value.getLong("durationMillis")); + int secs = safeLongToInt(value.getLong("durationSeconds")); + int mins = safeLongToInt(value.getLong("durationMinutes")); + int hrs = safeLongToInt(value.getLong("durationHours")); + int days = safeLongToInt(value.getLong("durationDays")); + int mos = safeLongToInt(value.getLong("durationMonths")); + int yrs = safeLongToInt(value.getLong("durationYears")); + if (millis != 0 || secs != 0 || mins != 0 || hrs != 0 || days != 0 || mos != 0 || yrs != 0) { + return new TimeDuration(millis, secs, mins, hrs, days, mos, yrs); + } + } + return ZeroTimeDuration; + } + + protected static int safeLongToInt(Long longObj) { + return longObj == null ? 0 : longObj.intValue(); + } + + protected static class NullDuration extends TimeDuration { + public Calendar addToCalendar(Calendar cal) { + return cal; + } + public Calendar subtractFromCalendar(Calendar cal) { + return cal; + } + } +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/calendar/TimeDuration.java ------------------------------------------------------------------------------ svn:eol-style = native |
Free forum by Nabble | Edit this page |