package brainslug.flow.node.task;
import brainslug.flow.node.FlowNodeDefinition;
import brainslug.util.Option;
import java.util.HashMap;
import java.util.Map;
abstract public class AbstractTaskDefinition<SelfType extends AbstractTaskDefinition> extends FlowNodeDefinition<SelfType> {
protected Class<?> delegateClass;
protected TaskScript taskScript;
protected boolean async;
protected boolean retryAsync;
protected CallDefinition methodCall;
protected RetryStrategy retryStrategy;
protected Option<GoalDefinition> goal = Option.empty();
protected Map<String, String> configuration = new HashMap<String, String>();
/**
* sets a delegate class to be executed as action for this task
*
* Example:
* <pre>
* {@code {@literal @}Override public void define() {
* start(event(id(START)))
* .execute(task(id(TASK)).delegate(Delegate.class))
* .end(event(id(END)));
* }
* }
* </pre>
*
* @param delegateClass type of the delegate class to lookup in the Registry
* @return the task definition
*
*/
public SelfType delegate(Class<?> delegateClass) {
this.delegateClass = delegateClass;
return self();
}
/**
* sets a method invocation as action for this task
*
* Example:
*
* <pre>
* {@code {@literal @}Override public void define() {
* start(event(id(START)))
* .execute(task(id(TASK)).call(method(TestService.class).name("getString")))
* .end(event(id(END)));
* }
* }
* </pre>
*
* @param methodCall the method invocation
* @return the task definition
*
*/
public SelfType call(CallDefinition methodCall) {
this.methodCall = methodCall;
return self();
}
/**
* flag the task for async execution. The execution will be paused
* and continued asynchronously when reaching this task.
*
* Example:
*
* <pre>
* {@code {@literal @}Override public void define() {
* start(event(id(START)))
* .execute(task(id(TASK)).async(true))
* .end(event(id(END)));
* }
* }
* </pre>
*
* @param async true if task execution should be async
* @return the task definition
*
*/
public SelfType async(boolean async) {
this.async = async;
return self();
}
/**
* flag the task for async execution in case of error. The execution will be paused
* and continued asynchronously when the execution of this task fails.
*
* Be aware that this will not be possible int transactional environments if the transaction
* is already set to rollback because of the error.
*
* Example:
*
* <pre>
* {@code {@literal @}Override public void define() {
* start(event(id(START)))
* .execute(task(id(TASK)).retryAsync(true))
* .end(event(id(END)));
* }
* }
* </pre>
*
* @param retryAsync true if task execution should be scheduled for async retry
* @return the task definition
*
*/
public SelfType retryAsync(boolean retryAsync) {
this.retryAsync = retryAsync;
return self();
}
/**
* set the retry strategy in case of async execution.
*
* Example:
*
* <pre>
* {@code new FlowBuilder() {
* {@literal @}Override
* public void define() {
* GoalDefinition testGoal = goal(id("aGoal")).check(predicate(goalCondition));
*
* start(id("start"))
* .execute(task(id("simpleTask")).retryAsync(true).retryStrategy(retryStrategy))
* .end(id("end"));
* }
* }
* }
* </pre>
* @param retryStrategy the retry strategy
* @return this task definition with retryStrategy defined
*/
public SelfType retryStrategy(RetryStrategy retryStrategy) {
this.retryStrategy = retryStrategy;
return self();
}
/**
* A goal groups tasks by the outcome they contribute to.
* Tasks with a goal defined will only be executed if the goal is
* not fulfilled yet.
*
* Goals must have a predicate to check the state of fulfilment.
*
* Example:
*
* <pre>
* {@code new FlowBuilder() {
* {@literal @}Override
* public void define() {
* GoalDefinition testGoal = goal(id("aGoal")).check(predicate(goalCondition));
*
* start(event(id("START")))
* .execute(task(id("TASK"), simpleTask).goal(testGoal))
* .end(event(id("END")));
* }
* }
* }
* </pre>
*
* @param goal the goal this task belongs to
* @return this task definition with goal defined
*/
public SelfType goal(GoalDefinition goal) {
this.goal = Option.of(goal);
return self();
}
public SelfType script(String language, String text) {
this.taskScript = new TaskScript(language, text);
return self();
}
public ConfiugrationBuilder withConfiguration() {
return new ConfiugrationBuilder(self());
}
public Class<?> getDelegateClass() {
return delegateClass;
}
public CallDefinition getMethodCall() {
return methodCall;
}
public Option<TaskScript> getTaskScript() {
return Option.of(taskScript);
}
public Option<GoalDefinition> getGoal() {
return goal;
}
public boolean isAsync() {
return async;
}
public boolean isRetryAsync() {
return retryAsync;
}
public Option<RetryStrategy> getRetryStrategy() {
return Option.of(retryStrategy);
}
public Map<String, String> getConfiguration() {
return configuration;
}
public class ConfiugrationBuilder {
SelfType task;
public ConfiugrationBuilder(SelfType task) {
this.task = task;
}
public ConfiugrationBuilder parameter(String parameterName, String parameterValue) {
configuration.put(parameterName, parameterValue);
return this;
}
public ConfiugrationBuilder parameters(Map<? extends String, ? extends String> parameters) {
configuration.putAll(parameters);
return this;
}
public SelfType done() {
return task;
}
}
}