All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.flowable.engine.common.impl.calendar.AdvancedCycleBusinessCalendar Maven / Gradle / Ivy

/* Licensed 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.flowable.engine.common.impl.calendar;

import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

import org.flowable.engine.common.api.FlowableIllegalArgumentException;
import org.flowable.engine.common.impl.runtime.ClockReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An BusinessCalendar implementation for cycle based schedules that takes into account a different daylight savings time zone than the one that the server is configured for.
 * 

* For CRON strings DSTZONE is used as the time zone that the CRON schedule refers to. Leave it out to use the server time zone. *

* For ISO strings the time zone offset for the date/time specified is part of the string itself. DSTZONE is used to determine what the offset should be NOW, which may be different than when the * workflow was scheduled if it is scheduled to run across a DST event. * *

 *   For example:
 *      R/2013-10-01T20:30:00/P1D DSTZONE:US/Eastern
 *      R/2013-10-01T20:30:00/P1D DSTZONE:UTC
 *      R/2013-10-01T20:30:00/P1D DSTZONE:US/Arizona
 *      0 30 20 ? * MON,TUE,WED,THU,FRI * DSTZONE:US/Eastern
 *      0 30 20 ? * MON,TUE,WED,THU,FRI * DSTZONE:UTC
 *      0 30 20 ? * MON,TUE,WED,THU,FRI * DSTZONE:US/Arizona
 * 
* * Removing the DSTZONE key will cause to use the server's time zone. This is the original behavior. *

* Schedule strings are versioned. Version 1 strings will use the original CycleBusinessCalendar implementation. All new properties are ignored. Version 2 strings will use the new daylight saving time * logic. * *

 *   For example:
 *      R/2013-10-01T20:30:00/P1D VER:2 DSTZONE:US/Eastern
 *      0 30 20 ? * MON,TUE,WED,THU,FRI * VER:1 DSTZONE:US/Arizona
 * 
* * By default (if no VER key is included in the string), it assumes version 2. This can be changed by modifying the defaultScheduleVersion property. *

* * @author mseiden */ public class AdvancedCycleBusinessCalendar extends CycleBusinessCalendar { private Integer defaultScheduleVersion; private static final Integer DEFAULT_VERSION = 2; private static final Logger LOGGER = LoggerFactory.getLogger(AdvancedCycleBusinessCalendar.class); private static final Map resolvers; static { resolvers = new ConcurrentHashMap<>(); resolvers.put(1, new AdvancedSchedulerResolverWithoutTimeZone()); resolvers.put(2, new AdvancedSchedulerResolverWithTimeZone()); } public AdvancedCycleBusinessCalendar(ClockReader clockReader) { super(clockReader); } public AdvancedCycleBusinessCalendar(ClockReader clockReader, Integer defaultScheduleVersion) { this(clockReader); this.defaultScheduleVersion = defaultScheduleVersion; } public Integer getDefaultScheduleVersion() { return defaultScheduleVersion == null ? DEFAULT_VERSION : defaultScheduleVersion; } public void setDefaultScheduleVersion(Integer defaultScheduleVersion) { this.defaultScheduleVersion = defaultScheduleVersion; } @Override public Date resolveDuedate(String duedateDescription, int maxIterations) { LOGGER.info("Resolving Due Date: {}", duedateDescription); String timeZone = getValueFrom("DSTZONE", duedateDescription); String version = getValueFrom("VER", duedateDescription); // START is a legacy value that is no longer used, but may still exist in deployed job schedules // Could be used in the future as a start date for a CRON job // String startDate = getValueFrom("START", duedateDescription); duedateDescription = removeValueFrom("VER", removeValueFrom("START", removeValueFrom("DSTZONE", duedateDescription))).trim(); try { LOGGER.info("Base Due Date: {}", duedateDescription); Date date = resolvers.get(version == null ? getDefaultScheduleVersion() : Integer.valueOf(version)).resolve(duedateDescription, clockReader, timeZone == null ? clockReader.getCurrentTimeZone() : TimeZone.getTimeZone(timeZone)); LOGGER.info("Calculated Date: {}", date == null ? "Will Not Run Again" : date); return date; } catch (Exception e) { throw new FlowableIllegalArgumentException("Cannot parse duration", e); } } private String getValueFrom(String field, String duedateDescription) { int fieldIndex = duedateDescription.indexOf(field + ":"); if (fieldIndex > -1) { int nextWhiteSpace = duedateDescription.indexOf(' ', fieldIndex); fieldIndex += field.length() + 1; if (nextWhiteSpace > -1) { return duedateDescription.substring(fieldIndex, nextWhiteSpace); } else { return duedateDescription.substring(fieldIndex); } } return null; } private String removeValueFrom(String field, String duedateDescription) { int fieldIndex = duedateDescription.indexOf(field + ":"); if (fieldIndex > -1) { int nextWhiteSpace = duedateDescription.indexOf(' ', fieldIndex); if (nextWhiteSpace > -1) { return duedateDescription.replace(duedateDescription.substring(fieldIndex, nextWhiteSpace), ""); } else { return duedateDescription.substring(0, fieldIndex); } } return duedateDescription; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy