Commits

timemachine  committed 1f6f096

Improved DateListSchedule to support provider data. Added ScriptingDateListProvider.

  • Participants
  • Parent commits 058e755
  • Branches 1.1.x

Comments (0)

Files changed (4)

File timemachine-hibernate/src/main/resources/timemachine/scheduler/hibernate/Schedule.hbm.xml

       		<key column="SCHEDULE_ID"/>
 			<property name="nextRunIndex" type="int" column="NEXT_RUN_INDEX" access="field" />
 			<property name="dateListProviderClassName" type="string" column="DATE_LIST_PROVIDER_CLASS" access="field" length="511"/>
+			<property name="dateListProviderData" type="string" column="DATE_LIST_PROVIDER_DATA" access="field" length="1024"/>
 			<list name="dates" table="DATE_LIST_SCHEDULE_DATES" lazy="false">
 				<key column="SCHEDULE_ID"/>
 				<list-index column="ORDER_INDEX"/>

File timemachine-scheduler/src/main/java/timemachine/scheduler/schedule/DateListSchedule.java

 	private List<Date> dates = new ArrayList<Date>();
 	private int nextRunIndex;
 	private String dateListProviderClassName;
+	private String dateListProviderData;
 
 	public DateListSchedule() {
 		missedRunPolicy = SKIP_TO_NOW_POLICY;
 	public DateListSchedule setDateListProviderClassName(Class<? extends DateListProvider> providerClass) {
 		return setDateListProviderClassName(providerClass.getName());
 	}
+
+	public String getDateListProviderData() {
+		return dateListProviderData;
+	}
+	
+	public void setDateListProviderData(String dateListProviderData) {
+		this.dateListProviderData = dateListProviderData;
+	}
 }

File timemachine-scheduler/src/main/java/timemachine/scheduler/schedule/ScriptingDateListProvider.java

+/*
+ * Copyright 2012 Zemian Deng
+ * 
+ * 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 timemachine.scheduler.schedule;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import timemachine.scheduler.SchedulerException;
+import timemachine.scheduler.schedule.DateListSchedule.DateListProvider;
+import timemachine.scheduler.support.Utils;
+
+/**
+ * A date list provider that use an Scripting engine to let user customize the date list generation.
+ * <p>
+ * This provider will take data map with the following keys:
+ * <code>scriptEngineName</code> A java scripting engine name. Default to JavaScript.
+ * <code>scriptText</code> Script text that evaluate into java.util.List<Date> as result.
+ * 
+ * @author Zemian Deng
+ */
+public class ScriptingDateListProvider implements DateListProvider {
+
+	public static final String DEFUALT_SCRIPTING_ENGINE_NAME = "JavaScript";
+	
+	private static Logger logger = LoggerFactory.getLogger(ScriptingDateListProvider.class);
+	private ScriptEngine scriptEngine;
+	private String scriptEngineName;
+	private Map<String, String> providerDataMap;
+	
+	public void init(DateListSchedule schedule) {
+		String providerData = schedule.getDateListProviderData();
+		providerDataMap = Utils.toMap(providerData);
+		scriptEngineName = providerDataMap.get("scriptingEngineName");
+		if (scriptEngineName == null) 
+			scriptEngineName = DEFUALT_SCRIPTING_ENGINE_NAME;
+		
+		logger.debug("Loading scripting engine: {}", scriptEngineName);
+		ScriptEngineManager factory = new ScriptEngineManager();
+		scriptEngine = factory.getEngineByName(scriptEngineName);
+		if (scriptEngine == null) {
+			throw new SchedulerException("Failed to find ScriptEngine " + scriptEngineName);
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public List<Date> getDateList(DateListSchedule schedule) {
+		if (scriptEngine == null)
+			init(schedule);
+		
+		List<Date> result = null;
+		try {
+			Bindings bindings = scriptEngine.createBindings();
+			bindings.put("dateListSchedule", schedule);
+			bindings.put("dateListProvider", this);
+			bindings.put("dateListProviderDataMap", providerDataMap);
+			bindings.put("logger", logger);
+			
+			String scriptText = providerDataMap.get("scriptText");
+			result = (List<Date>)scriptEngine.eval(scriptText, bindings);
+		} catch (ScriptException e) {
+			throw new SchedulerException("Failed to evaluate script to date list.", e);
+		}
+		return result;
+	}
+}

File timemachine-scheduler/src/main/java/timemachine/scheduler/support/Utils.java

 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
 
 import timemachine.scheduler.JobContext;
 import timemachine.scheduler.JobDef;
  */
 public class Utils {
 	
+	/** Parse a input string into a map of string. */
+	public static Map<String, String> toMap(String data, String entrySep, String keyValueSep) {
+		Map<String, String> result = new HashMap<String, String>();
+		String[] words = StringUtils.split(data, entrySep);
+		for (String word : words) {
+			String[] keyValue = StringUtils.split(word, keyValueSep);
+			if (keyValue.length == 2)
+				result.put(keyValue[0], keyValue[1]);		
+		}
+		return result;
+	}
+
+	/** Parse string like "key1=a,key2=b" into a String map. */
+	public static Map<String, String> toMap(String data) {
+		return toMap(data, ",", "=");
+	}
+	
 	/** Given a configProps key and a prefix group, extract the next dot name from the key. Return empty String ("") if no name
 	 * is found. */
 	public static String extractNameInKey(String key, String prefix) {