/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.exec;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.antar.AlgorithmicUnit;
import org.openflexo.antar.Class;
import org.openflexo.antar.ControlGraph;
import org.openflexo.antar.Nop;
import org.openflexo.antar.Procedure;
import org.openflexo.antar.java.JavaFormattingException;
import org.openflexo.antar.java.JavaPrettyPrinter;
import org.openflexo.foundation.wkf.ExecutableWorkflowElement;
import org.openflexo.foundation.wkf.ExecutableWorkflowElement.ControlGraphFactory;
import org.openflexo.foundation.wkf.ExecutableWorkflowElement.WorkflowControlGraph;
import org.openflexo.foundation.wkf.FlexoProcess;
import org.openflexo.foundation.wkf.edge.FlexoPostCondition;
import org.openflexo.foundation.wkf.node.AbstractActivityNode;
import org.openflexo.foundation.wkf.node.ActionNode;
import org.openflexo.foundation.wkf.node.EventNode;
import org.openflexo.foundation.wkf.node.FlexoNode;
import org.openflexo.foundation.wkf.node.FlexoPreCondition;
import org.openflexo.foundation.wkf.node.OperationNode;
import org.openflexo.foundation.wkf.node.OperatorNode;
import org.openflexo.foundation.wkf.ws.FlexoPort;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.toolbox.ProgrammingLanguage;
import org.openflexo.toolbox.ToolBox;
public class ControlGraphFactories {
static final Logger logger = Logger.getLogger(ControlGraphFactories.class.getPackage().getName());
public static void init() {
if (logger.isLoggable(Level.INFO)) {
logger.info("Initializing control graph factories on ExecutableWorkflowElement");
}
FlexoNode.setActivationComputingFactory(new NodeActivationControlGraphFactory());
FlexoNode.setDesactivationComputingFactory(new NodeDesactivationControlGraphFactory());
OperatorNode.setExecutionComputingFactory(new OperatorNodeExecutionControlGraphFactory());
FlexoPostCondition.setExecutionComputingFactory(new SendTokenControlGraphFactory());
FlexoPreCondition.setExecutionComputingFactory(new PreConditionExecutionControlGraphFactory());
FlexoProcess.setExecutionComputingFactory(new ExecuteProcessControlGraphFactory());
}
protected abstract static class CommonControlGraphFactory<E extends ExecutableWorkflowElement> extends ControlGraphFactory<E> {
private static final JavaPrettyPrinter prettyPrinter = new JavaPrettyPrinter();
public CommonControlGraphFactory(String unlocalizedInfoLabel) {
super(unlocalizedInfoLabel);
}
@Override
public String prettyPrintedCode(AlgorithmicUnit algorithmicUnit, ProgrammingLanguage language) {
// Only java handled here for now !!!
if (language == ProgrammingLanguage.JAVA) {
return prettyPrintedJavaCode(algorithmicUnit);
} else {
return FlexoLocalization.localizedForKey("Programming language not supported yet: " + language);
}
}
public String prettyPrintedJavaCode(AlgorithmicUnit algorithmicUnit) {
String javaCode = prettyPrinter.getStringRepresentation(algorithmicUnit);
try {
if (algorithmicUnit instanceof Class) {
return JavaPrettyPrinter.formatJavaCodeAsClassCode(javaCode);
} else if (algorithmicUnit instanceof Procedure) {
return JavaPrettyPrinter.formatJavaCodeAsMethodCode(javaCode);
} else if (algorithmicUnit instanceof ControlGraph) {
return JavaPrettyPrinter.formatJavaCodeAsInlineCode(javaCode);
}
logger.warning("Unknown algorithmic unit type");
} catch (JavaFormattingException e) {
// Could not be formatted, warn it
logger.warning("Could not format java code, escaping");
}
return javaCode;
}
}
protected static class NodeActivationControlGraphFactory extends CommonControlGraphFactory<FlexoNode> {
public NodeActivationControlGraphFactory() {
super("control_flow_graph_executed_when_node_is_activated");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(FlexoNode node, boolean interprocedural) {
return computeAlgorithmicUnit(node, null, interprocedural);
}
public AlgorithmicUnit computeAlgorithmicUnit(FlexoNode node, FlexoPreCondition pre, boolean interprocedural) {
try {
ControlGraphBuilder cgBuilder = NodeActivation.getActivationNodeBuilder(node, pre);
if (interprocedural) {
return cgBuilder.makeProcedure();
} else {
return cgBuilder.makeControlGraph(interprocedural);
}
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
@Override
public WorkflowControlGraph<FlexoNode> makeWorkflowControlGraph(FlexoNode object) {
return new NodeActivationWorkflowControlGraph(object, this);
}
protected static class NodeActivationWorkflowControlGraph extends WorkflowControlGraph<FlexoNode> {
private FlexoPreCondition precondition;
public NodeActivationWorkflowControlGraph(FlexoNode node, NodeActivationControlGraphFactory factory) {
super(node, factory);
if (node.getPreConditions().size() > 0) {
precondition = node.getPreConditions().firstElement();
refresh();
}
}
public FlexoPreCondition getPrecondition() {
return precondition;
}
public void setPrecondition(FlexoPreCondition precondition) {
this.precondition = precondition;
refresh();
}
public Vector<FlexoPreCondition> getAllPreconditions() {
return getObject().getPreConditions();
}
@Override
protected void refreshAlgorithmicUnit() {
if (logger.isLoggable(Level.INFO)) {
logger.info("Recomputing control flow graph for " + getObject() + " and precondition " + getPrecondition()
+ " interprocedural=" + isInterprocedural());
}
algorithmicUnit = getFactory().computeAlgorithmicUnit(getObject(), getPrecondition(), isInterprocedural());
refreshPrettyPrintedCode();
}
@Override
public NodeActivationControlGraphFactory getFactory() {
return (NodeActivationControlGraphFactory) super.getFactory();
}
@Override
public String getInfoLabel() {
if (getAllPreconditions().size() == 0 || getAllPreconditions().size() == 1
&& getAllPreconditions().firstElement().getAttachedBeginNode() == null || getPrecondition() == null) {
return FlexoLocalization.localizedForKey("control_flow_graph_executed_when_node_is_activated");
} else {
return FlexoLocalization.localizedForKeyWithParams(
"control_flow_graph_executed_when_node_is_activated_by_precondition_($0)", getPrecondition().getName());
}
}
}
}
protected static class NodeDesactivationControlGraphFactory extends CommonControlGraphFactory<FlexoNode> {
public NodeDesactivationControlGraphFactory() {
super("control_flow_graph_executed_when_node_is_desactivated");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(FlexoNode node, boolean interprocedural) {
try {
ControlGraphBuilder cgBuilder = NodeDesactivation.getDesactivationNodeBuilder(node);
if (interprocedural) {
return cgBuilder.makeProcedure();
} else {
return cgBuilder.makeControlGraph(interprocedural);
}
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
}
protected static class OperatorNodeExecutionControlGraphFactory extends CommonControlGraphFactory<OperatorNode> {
public OperatorNodeExecutionControlGraphFactory() {
super("control_flow_graph_executed_when_operator_node_is_reached");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(OperatorNode operatorNode, boolean interprocedural) {
return computeAlgorithmicUnit(operatorNode, null, interprocedural);
}
public AlgorithmicUnit computeAlgorithmicUnit(OperatorNode operatorNode, FlexoPostCondition<?, ?> edge, boolean interprocedural) {
try {
ControlGraphBuilder cgBuilder = OperatorNodeExecution.getExecutionNodeBuilder(operatorNode, edge);
if (interprocedural) {
return cgBuilder.makeProcedure();
} else {
return cgBuilder.makeControlGraph(interprocedural);
}
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
@Override
public WorkflowControlGraph<OperatorNode> makeWorkflowControlGraph(OperatorNode operatorNode) {
return new OperatorNodeExecutionWorkflowControlGraph(operatorNode, this);
}
protected static class OperatorNodeExecutionWorkflowControlGraph extends WorkflowControlGraph<OperatorNode> {
private FlexoPostCondition<?, ?> edge;
public OperatorNodeExecutionWorkflowControlGraph(OperatorNode operatorNode, OperatorNodeExecutionControlGraphFactory factory) {
super(operatorNode, factory);
if (operatorNode.getIncomingPostConditions().size() > 0) {
edge = operatorNode.getIncomingPostConditions().firstElement();
refresh();
}
}
public FlexoPostCondition<?, ?> getEdge() {
return edge;
}
public void setEdge(FlexoPostCondition<?, ?> edge) {
this.edge = edge;
refresh();
}
public Vector getAllEdges() {
return getObject().getIncomingPostConditions();
}
@Override
protected void refreshAlgorithmicUnit() {
if (logger.isLoggable(Level.INFO)) {
logger.info("Recomputing control flow graph for " + getObject() + " and edge " + getEdge() + " interprocedural="
+ interprocedural);
}
algorithmicUnit = getFactory().computeAlgorithmicUnit(getObject(), getEdge(), isInterprocedural());
refreshPrettyPrintedCode();
}
@Override
public OperatorNodeExecutionControlGraphFactory getFactory() {
return (OperatorNodeExecutionControlGraphFactory) super.getFactory();
}
@Override
public String getInfoLabel() {
if (getAllEdges().size() <= 1 || getEdge() == null) {
return FlexoLocalization.localizedForKey("control_flow_graph_executed_when_operator_node_is_reached");
} else {
return FlexoLocalization.localizedForKeyWithParams(
"control_flow_graph_executed_when_operator_node_is_reached_from_edge_($0)",
((FlexoPostCondition) edge).getDerivedNameFromStartingObject());
}
}
}
}
protected static class EventNodeExecutionControlGraphFactory extends CommonControlGraphFactory<EventNode> {
public EventNodeExecutionControlGraphFactory() {
super("control_flow_graph_executed_when_event_node_is_reached");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(EventNode operatorNode, boolean interprocedural) {
try {
ControlGraphBuilder cgBuilder = EventNodeExecution.getExecutionNodeBuilder(operatorNode);
if (interprocedural) {
return cgBuilder.makeProcedure();
} else {
return cgBuilder.makeControlGraph(interprocedural);
}
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
@Override
public WorkflowControlGraph<EventNode> makeWorkflowControlGraph(EventNode operatorNode) {
return new EventNodeExecutionWorkflowControlGraph(operatorNode, this);
}
protected static class EventNodeExecutionWorkflowControlGraph extends WorkflowControlGraph<EventNode> {
public EventNodeExecutionWorkflowControlGraph(EventNode operatorNode, EventNodeExecutionControlGraphFactory factory) {
super(operatorNode, factory);
}
public Vector getAllEdges() {
return getObject().getIncomingPostConditions();
}
@Override
protected void refreshAlgorithmicUnit() {
if (logger.isLoggable(Level.INFO)) {
logger.info("Recomputing control flow graph for " + getObject() + " interprocedural=" + interprocedural);
}
algorithmicUnit = getFactory().computeAlgorithmicUnit(getObject(), isInterprocedural());
refreshPrettyPrintedCode();
}
@Override
public EventNodeExecutionControlGraphFactory getFactory() {
return (EventNodeExecutionControlGraphFactory) super.getFactory();
}
@Override
public String getInfoLabel() {
return FlexoLocalization.localizedForKey("control_flow_graph_executed_when_event_node_is_reached");
}
}
}
protected static class SendTokenControlGraphFactory extends CommonControlGraphFactory<FlexoPostCondition<?, ?>> {
public SendTokenControlGraphFactory() {
super("control_flow_graph_executed_when_a_token_is_sent_through_edge");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(FlexoPostCondition<?, ?> edge, boolean interprocedural) {
try {
return SendToken.sendToken(edge, interprocedural);
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
}
protected static class PreConditionExecutionControlGraphFactory extends CommonControlGraphFactory<FlexoPreCondition> {
public PreConditionExecutionControlGraphFactory() {
super("control_flow_graph_executed_when_precondition_receives_a_new_token");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(FlexoPreCondition pre, boolean interprocedural) {
return computeAlgorithmicUnit(pre, null, interprocedural);
}
public AlgorithmicUnit computeAlgorithmicUnit(FlexoPreCondition pre, FlexoPostCondition<?, ?> edge, boolean interprocedural) {
try {
ControlGraphBuilder cgBuilder = SendTokenToPrecondition.getSendTokenToPreconditionBuilder(pre, edge);
if (interprocedural) {
return cgBuilder.makeProcedure();
} else {
return cgBuilder.makeControlGraph(interprocedural);
}
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
@Override
public WorkflowControlGraph<FlexoPreCondition> makeWorkflowControlGraph(FlexoPreCondition pre) {
return new PreConditionExecutionWorkflowControlGraph(pre, this);
}
protected static class PreConditionExecutionWorkflowControlGraph extends WorkflowControlGraph<FlexoPreCondition> {
private FlexoPostCondition<?, ?> edge;
public PreConditionExecutionWorkflowControlGraph(FlexoPreCondition pre, PreConditionExecutionControlGraphFactory factory) {
super(pre, factory);
if (pre.getIncomingPostConditions().size() > 0) {
edge = pre.getIncomingPostConditions().firstElement();
refresh();
}
}
public FlexoPostCondition<?, ?> getEdge() {
return edge;
}
public void setEdge(FlexoPostCondition<?, ?> edge) {
this.edge = edge;
refresh();
}
public Vector<FlexoPostCondition<?, ?>> getAllEdges() {
return new Vector<FlexoPostCondition<?, ?>>(getObject().getIncomingPostConditions());
}
@Override
protected void refreshAlgorithmicUnit() {
if (logger.isLoggable(Level.INFO)) {
logger.info("Recomputing control flow graph for " + getObject() + " and edge " + getEdge() + " interprocedural="
+ interprocedural);
}
algorithmicUnit = getFactory().computeAlgorithmicUnit(getObject(), getEdge(), isInterprocedural());
refreshPrettyPrintedCode();
}
@Override
public PreConditionExecutionControlGraphFactory getFactory() {
return (PreConditionExecutionControlGraphFactory) super.getFactory();
}
@Override
public String getInfoLabel() {
if (getAllEdges().size() <= 1 || getEdge() == null) {
return FlexoLocalization.localizedForKey("control_flow_graph_executed_when_precondition_receives_a_new_token");
} else {
return FlexoLocalization.localizedForKeyWithParams(
"control_flow_graph_executed_when_precondition_receives_a_new_token_from_edge_($0)",
((FlexoPostCondition) edge).getDerivedNameFromStartingObject());
}
}
}
}
protected static class ExecuteProcessControlGraphFactory extends CommonControlGraphFactory<FlexoProcess> {
public ExecuteProcessControlGraphFactory() {
super("control_flow_graph_executed_when_a_token_is_sent_through_edge");
}
@Override
public AlgorithmicUnit computeAlgorithmicUnit(FlexoProcess process, boolean interprocedural) {
try {
Vector<Procedure> allProcedures = new Vector<Procedure>();
for (AbstractActivityNode n : process.getAllAbstractActivityNodes()) {
appendProcedureForActivity(n, allProcedures);
}
for (OperatorNode op : process.getAllOperatorNodes()) {
appendProcedureForOperator(op, allProcedures);
}
for (EventNode op : process.getAllEventNodes()) {
appendProcedureForEvent(op, allProcedures);
}
for (FlexoPort port : process.getPortRegistery().getAllPorts()) {
appendProcedureForPort(port, allProcedures);
}
Class returned = new Class(ToolBox.capitalize(process.getExecutionClassName()), process.getExecutionGroupName(),
allProcedures);
returned.setComment(FlexoLocalization.localizedForKeyWithParams(
"this_method_represents_all_code_to_be_executed_in_the_context_of_process_($0)_execution", process.getName()));
return returned;
} catch (NotSupportedException e) {
return new Nop("NotSupportedException: " + e.getMessage());
} catch (InvalidModelException e) {
return new Nop("InvalidModelException: " + e.getMessage());
}
}
private void appendProcedureForActivity(AbstractActivityNode node, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(NodeActivation.getActivationNodeBuilder(node, null).makeProcedure());
allProcedures.add(NodeDesactivation.getDesactivationNodeBuilder(node).makeProcedure());
for (FlexoPreCondition pre : node.getPreConditions()) {
allProcedures.add(SendTokenToPrecondition.getSendTokenToPreconditionBuilder(pre, null).makeProcedure());
}
for (OperationNode operation : node.getAllOperationNodes()) {
appendProcedureForOperation(operation, allProcedures);
}
for (OperatorNode op : node.getAllOperatorNodes()) {
appendProcedureForOperator(op, allProcedures);
}
for (EventNode op : node.getAllEventNodes()) {
appendProcedureForEvent(op, allProcedures);
}
}
private void appendProcedureForOperation(OperationNode node, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(NodeActivation.getActivationNodeBuilder(node, null).makeProcedure());
allProcedures.add(NodeDesactivation.getDesactivationNodeBuilder(node).makeProcedure());
for (FlexoPreCondition pre : node.getPreConditions()) {
allProcedures.add(SendTokenToPrecondition.getSendTokenToPreconditionBuilder(pre, null).makeProcedure());
}
for (ActionNode action : node.getAllActionNodes()) {
appendProcedureForAction(action, allProcedures);
}
for (OperatorNode op : node.getAllOperatorNodes()) {
appendProcedureForOperator(op, allProcedures);
}
for (EventNode op : node.getAllEventNodes()) {
appendProcedureForEvent(op, allProcedures);
}
}
private void appendProcedureForAction(ActionNode node, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(NodeActivation.getActivationNodeBuilder(node, null).makeProcedure());
allProcedures.add(NodeDesactivation.getDesactivationNodeBuilder(node).makeProcedure());
for (FlexoPreCondition pre : node.getPreConditions()) {
allProcedures.add(SendTokenToPrecondition.getSendTokenToPreconditionBuilder(pre, null).makeProcedure());
}
}
private void appendProcedureForOperator(OperatorNode operatorNode, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(OperatorNodeExecution.getExecutionNodeBuilder(operatorNode, null).makeProcedure());
}
private void appendProcedureForEvent(EventNode eventNode, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(EventNodeExecution.getExecutionNodeBuilder(eventNode).makeProcedure());
}
private void appendProcedureForPort(FlexoPort port, Vector<Procedure> allProcedures) throws InvalidModelException,
NotSupportedException {
allProcedures.add(PortActivation.getActivationPortBuilder(port).makeProcedure());
allProcedures.add(PortDesactivation.getDesactivationPortBuilder(port).makeProcedure());
}
}
}