/** * */ package com.trendrr.oss.taskprocessor; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.trendrr.oss.DynMap; import com.trendrr.oss.Reflection; import com.trendrr.oss.Regex; /** * @author Dustin Norlander * @created Sep 24, 2012 * */ public class Task { protected static Log log = LogFactory.getLog(Task.class); protected static AtomicLong ids = new AtomicLong(); public static enum ASYNCH { FAIL_ON_TIMEOUNT, CONTINUE_ON_TIMEOUT, DO_NOTHING_ON_TIMEOUT } //date when it was submitted to process. protected Date started = null; protected String id = Long.toString(ids.incrementAndGet()); protected List<TaskFilter> filters = new LinkedList<TaskFilter>(); //these have not been run. protected List<TaskFilter> filtersExecuted = new LinkedList<TaskFilter>(); //these have been run. protected TaskProcessor processor; protected TaskCallback callback; /** * protected constuctor. use the instance methods. */ protected Task() { //constructor is protected. } public TaskCallback getCallback() { return callback; } public void setCallback(TaskCallback callback) { this.callback = callback; } /** * is this task set as asynch? if true this task is currently waiting for some asynch op to complete before it * continues its execution. * @return */ public boolean isAsynch() { return asynch; } protected DynMap content = new DynMap(); boolean asynch = false; public static Task instance(Class ...filterClasses) throws Exception { Task t = new Task(); for (Class c : filterClasses) { t.addFilter(c); } return t; } public static Task instance(String ...filterClassNames) throws Exception { Task t = new Task(); for (String c : filterClassNames) { t.addFilter(c); } return t; } public static Task instance(TaskFilter ...filters) { Task t = new Task(); for (TaskFilter c : filters) { t.addFilter(c); } return t; } public static Task instance(Collection<TaskFilter> filters) { Task t = new Task(); for (TaskFilter c : filters) { t.addFilter(c); } return t; } public String getId() { return this.id; } /** * adds a filter by its full classname * @param className */ public void addFilter(String className) throws Exception{ TaskFilter f = Reflection.defaultInstance(TaskFilter.class, className); this.addFilter(f); } public void addFilter(Class cls) throws Exception { Object obj = Reflection.defaultInstance(cls); if (obj instanceof TaskFilter) { this.addFilter((TaskFilter)obj); } else { log.error("Class : " + cls + " is not a TaskFilter!"); } } public void addFilter(TaskFilter filter) { this.filters.add(filter); } public void removeFilter(Class cls) { List<TaskFilter> tmp = new LinkedList<TaskFilter>(); for (TaskFilter f : this.filters) { if (!cls.isInstance(f)) { tmp.add(f); } } this.filters = tmp; } /** * removes any filters that match the supplied regex * @param regex */ public void removeFiltersRegex(String regex) { Pattern pattern = Pattern.compile(regex); this.removeFiltersRegex(pattern); } public void removeFiltersRegex(Pattern pattern) { List<TaskFilter> tmp = new LinkedList<TaskFilter>(); for (TaskFilter f : this.filters) { Matcher matcher = pattern.matcher(f.getName()); if (!matcher.find()) { tmp.add(f); } } this.filters = tmp; } /** * called when the task is first submitted. this is called when * getSubmitted == null * */ public void submitted() { this.started = new Date(); } /** * returns the time when this task was submitted */ public Date getSubmitted() { return this.started; } /** * This would be set in the TaskFilter. sets this task to be asynchronous. * * After the current filter returns execution of filters will stop until task.asynchResume() is called, or * the timeout happens. * @param timeout */ public void asynch(ASYNCH asynch, long timeout) { this.asynch = true; this.getProcessor().setAsynch(this, asynch, timeout); } /** * call this once the asynch call returns, then the */ public void asynchResume() { //resume from asynch call. this.getProcessor().resumeAsynch(this); } /** * asynchronously listens for the future to return. on return the callback is called. * @param future * @param callback * @param timeout */ public void asynchFuture(Future future, FuturePollerCallback callback, long timeout) { this.asynch = true; this.getProcessor().submitFuture(this, future, callback, timeout); } /** * returns the next filter to be run. it is moved from the * unexecuted to executed lists. * @return */ public TaskFilter popFilter() { if (this.filters.isEmpty()) return null; TaskFilter f = filters.remove(0); this.filtersExecuted.add(f); return f; } public List<TaskFilter> getFiltersExecuted() { return filtersExecuted; } public List<TaskFilter> getFiltersUnexecuted() { return filters; } /** * sets the filters * @param filters */ public void addFilters(List<TaskFilter> filters) { this.filters.addAll(filters); } public TaskProcessor getProcessor() { return processor; } public void setProcessor(TaskProcessor processor) { this.processor = processor; } public DynMap getContent() { return content; } public void setContent(DynMap content) { this.content = content; } /** * shortcut to * getContent().get * * @param cls * @param key * @return */ public <T> T get(Class<T> cls, String key) { return this.get(cls, key, null); } /** * shortcut to * getContent().get * * @param cls * @param key * @param defaultValue * @return */ public <T> T get(Class<T> cls, String key, T defaultValue) { return this.content.get(cls, key, defaultValue); } /** * shortcut to * getContent().put * @param key * @param obj */ public void put(String key, Object obj) { this.content.put(key, obj); } /** * shortcut to * getContent().remove * @param key * @return */ public Object remove(String key) { return this.content.remove(key); } }