/* * (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; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.AttributeDataModification; import org.openflexo.foundation.Inspectors; import org.openflexo.foundation.utils.FlexoIndexManager; import org.openflexo.foundation.utils.Sortable; import org.openflexo.foundation.validation.Validable; import org.openflexo.foundation.wkf.dm.ChildrenOrderChanged; import org.openflexo.foundation.wkf.dm.ProcessAddedToFolder; import org.openflexo.foundation.wkf.dm.ProcessRemovedFromFolder; import org.openflexo.foundation.xml.FlexoWorkflowBuilder; import org.openflexo.inspector.InspectableObject; import org.openflexo.toolbox.EmptyVector; /** * A Process folder is a set of process nodes that simply aggregates some process into a logical category * * @author guillaume */ public class ProcessFolder extends FlexoFolderContainerNode implements InspectableObject, Sortable { private static final Logger logger = Logger.getLogger(ProcessFolder.class.getPackage().getName()); private FlexoFolderContainerNode parent; private Vector<FlexoProcessNode> processes; private int index = -1; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== public ProcessFolder(FlexoWorkflowBuilder builder) { this(builder.workflow); initializeDeserialization(builder); } public ProcessFolder(FlexoWorkflow workflow) { super(workflow.getProject(), workflow); processes = new Vector<FlexoProcessNode>(); } public ProcessFolder(FlexoWorkflow workflow, FlexoFolderContainerNode parent) { this(workflow); parent.addToFolders(this); } @Override public void delete() { super.delete(); for (FlexoProcessNode node : new Vector<FlexoProcessNode>(getProcesses())) { if (getParent() instanceof ProcessFolder) { ((ProcessFolder) getParent()).addToProcesses(node); } else { node.removeParentFolder(this); } } setParent(null); deleteObservers(); } public FlexoFolderContainerNode getParent() { return parent; } public void setParent(FlexoFolderContainerNode parent) { if (this.parent == parent) { return; } if (this.parent != null) { this.parent.removeFromFolders(this); } this.parent = parent; if (this.parent != null) { this.parent.addToFolders(this); } } @Override public String getInspectorName() { return Inspectors.WKF.PROCESS_FOLDER_INSPECTOR; } @Override public String getFullyQualifiedName() { return "PROCESS_FOLDER." + getName(); } public Vector<FlexoProcessNode> getProcesses() { return processes; } public void setProcesses(Vector<FlexoProcessNode> processes) { this.processes = processes; } public void addToProcesses(FlexoProcessNode process) { if (!processes.contains(process) && (process.getFatherProcessNode() == getProcessNode() || isDeserializing())) { if (process.getParentFolder() != null) { process.getParentFolder().removeFromProcesses(process); } processes.add(process); process.addParentFolder(this); if (!isDeserializing()) { setChanged(); notifyObservers(new ProcessAddedToFolder(process)); if (getProcessNode() != null) { getProcessNode().setChanged(); getProcessNode().notifyObservers(new ProcessAddedToFolder(process)); } else { getWorkflow().setChanged(); getWorkflow().notifyObservers(new ProcessAddedToFolder(process)); } } } } public void removeFromProcesses(FlexoProcessNode process) { if (processes.contains(process)) { processes.remove(process); process.removeParentFolder(this); if (!isDeserializing()) { setChanged(); notifyObservers(new ProcessRemovedFromFolder(process)); if (getProcessNode() != null) { getProcessNode().setChanged(); getProcessNode().notifyObservers(new ProcessRemovedFromFolder(process)); } else { getWorkflow().setChanged(); getWorkflow().notifyObservers(new ProcessRemovedFromFolder(process)); } } } } @Override public Vector<Validable> getAllEmbeddedValidableObjects() { return EmptyVector.EMPTY_VECTOR(Validable.class); } @Override public String getClassNameKey() { return "process_folder"; } @Override public int getIndex() { if (isBeingCloned()) { return -1; } if (index == -1 && getCollection() != null) { index = getCollection().length; FlexoIndexManager.reIndexObjectOfArray(getCollection()); } return index; } @Override public 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 index; } @Override public void setIndexValue(int index) { if (this.index == index) { return; } int old = this.index; this.index = index; setChanged(); notifyAttributeModification("index", old, index); if (!isDeserializing() && !isCreatedByCloning()) { getParent().setChanged(); getParent().notifyObservers(new ChildrenOrderChanged()); } } /** * Overrides getCollection * * @see org.openflexo.foundation.utils.Sortable#getCollection() */ @Override public ProcessFolder[] getCollection() { return getParent().getFolders().toArray(new ProcessFolder[0]); } public void setIndexForProcess(int index, FlexoProcessNode node) { if (processes.indexOf(node) > -1) { index = Math.min(processes.size() - 1, index); if (index < 0) { index = 0; } processes.remove(node); processes.insertElementAt(node, index); setChanged(); notifyObservers(new ChildrenOrderChanged()); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Trying to set index for a process which is not in this folder"); } } } @Override public FlexoProcessNode getProcessNode() { if (getParent() instanceof ProcessFolder) { return getParent().getProcessNode(); } if (getParent() instanceof FlexoProcessNode) { return (FlexoProcessNode) getParent(); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("No parent for process folder " + getName()); } return null; } } public Vector<FlexoProcessNode> getAllDirectSubProcessNodes() { Vector<FlexoProcessNode> nodes = new Vector<FlexoProcessNode>(processes); for (ProcessFolder folder : getFolders()) { nodes.addAll(folder.getAllDirectSubProcessNodes()); } return nodes; } public boolean isAcceptableParentFolder(ProcessFolder parent) { if (parent == null || parent.getProcessNode() == null) { return false; } ProcessFolder current = parent; while (current != null) { if (current == this) { return false; } if (current.getParent() instanceof ProcessFolder) { current = (ProcessFolder) current.getParent(); } else { break; } } if (getProcessNode() != parent.getProcessNode()) { for (FlexoProcessNode node : getAllDirectSubProcessNodes()) { if (node.getProcess().isAcceptableAsParentProcess(parent.getProcessNode().getProcess())) { return false; } } } return true; } }