/* * (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.Vector; import java.util.logging.Logger; import org.openflexo.foundation.bindings.Bindable; import org.openflexo.foundation.bindings.BindingModel; import org.openflexo.foundation.utils.FlexoModelObjectReference; import org.openflexo.foundation.utils.FlexoModelObjectReference.ReferenceOwner; import org.openflexo.foundation.validation.DeletionFixProposal; import org.openflexo.foundation.validation.ValidationIssue; import org.openflexo.foundation.validation.ValidationRule; import org.openflexo.foundation.validation.ValidationWarning; import org.openflexo.foundation.wkf.ExecutableWorkflowElement; import org.openflexo.foundation.wkf.FlexoLevel; import org.openflexo.foundation.wkf.FlexoProcess; import org.openflexo.foundation.wkf.Role; import org.openflexo.foundation.wkf.WKFObject; import org.openflexo.foundation.wkf.dm.RoleChanged; import org.openflexo.foundation.wkf.dm.WKFAttributeDataModification; import org.openflexo.foundation.xml.FlexoProcessBuilder; import org.openflexo.localization.FlexoLocalization; import org.openflexo.toolbox.ProgrammingLanguage; /** * Represents an Operator Node (AND or OR) * * @author sguerin */ public abstract class OperatorNode extends PetriGraphNode implements Bindable, ExecutableWorkflowElement, ReferenceOwner { private static final String RESIZABLE = "resizable"; static final Logger logger = Logger.getLogger(OperatorNode.class.getPackage().getName()); private FlexoModelObjectReference<Role> roleReference; // ================================================================ // ====================== Constructor ============================= // ================================================================ /** * Constructor used during deserialization */ public OperatorNode(FlexoProcessBuilder builder) { this(builder.process); initializeDeserialization(builder); } /** * Default constructor */ public OperatorNode(FlexoProcess process) { super(process); } @Override public abstract String getInspectorName(); @Override public OperatorNode getNode() { return this; } @Override public FlexoLevel getLevel() { if (getParentPetriGraph() != null) { return getParentPetriGraph().getLevel(); } return null; } public boolean isSendingTokens() { return hasOutgoingPostConditions(); } @Override public boolean isOperatorNode() { return true; } public boolean isTestNode() { return this instanceof IFOperator; } public boolean isAndNode() { return this instanceof ANDOperator; } public boolean isOrNode() { return this instanceof OROperator; } public boolean isSwitchNode() { return this instanceof SWITCHOperator; } public boolean isLoopNode() { return this instanceof LOOPOperator; } public final boolean isExclusiveGateway() { return this instanceof ExclusiveEventBasedOperator; } public final boolean isInclusiveGateway() { return this instanceof InclusiveOperator; } @Override public boolean mayHaveIncomingPostConditions() { return true; } @Override public boolean mayHaveOutgoingPostConditions() { return true; } public static String getResizableKeyForContext(String context) { return RESIZABLE + '_' + context; } public boolean isResizable(String context) { return _booleanGraphicalPropertyForKey(getResizableKeyForContext(context), false); } public void setIsResizable(boolean resizable, String context) { if (requireChange(isResizable(context), resizable)) { _setGraphicalPropertyForKey(resizable, getResizableKeyForContext(context)); setChanged(); notifyObservers(new WKFAttributeDataModification(getResizableKeyForContext(context), !resizable, resizable)); } } @Override public final void delete() { super.delete(); deleteObservers(); } /** * Build and return a vector of all the objects that will be deleted during this deletion * * @param aVector * of DeletableObject */ @Override public Vector<WKFObject> getAllEmbeddedDeleted() { return getAllEmbeddedWKFObjects(); } // Used when serializing public FlexoModelObjectReference<Role> getRoleReference() { return roleReference; } // Used when deserializing public void setRoleReference(FlexoModelObjectReference<Role> aRoleReference) { this.roleReference = aRoleReference; } public Role getRole() { if (roleReference != null) { Role object = roleReference.getObject(); if (object != null) { return object; } else { return getWorkflow().getCachedRole(roleReference); } } else { return null; } } public void setRole(Role aRole) { if (aRole != null && aRole.isCache()) { aRole = aRole.getUncachedObject(); if (aRole == null) { return; } } Role oldRole = getRole(); if (oldRole != aRole) { if (roleReference != null) { roleReference.delete(false); roleReference = null; } if (aRole != null) { roleReference = new FlexoModelObjectReference<Role>(aRole); roleReference.setOwner(this); } setChanged(); notifyObservers(new RoleChanged(oldRole, aRole)); } } @Override public void notifyObjectLoaded(FlexoModelObjectReference<?> reference) { // TODO Auto-generated method stub } @Override public void objectCantBeFound(FlexoModelObjectReference<?> reference) { setRole(null); } @Override public void objectDeleted(FlexoModelObjectReference<?> reference) { setRole(null); } @Override public void objectSerializationIdChanged(FlexoModelObjectReference<?> reference) { setChanged(); } public static class OperatorNodeShouldSendTokens extends ValidationRule<OperatorNodeShouldSendTokens, OperatorNode> { public OperatorNodeShouldSendTokens() { super(OperatorNode.class, "operator_node_should_send_tokens"); } @Override public ValidationIssue<OperatorNodeShouldSendTokens, OperatorNode> applyValidation(OperatorNode node) { if (!node.isSendingTokens()) { ValidationWarning<OperatorNodeShouldSendTokens, OperatorNode> warning = new ValidationWarning<OperatorNodeShouldSendTokens, OperatorNode>( this, node, "operator_node_($object.name)_never_send_any_tokens"); warning.addToFixProposals(new DeletionFixProposal<OperatorNodeShouldSendTokens, OperatorNode>("delete_this_node")); return warning; } return null; } } /** * Overrides getClassNameKey * * @see org.openflexo.foundation.FlexoModelObject#getClassNameKey() */ @Override public String getClassNameKey() { return "operator_node"; } @Override public BindingModel getBindingModel() { if (getProcess() != null) { return getProcess().getBindingModel(); } return null; } // ========================================================= // ============= Control graph management ================== // ========================================================= private static ControlGraphFactory<OperatorNode> _executionComputingFactory; public static void setExecutionComputingFactory(ControlGraphFactory<OperatorNode> factory) { _executionComputingFactory = factory; } public WorkflowControlGraph<OperatorNode> getExecution() { if (_executionComputingFactory != null) { return _executionComputingFactory.getControlGraph(this); } return null; } @Override public void setProgrammingLanguageForControlGraphComputation(ProgrammingLanguage language) { if (getExecution() != null) { getExecution().setProgrammingLanguage(language); } } @Override public void setInterproceduralForControlGraphComputation(boolean interprocedural) { if (getExecution() != null) { getExecution().setInterprocedural(interprocedural); } } @Override public String getExecutableElementName() { return FlexoLocalization.localizedForKeyWithParams("operator_($0)", getName()); } }