/* * (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.ws; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.AttributeDataModification; import org.openflexo.foundation.DataModification; import org.openflexo.foundation.FlexoObservable; import org.openflexo.foundation.FlexoObserver; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.NameChanged; import org.openflexo.foundation.bindings.Bindable; import org.openflexo.foundation.bindings.BindingModel; import org.openflexo.foundation.utils.FlexoIndexManager; import org.openflexo.foundation.utils.Sortable; import org.openflexo.foundation.validation.DeletionFixProposal; import org.openflexo.foundation.validation.ValidationError; import org.openflexo.foundation.validation.ValidationIssue; import org.openflexo.foundation.validation.ValidationRule; import org.openflexo.foundation.wkf.DuplicateWKFObjectException; import org.openflexo.foundation.wkf.FlexoLevel; import org.openflexo.foundation.wkf.FlexoProcess; import org.openflexo.foundation.wkf.WKFObject; import org.openflexo.foundation.wkf.dm.ChildrenOrderChanged; import org.openflexo.foundation.wkf.edge.FlexoPostCondition; import org.openflexo.foundation.wkf.edge.MessageEdge; import org.openflexo.foundation.wkf.node.AbstractNode; import org.openflexo.foundation.wkf.node.SubProcessNode; import org.openflexo.foundation.xml.FlexoProcessBuilder; /** * Abstract representation of connexion between an operation associated to a ServiceInterface (for PortRegistry, a DefaultServiceInterface) * associated to a FlexoProcess and the SubProcessNode and thus, related petri graph where the SubProcessNode is embedded: this make the * connexion between the abstract representation of a FlexoProcess, and the instanciation of this process inside a SubProcessNode. * * @author sguerin * */ public class FlexoPortMap extends AbstractNode implements Bindable, FlexoObserver, Sortable { private static final Logger logger = Logger.getLogger(FlexoPortMap.class.getPackage().getName()); // ========================================================================== // ============================= Variables // ================================== // ========================================================================== private ServiceOperation _operation; // equal to operation name. private String _portName; private PortMapRegistery _portMapRegistery; private int index = -1; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== /** * Constructor used during deserialization */ public FlexoPortMap(FlexoProcessBuilder builder) { this(builder.process); initializeDeserialization(builder); } /** * Default constructor */ public FlexoPortMap(FlexoProcess process) { super(process); } /** * Constructor with port and process NB: process of the port is NOT the same that aProcess !!! */ public FlexoPortMap(ServiceOperation op, FlexoProcess aProcess) { this(aProcess); setOperation(op); } @Override public String getDefaultName() { return getOperation().getName(); } public FlexoProcess getRelatedSubProcess() { if (getPortMapRegistery() != null && getPortMapRegistery().getSubProcessNode() != null) { return getPortMapRegistery().getSubProcessNode().getSubProcess(); } return null; } private ServiceInterface getServiceInterface() { if (getRelatedSubProcess() != null) { return getPortMapRegistery().getServiceInterface(); } return null; } @Override public String getName() { if (getOperation() != null) { return getOperation().getName(); } if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find port !"); } return null; } @Override public void setName(String aName) { try { getOperation().setName(aName); } catch (DuplicateWKFObjectException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception in setName FlexoPortMap"); e.printStackTrace(); } } } public ServiceOperation getOperation() { if (logger.isLoggable(Level.FINEST)) { logger.finest("getOperation(): op=" + _operation + " name:" + _portName); } if (_operation == null && _portName != null) { lookupOperation(); } return _operation; } public void setOperation(ServiceOperation anOp) { if (_operation != null) { _operation.deleteObserver(this); } _operation = anOp; if (_operation != null) { _operation.addObserver(this); } } private void lookupOperation() { // the portName can store the operationName... if (logger.isLoggable(Level.FINEST)) { logger.finest("lookupOperation:" + getServiceInterface()); } if (getServiceInterface() != null && _portName != null) { _operation = getServiceInterface().operationWithName(_portName); if (_operation == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find operation named: " + _portName); } } else { _operation.addObserver(this); for (FlexoPostCondition<AbstractNode, AbstractNode> entry : getIncomingPostConditions()) { if (entry instanceof MessageEdge) { ((MessageEdge<AbstractNode, AbstractNode>) entry).lookupMessageDefinition(); } } for (FlexoPostCondition<AbstractNode, AbstractNode> exit : getOutgoingPostConditions()) { if (exit instanceof MessageEdge) { ((MessageEdge<AbstractNode, AbstractNode>) exit).lookupMessageDefinition(); } } } } } /** * * @return the operation name is the portMap is mapping a ServiceOperation ! */ public String getPortName() { if (getOperation() != null) { return getOperation().getName(); } return _portName; } public void setPortName(String name) { _portName = name; if (_operation != null && !_portName.equals(_operation.getName())) { lookupOperation(); } } @Override public String getInspectorName() { return Inspectors.WKF.PORTMAP_INSPECTOR; /* * if (getOperation().getPort() instanceof InPort) { return Inspectors.WKF.IN_PORTMAP_INSPECTOR; } else if (getOperation().getPort() * instanceof OutPort) { return Inspectors.WKF.OUT_PORTMAP_INSPECTOR; } else if (getOperation().getPort() instanceof InOutPort) { * return Inspectors.WKF.IN_OUT_PORTMAP_INSPECTOR; } else if (getOperation().getPort() instanceof NewPort) { return * Inspectors.WKF.NEW_PORTMAP_INSPECTOR; } else if (getOperation().getPort() instanceof DeletePort) { return * Inspectors.WKF.DELETE_PORTMAP_INSPECTOR; } return null; */ } @Override public AbstractNode getNode() { return this; } /** * Return a Vector of all embedded WKFObjects * * @return a Vector of WKFObject instances */ @Override public Vector<WKFObject> getAllEmbeddedWKFObjects() { Vector<WKFObject> returned = super.getAllEmbeddedWKFObjects(); returned.addAll(getOutgoingPostConditions()); returned.addAll(getIncomingPostConditions()); return returned; } /** * 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(); } @Override public FlexoLevel getLevel() { return FlexoLevel.ACTIVITY; } public SubProcessNode getSubProcessNode() { if (getPortMapRegistery() != null) { return getPortMapRegistery().getSubProcessNode(); } else { return null; } } private boolean isRegisteredUnderSubProcessNode = false; public void registerUnderSubProcessNode() { if (getSubProcessNode() != null && !isRegisteredUnderSubProcessNode) { getSubProcessNode().addObserver(this); isRegisteredUnderSubProcessNode = true; } } public PortMapRegistery getPortMapRegistery() { return _portMapRegistery; } public void setPortMapRegistery(PortMapRegistery portMapRegistery) { _portMapRegistery = portMapRegistery; } public boolean isInputPort() { if (getOperation() != null) { return getOperation().isInputOperation(); } return false; } public boolean isOutputPort() { if (getOperation() != null) { return getOperation().isOutputOperation(); } return false; } public boolean isNewPort() { return getOperation().getPort() instanceof NewPort; } /** * Return the father which is the FlexoProcess * * @return */ public FlexoProcess getFather() { return getProcess(); } @Override public String getFullyQualifiedName() { if (getSubProcessNode() != null) { return getSubProcessNode().getFullyQualifiedName() + ".PORTMAP." + formattedString(getName()); } else { return "NULL." + formattedString(getNodeName()); } } @Override public BindingModel getBindingModel() { if (getProcess() != null) { return getProcess().getBindingModel(); } else { return null; } } @Override public boolean mayHaveIncomingPostConditions() { if (getOperation() != null) { return isInputPort(); } return true; } @Override public boolean mayHaveOutgoingPostConditions() { if (getOperation() != null) { return isOutputPort(); } return true; } // ========================================================================== // ================================= Delete =============================== // ========================================================================== @Override public final void delete() { if (_operation != null) { _operation.deleteObserver(this); } getPortMapRegistery().removeFromPortMaps(this); super.delete(); deleteObservers(); } @Override public boolean isContainedIn(WKFObject obj) { if (obj instanceof PortMapRegistery) { return ((PortMapRegistery) obj).getPortMaps().contains(this); } return super.isContainedIn(obj); } @Override public boolean getIsVisible() { return getIsVisible(true); } public boolean getIsHidden() { return !getIsVisible(); } public void setIsHidden(boolean hidePortMap) { setIsVisible(!hidePortMap); } @Override public void update(FlexoObservable observable, DataModification dataModification) { if (dataModification instanceof NameChanged) { setChanged(); notifyObservers(dataModification); } } /** * Overrides getClassNameKey * * @see org.openflexo.foundation.FlexoModelObject#getClassNameKey() */ @Override public String getClassNameKey() { return "flexo_port_map"; } public boolean getHasInputMessage() { return getInputMessageDefinition() != null; } public boolean getHasOutputMessage() { return getOutputMessageDefinition() != null; } public ServiceMessageDefinition getInputMessageDefinition() { if (isInputPort()) { return getOperation().getInputMessageDefinition(); } return null; } public ServiceMessageDefinition getOutputMessageDefinition() { if (isOutputPort()) { return getOperation().getOutputMessageDefinition(); } return null; } @Override public int getIndex() { if (isBeingCloned()) { return -1; } if (index == -1 && getCollection() != null) { index = getCollection().length; FlexoIndexManager.reIndexObjectOfArray(getCollection()); } return index; } @Override public final void setIndex(int index) { if (isDeserializing() || isCreatedByCloning()) { setIndexValue(index); return; } FlexoIndexManager.switchIndexForKey(this.index, index, this); if (getIndex() != index) { setChanged(); AttributeDataModification dm = new AttributeDataModification("index", null, getIndex()); dm.setReentrant(true); notifyObservers(dm); } } @Override public int getIndexValue() { return getIndex(); } @Override public final void setIndexValue(int index) { if (index == this.index) { return; } int old = this.index; this.index = index; setChanged(); notifyAttributeModification("index", old, index); if (!isDeserializing() && getPortMapRegistery() != null) { getPortMapRegistery().setChanged(); getPortMapRegistery().notifyObservers(new ChildrenOrderChanged()); } } /** * Overrides getCollection * * @see org.openflexo.foundation.utils.Sortable#getCollection() */ @Override public FlexoPortMap[] getCollection() { if (getPortMapRegistery() == null) { return null; } return getPortMapRegistery().getPortMaps().toArray(new FlexoPortMap[0]); } // ========================================================================== // ============================= Validation // ================================= // ========================================================================== /** * must refer to a port OR an operation */ public static class PortMapMustReferToAServiceOperation extends ValidationRule<PortMapMustReferToAServiceOperation, FlexoPortMap> { public PortMapMustReferToAServiceOperation() { super(FlexoPortMap.class, "portmap_must_be_linked_to_a_service_operation"); } @Override public ValidationIssue<PortMapMustReferToAServiceOperation, FlexoPortMap> applyValidation(FlexoPortMap portMap) { if (portMap.getOperation() == null) { ValidationError<PortMapMustReferToAServiceOperation, FlexoPortMap> error = new ValidationError<PortMapMustReferToAServiceOperation, FlexoPortMap>( this, portMap, "portmap_is_not_linked_to_a_service_operation"); error.addToFixProposals(new DeletionFixProposal<PortMapMustReferToAServiceOperation, FlexoPortMap>("delete_this_portmap")); return error; } return null; } } }