/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. 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 com.esri.gpt.framework.scheduler;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.util.TimePeriod;
import com.esri.gpt.framework.util.LogUtil;
import com.esri.gpt.framework.util.Val;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Thread definition.
*/
public class ThreadDefinition implements Serializable {
// class variables =============================================================
// instance variables ==========================================================
/** thread class */
private String _className = "";
/** delay */
private TimePeriod _delay = new TimePeriod();
/** period */
private TimePeriod _period = new TimePeriod();
/** date of the execution */
private Date _at = extractTime(new Date());
/** has delay indicator */
private boolean _hasDelay;
/** has period indicator */
private boolean _hasPeriod;
/** has date indicator */
private boolean _hasAt;
/** additional parameters */
private StringAttributeMap _parameters = new StringAttributeMap();
// constructors ================================================================
// properties ==================================================================
/**
* Checks if thread definition has delay.
* @return <code>true</code> if has delay
*/
public boolean hasDelay() {
return _hasDelay;
}
/**
* Checks if thread definition has period.
* @return <code>true</code> if has period
*/
public boolean hasPeriod() {
return _hasPeriod;
}
/**
* Checks if thread definition has date.
* @return <code>true</code> if has date
*/
public boolean hasAt() {
return _hasAt;
}
/**
* Gets thread class name.
* @return thread class name
*/
public String getClassName() {
return _className;
}
/**
* Sets thread class name.
* @param className thread class name
*/
public void setClassName(String className) {
_className = Val.chkStr(className);
}
/**
* Gets delay.
* @return return delay
*/
public TimePeriod getDelay() {
return _delay;
}
/**
* Sets delay.
* <i>hasDelay</i> flag wil be set to <code>true</code>. <i>hasAt</i> flag will
* be set to <code>false</code>.
* @param delay delay (<code>null</code> to clear delay)
*/
public void setDelay(TimePeriod delay) {
_delay = delay != null ? delay : new TimePeriod();
_hasDelay = delay != null;
if (_hasDelay) {
_hasAt = false;
}
}
/**
* Gets period.
* @return period
*/
public TimePeriod getPeriod() {
return _period;
}
/**
* Sets period.
* <i>hasPeriod</i> flag wil be set to <code>true</code>. <i>hasAt</i> flag will
* be set to <code>false</code>.
* @param period period
*/
public void setPeriod(TimePeriod period) {
_period = period != null ? period : new TimePeriod();
_hasPeriod = period != null;
if (_hasPeriod) {
_hasAt = false;
}
}
/**
* Gets time.
* @return time of the daily execution
*/
public Date getAt() {
return _at;
}
/**
* Sets time.
* @param time time of the daily execution
*/
public void setAt(Date time) {
_at = time != null ? extractTime(time) : extractTime(new Date());
_hasAt = time != null;
if (_hasAt) {
_hasDelay = false;
_hasPeriod = false;
}
}
/**
* Sets additional parameters.
* @param parameters parameters
*/
public void setParameters(StringAttributeMap parameters) {
_parameters = parameters!=null? parameters: new StringAttributeMap();
}
// methods =====================================================================
/**
* Schedules thread.
* @param service service used to schedule
* @return scheduled future
*/
public ScheduledFuture schedule(ScheduledExecutorService service) {
if (service != null) {
Runnable runnable = createRunnable();
if (runnable != null) {
if (runnable instanceof IScheduledTask) {
IScheduledTask scheduledTask = (IScheduledTask)runnable;
scheduledTask.setParameters(_parameters);
}
if (hasAt()) {
return scheduleAt(runnable, service);
} else if (hasPeriod()) {
return schedulePeriodical(runnable, service);
} else {
return scheduleOnce(runnable, service);
}
}
}
return null;
}
/**
* Schedule thread at fixed rate.
* @param runnable runnable to schedule
* @param service service used to schedule
* @return scheduled future
*/
private ScheduledFuture scheduleAt(Runnable runnable,
ScheduledExecutorService service) {
Date now = extractTime(new Date());
long delay = getAt().getTime() - now.getTime();
if (delay < 0) {
delay += 86400000L;
}
return service.scheduleAtFixedRate(
runnable, delay, 86400000L, TimeUnit.MILLISECONDS);
}
/**
* Schedules periodical task.
* @param runnable runnable to schedule
* @param service service used to schedule
* @return scheduled future
*/
private ScheduledFuture schedulePeriodical(Runnable runnable,
ScheduledExecutorService service) {
return service.scheduleWithFixedDelay(
runnable, getDelay().getValue(), getPeriod().getValue(),
TimeUnit.MILLISECONDS);
}
/**
* Schedules one shot task.
* @param runnable runnable to schedule
* @param service service used to schedule
* @return scheduled future
*/
private ScheduledFuture scheduleOnce(Runnable runnable,
ScheduledExecutorService service) {
return service.schedule(runnable, getDelay().getValue(), TimeUnit.MILLISECONDS);
}
/**
* Creates instance of the runnable class.
* @return instance of the runnable class
*/
private Runnable createRunnable() {
Runnable runnable = null;
if (getClassName().length() > 0) {
try {
Class classObj = Class.forName(getClassName());
runnable = (Runnable) classObj.newInstance();
} catch (ClassNotFoundException ex) {
LogUtil.getLogger().severe("Error creating runnable: " + ex.getMessage());
} catch (InstantiationException ex) {
LogUtil.getLogger().severe("Error creating runnable: " + ex.getMessage());
} catch (IllegalAccessException ex) {
LogUtil.getLogger().severe("Error creating runnable: " + ex.getMessage());
} catch (ClassCastException ex) {
LogUtil.getLogger().severe("Error creating runnable: " + ex.getMessage());
}
}
return runnable;
}
/**
* Extract date (hour, minue) from given date.
* @param date given date
* @return date
*/
private Date extractTime(Date date) {
if (date != null) {
Calendar initCal = Calendar.getInstance();
initCal.setTime(date);
Calendar timeCal = Calendar.getInstance();
timeCal.clear();
timeCal.set(Calendar.HOUR_OF_DAY, initCal.get(Calendar.HOUR_OF_DAY));
timeCal.set(Calendar.MINUTE, initCal.get(Calendar.MINUTE));
return timeCal.getTime();
}
return null;
}
}