/*
* Copyright 2004 - 2009 University of Cardiff.
*
* 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 org.trianacode.gui.service;
import org.trianacode.enactment.io.IoConfiguration;
import org.trianacode.enactment.io.IoHandler;
import org.trianacode.enactment.io.NodeMappings;
import org.trianacode.enactment.logging.ExecutionStateLogger;
import org.trianacode.taskgraph.*;
import org.trianacode.taskgraph.clipin.HistoryClipIn;
import org.trianacode.taskgraph.imp.ToolImp;
import org.trianacode.taskgraph.proxy.ProxyInstantiationException;
import org.trianacode.taskgraph.proxy.java.JavaProxy;
import org.trianacode.taskgraph.service.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;
/**
* Class Description Here...
*
* @author Andrew Harrison
* @version $Revision:$
*/
public class LocalServer implements TrianaClient, TrianaServer {
/**
* the taskgraph this client handles
*/
private TaskGraph taskgraph;
/**
* the scheduler responsible for running this taskgraph
*/
private SchedulerInterface scheduler;
/**
* a list of the processes awaiting execution when the task is fully instantiated
*/
private Vector processWaiting = new Vector();
/**
* Constructs a local server.
*/
public LocalServer(TaskGraph taskgraph) {
this.taskgraph = taskgraph;
this.scheduler = new Scheduler(taskgraph);
this.scheduler.addExecutionListener(new ExecutionStateLogger());
}
public LocalServer(TaskGraph taskgraph, SchedulerInterface scheduler) {
this.taskgraph = taskgraph;
this.scheduler = scheduler;
}
/**
* @return the taskgraph handled by this local server
*/
public TaskGraph getTaskGraph() {
return taskgraph;
}
/**
* Sends a message to the sever to run the taskgraph.
*/
public void run() throws ClientException {
taskgraph.getProperties().getEngine().execute(new Runnable() {
public void run() {
int result = WorkflowActionManager.CANCEL;
try {
result = WorkflowActionManager.authorizeWorkflowAction(WorkflowActions.RUN_ACTION, taskgraph,
scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (result == WorkflowActionManager.AUTHORIZE) {
scheduler.runTaskGraph();
} else {
handleCancel(result, null);
}
} catch (SchedulerException except) {
except.printStackTrace();
}
}
});
}
/**
* Sends a message to the sever to run the taskgraph. The specfied history clip-ins is attached to every input task
*/
public void run(final HistoryClipIn history) throws ClientException {
taskgraph.getProperties().getEngine().execute(new Runnable() {
public void run() {
int result = WorkflowActionManager.CANCEL;
try {
result = WorkflowActionManager.authorizeWorkflowAction(WorkflowActions.RUN_ACTION, taskgraph,
scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (result == WorkflowActionManager.AUTHORIZE) {
scheduler.runTaskGraph(history);
} else {
handleCancel(result, history);
}
} catch (SchedulerException except) {
except.printStackTrace();
}
}
});
}
@Override
public void run(final IoConfiguration ioConfiguration) throws ClientException {
taskgraph.getProperties().getEngine().execute(new Runnable() {
public void run() {
ArrayList<Task> dummyTasks = new ArrayList<Task>();
try {
IoHandler handler = new IoHandler();
NodeMappings mappings = handler.map(ioConfiguration, taskgraph);
if (mappings != null) {
Node[] inputNodes = new Node[taskgraph.getInputNodeCount()];
for (int i = 0; i < taskgraph.getInputNodes().length; i++) {
Node inputNode = taskgraph.getInputNode(i);
inputNodes[i] = inputNode.getTopLevelNode();
}
System.out.println("Data mappings size : " + mappings.getMap().size());
Iterator<Integer> it = mappings.iterator();
while (it.hasNext()) {
Integer integer = it.next();
Object val = mappings.getValue(integer);
System.out.println("Data : " + val.toString() + " will be sent to input number " + integer);
Task varTask = getVarTask(taskgraph, val);
Node taskNode = getNodeInScope(inputNodes[integer], varTask.getParent());
taskgraph.connect(varTask.getDataOutputNode(0), taskNode);
dummyTasks.add(varTask);
}
} else {
System.out.println("Mappings was null");
}
} catch (Exception e) {
e.printStackTrace();
}
// run();
int result = WorkflowActionManager.CANCEL;
try {
result = WorkflowActionManager.authorizeWorkflowAction(WorkflowActions.RUN_ACTION, taskgraph,
scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (result == WorkflowActionManager.AUTHORIZE) {
scheduler.runTaskGraph();
} else {
handleCancel(result, null);
}
} catch (SchedulerException except) {
except.printStackTrace();
}
while (!isFinished(taskgraph)) {
synchronized (this) {
try {
wait(100);
} catch (InterruptedException e) {
}
}
}
for (Task dummyTask : dummyTasks) {
taskgraph.removeTask(dummyTask);
}
try {
TaskLayoutUtils.resolveGroupNodes(taskgraph);
} catch (TaskGraphException e) {
e.printStackTrace();
}
}
});
}
private Node getNodeInScope(Node inputNode, TaskGraph taskGraph) {
Node scopeNode = inputNode.getTopLevelNode();
while (scopeNode.getTask().getParent() != taskGraph && scopeNode != null) {
scopeNode = scopeNode.getChildNode();
}
return scopeNode;
}
private Task getVarTask(TaskGraph taskgraph, Object variable) throws TaskException, ProxyInstantiationException {
ToolImp varTool = new ToolImp(taskgraph.getProperties());
varTool.setDataOutputNodeCount(1);
varTool.setToolPackage(VariableDummyUnit.class.getPackage().getName());
varTool.setProxy(new JavaProxy(VariableDummyUnit.class.getSimpleName(), VariableDummyUnit.class.getPackage().getName()));
varTool.setParameter("variable", variable);
varTool.setToolName("DummyTool");
return taskgraph.createTask(varTool);
}
private boolean isFinished(TaskGraph taskgraph) {
Task[] tasks = taskgraph.getTasks(true);
boolean finished = true;
for (int count = 0; (count < tasks.length) && (finished); count++) {
if (tasks[count] instanceof RunnableInstance) {
finished = finished && ((tasks[count]).getExecutionState()
== ExecutionState.COMPLETE);
}
if (tasks[count] instanceof TaskGraph) {
finished = finished && isFinished((TaskGraph) tasks[count]);
}
}
return finished;
}
public SchedulerInterface getSchedulerInterface() {
return scheduler;
}
/**
* Sends a message to the sever to run the specified task within a running taskgraph
*/
public void runTask(Task task) throws SchedulerException {
scheduler.runTask(task);
}
/**
* Sends a message to the server to stop running the taskgraph.
*/
public void pause() throws ClientException {
taskgraph.getProperties().getEngine().execute(new Runnable() {
public void run() {
int result = WorkflowActionManager.CANCEL;
try {
result = WorkflowActionManager.authorizeWorkflowAction(WorkflowActions.PAUSE_ACTION, taskgraph,
scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (result == WorkflowActionManager.AUTHORIZE) {
scheduler.pauseTaskGraph();
} else {
handleCancel(result, null);
}
} catch (SchedulerException except) {
except.printStackTrace();
}
}
});
}
/**
* Sends a message to the server to reset the taskgraph.
*/
public void reset() throws ClientException {
taskgraph.getProperties().getEngine().execute(new Runnable() {
public void run() {
int result = WorkflowActionManager.CANCEL;
try {
result = WorkflowActionManager.authorizeWorkflowAction(WorkflowActions.RESET_ACTION, taskgraph,
scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (result == WorkflowActionManager.AUTHORIZE) {
scheduler.resetTaskGraph();
} else {
handleCancel(result, null);
}
} catch (SchedulerException except) {
except.printStackTrace();
}
}
});
}
/**
* Sends a message to the server to flush the taskgraph
*/
public void flush() throws ClientException {
try {
scheduler.flushTaskGraph();
} catch (SchedulerException except) {
throw (new ClientException(except));
}
}
/**
* Handles the various cancel results from the WorkflowActionManager
*/
private void handleCancel(int result, HistoryClipIn history) throws SchedulerException {
if (result == WorkflowActionManager.CANCEL) {
return;
} else if (result == WorkflowActionManager.RESET) {
handleResetAfterCancel();
} else if (result == WorkflowActionManager.RESET_AND_RUN) {
handleResetRunAfterCancel(history);
}
}
private void handleResetAfterCancel() throws SchedulerException {
try {
int newresult = WorkflowActionManager
.authorizeWorkflowAction(WorkflowActions.RESET_ACTION, taskgraph, scheduler.getExecutionState());
if (newresult == WorkflowActionManager.AUTHORIZE) {
scheduler.resetTaskGraph();
}
} catch (WorkflowException except) {
}
}
private void handleResetRunAfterCancel(HistoryClipIn history) throws SchedulerException {
int newresult = WorkflowActionManager.CANCEL;
try {
newresult = WorkflowActionManager
.authorizeWorkflowAction(WorkflowActions.RESET_ACTION, taskgraph, scheduler.getExecutionState());
} catch (WorkflowException except) {
except.printStackTrace();
}
try {
if (newresult == WorkflowActionManager.AUTHORIZE) {
scheduler.resetTaskGraph();
newresult = WorkflowActionManager
.authorizeWorkflowAction(WorkflowActions.RUN_ACTION, taskgraph, scheduler.getExecutionState());
if (newresult == WorkflowActionManager.AUTHORIZE) {
if (history != null) {
scheduler.runTaskGraph(history);
} else {
scheduler.runTaskGraph();
}
}
}
} catch (WorkflowException except) {
except.printStackTrace();
}
}
/**
* Disposes of the server
*/
public void dispose() throws ClientException {
try {
scheduler.pauseTaskGraph();
scheduler.flushTaskGraph();
taskgraph = null;
processWaiting.setSize(0);
} catch (SchedulerException except) {
throw (new ClientException(except));
}
}
/**
* Called be a runnable instance to notify that an error has occured
*/
public void notifyError(RunnableInstance runnable, String message) {
scheduler.notifyError(runnable, message);
}
}