/* * (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.wkf.node; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; import org.openflexo.foundation.DataModification; import org.openflexo.foundation.FlexoObservable; import org.openflexo.foundation.FlexoObserver; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.ObjectDeleted; import org.openflexo.foundation.ie.ComponentInstance; import org.openflexo.foundation.ie.ComponentInstanceOwner; import org.openflexo.foundation.ie.IEOperationComponent; import org.openflexo.foundation.ie.TabComponentInstance; import org.openflexo.foundation.ie.cl.ComponentDefinition; import org.openflexo.foundation.ie.cl.FlexoComponentFolder; import org.openflexo.foundation.ie.cl.TabComponentDefinition; import org.openflexo.foundation.ie.dm.ButtonRemoved; import org.openflexo.foundation.ie.dm.table.WidgetRemovedFromTable; import org.openflexo.foundation.ie.util.FolderType; import org.openflexo.foundation.ie.util.HyperlinkType; import org.openflexo.foundation.ie.widget.IEHyperlinkWidget; import org.openflexo.foundation.ie.widget.IEWidget; import org.openflexo.foundation.rm.DuplicateResourceException; import org.openflexo.foundation.validation.FixProposal; import org.openflexo.foundation.validation.Validable; import org.openflexo.foundation.validation.ValidationError; import org.openflexo.foundation.validation.ValidationIssue; import org.openflexo.foundation.validation.ValidationRule; import org.openflexo.foundation.validation.ValidationWarning; import org.openflexo.foundation.wkf.FlexoLevel; import org.openflexo.foundation.wkf.FlexoProcess; import org.openflexo.foundation.wkf.Status; import org.openflexo.foundation.wkf.WKFObject; import org.openflexo.foundation.wkf.dm.ButtonWidgetAssociated; import org.openflexo.foundation.wkf.dm.DisplayOperationSet; import org.openflexo.foundation.wkf.dm.DisplayProcessSet; import org.openflexo.foundation.wkf.dm.WKFAttributeDataModification; import org.openflexo.foundation.wkf.edge.FlexoPostCondition; import org.openflexo.foundation.wkf.utils.OperationAssociatedWithComponentSuccessfully; import org.openflexo.foundation.wkf.ws.DeletePort; import org.openflexo.foundation.wkf.ws.FlexoPort; import org.openflexo.foundation.wkf.ws.FlexoPortMap; import org.openflexo.foundation.wkf.ws.InOutPort; import org.openflexo.foundation.wkf.ws.InPort; import org.openflexo.foundation.wkf.ws.NewPort; import org.openflexo.foundation.wkf.ws.OutPort; import org.openflexo.foundation.xml.FlexoProcessBuilder; import org.openflexo.localization.FlexoLocalization; /** * This represents a FlexoNode at the level 'Action' * * @author sguerin * */ public class ActionNode extends FlexoNode implements ChildNode, ComponentInstanceOwner, FlexoObserver { private static final Logger logger = Logger.getLogger(ActionNode.class.getPackage().getName()); protected ActionType _actionType; protected transient Status _newStatus; protected transient FlexoProcess _subProcess; private FlexoProcess displayProcess; private OperationNode displayOperation; // private boolean bypassLogicalWorkFlow = false; private long displayProcessFlexoID = -1; private long displayOperationFlexoID = -1; private IEHyperlinkWidget associatedButtonWidget; private long associatedButtonFlexoID = -1; private transient TabComponentInstance _tabComponentInstance; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== /** * Constructor used during deserialization */ public ActionNode(FlexoProcessBuilder builder) { this(builder.process); initializeDeserialization(builder); } /** * Default constructor */ public ActionNode(FlexoProcess process) { super(process); _actionType = ActionType.FLEXO_ACTION; } public static String DEFAULT_ACTION_NODE_NAME() { return FlexoLocalization.localizedForKey("action_default_name"); } @Override public String getDefaultName() { if (isBeginNode() || isEndNode()) { return super.getDefaultName(); } else if (getActionType() != null) { return FlexoLocalization.localizedForKey(getActionType().getName()); } else { return DEFAULT_ACTION_NODE_NAME(); } } public String getDisplayString() { return FlexoLocalization.localizedForKeyWithParams("action_($name)_in_operation_($operationNode.name)", this); } @Override public FlexoLevel getLevel() { return FlexoLevel.ACTION; } public Vector getAllActionNodes() { return getOperationNode().getAllActionNodes(); } @Override public String getInspectorName() { if (getActionType() == ActionType.DISPLAY_ACTION) { return Inspectors.WKF.DISPLAY_ACTION_NODE_INSPECTOR; } else if (getActionType() == ActionType.FLEXO_ACTION) { return Inspectors.WKF.FLEXO_ACTION_NODE_INSPECTOR; } if (getNodeType() == NodeType.NORMAL) { return Inspectors.WKF.ACTION_NODE_INSPECTOR; } else if (getNodeType() == NodeType.BEGIN) { return Inspectors.WKF.BEGIN_NODE_INSPECTOR; } else if (getNodeType() == NodeType.END) { return Inspectors.WKF.END_NODE_INSPECTOR; } else { return super.getInspectorName(); } } @Override public OperationNode getFather() { return getOperationNode(); } @Override public final void delete() { removeTabComponentInstance(); // getParentPetriGraph().removeFromNodes(this); super.delete(); deleteObservers(); } // ========================================================================== // ========================== Embedding implementation ===================== // ========================================================================== @Override public String getFullyQualifiedName() { if (getFather() != null) { return getFather().getFullyQualifiedName() + "." + formattedString(getNodeName()); } else { return "NULL." + formattedString(getNodeName()); } } public ActionType getActionType() { return _actionType; } public void setActionType(ActionType type) { ActionType old = _actionType; _actionType = type; if (isDisplayAction()) { Vector<FlexoPostCondition> posts = (Vector<FlexoPostCondition>) getOutgoingPostConditions().clone(); Enumeration<FlexoPostCondition> en = posts.elements(); while (en.hasMoreElements()) { FlexoPostCondition post = en.nextElement(); removeFromOutgoingPostConditions(post); } } setChanged(); notifyObservers(new WKFAttributeDataModification("actionType", old, _actionType)); } public boolean isDisplayAction() { return _actionType == ActionType.DISPLAY_ACTION; } public ImageIcon getImageIcon() { // if (getActionType() != null) { // return getActionType().getImageIcon(); // } return null; } public IEHyperlinkWidget getAssociatedButtonWidget() { if (associatedButtonFlexoID > -1 && associatedButtonWidget == null && getOperationNode().hasWOComponent()) { Enumeration en = getOperationNode().getOperationComponent().getWOComponent().getAllButtonInterface().elements(); while (en.hasMoreElements() && associatedButtonWidget == null) { IEHyperlinkWidget w = (IEHyperlinkWidget) en.nextElement(); if (((IEWidget) w).getFlexoID() == associatedButtonFlexoID) { associatedButtonWidget = w; } } if (associatedButtonWidget == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("The associated button of the action node " + getFullyQualifiedName() + " could not be found!"); } associatedButtonFlexoID = -1; } else { associatedButtonWidget.addObserver(this); } } return associatedButtonWidget; } public void setAssociatedButtonWidget(IEHyperlinkWidget associatedButtonWidget) { if (this.associatedButtonWidget != null) { this.associatedButtonWidget.deleteObserver(this); } IEHyperlinkWidget old = this.associatedButtonWidget; this.associatedButtonWidget = associatedButtonWidget; if (associatedButtonWidget != null) { associatedButtonFlexoID = ((IEWidget) associatedButtonWidget).getFlexoID(); associatedButtonWidget.addObserver(this); setActionType(associatedButtonWidget.getIsDisplayAction() ? ActionType.DISPLAY_ACTION : ActionType.FLEXO_ACTION); } else { associatedButtonFlexoID = -1; } setChanged(); notifyObservers(new ButtonWidgetAssociated(old, associatedButtonWidget)); } public long getAssociatedButtonWidgetFlexoID() { return associatedButtonFlexoID; } public void setAssociatedButtonWidgetFlexoID(long buttonFlexoID) { long old = associatedButtonFlexoID; associatedButtonFlexoID = buttonFlexoID; associatedButtonWidget = null; setChanged(); notifyObservers(new WKFAttributeDataModification("associatedButtonWidgetFlexoID", new Long(old), new Long(buttonFlexoID))); } /** * Overrides getClassNameKey * * @see org.openflexo.foundation.FlexoModelObject#getClassNameKey() */ @Override public String getClassNameKey() { return "action_node"; } public OperationNode getDisplayOperation() { if (displayOperation == null && displayOperationFlexoID > -1) { if (getDisplayProcess() != null) { displayOperation = getDisplayProcess().getOperationNodeWithFlexoID(displayOperationFlexoID); if (displayOperation == null) { if (!isSerializing() && !isDeserializing() && getProject() != null) { displayOperationFlexoID = -1; setChanged(); } } else { displayOperation.addObserver(this); } } } return displayOperation; } public void setDisplayOperation(OperationNode displayOperation) { OperationNode old = this.displayOperation; if (old != null) { old.deleteObserver(this); } removeTabComponentInstance(); this.displayOperation = displayOperation; if (displayOperation != null) { displayOperation.addObserver(this); displayOperationFlexoID = displayOperation.getFlexoID(); } else { displayOperationFlexoID = -1; } setChanged(); notifyObservers(new DisplayOperationSet(old, displayOperation)); } public FlexoProcess getDisplayProcess() { if (displayProcess == null && displayProcessFlexoID > -1 && getProject() != null) { displayProcess = getProject().getFlexoWorkflow().getLocalFlexoProcessWithFlexoID(displayProcessFlexoID); if (displayProcess == null) { if (!isSerializing() && !isDeserializing()) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find process with flexoID " + displayProcessFlexoID); } displayProcessFlexoID = -1; setDisplayOperation(null); setChanged(); } } else { displayProcess.addObserver(this); } } return displayProcess; } public void setDisplayProcess(FlexoProcess displayProcess) { FlexoProcess old = this.displayProcess; if (old != null) { old.deleteObserver(this); } this.displayProcess = displayProcess; if (displayProcess != null) { displayProcess.addObserver(this); displayProcessFlexoID = displayProcess.getFlexoID(); } else { logger.warning("setting display process to null"); displayProcessFlexoID = -1; } setDisplayOperation(null); setChanged(); notifyObservers(new DisplayProcessSet(old, displayProcess)); } public boolean isAcceptableAsDisplayProcess(FlexoProcess process) { return process != null && !process.isImported(); } public long getDisplayOperationFlexoID() { if (getDisplayOperation() != null) { return getDisplayOperation().getFlexoID(); } else if (isSerializing()) { return displayOperationFlexoID; } return -1; } public void setDisplayOperationFlexoID(long displayOperationFlexoID) { if (getDisplayOperation() != null) { displayOperation = null; } this.displayOperationFlexoID = displayOperationFlexoID; } public long getDisplayProcessFlexoID() { if (getDisplayProcess() != null) { return getDisplayProcess().getFlexoID(); } else if (isSerializing()) { return displayProcessFlexoID; } return -1; } public void setDisplayProcessFlexoID(long displayProcessFlexoID) { if (getDisplayProcess() != null) { displayProcess = null; } this.displayProcessFlexoID = displayProcessFlexoID; } /** * * * @see org.openflexo.foundation.wkf.node.AbstractNode#update(org.openflexo.foundation.FlexoObservable, * org.openflexo.foundation.DataModification) */ @Override public void update(FlexoObservable observable, DataModification dataModification) { if (observable == associatedButtonWidget && (dataModification instanceof WidgetRemovedFromTable || dataModification instanceof ButtonRemoved)) { associatedButtonWidget.deleteObserver(this); setAssociatedButtonWidget(null); } if (observable == getDisplayOperation()) { if (dataModification instanceof ObjectDeleted) { setDisplayOperation(null); } else if (dataModification.propertyName() != null && dataModification.propertyName().equals("flexoID")) { setChanged(); } } else if (observable == getDisplayProcess()) { if (dataModification instanceof ObjectDeleted) { setDisplayProcess(null); } else if (dataModification.propertyName() != null && dataModification.propertyName().equals("flexoID")) { setChanged(); } } } public static class ActionTypeMustMatchButtonType extends ValidationRule<ActionTypeMustMatchButtonType, ActionNode> { public ActionTypeMustMatchButtonType() { super(ActionNode.class, "action_type_must_match_button_action_type"); } /** * Overrides applyValidation * * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue<ActionTypeMustMatchButtonType, ActionNode> applyValidation(ActionNode node) { ValidationError<ActionTypeMustMatchButtonType, ActionNode> err = null; if (node.getAssociatedButtonWidget() != null) { if (node.getAssociatedButtonWidget().getIsDisplayAction() && node.getActionType() != ActionType.DISPLAY_ACTION) { err = new ValidationError<ActionTypeMustMatchButtonType, ActionNode>(this, node, "action_type_must_match_button_action_type"); err.addToFixProposals(new ChangeActionType(node)); } } return err; } public class ChangeActionType extends FixProposal<ActionTypeMustMatchButtonType, ActionNode> { private ActionNode node; /** * @param aMessage */ public ChangeActionType(ActionNode node) { super("change_action_type"); this.node = node; } /** * Overrides fixAction * * @see org.openflexo.foundation.validation.FixProposal#fixAction() */ @Override protected void fixAction() { if (node.getAssociatedButtonWidget().getIsDisplayAction()) { node.setActionType(ActionType.DISPLAY_ACTION); Enumeration en = ((Vector) node.getOutgoingPostConditions().clone()).elements(); while (en.hasMoreElements()) { FlexoPostCondition element = (FlexoPostCondition) en.nextElement(); element.delete(); } /* * en = ((Vector) node.getIncomingPostConditions().clone()).elements(); while (en.hasMoreElements()) { * FlexoPostCondition element = (FlexoPostCondition) en.nextElement(); element.delete(); } */ } else if (node.getAssociatedButtonWidget().getIsFlexoAction()) { node.setActionType(ActionType.DISPLAY_ACTION); OperationNode.linkActionToBeginAndEndNode(node); } } } } public static class OnlyOneActionNodeMustBeBoundToOperationComponentAction extends ValidationRule<OnlyOneActionNodeMustBeBoundToOperationComponentAction, ActionNode> { /** * @param objectType * @param ruleName */ public OnlyOneActionNodeMustBeBoundToOperationComponentAction() { super(ActionNode.class, "only_one_action_node_must_be_bound_to_operation_component_actions"); } /** * Overrides applyValidation * * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue<OnlyOneActionNodeMustBeBoundToOperationComponentAction, ActionNode> applyValidation(ActionNode node) { ValidationError<OnlyOneActionNodeMustBeBoundToOperationComponentAction, ActionNode> err = null; Enumeration en = node.getAllActionNodes().elements(); while (en.hasMoreElements()) { ActionNode act = (ActionNode) en.nextElement(); if (act.getAssociatedButtonWidget() != null && act != node && act.getAssociatedButtonWidget() == node.getAssociatedButtonWidget()) { err = new ValidationError<OnlyOneActionNodeMustBeBoundToOperationComponentAction, ActionNode>(this, node, "only_one_action_node_must_be_bound_to_operation_component_actions($object.name)"); break; } } return err; } } /* * public static class WorkFlowBypassingActionsMustSpecifyTargetNode extends * ValidationRule<WorkFlowBypassingActionsMustSpecifyTargetNode, ActionNode> { * * public WorkFlowBypassingActionsMustSpecifyTargetNode() { super(ActionNode.class, * "work_flow_bypassing_actions_must_specify_target_node"); } * * @Override public ValidationIssue<WorkFlowBypassingActionsMustSpecifyTargetNode, ActionNode> applyValidation(ActionNode object) { if * (object.getActionType()==ActionType.FLEXO_ACTION && object.bypassLogicalWorkFlow() && object.getDisplayOperation()==null && * object.hasIncomingEdges()) { return new ValidationError<WorkFlowBypassingActionsMustSpecifyTargetNode, ActionNode>(this, object, * "flexo_action_($object.name)_must_have_a_target_operation"); } return null; } * * } */ public static class DisplayActionMustHaveADisplayProcess extends ValidationRule<DisplayActionMustHaveADisplayProcess, ActionNode> { /** * @param objectType * @param ruleName */ public DisplayActionMustHaveADisplayProcess() { super(ActionNode.class, "display_action_must_have_a_display_process"); } /** * Overrides applyValidation * * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue<DisplayActionMustHaveADisplayProcess, ActionNode> applyValidation(ActionNode node) { ValidationError<DisplayActionMustHaveADisplayProcess, ActionNode> err = null; if (node._actionType == ActionType.DISPLAY_ACTION) { if (node.getDisplayProcess() == null && node.hasIncomingEdges()) { err = new ValidationError<DisplayActionMustHaveADisplayProcess, ActionNode>(this, node, "display_action_($object.name)_must_have_a_display_process"); } } return err; } } public static class DisplayActionShouldHaveADisplayOperation extends ValidationRule<DisplayActionShouldHaveADisplayOperation, ActionNode> { /** * @param objectType * @param ruleName */ public DisplayActionShouldHaveADisplayOperation() { super(ActionNode.class, "display_action_should_have_a_display_operation"); } /** * Overrides applyValidation * * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue<DisplayActionShouldHaveADisplayOperation, ActionNode> applyValidation(ActionNode node) { ValidationError<DisplayActionShouldHaveADisplayOperation, ActionNode> w = null; if (node._actionType == ActionType.DISPLAY_ACTION) { if (node.getDisplayProcess() != null && node.getDisplayOperation() == null && node.hasIncomingEdges()) { w = new ValidationError<DisplayActionShouldHaveADisplayOperation, ActionNode>(this, node, "display_action_($object.name)_should_have_a_display_operation"); } } return w; } } public static class DisplayActionShouldHaveASelectedTab extends ValidationRule<DisplayActionShouldHaveASelectedTab, ActionNode> { /** * @param objectType * @param ruleName */ public DisplayActionShouldHaveASelectedTab() { super(ActionNode.class, "display_action_should_have_a_selected_tab"); } /** * Overrides applyValidation * * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue<DisplayActionShouldHaveASelectedTab, ActionNode> applyValidation(ActionNode node) { ValidationError<DisplayActionShouldHaveASelectedTab, ActionNode> w = null; if (node._actionType == ActionType.DISPLAY_ACTION) { if (node.getNextOperationTabKey() == null && node.getDisplayProcess() != null && node.getDisplayOperation() != null && node.hasIncomingEdges()) { for (WorkflowPathToOperationNode workflowPath : node.getNextOperationForDisplayAction()) { OperationNode nextOpNode = workflowPath.getOperationNode(); if (nextOpNode != null) { if (nextOpNode.getOperationComponent() != null) { IEOperationComponent component = nextOpNode.getOperationComponent().getWOComponent(); if (component.hasTabContainer() && component.hasAtLeastOneTabDefined()) { w = new ValidationError<DisplayActionShouldHaveASelectedTab, ActionNode>(this, node, "display_action_($object.name)_should_have_a_selected_tab"); } } break; } } } } return w; } } public static class ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton extends ValidationRule<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode> { public ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton() { super(ActionNode.class, "action_node_($object.name)_can_only_be_bound_to_buttons_with_hyperlink_type_flexo_action_or_display_action"); } @Override public ValidationIssue<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode> applyValidation(ActionNode object) { if (object.getAssociatedButtonWidget() != null) { HyperlinkType type = object.getAssociatedButtonWidget().getHyperlinkType(); if (type == null || !type.isFlexoAction() && !type.isDisplayAction()) { Vector<FixProposal<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode>> fixes = new Vector<FixProposal<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode>>(); fixes.add(new ChangeButtonType()); fixes.add(new DeleteNode()); return new ValidationError<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode>(this, object, "action_node_can_be_bound_to_buttons_with_hyperlink_type_flexo_action_or_display_action", fixes); } } return null; } public static class DeleteNode extends FixProposal<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode> { public DeleteNode() { super("delete_this_node"); } @Override protected void fixAction() { getObject().delete(); } } public static class ChangeButtonType extends FixProposal<ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton, ActionNode> { @SuppressWarnings("hiding") private static final Logger logger = Logger .getLogger(ActionNode.ActionNodeCanBeBoundToFlexoActionOrDisplayActionButton.ChangeButtonType.class.getPackage() .getName()); public ChangeButtonType() { super("change_button_type"); } @Override protected void fixAction() { if (getObject().getAssociatedButtonWidget() != null) { if (getObject().getActionType() == ActionType.DISPLAY_ACTION) { getObject().getAssociatedButtonWidget().setHyperlinkType(HyperlinkType.DISPLAYACTION); } else if (getObject().getActionType() == ActionType.FLEXO_ACTION) { getObject().getAssociatedButtonWidget().setHyperlinkType(HyperlinkType.FLEXOACTION); } } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("No button associated to this node"); } } } } } public List<WorkflowPathToOperationNode> getNextOperationsForAction() { if (getActionType() == ActionType.DISPLAY_ACTION) { return getNextOperationForDisplayAction(); } else if (getActionType() == ActionType.FLEXO_ACTION) { return getNextOperationsForFlexoAction(); } else if (logger.isLoggable(Level.WARNING)) { logger.warning("Action type " + getActionType().getName() + " is not handled by generators"); } return new ArrayList<WorkflowPathToOperationNode>(); } protected List<WorkflowPathToOperationNode> getNextOperationForDisplayAction() { return getNextOperationForDisplayAction(new WorkflowPathToOperationNode()); } /** * @param action * @return */ protected List<WorkflowPathToOperationNode> getNextOperationForDisplayAction( WorkflowPathToOperationNode currentWorkflowPathToOperationNode) { if (getDisplayOperation() != null) { if (getDisplayOperation().hasWOComponent()) { List<WorkflowPathToOperationNode> retval = new ArrayList<WorkflowPathToOperationNode>(); currentWorkflowPathToOperationNode.setOperationNode(getDisplayOperation()); if (getDisplayOperation().getNewStatus() != null) { currentWorkflowPathToOperationNode.addNewStatus(getDisplayOperation().getNewStatus()); } else if (getDisplayOperation().getAbstractActivityNode().getNewStatus() != null) { currentWorkflowPathToOperationNode.addNewStatus(getDisplayOperation().getAbstractActivityNode().getNewStatus()); } retval.add(currentWorkflowPathToOperationNode); return retval; } else { return getNextOperationForFlexoNode(new ArrayList<AbstractNode>(), new ArrayList<WorkflowPathToOperationNode>(), getDisplayOperation(), currentWorkflowPathToOperationNode); } } else { FlexoProcess process = getDisplayProcess(); if (process == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Display process is null for DISPLAY_ACTION. Validation should catch this"); } return new ArrayList<WorkflowPathToOperationNode>(); } else { return getNextOperationForProcess(new ArrayList<AbstractNode>(), new ArrayList<WorkflowPathToOperationNode>(), process, currentWorkflowPathToOperationNode); } } } /** * @param action * @return */ private List<WorkflowPathToOperationNode> getNextOperationsForFlexoAction() { WorkflowPathToOperationNode currentWorkflowPath = new WorkflowPathToOperationNode(); if (getNewStatus() != null) { currentWorkflowPath.addNewStatus(getNewStatus()); } return getNextOperationForFlexoNode(new ArrayList<AbstractNode>(), new ArrayList<WorkflowPathToOperationNode>(), this, currentWorkflowPath); } private static List<WorkflowPathToOperationNode> getNextOperationForFlexoNode(List<AbstractNode> visitedNodes, List<WorkflowPathToOperationNode> returnedNodes, AbstractNode node, WorkflowPathToOperationNode currentWorkflowPathToOperationNode) { return getNextOperationForFlexoNode(visitedNodes, returnedNodes, node, currentWorkflowPathToOperationNode, true); } private static List<WorkflowPathToOperationNode> getNextOperationForFlexoNode(List<AbstractNode> visitedNodes, List<WorkflowPathToOperationNode> returnedNodes, AbstractNode node, WorkflowPathToOperationNode currentWorkflowPathToOperationNode, boolean includeDeadEndPath) { if (visitedNodes.contains(node)) { return returnedNodes; } else { visitedNodes.add(node); } Enumeration<FlexoPostCondition<AbstractNode, AbstractNode>> en; // now let's collect postconditions where a token is send Vector<FlexoPostCondition<AbstractNode, AbstractNode>> v = new Vector<FlexoPostCondition<AbstractNode, AbstractNode>>(); v.addAll(node.getOutgoingPostConditions()); // there are "normal" post condition boolean hasInsertedPathFromContainer = false; if (node instanceof FlexoNode && ((FlexoNode) node).isEndNode()) { // here we have reach an end node WKFObject container = ((PetriGraphNode) node).getParentPetriGraph().getContainer(); if (container instanceof AbstractNode) { int numberOfReturnedPath = returnedNodes.size(); getNextOperationForFlexoNode(new ArrayList<AbstractNode>(visitedNodes), returnedNodes, (AbstractNode) container, currentWorkflowPathToOperationNode.clone(), false); hasInsertedPathFromContainer = numberOfReturnedPath != returnedNodes.size(); } if (container instanceof LOOPOperator) { v.addAll(((LOOPOperator) container).getOutgoingPostConditions()); } } // if (node instanceof ActionNode) { // boolean hasDisplayActionInNextNodes = false; // for (FlexoPostCondition<AbstractNode, AbstractNode> edge : v) { // AbstractNode end = edge.getEndNode(); // if (end instanceof FlexoPreCondition) { // end = ((FlexoPreCondition) end).getAttachedBeginNode() == null ? ((FlexoPreCondition) end).getAttachedNode() // : ((FlexoPreCondition) end).getAttachedBeginNode(); // } // if (end instanceof ActionNode && ((ActionNode)end).getActionType() == ActionType.DISPLAY_ACTION) { // hasDisplayActionInNextNodes = true; // break; // } // } // if (hasDisplayActionInNextNodes) { // //returnedNodes.clear(); // for (FlexoPostCondition<AbstractNode, AbstractNode> edge : v) { // AbstractNode end = edge.getEndNode(); // if (end instanceof FlexoPreCondition) { // end = ((FlexoPreCondition) end).getAttachedBeginNode() == null ? ((FlexoPreCondition) end).getAttachedNode() // : ((FlexoPreCondition) end).getAttachedBeginNode(); // } // if (end instanceof ActionNode && ((ActionNode)end).getActionType() == ActionType.DISPLAY_ACTION) { // returnedNodes.addAll(((ActionNode)end).getNextOperationForDisplayAction(currentWorkflowPathToOperationNode)); // } // } // return returnedNodes; // } // } if (v.size() > 0) { en = v.elements(); while (en.hasMoreElements()) { WorkflowPathToOperationNode duplicatedWorkflowPath = currentWorkflowPathToOperationNode.clone(); FlexoPostCondition<AbstractNode, AbstractNode> post = en.nextElement(); if (node instanceof IFOperator) { duplicatedWorkflowPath.addIfOperator((IFOperator) node, ((IFOperator) node).isPositiveEvaluationPostcondition(post)); } if (post.getIsConditional() && (post.getConditionPrimitive() != null || post.getConditionDescription() != null && post.getConditionDescription().trim().length() > 0)) { duplicatedWorkflowPath.addCondition(post.getProcess(), post.getConditionDescription(), post.getConditionPrimitive(), true); } AbstractNode end = post.getEndNode(); if (end instanceof FlexoPreCondition) { end = ((FlexoPreCondition) end).getAttachedBeginNode() == null ? ((FlexoPreCondition) end).getAttachedNode() : ((FlexoPreCondition) end).getAttachedBeginNode(); } if (end instanceof PetriGraphNode) { if (((PetriGraphNode) end).getNewStatus() != null) { duplicatedWorkflowPath.addNewStatus(((PetriGraphNode) end).getNewStatus()); } } if (end instanceof ActionNode && ((ActionNode) end).isBeginNode()) { end = ((ActionNode) end).getOperationNode(); } if (end instanceof PetriGraphNode) { if (((PetriGraphNode) end).getNewStatus() != null) { duplicatedWorkflowPath.addNewStatus(((PetriGraphNode) end).getNewStatus()); } } if (end instanceof LoopSubProcessNode) { if (((PetriGraphNode) end).getNewStatus() != null) { duplicatedWorkflowPath.addNewStatus(((PetriGraphNode) end).getNewStatus()); } if (((LoopSubProcessNode) end).getPortMapRegistery() != null && ((LoopSubProcessNode) end).getPortMapRegistery().getAllNewPortmaps().size() > 0) { end = ((LoopSubProcessNode) end).getPortMapRegistery().getAllNewPortmaps().firstElement(); } } else if (node instanceof LOOPOperator) { if (((LOOPOperator) node).getExecutionPetriGraph().getAllBeginNodes().size() > 0) { end = ((LOOPOperator) node).getExecutionPetriGraph().getAllBeginNodes().firstElement(); } } if (end instanceof PetriGraphNode && isCreateProcess((PetriGraphNode) end)) { duplicatedWorkflowPath.getCreatedProcesses().add(end.getProcess()); } if (end instanceof PetriGraphNode && isDeleteProcess((PetriGraphNode) end, false)) { duplicatedWorkflowPath.getDeletedProcesses().add(end.getProcess()); } if (end instanceof OperationNode && ((OperationNode) end).hasWOComponent()) { duplicatedWorkflowPath.setOperationNode((OperationNode) end); if (((OperationNode) end).getNewStatus() != null) { duplicatedWorkflowPath.addNewStatus(((OperationNode) end).getNewStatus()); } returnedNodes.add(duplicatedWorkflowPath); } else if (end instanceof FlexoPortMap && ((FlexoPortMap) end).getOperation().getPort() instanceof NewPort) { getNextOperationForFlexoNode(visitedNodes, returnedNodes, ((FlexoPortMap) end).getOperation().getPort(), duplicatedWorkflowPath); } else if (end instanceof FlexoPortMap && ((FlexoPortMap) end).getOperation().getPort() instanceof DeletePort) { getNextOperationForFlexoNode(visitedNodes, returnedNodes, ((FlexoPortMap) end).getOperation().getPort(), duplicatedWorkflowPath); } else if (end instanceof FlexoPortMap && ((FlexoPortMap) end).getOperation().getPort() instanceof InPort) { getNextOperationForFlexoNode(visitedNodes, returnedNodes, ((FlexoPortMap) end).getOperation().getPort(), duplicatedWorkflowPath); } else if (end instanceof FlexoPortMap && ((FlexoPortMap) end).getOperation().getPort() instanceof InOutPort) { getNextOperationForFlexoNode(visitedNodes, returnedNodes, ((FlexoPortMap) end).getOperation().getPort(), duplicatedWorkflowPath); } else if (end instanceof OutPort) { Vector<FlexoPortMap> portMaps = ((FlexoPort) end).getAllPortMaps(); for (FlexoPortMap portMap : portMaps) { getNextOperationForFlexoNode(new ArrayList<AbstractNode>(visitedNodes), returnedNodes, portMap, duplicatedWorkflowPath.clone()); } } else if (end instanceof ActionNode && ((ActionNode) end).getActionType() == ActionType.DISPLAY_ACTION) { returnedNodes.addAll(((ActionNode) end).getNextOperationForDisplayAction(currentWorkflowPathToOperationNode)); } else { getNextOperationForFlexoNode(visitedNodes, returnedNodes, end, duplicatedWorkflowPath); } } } else if (includeDeadEndPath && !hasInsertedPathFromContainer) { if (node instanceof PetriGraphNode && isDeleteProcess((PetriGraphNode) node, true)) { currentWorkflowPathToOperationNode.getDeletedProcesses().add(node.getProcess()); } returnedNodes.add(currentWorkflowPathToOperationNode); } return returnedNodes; } private static boolean isCreateProcess(PetriGraphNode node) { return node != null && node.isProcessLevel() && isBeginNode(node); } private static boolean isBeginNode(AbstractNode node) { return node instanceof FlexoNode && ((FlexoNode) node).isBeginNode() || node instanceof EventNode && ((EventNode) node).isStart(); } private static boolean isDeleteProcess(PetriGraphNode node, boolean isDeadEnd) { if (isDeadEnd && isEndNode(node)) { node = node.getProcessLevelNode(); } return node != null && node.isProcessLevel() && isEndNode(node); } private static boolean isEndNode(AbstractNode node) { return node instanceof FlexoNode && ((FlexoNode) node).isEndNode() || node instanceof EventNode && ((EventNode) node).isEnd(); } private static List<WorkflowPathToOperationNode> getNextOperationForProcess(List<AbstractNode> visitedNodes, List<WorkflowPathToOperationNode> returnedNodes, FlexoProcess process, WorkflowPathToOperationNode currentWorkflowPathToOperationNode) { Enumeration en = process.getAllBeginNodes().elements(); while (en.hasMoreElements()) { AbstractActivityNode node = (AbstractActivityNode) en.nextElement(); if (!visitedNodes.contains(node)) { getNextOperationForFlexoNode(visitedNodes, returnedNodes, node, currentWorkflowPathToOperationNode.clone()); } } return returnedNodes; } // TABS public String getTabComponentName() { if (getTabComponent() != null) { return getTabComponent().getComponentName(); } return null; } public void setTabComponentName(String aComponentName) throws DuplicateResourceException, OperationAssociatedWithComponentSuccessfully { if (getTabComponentName() != null && getTabComponentName().equals(aComponentName)) { return; } if (_tabComponentInstance == null && (aComponentName == null || aComponentName.trim().equals(""))) { return; } ComponentDefinition foundComponent = getProject().getFlexoComponentLibrary().getComponentNamed(aComponentName); TabComponentDefinition newComponent = null; if (foundComponent instanceof TabComponentDefinition) { newComponent = (TabComponentDefinition) foundComponent; } else if (foundComponent != null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found a component named " + aComponentName + " but this is not a TabComponent. Aborting."); } throw new DuplicateResourceException(aComponentName); } if (newComponent == null) { if (logger.isLoggable(Level.INFO)) { logger.info("Creating a new Component named:" + aComponentName); } FlexoComponentFolder selectedFolder = getProject().getFlexoComponentLibrary().getRootFolder() .getFolderTyped(FolderType.TAB_FOLDER); newComponent = new TabComponentDefinition(aComponentName, getProject().getFlexoComponentLibrary(), selectedFolder, getProject()); } setTabComponent(newComponent); } public TabComponentDefinition getTabComponent() { if (_tabComponentInstance != null) { return _tabComponentInstance.getComponentDefinition(); } return null; } public void setTabComponent(TabComponentDefinition aComponentDefinition) { if (_tabComponentInstance != null && _tabComponentInstance.getComponentDefinition() == aComponentDefinition) { return; } if (_tabComponentInstance != null && aComponentDefinition == null) { removeTabComponentInstance(); } if (aComponentDefinition != null) { setTabActionComponentInstance(new TabComponentInstance(aComponentDefinition, this)); } } @Override public void setProcess(FlexoProcess p) { FlexoProcess old = getProcess(); super.setProcess(p); if (_tabComponentInstance != null) { _tabComponentInstance.updateDependancies(old, p); } } public TabComponentInstance getTabActionComponentInstance() { return _tabComponentInstance; } public void setTabActionComponentInstance(TabComponentInstance tabComponentInstance) { if (_tabComponentInstance != null) { removeTabComponentInstance(); } if (tabComponentInstance.getComponentDefinition() != null || isCreatedByCloning() && tabComponentInstance.getComponentName() != null) { _tabComponentInstance = tabComponentInstance; _tabComponentInstance.setActionNode(this); setChanged(); notifyAttributeModification("tabActionComponentInstance", null, _tabComponentInstance); } else if (logger.isLoggable(Level.SEVERE)) { logger.severe("TabComponentInstance does not have a component definition for component named " + tabComponentInstance.getComponentName()); } } public void removeTabComponentInstance() { if (_tabComponentInstance != null) { ComponentInstance oldComponentInstance = _tabComponentInstance; _tabComponentInstance.delete(); _tabComponentInstance = null; setChanged(); notifyAttributeModification("tabActionComponentInstance", oldComponentInstance, null); } } public boolean hasIncomingEdges() { /* * if (getIncomingPostConditions() != null && getIncomingPostConditions().size() > 0) return true; */ Enumeration<FlexoPreCondition> en = getPreConditions().elements(); while (en.hasMoreElements()) { if (en.nextElement().hasIncomingPostConditions()) { return true; } } return false; } public boolean isActivatedByAToken() { if (getIncomingPostConditions() != null && getIncomingPostConditions().size() > 0) { return true; } Enumeration<FlexoPreCondition> en = getPreConditions().elements(); while (en.hasMoreElements()) { if (en.nextElement().hasIncomingPostConditions()) { return true; } } return false; } public String getNextOperationTabKey() { if (getActionType() == ActionType.DISPLAY_ACTION) { for (WorkflowPathToOperationNode workflowPath : getNextOperationForDisplayAction()) { OperationNode nextOp = workflowPath.getOperationNode(); if (nextOp != null) { if (nextOp.getOperationComponent().getWOComponent().getTabWidgetForTabComponent(getTabComponent()) != null) { return nextOp.getOperationComponent().getWOComponent().getTabWidgetForTabComponent(getTabComponent()) .getTabKeyForGenerator(); } break; } } } return null; } /** * @see org.openflexo.foundation.FlexoXMLSerializableObject#setIsModified() */ @Override public synchronized void setIsModified() { if (ignoreNotifications()) { return; } super.setIsModified(); if (getOperationNode() != null) { getOperationNode().setIsModified(); } } @Override public boolean isInteractive() { return isNormalNode(); } public static class FlexoActionMustSendToken extends ValidationRule { public FlexoActionMustSendToken() { super(ActionNode.class, "flexo_action_must_send_token"); } /** * @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable) */ @Override public ValidationIssue applyValidation(Validable object) { ValidationWarning err = null; ActionNode node = (ActionNode) object; if (node.getActionType() == ActionType.FLEXO_ACTION && !node.isEndNode() && !node.isBeginNode() && (node.getOutgoingPostConditions() == null || node.getOutgoingPostConditions().size() == 0)) { err = new ValidationWarning(this, object, "flexo_action_($object.name)_must_send_token"); err.addToFixProposals(new ChangeToDisplayAction(node)); err.addToFixProposals(new DeleteFlexoAction(node)); } return err; } public class DeleteFlexoAction extends FixProposal { private ActionNode node; public DeleteFlexoAction(ActionNode node) { super("delete_flexo_action"); this.node = node; } /** * @see org.openflexo.foundation.validation.FixProposal#fixAction() */ @Override protected void fixAction() { if (node.getAssociatedButtonWidget() != null) { IEHyperlinkWidget button = node.getAssociatedButtonWidget(); if (button.getHyperlinkType() == HyperlinkType.FLEXOACTION) { button.setHyperlinkType(null); } if (button.getIsMandatoryFlexoAction()) { button.setIsMandatoryFlexoAction(false); } } node.delete(); } } public class ChangeToDisplayAction extends FixProposal { private ActionNode node; /** * @param aMessage */ public ChangeToDisplayAction(ActionNode node) { super("change_flexo_action_($object.name)_into_display_action"); this.node = node; } /** * @see org.openflexo.foundation.validation.FixProposal#fixAction() */ @Override protected void fixAction() { node.setActionType(ActionType.DISPLAY_ACTION); } } } }