Skip to content
Browse files

- parallel and relay module

  • Loading branch information...
1 parent a150330 commit 192fe4b70aa3d4c30ebc06c81e88214c132f2051 @sushantk committed
Showing with 725 additions and 176 deletions.
  1. +5 −0 ants/.classpath
  2. BIN ants/external/async-http-client-1.7.6-javadoc.jar
  3. BIN ants/external/async-http-client-1.7.6.jar
  4. +38 −0 ants/src/ants/ListDefault.java
  5. +10 −9 ants/src/ants/ModuleEcho.java
  6. +11 −11 ants/src/ants/ModuleFile.java
  7. +76 −0 ants/src/ants/ModuleSerial.java
  8. +99 −0 ants/src/ants/ModuleWebService.java
  9. +5 −4 ants/src/ants/ParamsDefault.java
  10. +3 −3 ants/src/ants/StringDefault.java
  11. +3 −3 ants/src/ants/StringLiteral.java
  12. +40 −0 ants/src/ants/StringUrl.java
  13. +0 −36 ants/src/ants/api/Data.java
  14. +1 −1 ants/src/ants/{api → core}/Configurable.java
  15. +2 −1 ants/src/ants/{ → core}/Const.java
  16. +2 −2 ants/src/ants/{api → core}/Context.java
  17. +2 −2 ants/src/ants/{api → core}/ContextModule.java
  18. +2 −2 ants/src/ants/{api → core}/ContextRequest.java
  19. +48 −0 ants/src/ants/core/Data.java
  20. +1 −1 ants/src/ants/{api → core}/IList.java
  21. +1 −1 ants/src/ants/{api → core}/IModule.java
  22. +1 −1 ants/src/ants/{api → core}/IObjectFactory.java
  23. +1 −1 ants/src/ants/{api → core}/IParams.java
  24. +1 −1 ants/src/ants/{api → core}/IString.java
  25. +1 −3 ants/src/ants/{ → core}/ObjectFactory.java
  26. +1 −2 ants/src/ants/{ → core}/ObjectStore.java
  27. +22 −19 ants/src/ants/{api → core}/Task.java
  28. +2 −3 ants/src/ants/{ → core}/TaskExecutor.java
  29. +1 −1 ants/src/ants/{ → core}/Util.java
  30. +5 −1 ants/src/ants/{api → ext}/CallbackCopy.java
  31. +6 −2 ants/src/ants/{api → ext}/Module.java
  32. +50 −0 ants/src/ants/ext/ModuleInstanceSpec.java
  33. +4 −1 ants/src/ants/{api → ext}/TaskCompleted.java
  34. +4 −1 ants/src/ants/{api → ext}/TaskFailed.java
  35. +55 −0 ants/src/ants/ext/TaskFork.java
  36. +12 −3 ants/src/ants/{api → ext}/TaskModule.java
  37. +6 −4 ants/src/ants/{api → ext}/TaskNIO.java
  38. +73 −0 ants/src/ants/ext/TaskRelay.java
  39. +15 −0 ants/store/ants/demo/echo.json
  40. +6 −15 ants/test/ants/test/ModuleEchoTest.java
  41. +8 −20 ants/test/ants/test/ModuleFileTest.java
  42. +3 −3 ants/test/ants/test/ModuleTaskTest.java
  43. +54 −0 ants/test/ants/test/ModuleWebServiceTest.java
  44. +2 −2 ants/test/ants/test/ObjectFactoryTest.java
  45. +3 −3 ants/test/ants/test/ParamsDefaultTest.java
  46. +26 −0 ants/test/ants/test/Util.java
  47. +6 −6 ants/test/ants/test/stub/TestModule.java
  48. +2 −2 ants/test/ants/test/stub/TestModuleContext.java
  49. +2 −2 ants/test/ants/test/stub/TestObjectFactory.java
  50. +3 −3 ants/test/ants/test/stub/TestString.java
  51. +1 −1 ants/test/ants/test/stub/TestTaskExecutor.java
View
5 ants/.classpath
@@ -8,5 +8,10 @@
<classpathentry kind="lib" path="external/slf4j-simple-1.7.1.jar"/>
<classpathentry kind="lib" path="external/jackson-all-1.9.9.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+ <classpathentry kind="lib" path="external/async-http-client-1.7.6.jar">
+ <attributes>
+ <attribute name="javadoc_location" value="jar:platform:/resource/ants/external/async-http-client-1.7.6-javadoc.jar!/"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
View
BIN ants/external/async-http-client-1.7.6-javadoc.jar
Binary file not shown.
View
BIN ants/external/async-http-client-1.7.6.jar
Binary file not shown.
View
38 ants/src/ants/ListDefault.java
@@ -0,0 +1,38 @@
+package ants;
+
+import java.util.LinkedHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ants.annotation.ConfigurableClass;
+import ants.annotation.ConfigurableMethod;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IList;
+import ants.exception.EvaluateException;
+
+/**
+ * Default list class to configure and hold a list of items
+ */
+@ConfigurableClass(expectsList = true)
+public class ListDefault extends Configurable implements IList {
+ static final Logger logger = LoggerFactory.getLogger(ListDefault.class);
+
+ private LinkedHashMap<String, Configurable> list;
+
+ public ListDefault(String tagName, String id) {
+ super(tagName, id);
+ }
+
+ @ConfigurableMethod(required = true, defaultListItemClass = "ants.StringDefault", listItemTag = "item")
+ public void setList(LinkedHashMap<String, Configurable> list) {
+ this.list = list;
+ }
+
+ @Override
+ public LinkedHashMap<String, Configurable> getItems(ContextModule context)
+ throws EvaluateException {
+ return this.list;
+ }
+}
View
19 ants/src/ants/ModuleEcho.java
@@ -1,18 +1,19 @@
package ants;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.Data;
-import ants.api.TaskCompleted;
-import ants.api.IModule;
-import ants.api.IString;
-import ants.api.ContextModule;
-import ants.api.Task;
-import ants.api.TaskFailed;
+import ants.core.Configurable;
+import ants.core.Const;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IString;
+import ants.core.Task;
import ants.exception.EvaluateException;
import ants.exception.ExecuteException;
+import ants.ext.Module;
+import ants.ext.TaskCompleted;
+import ants.ext.TaskFailed;
-public class ModuleEcho extends Configurable implements IModule {
+public class ModuleEcho extends Module {
private IString value;
View
22 ants/src/ants/ModuleFile.java
@@ -7,19 +7,18 @@
import java.util.Collection;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.Data;
-import ants.api.IModule;
-import ants.api.IString;
-import ants.api.ContextModule;
-import ants.api.Module;
-import ants.api.Task;
-import ants.api.TaskNIO;
-import ants.api.TaskFailed;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IString;
+import ants.core.Task;
import ants.exception.EvaluateException;
import ants.exception.ExecuteException;
+import ants.ext.Module;
+import ants.ext.TaskFailed;
+import ants.ext.TaskNIO;
-public class ModuleFile extends Module implements IModule {
+public class ModuleFile extends Module {
private IString path;
private IString mime;
@@ -65,7 +64,6 @@ public Task execute(ContextModule context, Data input) {
TaskNIO task = new TaskFile(data, this.toContextString(context, filePath));
channel.read(dst, 0, null, task);
-
return task;
} catch (EvaluateException e) {
return new TaskFailed(new ExecuteException(this.toContextString(context),
@@ -88,6 +86,8 @@ public TaskFile(Data data, String key) {
@Override
protected Collection<Task> runImpl() {
+ ByteBuffer buffer = (ByteBuffer)this.runData.getData();
+ buffer.rewind();
this.setAsyncData(runData);
return super.runImpl();
}
View
76 ants/src/ants/ModuleSerial.java
@@ -0,0 +1,76 @@
+package ants;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+
+import ants.annotation.ConfigurableMethod;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IList;
+import ants.core.Task;
+import ants.exception.EvaluateException;
+import ants.exception.ExecuteException;
+import ants.ext.Module;
+import ants.ext.ModuleInstanceSpec;
+import ants.ext.TaskFailed;
+import ants.ext.TaskRelay;
+import ants.ext.TaskModule;
+
+public class ModuleSerial extends Module implements TaskRelay.ICallback {
+
+ private IList members;
+ private ContextModule runContext;
+
+ public ModuleSerial(String tagName, String id) {
+ super(tagName, id);
+ }
+
+ @ConfigurableMethod(required = true, defaultClass="ants.ListDefault",
+ defaultListItemClass="ants.ModuleInstance", listItemTag="member")
+ public void setMembers(Configurable value) {
+ this.members = IList.class.cast(value);
+ }
+
+ @Override
+ public Task execute(ContextModule context, Data data) {
+ this.runContext = context;
+
+ try {
+ LinkedHashMap<String, Task> tasks = new LinkedHashMap<>();
+
+ LinkedHashMap<String, Configurable> members = this.members.getItems(context);
+ Iterator<Entry<String, Configurable>> iter = members.entrySet()
+ .iterator();
+ while (iter.hasNext()) {
+ Entry<String, Configurable> entry = iter.next();
+ Configurable configurable = entry.getValue();
+
+ ModuleInstanceSpec spec = ModuleInstanceSpec.class.cast(configurable);
+ ContextModule instanceContext = spec.createContext(context);
+ TaskModule task = new TaskModule(instanceContext, data);
+ tasks.put(entry.getKey(), task);
+ }
+
+ Task fork = new TaskRelay(this.toContextString(context), tasks, this);
+ return fork;
+ } catch (EvaluateException e) {
+ return new TaskFailed(new ExecuteException(this.toContextString(context),
+ "Failed to evaluate members' list", e));
+ } catch(ExecuteException e) {
+ return new TaskFailed(new ExecuteException(this.toContextString(context),
+ "Failed to create member's context", e));
+ }
+ }
+
+ @Override
+ public Data filter(String taskId, Task task) throws ExecuteException {
+ if(Task.Result.COMPLETED == task.getResult()) {
+ return task.getData();
+ }
+
+ throw new ExecuteException(this.toContextString(this.runContext), "Failed to execute module: " + taskId);
+ }
+
+}
View
99 ants/src/ants/ModuleWebService.java
@@ -0,0 +1,99 @@
+package ants;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.http.client.AsyncCompletionHandlerBase;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
+import com.ning.http.client.Request;
+import com.ning.http.client.Response;
+
+import ants.annotation.ConfigurableMethod;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IString;
+import ants.core.Task;
+import ants.exception.EvaluateException;
+import ants.exception.ExecuteException;
+import ants.ext.Module;
+import ants.ext.TaskFailed;
+
+public class ModuleWebService extends Module {
+ private static final Logger logger = LoggerFactory.getLogger(ModuleWebService.class);
+ private static AsyncHttpClient httpClient = new AsyncHttpClient();
+
+ private IString url;
+
+ public ModuleWebService(String tagName, String id) {
+ super(tagName, id);
+ }
+
+ @ConfigurableMethod(required=true)
+ public void setUrl(Configurable value) {
+ this.url = IString.class.cast(value);
+ }
+
+ @Override
+ public Task execute(ContextModule context, Data input) {
+
+ String url = null;
+ try {
+ url = this.url.getValue(context);
+
+ BoundRequestBuilder requestBuilder = httpClient.prepareGet(url);
+ Request request = requestBuilder.build();
+
+ TaskNing task = new TaskNing(this.toContextString(context, url));
+ httpClient.executeRequest(request, task.new NingHandler());
+ return task;
+ } catch (EvaluateException e) {
+ return new TaskFailed(new ExecuteException(this.toContextString(context),
+ "Failed to evaluate configured parameter", e));
+ } catch (Exception e) {
+ return new TaskFailed(new ExecuteException(this.toContextString(context, url),
+ "Failed to initiate webservice fetch", e));
+ }
+ }
+
+ public static class TaskNing extends Task {
+ private Response response;
+ private Throwable exception;
+
+ public TaskNing(String key) {
+ super(Task.Type.ASYNC, key);
+ }
+
+ @Override
+ protected Collection<Task> runImpl() {
+ if (null != this.exception) {
+ super.failed(null, new ExecuteException(this.toString(), "Failed to fetch", this.exception));
+ } else if(null == this.response) {
+ super.failed(null, new ExecuteException(this.toString(), "Internal error, failed to get response"));
+ }
+
+ super.completed(new Data(this.response, "object/" + Response.class.getName()));
+ return Collections.emptyList();
+ }
+
+ public class NingHandler extends AsyncCompletionHandlerBase {
+ @Override
+ public Response onCompleted(Response response) throws Exception {
+ TaskNing.this.response = response;
+ TaskNing.this.ready();
+ return response;
+ }
+
+ @Override
+ public void onThrowable(Throwable t) {
+ TaskNing.this.exception = t;
+ TaskNing.this.ready();
+ }
+ }
+ }
+
+}
View
9 ants/src/ants/ParamsDefault.java
@@ -9,10 +9,11 @@
import ants.annotation.ConfigurableClass;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.ContextModule;
-import ants.api.IParams;
-import ants.api.IString;
+import ants.core.Configurable;
+import ants.core.Const;
+import ants.core.ContextModule;
+import ants.core.IParams;
+import ants.core.IString;
import ants.exception.EvaluateException;
/**
View
6 ants/src/ants/StringDefault.java
@@ -5,9 +5,9 @@
import ants.annotation.ConfigurableClass;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.IString;
-import ants.api.ContextModule;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IString;
@ConfigurableClass(expectsValue=true)
public class StringDefault extends Configurable
View
6 ants/src/ants/StringLiteral.java
@@ -2,9 +2,9 @@
import ants.annotation.ConfigurableClass;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.IString;
-import ants.api.ContextModule;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IString;
@ConfigurableClass(expectsValue=true)
public class StringLiteral extends Configurable
View
40 ants/src/ants/StringUrl.java
@@ -0,0 +1,40 @@
+package ants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ants.annotation.ConfigurableClass;
+import ants.annotation.ConfigurableMethod;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IString;
+import ants.exception.EvaluateException;
+
+@ConfigurableClass(expectsValue=true)
+public class StringUrl extends Configurable
+ implements IString {
+ private static final Logger logger = LoggerFactory.getLogger(StringUrl.class);
+
+ private IString base;
+
+ public StringUrl(String tagName, String id) {
+ super(tagName, id);
+ }
+
+ public void setValue(String value) {
+ StringLiteral literal = new StringLiteral("base", "");
+ literal.setValue(value);
+ this.base = literal;
+ }
+
+ @ConfigurableMethod(required=true)
+ public void setBase(Configurable value) {
+ this.base = IString.class.cast(value);
+ }
+
+ @Override
+ public String getValue(ContextModule context) throws EvaluateException {
+ return this.base.getValue(context);
+ }
+
+}
View
36 ants/src/ants/api/Data.java
@@ -1,36 +0,0 @@
-package ants.api;
-
-public class Data {
-
- private Object dataObject;
- private String mimeType;
- private String charSet = "";
-
- private String uri = "";
-
- public Data(Object dataObject, String mimeType, String charSet) {
- this.dataObject = dataObject;
- this.mimeType = mimeType;
- this.charSet = charSet;
- }
-
- public Object getObject() {
- return this.dataObject;
- }
-
- public String getMimeType() {
- return this.mimeType;
- }
-
- public String getCharSet() {
- return this.charSet;
- }
-
- public String getUri() {
- return uri;
- }
-
- public void setUri(String uri) {
- this.uri = uri;
- }
-}
View
2 ants/src/ants/api/Configurable.java → ants/src/ants/core/Configurable.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import java.util.Map;
import java.util.TreeMap;
View
3 ants/src/ants/Const.java → ants/src/ants/core/Const.java
@@ -1,4 +1,4 @@
-package ants;
+package ants.core;
public final class Const {
@@ -23,6 +23,7 @@
public static class mime {
public static final String plain = "text/plain";
+ public static final String object = "object";
}
public static class charSet {
View
4 ants/src/ants/api/Context.java → ants/src/ants/core/Context.java
@@ -1,8 +1,8 @@
-package ants.api;
+package ants.core;
import java.util.LinkedHashMap;
-import ants.api.IParams.Type;
+import ants.core.IParams.Type;
public abstract class Context {
View
4 ants/src/ants/api/ContextModule.java → ants/src/ants/core/ContextModule.java
@@ -1,8 +1,8 @@
-package ants.api;
+package ants.core;
import java.util.LinkedHashMap;
-import ants.api.IParams.Type;
+import ants.core.IParams.Type;
public class ContextModule extends Context {
View
4 ants/src/ants/api/ContextRequest.java → ants/src/ants/core/ContextRequest.java
@@ -1,8 +1,8 @@
-package ants.api;
+package ants.core;
import java.util.LinkedHashMap;
-import ants.api.IParams.Type;
+import ants.core.IParams.Type;
public class ContextRequest extends Context {
View
48 ants/src/ants/core/Data.java
@@ -0,0 +1,48 @@
+package ants.core;
+
+public class Data {
+
+ private Object data;
+ private String mimeType;
+ private String charSet;
+
+ //TODO: aspect of this data as other pojos
+ // private List<Data> aspects;
+
+ private String uri = "";
+
+ public Data(Object data, String mimeType) {
+ this(data, mimeType, "");
+ }
+
+ public Data(Object data, String mimeType, String charSet) {
+ this.data = data;
+ this.mimeType = mimeType;
+ this.charSet = charSet;
+ }
+
+ public Object getData() {
+ return this.data;
+ }
+
+ public Data getAspect(Class<?> klass) {
+ // object/klass.getname mimetype
+ return null;
+ }
+
+ public String getMimeType() {
+ return this.mimeType;
+ }
+
+ public String getCharSet() {
+ return this.charSet;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+}
View
2 ants/src/ants/api/IList.java → ants/src/ants/core/IList.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import java.util.LinkedHashMap;
View
2 ants/src/ants/api/IModule.java → ants/src/ants/core/IModule.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
public interface IModule {
View
2 ants/src/ants/api/IObjectFactory.java → ants/src/ants/core/IObjectFactory.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import ants.exception.ObjectConfigureException;
import ants.exception.ParseException;
View
2 ants/src/ants/api/IParams.java → ants/src/ants/core/IParams.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import java.util.LinkedHashMap;
View
2 ants/src/ants/api/IString.java → ants/src/ants/core/IString.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import ants.exception.EvaluateException;
View
4 ants/src/ants/ObjectFactory.java → ants/src/ants/core/ObjectFactory.java
@@ -1,4 +1,4 @@
-package ants;
+package ants.core;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -25,8 +25,6 @@
import ants.annotation.ConfigurableClass;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
-import ants.api.IObjectFactory;
import ants.exception.ObjectConfigureException;
import ants.exception.ObjectCreateException;
import ants.exception.ObjectIncompleteException;
View
3 ants/src/ants/ObjectStore.java → ants/src/ants/core/ObjectStore.java
@@ -1,10 +1,9 @@
-package ants;
+package ants.core;
import java.io.InputStream;
import org.codehaus.jackson.JsonNode;
-import ants.api.Configurable;
import ants.exception.ObjectConfigureException;
import ants.exception.ParseException;
View
41 ants/src/ants/api/Task.java → ants/src/ants/core/Task.java
@@ -1,4 +1,4 @@
-package ants.api;
+package ants.core;
import java.util.Collection;
import java.util.LinkedList;
@@ -28,23 +28,6 @@
private static final Logger logger = LoggerFactory.getLogger(Task.class);
/**
- * Used by the task manager to monitor task activity and run the next set of
- * tasks of returned by the callbacks
- */
- public interface IExecutor {
-
- /**
- * Notify the executor when an async task is ready to run
- */
- void onAsyncReady(final Task task);
-
- /**
- * Notify the monitor when the task has finished fetching the data
- */
- void onDone(final Task task, Collection<ICallback> calbacks);
- }
-
- /**
* Callback to send the task completion notification to one or more
* listeners.
*/
@@ -78,6 +61,10 @@ public Type getType() {
return this.type;
}
+ public String getKey() {
+ return this.key;
+ }
+
public Status getStatus() {
return this.status;
}
@@ -161,5 +148,21 @@ private void done(Data data, Result result) {
this.result = result;
this.executor.onDone(this, this.callbacks);
}
-
+
+ /**
+ * Used by the task manager to monitor task activity and run the next set of
+ * tasks of returned by the callbacks
+ */
+ public interface IExecutor {
+
+ /**
+ * Notify the executor when an async task is ready to run
+ */
+ void onAsyncReady(final Task task);
+
+ /**
+ * Notify the monitor when the task has finished fetching the data
+ */
+ void onDone(final Task task, Collection<ICallback> calbacks);
+ }
}
View
5 ants/src/ants/TaskExecutor.java → ants/src/ants/core/TaskExecutor.java
@@ -1,4 +1,4 @@
-package ants;
+package ants.core;
import java.util.Collection;
import java.util.LinkedList;
@@ -9,7 +9,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import ants.api.Task;
/**
* Provides foundation for task execution
@@ -64,7 +63,7 @@ private void submit(Task task, boolean queue) {
}
/**
- * @see ants.api.Task.Monitor#onAsyncReady(ants.api.Task)
+ * @see ants.core.Task.Monitor#onAsyncReady(ants.core.Task)
*/
@Override
public void onAsyncReady(Task task) {
View
2 ants/src/ants/Util.java → ants/src/ants/core/Util.java
@@ -1,4 +1,4 @@
-package ants;
+package ants.core;
public class Util {
View
6 ants/src/ants/api/CallbackCopy.java → ants/src/ants/ext/CallbackCopy.java
@@ -1,8 +1,12 @@
-package ants.api;
+package ants.ext;
import java.util.Collection;
import java.util.Collections;
+import ants.core.Task;
+import ants.core.Task.ICallback;
+import ants.core.Task.Result;
+
public class CallbackCopy implements Task.ICallback {
Task target;
View
8 ants/src/ants/api/Module.java → ants/src/ants/ext/Module.java
@@ -1,6 +1,10 @@
-package ants.api;
+package ants.ext;
-public abstract class Module extends Configurable {
+import ants.core.Configurable;
+import ants.core.Context;
+import ants.core.IModule;
+
+public abstract class Module extends Configurable implements IModule {
public Module(String tagName, String id) {
super(tagName, id);
View
50 ants/src/ants/ext/ModuleInstanceSpec.java
@@ -0,0 +1,50 @@
+package ants.ext;
+
+import java.util.LinkedHashMap;
+
+import ants.annotation.ConfigurableMethod;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IParams;
+import ants.core.IString;
+import ants.core.IParams.Type;
+import ants.exception.EvaluateException;
+import ants.exception.ExecuteException;
+
+public class ModuleInstanceSpec extends Configurable {
+
+ private IString moduleId;
+ private IParams params;
+
+ public ModuleInstanceSpec(String tagName, String id) {
+ super(tagName, id);
+ }
+
+ @ConfigurableMethod(required=true, defaultClass = "ants.StringLiteral")
+ public void setModuleId(Configurable value) {
+ this.moduleId = IString.class.cast(value);
+ }
+
+ public void setParams(Configurable params) {
+ this.params = IParams.class.cast(params);
+ }
+
+ public ContextModule createContext(ContextModule context) throws ExecuteException {
+ try {
+ String moduleId = this.moduleId.getValue(context);
+
+ LinkedHashMap<String, Type> params;
+ if(null != this.params) {
+ params = this.params.getPairs(context, false);
+ } else {
+ params = new LinkedHashMap<>();
+ }
+
+ return new ContextModule(moduleId, params, context);
+ } catch (EvaluateException e) {
+ throw new ExecuteException(this.toContextString(context),
+ "Failed to evaluate configured parameter", e);
+ }
+ }
+
+}
View
5 ants/src/ants/api/TaskCompleted.java → ants/src/ants/ext/TaskCompleted.java
@@ -1,8 +1,11 @@
-package ants.api;
+package ants.ext;
import java.util.Collection;
import java.util.Collections;
+import ants.core.Data;
+import ants.core.Task;
+
/**
* A dummy task that can respond to the run method with a
* pre set data
View
5 ants/src/ants/api/TaskFailed.java → ants/src/ants/ext/TaskFailed.java
@@ -1,8 +1,11 @@
-package ants.api;
+package ants.ext;
import java.util.Collection;
import java.util.Collections;
+import ants.core.Data;
+import ants.core.Task;
+
/**
* A dummy task that can respond to the run method with an
* exception and data if any
View
55 ants/src/ants/ext/TaskFork.java
@@ -0,0 +1,55 @@
+package ants.ext;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import ants.core.Data;
+import ants.core.Task;
+import ants.exception.ExecuteException;
+
+/**
+ * A task that runs multiple other tasks
+ */
+public class TaskFork extends Task implements Task.ICallback {
+
+ public interface ICallback {
+ Data join(Map<String, Task> tasks) throws ExecuteException;
+ }
+
+ Map<String, Task> tasks;
+ ICallback runCallback;
+ int runTaskCount = 0;
+
+ public TaskFork(String key, Map<String, Task> tasks, ICallback callback) {
+ super(Task.Type.SYNC, key);
+
+ this.tasks = tasks;
+ this.runCallback = callback;
+ }
+
+ @Override
+ protected Collection<Task> runImpl() {
+ Collection<Task> tasks = this.tasks.values();
+ for(Task task : tasks) {
+ task.addCallback(this);
+ }
+
+ return tasks;
+ }
+
+ @Override
+ public Collection<Task> onDone(Task task) {
+ if(++this.runTaskCount == this.tasks.size()) {
+ try {
+ Data data = this.runCallback.join(this.tasks);
+ this.completed(data);
+ } catch(ExecuteException e) {
+ this.failed(null, e);
+ }
+ }
+
+ return Collections.emptyList();
+ }
+
+}
View
15 ants/src/ants/api/TaskModule.java → ants/src/ants/ext/TaskModule.java
@@ -1,9 +1,14 @@
-package ants.api;
+package ants.ext;
import java.util.Collection;
import java.util.Collections;
-import ants.Const;
+import ants.core.Const;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IModule;
+import ants.core.IObjectFactory;
+import ants.core.Task;
public class TaskModule extends Task {
@@ -11,11 +16,15 @@
private Data input;
public TaskModule(ContextModule context, Data input) {
- super(Task.Type.SYNC, "");
+ super(Task.Type.SYNC, context.toString());
this.context = context;
this.input = input;
}
+
+ public ContextModule getContext() {
+ return this.context;
+ }
@Override
protected Collection<Task> runImpl() {
View
10 ants/src/ants/api/TaskNIO.java → ants/src/ants/ext/TaskNIO.java
@@ -1,9 +1,12 @@
-package ants.api;
+package ants.ext;
import java.nio.channels.CompletionHandler;
import java.util.Collection;
import java.util.Collections;
+import ants.core.Data;
+import ants.core.Task;
+import ants.core.Task.Type;
import ants.exception.ExecuteException;
public class TaskNIO extends Task implements CompletionHandler<Integer, Object> {
@@ -29,10 +32,9 @@ public void setAsyncException(Throwable e) {
super.failed(null, new ExecuteException(this.toString(), "Failed to execute", this.asyncException));
} else if(null == this.asyncData) {
super.failed(null, new ExecuteException(this.toString(), "Internal error, failed to set data"));
- } else {
- super.completed(this.asyncData);
}
-
+
+ super.completed(this.asyncData);
return Collections.emptyList();
}
View
73 ants/src/ants/ext/TaskRelay.java
@@ -0,0 +1,73 @@
+package ants.ext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+
+import ants.core.Data;
+import ants.core.Task;
+import ants.exception.ExecuteException;
+
+/**
+ * A task that runs multiple other tasks in sequence. Data from the last
+ * task is used after filtering
+ */
+public class TaskRelay extends Task implements Task.ICallback {
+
+ public interface ICallback {
+ Data filter(String taskId, Task task) throws ExecuteException;
+ }
+
+ LinkedHashMap<String, Task> tasks;
+ ICallback runCallback;
+ Iterator<Entry<String, Task>> runTaskIterator;
+ Entry<String, Task> runTaskEntry;
+
+ public TaskRelay(String key, LinkedHashMap<String, Task> tasks, ICallback callback) {
+ super(Task.Type.SYNC, key);
+
+ this.tasks = tasks;
+ this.runCallback = callback;
+ }
+
+ @Override
+ protected Collection<Task> runImpl() {
+ this.runTaskIterator = this.tasks.entrySet().iterator();
+
+ this.runTaskEntry = this.runTaskIterator.next();
+ Task firstTask = this.runTaskEntry.getValue();
+ firstTask.addCallback(this);
+
+ ArrayList<Task> firstTaskList = new ArrayList<>();
+ firstTaskList.add(firstTask);
+ return firstTaskList;
+ }
+
+ @Override
+ public Collection<Task> onDone(Task task) {
+ Data data = null;
+ try {
+ data = this.runCallback.filter(this.runTaskEntry.getKey(), task);
+ } catch(ExecuteException e) {
+ this.failed(null, e);
+ }
+
+ if(this.runTaskIterator.hasNext()) {
+ this.runTaskEntry = this.runTaskIterator.next();
+ Task nextTask = this.runTaskEntry.getValue();
+ nextTask.addCallback(this);
+
+ ArrayList<Task> nextTaskList = new ArrayList<>();
+ nextTaskList.add(nextTask);
+ return nextTaskList;
+ } else {
+ this.completed(data);
+ }
+
+ return Collections.emptyList();
+ }
+
+}
View
15 ants/store/ants/demo/echo.json
@@ -0,0 +1,15 @@
+{
+ "fetcher": {
+ "@class": "ants.FetcherEcho",
+ "string": "Hello World"
+ }
+
+ "module": {
+ "fetcher": {
+ "id": "echo",
+ "params": {
+ "string": "Hello World"
+ }
+ }
+ }
+}
View
21 ants/test/ants/test/ModuleEchoTest.java
@@ -3,14 +3,11 @@
import org.junit.Test;
import static org.junit.Assert.*;
-import ants.Const;
import ants.ModuleEcho;
-import ants.api.Data;
-import ants.api.ContextModule;
-import ants.api.Task;
-import ants.test.stub.TestModuleContext;
+import ants.core.Const;
+import ants.core.Data;
+import ants.core.Task;
import ants.test.stub.TestString;
-import ants.test.stub.TestTaskExecutor;
public class ModuleEchoTest {
@@ -21,16 +18,13 @@ public void testSuccess() {
ModuleEcho fetcher = new ModuleEcho("fetcher", "");
fetcher.setString(new TestString(testStr));
- ContextModule context = new TestModuleContext();
- Task task = fetcher.execute(context, null);
- TestTaskExecutor taskExecutor = new TestTaskExecutor();
- taskExecutor.submit(task);
+ Task task = Util.executeModule(fetcher);
assertEquals("Task is done", Task.Status.DONE, task.getStatus());
assertEquals("Result is success", Task.Result.COMPLETED, task.getResult());
Data data = task.getData();
assertEquals("Data mime type is plain", Const.mime.plain, data.getMimeType());
- assertEquals("Data is as given", testStr, data.getObject());
+ assertEquals("Data is as given", testStr, data.getData());
}
@Test
@@ -38,10 +32,7 @@ public void testFail() {
ModuleEcho fetcher = new ModuleEcho("fetcher", "");
fetcher.setString(new TestString());
- ContextModule context = new TestModuleContext();
- Task task = fetcher.execute(context, null);
- TestTaskExecutor taskExecutor = new TestTaskExecutor();
- taskExecutor.submit(task);
+ Task task = Util.executeModule(fetcher);
assertEquals("Task is done", Task.Status.DONE, task.getStatus());
assertEquals("Result is failed", Task.Result.FAILED, task.getResult());
View
28 ants/test/ants/test/ModuleFileTest.java
@@ -8,14 +8,11 @@
import org.junit.Test;
import static org.junit.Assert.*;
-import ants.Const;
import ants.ModuleFile;
-import ants.api.Data;
-import ants.api.ContextModule;
-import ants.api.Task;
-import ants.test.stub.TestModuleContext;
+import ants.core.Const;
+import ants.core.Data;
+import ants.core.Task;
import ants.test.stub.TestString;
-import ants.test.stub.TestTaskExecutor;
public class ModuleFileTest {
@@ -28,12 +25,7 @@ public void testSuccess() throws InterruptedException, CharacterCodingException
fetcher.setCharSet(new TestString(Const.charSet.ascii));
fetcher.setPath(new TestString(path.getPath()));
- ContextModule context = new TestModuleContext();
- Task task = fetcher.execute(context, null);
-
- TestTaskExecutor taskExecutor = new TestTaskExecutor();
- taskExecutor.submit(task);
- taskExecutor.wait(task, 5000);
+ Task task = Util.executeModule(fetcher, 1000);
assertEquals("Task is done", Task.Status.DONE, task.getStatus());
assertEquals("Result is success", Task.Result.COMPLETED, task.getResult());
@@ -41,26 +33,22 @@ public void testSuccess() throws InterruptedException, CharacterCodingException
assertEquals("Data mime type is plain", Const.mime.plain, data.getMimeType());
assertEquals("Data charset is ascii", Const.charSet.ascii, data.getCharSet());
- ByteBuffer buffer = (ByteBuffer)data.getObject();
- buffer.rewind();
+ ByteBuffer buffer = (ByteBuffer)data.getData();
String content = Charset.forName(data.getCharSet()).newDecoder().decode(buffer).toString();
assertEquals("Data is as given", "dummy", content);
}
@Test
- public void testFail() throws InterruptedException {
+ public void testFail() {
ModuleFile fetcher = new ModuleFile("fetcher", "");
fetcher.setMimeType(new TestString(Const.mime.plain));
fetcher.setCharSet(new TestString(Const.charSet.ascii));
fetcher.setPath(new TestString("data/non_existent"));
- ContextModule context = new TestModuleContext();
- Task task = fetcher.execute(context, null);
-
- TestTaskExecutor taskExecutor = new TestTaskExecutor();
- taskExecutor.submit(task);
+ Task task = Util.executeModule(fetcher);
assertEquals("Task is done", Task.Status.DONE, task.getStatus());
assertEquals("Result is failed", Task.Result.FAILED, task.getResult());
}
+
}
View
6 ants/test/ants/test/ModuleTaskTest.java
@@ -4,9 +4,9 @@
import org.junit.Test;
-import ants.api.Data;
-import ants.api.TaskModule;
-import ants.api.Task;
+import ants.core.Data;
+import ants.core.Task;
+import ants.ext.TaskModule;
import ants.test.stub.TestModuleContext;
import ants.test.stub.TestModule;
import ants.test.stub.TestObjectFactory;
View
54 ants/test/ants/test/ModuleWebServiceTest.java
@@ -0,0 +1,54 @@
+package ants.test;
+
+import org.junit.Test;
+
+import com.ning.http.client.Response;
+
+import static org.junit.Assert.*;
+
+import ants.ModuleWebService;
+import ants.core.Const;
+import ants.core.Data;
+import ants.core.Task;
+import ants.test.stub.TestString;
+
+public class ModuleWebServiceTest {
+
+ @Test
+ public void testSuccess() throws InterruptedException {
+ ModuleWebService fetcher = new ModuleWebService("fetcher", "");
+ fetcher.setUrl(new TestString("http://www.google.com"));
+
+ Task task = Util.executeModule(fetcher, 5000);
+
+ assertEquals("Task is done", Task.Status.DONE, task.getStatus());
+ assertEquals("Result is success", Task.Result.COMPLETED, task.getResult());
+ Data data = task.getData();
+ assertTrue("Data mime type is object", data.getMimeType().startsWith(Const.mime.object));
+ Response response = (Response)data.getData();
+ assertEquals("Response is 200", 200, response.getStatusCode());
+ }
+
+ @Test
+ public void testFailConfiguration() {
+ ModuleWebService fetcher = new ModuleWebService("fetcher", "");
+ fetcher.setUrl(new TestString());
+
+ Task task = Util.executeModule(fetcher);
+
+ assertEquals("Task is done", Task.Status.DONE, task.getStatus());
+ assertEquals("Result is failed", Task.Result.FAILED, task.getResult());
+ }
+
+ @Test
+ public void testFailBadUrl() {
+ ModuleWebService fetcher = new ModuleWebService("fetcher", "");
+ fetcher.setUrl(new TestString("bad://www.host.com"));
+
+ Task task = Util.executeModule(fetcher);
+
+ assertEquals("Task is done", Task.Status.DONE, task.getStatus());
+ assertEquals("Result is failed", Task.Result.FAILED, task.getResult());
+ }
+
+}
View
4 ants/test/ants/test/ObjectFactoryTest.java
@@ -9,12 +9,12 @@
import org.junit.Test;
import static org.junit.Assert.*;
-import ants.ObjectFactory;
import ants.ParamsDefault;
import ants.StringDefault;
import ants.annotation.ConfigurableClass;
import ants.annotation.ConfigurableMethod;
-import ants.api.Configurable;
+import ants.core.Configurable;
+import ants.core.ObjectFactory;
import ants.exception.ObjectConfigureException;
import ants.exception.ObjectCreateException;
import ants.exception.ObjectIncompleteException;
View
6 ants/test/ants/test/ParamsDefaultTest.java
@@ -9,10 +9,10 @@
import org.codehaus.jackson.JsonNode;
import org.junit.Test;
-import ants.ObjectFactory;
import ants.ParamsDefault;
-import ants.api.IParams.Type;
-import ants.api.ContextModule;
+import ants.core.ContextModule;
+import ants.core.ObjectFactory;
+import ants.core.IParams.Type;
import ants.exception.ObjectConfigureException;
import ants.exception.EvaluateException;
import ants.exception.ParseException;
View
26 ants/test/ants/test/Util.java
@@ -1,4 +1,30 @@
package ants.test;
+import ants.core.ContextModule;
+import ants.core.IModule;
+import ants.core.Task;
+import ants.test.stub.TestModuleContext;
+import ants.test.stub.TestTaskExecutor;
+
public class Util {
+
+ public static Task executeModule(IModule module) {
+ try {
+ return Util.executeModule(module, 0);
+ } catch (InterruptedException e) {
+ // ignored
+ return null;
+ }
+ }
+
+ public static Task executeModule(IModule module, int timeout) throws InterruptedException {
+ ContextModule context = new TestModuleContext();
+ Task task = module.execute(context, null);
+ TestTaskExecutor taskExecutor = new TestTaskExecutor();
+ taskExecutor.submit(task);
+ if(timeout > 0) {
+ taskExecutor.wait(task, timeout);
+ }
+ return task;
+ }
}
View
12 ants/test/ants/test/stub/TestModule.java
@@ -3,13 +3,13 @@
import java.util.Collection;
import java.util.Collections;
-import ants.api.Configurable;
-import ants.api.Data;
-import ants.api.IModule;
-import ants.api.ContextModule;
-import ants.api.Module;
-import ants.api.Task;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.Data;
+import ants.core.IModule;
+import ants.core.Task;
import ants.exception.ExecuteException;
+import ants.ext.Module;
public class TestModule extends Module implements IModule {
View
4 ants/test/ants/test/stub/TestModuleContext.java
@@ -1,7 +1,7 @@
package ants.test.stub;
-import ants.api.ContextModule;
-import ants.api.ContextRequest;
+import ants.core.ContextModule;
+import ants.core.ContextRequest;
public class TestModuleContext extends ContextModule {
public TestModuleContext() {
View
4 ants/test/ants/test/stub/TestObjectFactory.java
@@ -1,7 +1,7 @@
package ants.test.stub;
-import ants.api.Configurable;
-import ants.api.IObjectFactory;
+import ants.core.Configurable;
+import ants.core.IObjectFactory;
import ants.exception.ObjectConfigureException;
import ants.exception.ParseException;
View
6 ants/test/ants/test/stub/TestString.java
@@ -1,8 +1,8 @@
package ants.test.stub;
-import ants.api.Configurable;
-import ants.api.IString;
-import ants.api.ContextModule;
+import ants.core.Configurable;
+import ants.core.ContextModule;
+import ants.core.IString;
import ants.exception.EvaluateException;
public class TestString extends Configurable
View
2 ants/test/ants/test/stub/TestTaskExecutor.java
@@ -3,7 +3,7 @@
import java.util.Collection;
import java.util.LinkedList;
-import ants.api.Task;
+import ants.core.Task;
public class TestTaskExecutor implements Task.IExecutor {

0 comments on commit 192fe4b

Please sign in to comment.
Something went wrong with that request. Please try again.