/* * (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.wkf.controller.action; import java.util.EventObject; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Icon; import org.openflexo.components.AskParametersDialog; import org.openflexo.foundation.FlexoEditor; import org.openflexo.foundation.FlexoException; import org.openflexo.foundation.InvalidArgumentException; import org.openflexo.foundation.action.ExecutionContext; import org.openflexo.foundation.action.FlexoActionFinalizer; import org.openflexo.foundation.action.FlexoActionInitializer; import org.openflexo.foundation.action.FlexoActionRedoInitializer; import org.openflexo.foundation.action.FlexoActionType; import org.openflexo.foundation.action.FlexoActionUndoFinalizer; import org.openflexo.foundation.action.FlexoActionVisibleCondition; import org.openflexo.foundation.action.FlexoExceptionHandler; import org.openflexo.foundation.param.NodeParameter; import org.openflexo.foundation.param.NodeParameter.NodeSelectingConditional; import org.openflexo.foundation.param.RadioButtonListParameter; import org.openflexo.foundation.param.TextFieldParameter; import org.openflexo.foundation.wkf.FlexoPetriGraph; import org.openflexo.foundation.wkf.WKFObject; import org.openflexo.foundation.wkf.action.CreateExecutionPetriGraph; import org.openflexo.foundation.wkf.action.CreateNode; import org.openflexo.foundation.wkf.action.CreatePetriGraph; import org.openflexo.foundation.wkf.action.CreatePreCondition; import org.openflexo.foundation.wkf.node.AbstractActivityNode; import org.openflexo.foundation.wkf.node.AbstractNode; import org.openflexo.foundation.wkf.node.FatherNode; import org.openflexo.foundation.wkf.node.FlexoNode; import org.openflexo.foundation.wkf.node.OperationNode; import org.openflexo.foundation.wkf.node.SelfExecutableActivityNode; import org.openflexo.foundation.wkf.node.SelfExecutableNode; import org.openflexo.foundation.wkf.node.SelfExecutableOperationNode; import org.openflexo.icon.WKFIconLibrary; import org.openflexo.localization.FlexoLocalization; import org.openflexo.module.UserType; import org.openflexo.view.controller.ActionInitializer; import org.openflexo.view.controller.ControllerActionInitializer; import org.openflexo.view.controller.FlexoController; public class CreatePreconditionInitializer extends ActionInitializer<CreatePreCondition, FlexoNode, WKFObject> { private static final Logger logger = Logger.getLogger(ControllerActionInitializer.class.getPackage().getName()); CreatePreconditionInitializer(WKFControllerActionInitializer actionInitializer) { super(CreatePreCondition.actionType, actionInitializer); } @Override protected WKFControllerActionInitializer getControllerActionInitializer() { return (WKFControllerActionInitializer) super.getControllerActionInitializer(); } private class CreatePreConditionExecutionContext extends ExecutionContext { // Actions that may be embbeded in initializer protected CreatePetriGraph createPg = null; protected CreateExecutionPetriGraph createExecutionPetriGraph; protected CreateNode createBeginNodeAction = null; public CreatePreConditionExecutionContext(CreatePreCondition action) { super(action); } } @Override protected FlexoActionInitializer<CreatePreCondition> getDefaultInitializer() { return new FlexoActionInitializer<CreatePreCondition>() { @Override public boolean run(EventObject e, final CreatePreCondition action) { CreatePreConditionExecutionContext executionContext = new CreatePreConditionExecutionContext(action); action.setExecutionContext(executionContext); if ((action.getFocusedObject() instanceof FatherNode || action.getFocusedObject() instanceof SelfExecutableNode) && !(action.getFocusedObject() instanceof OperationNode && action.getFocusedObject().isBeginNode()) && !(action.getFocusedObject() instanceof OperationNode && action.getFocusedObject().isEndNode())) { FlexoPetriGraph pg = null; if (action.getFocusedObject() instanceof SelfExecutableNode) { pg = ((SelfExecutableNode) action.getFocusedObject()).getExecutionPetriGraph(); } else if (action.getFocusedObject() instanceof FatherNode) { pg = ((FatherNode) action.getFocusedObject()).getContainedPetriGraph(); } if (pg == null) { if (action.getFocusedObject() instanceof SelfExecutableNode) { executionContext.createExecutionPetriGraph = CreateExecutionPetriGraph.actionType.makeNewEmbeddedAction( action.getFocusedObject(), null, action); executionContext.createExecutionPetriGraph.doAction(); pg = executionContext.createExecutionPetriGraph.getNewPetriGraph(); if (!executionContext.createExecutionPetriGraph.hasActionExecutionSucceeded()) { return false; } pg = ((SelfExecutableNode) action.getFocusedObject()).getExecutionPetriGraph(); } else if (action.getFocusedObject() instanceof FatherNode) { pg = ((FatherNode) action.getFocusedObject()).getContainedPetriGraph(); executionContext.createPg = CreatePetriGraph.actionType.makeNewEmbeddedAction( (FatherNode) action.getFocusedObject(), null, action); executionContext.createPg.doAction(); pg = executionContext.createPg.getNewPetriGraph(); if (!executionContext.createPg.hasActionExecutionSucceeded()) { return false; } } } if (action.getAttachedBeginNode() == null && pg != null) { if (action.isForceNewCreation()) { String nodeNameProposal; if (action.getFocusedObject() instanceof AbstractActivityNode) { nodeNameProposal = pg.getProcess().findNextInitialName(FlexoLocalization.localizedForKey("begin_node"), (AbstractActivityNode) action.getFocusedObject()); } else if (action.getFocusedObject() instanceof OperationNode) { nodeNameProposal = pg.getProcess().findNextInitialName(FlexoLocalization.localizedForKey("begin_node"), (OperationNode) action.getFocusedObject()); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Unknown father node type: " + action.getFocusedObject().getClassNameKey()); } nodeNameProposal = FlexoLocalization.localizedForKey("begin_node"); } return createNewBeginNode(action, executionContext, nodeNameProposal); } Vector<FlexoNode> unboundBeginNodes = pg.getUnboundBeginNodes(); Vector<FlexoNode> alreadyBoundBeginNodes = pg.getBoundBeginNodes(); FlexoNode firstUnboundBeginNode = unboundBeginNodes.size() > 0 ? unboundBeginNodes.firstElement() : null; FlexoNode firstBoundBeginNode = alreadyBoundBeginNodes.size() > 0 ? alreadyBoundBeginNodes.firstElement() : null; boolean hasUnboundBeginNodes = unboundBeginNodes.size() > 0; boolean hasAlreadyBoundBeginNodes = alreadyBoundBeginNodes.size() > 0; if (unboundBeginNodes.size() != 1 || hasAlreadyBoundBeginNodes) { String CREATE_NEW_BEGIN_NODE = FlexoLocalization.localizedForKey("create_new_begin_node"); String CHOOSE_EXISTING_UNBOUND_BEGIN_NODE = FlexoLocalization .localizedForKey("choose_existing_and_unbound_begin_node"); String CHOOSE_EXISTING_ALREADY_BOUND_BEGIN_NODE = FlexoLocalization .localizedForKey("choose_existing_and_already_bound_begin_node"); Vector<String> availableChoices = new Vector<String>(); availableChoices.add(CREATE_NEW_BEGIN_NODE); if (hasUnboundBeginNodes) { availableChoices.add(CHOOSE_EXISTING_UNBOUND_BEGIN_NODE); } if (hasAlreadyBoundBeginNodes && action.allowsToSelectPreconditionOnly()) { availableChoices.add(CHOOSE_EXISTING_ALREADY_BOUND_BEGIN_NODE); } String[] choices = availableChoices.toArray(new String[availableChoices.size()]); RadioButtonListParameter<String> choiceParam = new RadioButtonListParameter<String>("choice", "choose_an_option", firstUnboundBeginNode != null ? CHOOSE_EXISTING_UNBOUND_BEGIN_NODE : firstBoundBeginNode != null && action.allowsToSelectPreconditionOnly() ? CHOOSE_EXISTING_ALREADY_BOUND_BEGIN_NODE : CREATE_NEW_BEGIN_NODE, choices); String nodeNameProposal; if (action.getFocusedObject() instanceof AbstractActivityNode) { nodeNameProposal = pg.getProcess().findNextInitialName(FlexoLocalization.localizedForKey("begin_node"), (AbstractActivityNode) action.getFocusedObject()); } else if (action.getFocusedObject() instanceof OperationNode) { nodeNameProposal = pg.getProcess().findNextInitialName(FlexoLocalization.localizedForKey("begin_node"), (OperationNode) action.getFocusedObject()); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Unknown father node type: " + action.getFocusedObject().getClassNameKey()); } nodeNameProposal = FlexoLocalization.localizedForKey("begin_node"); } TextFieldParameter newBeginNodeNameParam = new TextFieldParameter("newBeginNodeName", "new_begin_node_name", nodeNameProposal); newBeginNodeNameParam.setDepends("choice"); newBeginNodeNameParam.setConditional("choice=" + '"' + CREATE_NEW_BEGIN_NODE + '"'); NodeParameter unboundNodeParameter = new NodeParameter("unboundNode", "used_begin_node", firstUnboundBeginNode); unboundNodeParameter.setRootObject(action.getFocusedObject()); unboundNodeParameter.setNodeSelectingConditional(new NodeSelectingConditional() { @Override public boolean isSelectable(AbstractNode node) { return node instanceof FlexoNode && ((FlexoNode) node).isBeginNode() && ((FlexoNode) node).getParentPetriGraph() != null && ((FlexoNode) node).getParentPetriGraph().getContainer() == action.getFocusedObject() && ((FlexoNode) node).getAttachedPreCondition() == null; } }); unboundNodeParameter.setDepends("choice"); unboundNodeParameter.setConditional("choice=" + '"' + CHOOSE_EXISTING_UNBOUND_BEGIN_NODE + '"'); NodeParameter alreadyBoundNodeParameter = new NodeParameter("alreadyBoundNode", "used_begin_node", firstBoundBeginNode); alreadyBoundNodeParameter.setRootObject(action.getFocusedObject()); alreadyBoundNodeParameter.setNodeSelectingConditional(new NodeSelectingConditional() { @Override public boolean isSelectable(AbstractNode node) { return node instanceof FlexoNode && ((FlexoNode) node).isBeginNode() && ((FlexoNode) node).getParentPetriGraph() != null && ((FlexoNode) node).getParentPetriGraph().getContainer() == action.getFocusedObject() && ((FlexoNode) node).getAttachedPreCondition() != null; } }); alreadyBoundNodeParameter.setDepends("choice"); alreadyBoundNodeParameter.setConditional("choice=" + '"' + CHOOSE_EXISTING_ALREADY_BOUND_BEGIN_NODE + '"'); AskParametersDialog dialog = AskParametersDialog.createAskParametersDialog(getProject(), null, action.getLocalizedName(), FlexoLocalization.localizedForKey("what_would_you_like_to_do"), choiceParam, newBeginNodeNameParam, unboundNodeParameter, alreadyBoundNodeParameter); if (dialog.getStatus() == AskParametersDialog.VALIDATE) { if (choiceParam.getValue().equals(CHOOSE_EXISTING_UNBOUND_BEGIN_NODE)) { action.setAttachedBeginNode((FlexoNode) unboundNodeParameter.getValue()); } else if (choiceParam.getValue().equals(CHOOSE_EXISTING_ALREADY_BOUND_BEGIN_NODE) && alreadyBoundNodeParameter.getValue() != null) { // In this case the pre-condition is already existing, just select it action.setSelectedPreCondition(((FlexoNode) alreadyBoundNodeParameter.getValue()) .getAttachedPreCondition()); } else if (choiceParam.getValue().equals(CREATE_NEW_BEGIN_NODE)) { return createNewBeginNode(action, executionContext, newBeginNodeNameParam.getValue()); } return true; } else { return false; } } else { action.setAttachedBeginNode(unboundBeginNodes.firstElement()); return true; } } } return true; } public boolean createNewBeginNode(final CreatePreCondition action, CreatePreConditionExecutionContext executionContext, String name) { if (action.getFocusedObject() instanceof AbstractActivityNode || action.getFocusedObject() instanceof OperationNode || action.getFocusedObject() instanceof SelfExecutableNode) { if (action.getFocusedObject() instanceof SelfExecutableNode) { if (action.getFocusedObject() instanceof SelfExecutableActivityNode) { executionContext.createBeginNodeAction = CreateNode.createActivityBeginNode.makeNewEmbeddedAction( action.getFocusedObject(), null, action); } else if (action.getFocusedObject() instanceof SelfExecutableOperationNode) { executionContext.createBeginNodeAction = CreateNode.createOperationBeginNode.makeNewEmbeddedAction( action.getFocusedObject(), null, action); } else { executionContext.createBeginNodeAction = CreateNode.createActionBeginNode.makeNewEmbeddedAction( action.getFocusedObject(), null, action); } } else { if (action.getFocusedObject() instanceof AbstractActivityNode) { executionContext.createBeginNodeAction = CreateNode.createOperationBeginNode.makeNewEmbeddedAction( action.getFocusedObject(), null, action); } else { executionContext.createBeginNodeAction = CreateNode.createActionBeginNode.makeNewEmbeddedAction( action.getFocusedObject(), null, action); } } executionContext.createBeginNodeAction.setNewNodeName(name); executionContext.createBeginNodeAction.doAction(); if (!executionContext.createBeginNodeAction.hasActionExecutionSucceeded()) { if (executionContext.createPg != null) { executionContext.createPg.undoAction(); } return false; } action.setAttachedBeginNode((FlexoNode) executionContext.createBeginNodeAction.getNewNode()); } return true; } }; } @Override protected FlexoActionFinalizer<CreatePreCondition> getDefaultFinalizer() { return new FlexoActionFinalizer<CreatePreCondition>() { @Override public boolean run(EventObject e, CreatePreCondition action) { if (!action.isEmbedded()) { getControllerActionInitializer().getWKFController().getSelectionManager() .setSelectedObject(action.getNewPreCondition()); } return true; } }; } @Override protected FlexoActionUndoFinalizer<CreatePreCondition> getDefaultUndoFinalizer() { return new FlexoActionUndoFinalizer<CreatePreCondition>() { @Override public boolean run(EventObject e, CreatePreCondition action) { CreatePreConditionExecutionContext executionContext = (CreatePreConditionExecutionContext) action.getExecutionContext(); if (executionContext.createBeginNodeAction != null) { executionContext.createBeginNodeAction.undoAction(); } if (executionContext.createPg != null) { executionContext.createPg.undoAction(); } if (executionContext.createExecutionPetriGraph != null) { executionContext.createExecutionPetriGraph.undoAction(); } return true; } }; } @Override protected FlexoActionRedoInitializer<CreatePreCondition> getDefaultRedoInitializer() { return new FlexoActionRedoInitializer<CreatePreCondition>() { @Override public boolean run(EventObject e, CreatePreCondition action) { CreatePreConditionExecutionContext executionContext = (CreatePreConditionExecutionContext) action.getExecutionContext(); if (executionContext.createPg != null) { executionContext.createPg.redoAction(); } if (executionContext.createExecutionPetriGraph != null) { executionContext.createExecutionPetriGraph.redoAction(); } if (executionContext.createBeginNodeAction != null) { executionContext.createBeginNodeAction.redoAction(); } return true; } }; } @Override protected FlexoActionVisibleCondition<CreatePreCondition, FlexoNode, WKFObject> getVisibleCondition() { return new FlexoActionVisibleCondition<CreatePreCondition, FlexoNode, WKFObject>() { @Override public boolean isVisible(FlexoActionType<CreatePreCondition, FlexoNode, WKFObject> actionType, FlexoNode object, Vector<WKFObject> globalSelection, FlexoEditor editor) { return UserType.isDevelopperRelease() || UserType.isMaintainerRelease(); } }; } @Override protected FlexoExceptionHandler<CreatePreCondition> getDefaultExceptionHandler() { return new FlexoExceptionHandler<CreatePreCondition>() { @Override public boolean handleException(FlexoException exception, CreatePreCondition action) { if (exception instanceof InvalidArgumentException) { FlexoController.notify(exception.getLocalizedMessage()); return true; } return false; } }; } @Override protected Icon getEnabledIcon() { return WKFIconLibrary.PRECONDITION_ICON; } }