/*
* (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.Enumeration;
import java.util.Vector;
import java.util.logging.Logger;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.validation.FixProposal;
import org.openflexo.foundation.validation.ValidationIssue;
import org.openflexo.foundation.validation.ValidationRule;
import org.openflexo.foundation.validation.ValidationWarning;
import org.openflexo.foundation.wkf.FlexoProcess;
import org.openflexo.foundation.wkf.edge.FlexoPostCondition;
import org.openflexo.foundation.wkf.edge.InternalMessageInEdge;
import org.openflexo.foundation.wkf.node.AbstractNode;
import org.openflexo.foundation.xml.FlexoProcessBuilder;
import org.openflexo.localization.FlexoLocalization;
/**
* Input/output data port associated to a PortRegistery associated to a SubProcessNode This kind of port is used to modelize synchronous
* call.
*
* @author sguerin
*
*/
public final class InOutPort extends AbstractInPort implements OutputPort {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(InOutPort.class.getPackage().getName());
/**
* Stores the incoming post conditions, as a Vector of PortEntry
*/
private final Vector<FlexoPostCondition> _incomingPostConditions;
/**
* Stores the input message definition
*/
private MessageDefinition _outputMessageDefinition;
// ==========================================================================
// ============================= Constructor
// ================================
// ==========================================================================
/**
* Constructor used during deserialization
*/
public InOutPort(FlexoProcessBuilder builder) {
this(builder.process);
initializeDeserialization(builder);
}
/**
* Constructor with process and name
*/
public InOutPort(FlexoProcess process, String aName) {
this(process);
setPortRegistery(process.getPortRegistery());
setName(aName);
}
/**
* Default constructor
*/
public InOutPort(FlexoProcess process) {
super(process);
_incomingPostConditions = new Vector<FlexoPostCondition>();
}
@Override
public String getPrefixForFullQualifiedName() {
return "IN_OUT_PORT";
}
@Override
public String getInspectorName() {
return Inspectors.WKF.IN_OUT_PORT_INSPECTOR;
}
@Override
public String getDefaultName() {
return getDefaultInitialName();
}
public static String getDefaultInitialName() {
return FlexoLocalization.localizedForKey("in_out_port_name");
}
@Override
public boolean isOutPort() {
return true;
}
@Override
public MessageDefinition getOutputMessageDefinition() {
if (_outputMessageDefinition == null) {
_outputMessageDefinition = new MessageDefinition(getProcess(), this);
_outputMessageDefinition.setIsOutputMessageDefinition();
_outputMessageDefinition.setName(_outputMessageDefinition.getDefaultName());
}
return _outputMessageDefinition;
}
@Override
public void setOutputMessageDefinition(MessageDefinition aMessageDefinition) {
if (aMessageDefinition != _outputMessageDefinition) {
if (aMessageDefinition != null) {
aMessageDefinition.setPort(this);
_outputMessageDefinition = aMessageDefinition;
_outputMessageDefinition.setIsOutputMessageDefinition();
} else {
_outputMessageDefinition = null;
}
setChanged();
}
}
@Override
public boolean mayHaveIncomingPostConditions() {
return true;
}
// ==========================================================================
// ============================= Validation
// =================================
// ==========================================================================
@Override
public boolean isCorrectelyLinked() {
return getOutgoingPostConditions().size() > 0 && getInvalidOutgoingPostConditions().size() == 0;
}
protected Vector<FlexoPostCondition<AbstractNode, AbstractNode>> getInvalidOutgoingPostConditions() {
Vector<FlexoPostCondition<AbstractNode, AbstractNode>> returnedVector = new Vector<FlexoPostCondition<AbstractNode, AbstractNode>>();
for (Enumeration<FlexoPostCondition<AbstractNode, AbstractNode>> e = getOutgoingPostConditions().elements(); e.hasMoreElements();) {
FlexoPostCondition<AbstractNode, AbstractNode> next = e.nextElement();
if (!next.isEdgeValid()) {
returnedVector.add(next);
}
}
return returnedVector;
}
public static class InOutPortMustBeLinkedToAtLeastAnActivityNode extends
ValidationRule<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort> {
public InOutPortMustBeLinkedToAtLeastAnActivityNode() {
super(InOutPort.class, "in_out_port_must_be_linked_to_at_least_an_activity_node");
}
@Override
public ValidationIssue<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort> applyValidation(InOutPort port) {
if (!port.isCorrectelyLinked()) {
Vector invalidEdges = port.getInvalidOutgoingPostConditions();
ValidationWarning<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort> error;
if (invalidEdges.size() == 0) {
error = new ValidationWarning<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort>(this, port,
"port_has_no_outgoing_edges");
} else {
error = new ValidationWarning<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort>(this, port,
"port_has_invalid_outgoing_edges");
error.addToFixProposals(new DeleteInvalidEdges(invalidEdges));
}
return error;
}
return null;
}
public static class DeleteInvalidEdges extends FixProposal<InOutPortMustBeLinkedToAtLeastAnActivityNode, InOutPort> {
public Vector invalidEdges;
public DeleteInvalidEdges(Vector invalidEdges) {
super("delete_invalid_edges");
this.invalidEdges = invalidEdges;
}
@Override
protected void fixAction() {
for (Enumeration e = invalidEdges.elements(); e.hasMoreElements();) {
InternalMessageInEdge next = (InternalMessageInEdge) e.nextElement();
next.delete();
}
}
}
}
/**
* Overrides getClassNameKey
*
* @see org.openflexo.foundation.FlexoModelObject#getClassNameKey()
*/
@Override
public String getClassNameKey() {
return "in_out_port";
}
}