/*
* (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.action;
import java.io.File;
import java.io.FileInputStream;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.FlexoEditor;
import org.openflexo.foundation.FlexoException;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.action.FlexoActionType;
import org.openflexo.foundation.action.FlexoUndoableAction;
import org.openflexo.foundation.wkf.ActionPetriGraph;
import org.openflexo.foundation.wkf.ActivityPetriGraph;
import org.openflexo.foundation.wkf.FlexoPetriGraph;
import org.openflexo.foundation.wkf.FlexoProcess;
import org.openflexo.foundation.wkf.MetricsValue.MetricsValueOwner;
import org.openflexo.foundation.wkf.OperationPetriGraph;
import org.openflexo.foundation.wkf.Role;
import org.openflexo.foundation.wkf.WKFArtefact;
import org.openflexo.foundation.wkf.WKFElementType;
import org.openflexo.foundation.wkf.WKFGroup;
import org.openflexo.foundation.wkf.WKFObject;
import org.openflexo.foundation.wkf.node.AbstractActivityNode;
import org.openflexo.foundation.wkf.node.AbstractNode;
import org.openflexo.foundation.wkf.node.ActionNode;
import org.openflexo.foundation.wkf.node.ActivityNode;
import org.openflexo.foundation.wkf.node.EventNode;
import org.openflexo.foundation.wkf.node.FlexoNode;
import org.openflexo.foundation.wkf.node.OperatorNode;
import org.openflexo.foundation.wkf.node.PetriGraphNode;
import org.openflexo.foundation.wkf.node.SubProcessNode;
import org.openflexo.foundation.wkf.node.TaskType;
import org.openflexo.foundation.wkf.node.WKFNode;
import org.openflexo.xmlcode.XMLDecoder;
import org.openflexo.xmlcode.XMLMapping;
public class DropWKFElement extends FlexoUndoableAction<DropWKFElement, FlexoPetriGraph, WKFObject> {
private static final Logger logger = Logger.getLogger(DropWKFElement.class.getPackage().getName());
public static FlexoActionType<DropWKFElement, FlexoPetriGraph, WKFObject> actionType = new FlexoActionType<DropWKFElement, FlexoPetriGraph, WKFObject>(
"drag_wkf_element", FlexoActionType.newMenu, FlexoActionType.defaultGroup, FlexoActionType.ADD_ACTION_TYPE) {
/**
* Factory method
*/
@Override
public DropWKFElement makeNewAction(FlexoPetriGraph focusedObject, Vector<WKFObject> globalSelection, FlexoEditor editor) {
return new DropWKFElement(focusedObject, globalSelection, editor);
}
@Override
public boolean isVisibleForSelection(FlexoPetriGraph object, Vector<WKFObject> globalSelection) {
return false;
}
@Override
public boolean isEnabledForSelection(FlexoPetriGraph object, Vector<WKFObject> globalSelection) {
return object != null && object.getProcess() != null;
}
};
static {
FlexoModelObject.addActionForClass(actionType, FlexoPetriGraph.class);
}
DropWKFElement(FlexoPetriGraph focusedObject, Vector<WKFObject> globalSelection, FlexoEditor editor) {
super(actionType, focusedObject, globalSelection, editor);
parameters = new Hashtable<String, FlexoModelObject>();
}
public static final String SUB_PROCESS = "SUB_PROCESS";
private boolean leaveSubProcessNodeUnchanged = false;
private WKFObject object;
private double posX = -1;
private double posY = -1;
private Hashtable<String, FlexoModelObject> parameters;
private boolean resetNodeName = true;
private boolean editNodeLabel = false;
private Role roleToAssociate;
private String graphicalContext; // eg BPE, SWL ...
private WKFGroup group;
public FlexoProcess getProcess() {
if (getFocusedObject() != null) {
return getFocusedObject().getProcess();
}
return null;
}
public void setParameter(String key, FlexoModelObject value) {
parameters.put(key, value);
}
@Override
protected void doAction(Object context) throws InvalidLevelException {
logger.info("Insert WKF element");
if (getProcess() != null && getObject() != null && getPetriGraph() != null) {
if (getGraphicalContext() != null) {
getObject().setX(posX, getGraphicalContext());
getObject().setY(posY, getGraphicalContext());
}
if (getObject() instanceof PetriGraphNode) {
PetriGraphNode node = (PetriGraphNode) getObject();
if (getRoleToAssociate() != null) {
if (roleToAssociate == getProject().getWorkflow().getDefaultRole()) {
roleToAssociate = null;
}
if (node instanceof AbstractActivityNode) {
((AbstractActivityNode) node).setRole(roleToAssociate);
} else if (node instanceof OperatorNode) {
((OperatorNode) node).setRole(roleToAssociate);
} else if (node instanceof EventNode) {
((EventNode) node).setRole(roleToAssociate);
}
}
if (node instanceof OperatorNode || node instanceof EventNode || node.getLevel() == getPetriGraph().getLevel()) {
FlexoProcess process = getPetriGraph().getProcess();
if (resetNodeName) {
resetNodeName(getPetriGraph(), node);
}
setProcessOnNode(process, node);
if (node instanceof SubProcessNode) {
SubProcessNode subProcessNode = (SubProcessNode) node;
FlexoProcess subProcess = (FlexoProcess) parameters.get(SUB_PROCESS);
if (subProcess != null) {
subProcessNode.setName(subProcess.getName());
subProcessNode.setSubProcess(subProcess);
}
}
getProcess().getProject().register(node);
getPetriGraph().addToNodes(node);
if (node instanceof MetricsValueOwner) {
((MetricsValueOwner) node).updateMetricsValues();
}
if (node instanceof FlexoNode) {
if (node instanceof ActivityNode) {
((ActivityNode) node).setTaskType(TaskType.User);
}
if (((FlexoNode) node).isBeginOrEndNode()) {
node.setDontGenerate(true);
((FlexoNode) node).resetLabelLocation(getGraphicalContext());
}
if (((FlexoNode) node).isSelfExecutableNode()) {
((FlexoNode) node).resetLabelLocation(getGraphicalContext());
}
if (node instanceof ActionNode) {
((FlexoNode) node).resetLabelLocation(getGraphicalContext());
}
}
if (getGroup() != null) {
getGroup().addToNodes(node);
getGroup().notifyGroupUpdated();
}
if (node instanceof EventNode) {
EventNode eventNode = (EventNode) node;
if (((EventNode) node).isStartOrEnd()) {
node.setDontGenerate(true);
}
eventNode.resetLabelLocation(getGraphicalContext());
// eventNode.setLabelX(25, getGraphicalContext());
// eventNode.setLabelY(45, getGraphicalContext());
}
return;
}
}
else if (object instanceof WKFArtefact) {
WKFArtefact artefact = (WKFArtefact) getObject();
logger.info("Insert an artefact...");
FlexoProcess process = getPetriGraph().getProcess();
setProcessOnNode(process, artefact);
getPetriGraph().addToArtefacts(artefact);
artefact.updateMetricsValues();
}
else {
throw new InvalidLevelException("Cannot insert this element at this level");
}
} else {
logger.warning("Something strange happened: " + getProcess() + ", " + getObject() + ", " + getPetriGraph());
}
}
private void setProcessOnNode(FlexoProcess process, WKFNode node) {
node.setProcess(process);
Collection<FlexoModelObject> embedded = node.getAllRecursivelyEmbeddedObjects();
Iterator<FlexoModelObject> i = embedded.iterator();
while (i.hasNext()) {
FlexoModelObject o = i.next();
if (o instanceof WKFObject) {
((WKFObject) o).setProcess(process);
}
}
}
// public FlexoColor getBackgroundColor() {
// return backgroundColor;
// }
// public void setBackgroundColor(FlexoColor backgroundColor) {
// this.backgroundColor = backgroundColor;
// }
private void resetNodeName(FlexoPetriGraph petriGraph, AbstractNode newNode) {
FlexoProcess process = petriGraph.getProcess();
if (petriGraph instanceof ActivityPetriGraph) {
if (newNode instanceof SubProcessNode) {
newNode.setNodeName(process.findNextInitialName(newNode.getName()));
} else {
newNode.setNodeName(process.findNextInitialName(newNode.getDefaultName()));
}
} else if (petriGraph instanceof OperationPetriGraph) {
newNode.setNodeName(process.findNextInitialName(newNode.getDefaultName(),
((OperationPetriGraph) petriGraph).getAbstractActivityNode()));
} else if (petriGraph instanceof ActionPetriGraph) {
newNode.setNodeName(process.findNextInitialName(newNode.getDefaultName(), ((ActionPetriGraph) petriGraph).getOperationNode()));
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Inconsistent data: petri graph is a " + petriGraph.getClass().getName());
}
}
}
public WKFObject getObject() {
return object;
}
public void setObject(WKFObject anObject) {
object = anObject;
}
public double getPosX() {
return posX;
}
public void setPosX(double posX) {
this.posX = posX;
}
public double getPosY() {
return posY;
}
public void setPosY(double posY) {
this.posY = posY;
}
public void setLocation(double posX, double posY) {
setPosX(posX);
setPosY(posY);
}
public boolean getEditNodeLabel() {
return editNodeLabel;
}
public void setEditNodeLabel(boolean editNodeLabel) {
this.editNodeLabel = editNodeLabel;
}
public boolean getResetNodeName() {
return resetNodeName;
}
public void setResetNodeName(boolean resetNodeName) {
this.resetNodeName = resetNodeName;
}
public FlexoPetriGraph getPetriGraph() {
return getFocusedObject();
}
private static AbstractNode buildDroppedElement(String elementXMLRepresentation, FlexoProcess process) {
AbstractNode node = null;
try {
XMLMapping wkfMapping = process.getXMLMapping();
node = (AbstractNode) XMLDecoder.decodeObjectWithMapping(elementXMLRepresentation, wkfMapping, process.instanciateNewBuilder(),
process.getStringEncoder());
} catch (Exception e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Failed building element: " + elementXMLRepresentation);
}
e.printStackTrace();
}
return node;
}
private static AbstractNode buildDroppedElement(File elementXMLFile, FlexoProcess process) {
AbstractNode node = null;
try {
XMLMapping wkfMapping = process.getXMLMapping();
// Read the node
AbstractNode readNode = (AbstractNode) XMLDecoder.decodeObjectWithMapping(new FileInputStream(elementXMLFile), wkfMapping,
process.instanciateNewBuilder(), process.getStringEncoder());
// We clone here in order to get a node with identifiers well resetted (and all other stuff)
node = (AbstractNode) readNode.cloneUsingXMLMapping();
} catch (Exception e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Failed building element from file " + elementXMLFile);
}
e.printStackTrace();
}
return node;
}
public void setElementType(WKFElementType elementType) {
setObject((WKFObject) elementType.instanciateNewObject().cloneUsingXMLMapping(getPetriGraph().getProcess().instanciateNewBuilder(),
true, getPetriGraph().getProcess().getXMLMapping()));
}
@Override
protected void redoAction(Object context) throws FlexoException {
doAction(context);
}
@Override
protected void undoAction(Object context) throws FlexoException {
getObject().delete();
}
public String getGraphicalContext() {
return graphicalContext;
}
public void setGraphicalContext(String graphicalContext) {
this.graphicalContext = graphicalContext;
}
public WKFGroup getGroup() {
return group;
}
public void setGroup(WKFGroup group) {
this.group = group;
}
public Role getRoleToAssociate() {
return roleToAssociate;
}
public void setRoleToAssociate(Role roleToAssociate) {
this.roleToAssociate = roleToAssociate;
}
public boolean leaveSubProcessNodeUnchanged() {
return leaveSubProcessNodeUnchanged;
}
public void setLeaveSubProcessNodeUnchanged(boolean leaveSubProcessNodeUnchanged) {
this.leaveSubProcessNodeUnchanged = leaveSubProcessNodeUnchanged;
}
private boolean handlePaletteOffset = true;
public boolean handlePaletteOffset() {
return handlePaletteOffset;
}
public void setHandlePaletteOffset(boolean handlePaletteOffset) {
this.handlePaletteOffset = handlePaletteOffset;
}
}