/*
* (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;
/*
* FlexoProcess.java
* Project WorkflowEditor
*
* Created by benoit on Mar 3, 2004
*/
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import javax.naming.InvalidNameException;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;
import org.openflexo.foundation.AttributeDataModification;
import org.openflexo.foundation.CodeType;
import org.openflexo.foundation.FlexoException;
import org.openflexo.foundation.FlexoImportableObject;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.NameChanged;
import org.openflexo.foundation.TargetType;
import org.openflexo.foundation.action.FlexoActionizer;
import org.openflexo.foundation.bindings.Bindable;
import org.openflexo.foundation.bindings.BindingModel;
import org.openflexo.foundation.bindings.BindingVariable;
import org.openflexo.foundation.dm.AutoGeneratedProcessBusinessDataDMEntity;
import org.openflexo.foundation.dm.DMEntity;
import org.openflexo.foundation.dm.DMModel;
import org.openflexo.foundation.dm.DMObject;
import org.openflexo.foundation.dm.DMProperty;
import org.openflexo.foundation.dm.DMPropertyImplementationType;
import org.openflexo.foundation.dm.DMType;
import org.openflexo.foundation.dm.DuplicatePropertyNameException;
import org.openflexo.foundation.dm.ProcessDMEntity;
import org.openflexo.foundation.dm.ProcessInstanceRepository;
import org.openflexo.foundation.dm.eo.DMEOAttribute;
import org.openflexo.foundation.dm.eo.DMEOEntity;
import org.openflexo.foundation.dm.eo.EOAccessException;
import org.openflexo.foundation.gen.FlexoProcessImageBuilder;
import org.openflexo.foundation.help.ApplicationHelpEntryPoint;
import org.openflexo.foundation.ie.ComponentInstance;
import org.openflexo.foundation.ie.IEWOComponent;
import org.openflexo.foundation.ie.OperationComponentInstance;
import org.openflexo.foundation.ie.TabComponentInstance;
import org.openflexo.foundation.ie.cl.TabComponentDefinition;
import org.openflexo.foundation.ie.dm.ComponentDeleteRequest;
import org.openflexo.foundation.ie.dm.ComponentDeleted;
import org.openflexo.foundation.ie.dm.ComponentNameChanged;
import org.openflexo.foundation.ie.util.TextFieldType;
import org.openflexo.foundation.ie.widget.IECheckBoxWidget;
import org.openflexo.foundation.ie.widget.IEDropDownWidget;
import org.openflexo.foundation.ie.widget.IEHyperlinkWidget;
import org.openflexo.foundation.ie.widget.IERadioButtonWidget;
import org.openflexo.foundation.ie.widget.IEStringWidget;
import org.openflexo.foundation.ie.widget.IETabWidget;
import org.openflexo.foundation.ie.widget.IETextAreaWidget;
import org.openflexo.foundation.ie.widget.IETextFieldWidget;
import org.openflexo.foundation.ie.widget.IEWidget;
import org.openflexo.foundation.ie.widget.IEWidgetWithValueList;
import org.openflexo.foundation.ie.widget.IEWysiwygWidget;
import org.openflexo.foundation.param.DMEntityParameter;
import org.openflexo.foundation.param.ParameterDefinition;
import org.openflexo.foundation.param.TextFieldParameter;
import org.openflexo.foundation.rm.DuplicateResourceException;
import org.openflexo.foundation.rm.FlexoProcessResource;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.FlexoResource;
import org.openflexo.foundation.rm.FlexoWorkflowResource;
import org.openflexo.foundation.rm.FlexoXMLStorageResource;
import org.openflexo.foundation.rm.InvalidFileNameException;
import org.openflexo.foundation.rm.ProjectRestructuration;
import org.openflexo.foundation.rm.RMNotification;
import org.openflexo.foundation.rm.SaveResourceException;
import org.openflexo.foundation.rm.XMLStorageResourceData;
import org.openflexo.foundation.stats.ProcessStatistics;
import org.openflexo.foundation.utils.FlexoCSS;
import org.openflexo.foundation.utils.FlexoIndexManager;
import org.openflexo.foundation.utils.FlexoModelObjectReference;
import org.openflexo.foundation.utils.FlexoModelObjectReference.ReferenceOwner;
import org.openflexo.foundation.utils.FlexoProjectFile;
import org.openflexo.foundation.validation.FixProposal;
import org.openflexo.foundation.validation.ParameteredFixProposal;
import org.openflexo.foundation.validation.Validable;
import org.openflexo.foundation.validation.ValidationError;
import org.openflexo.foundation.validation.ValidationIssue;
import org.openflexo.foundation.validation.ValidationModel;
import org.openflexo.foundation.validation.ValidationReport;
import org.openflexo.foundation.validation.ValidationRule;
import org.openflexo.foundation.validation.ValidationWarning;
import org.openflexo.foundation.wkf.MetricsValue.MetricsValueOwner;
import org.openflexo.foundation.wkf.action.AddProcessMetricsValue;
import org.openflexo.foundation.wkf.action.AddStatus;
import org.openflexo.foundation.wkf.action.DeleteMetricsValue;
import org.openflexo.foundation.wkf.action.WKFDelete;
import org.openflexo.foundation.wkf.dm.AssociationInserted;
import org.openflexo.foundation.wkf.dm.PostInserted;
import org.openflexo.foundation.wkf.dm.ProcessInserted;
import org.openflexo.foundation.wkf.dm.ProcessRemoved;
import org.openflexo.foundation.wkf.dm.ServiceInterfaceInserted;
import org.openflexo.foundation.wkf.dm.ServiceInterfaceRemoved;
import org.openflexo.foundation.wkf.dm.WKFAttributeDataModification;
import org.openflexo.foundation.wkf.edge.FlexoPostCondition;
import org.openflexo.foundation.wkf.edge.InternalMessageInEdge;
import org.openflexo.foundation.wkf.edge.InternalMessageOutEdge;
import org.openflexo.foundation.wkf.edge.InvalidEdgeException;
import org.openflexo.foundation.wkf.edge.MessageEdge;
import org.openflexo.foundation.wkf.edge.WKFAssociation;
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.LOOPOperator;
import org.openflexo.foundation.wkf.node.OperationNode;
import org.openflexo.foundation.wkf.node.OperatorNode;
import org.openflexo.foundation.wkf.node.PetriGraphNode;
import org.openflexo.foundation.wkf.node.SelfExecutableNode;
import org.openflexo.foundation.wkf.node.SubProcessNode;
import org.openflexo.foundation.wkf.node.WKFNode;
import org.openflexo.foundation.wkf.ws.DefaultServiceInterface;
import org.openflexo.foundation.wkf.ws.DeletePort;
import org.openflexo.foundation.wkf.ws.FlexoPort;
import org.openflexo.foundation.wkf.ws.FlexoPortMap;
import org.openflexo.foundation.wkf.ws.NewPort;
import org.openflexo.foundation.wkf.ws.OutPort;
import org.openflexo.foundation.wkf.ws.PortRegistery;
import org.openflexo.foundation.wkf.ws.ServiceInterface;
import org.openflexo.foundation.ws.DuplicateWSObjectException;
import org.openflexo.foundation.xml.FlexoProcessBuilder;
import org.openflexo.inspector.InspectableObject;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.toolbox.EmptyVector;
import org.openflexo.toolbox.FileUtils;
import org.openflexo.toolbox.JavaUtils;
import org.openflexo.toolbox.ProgrammingLanguage;
import org.openflexo.toolbox.ReservedKeyword;
import org.openflexo.toolbox.ToolBox;
import org.openflexo.ws.client.PPMWebService.PPMObject;
import org.openflexo.ws.client.PPMWebService.PPMProcess;
import org.openflexo.xmlcode.XMLMapping;
/**
* TODO: rewrite this, since it's no more up-to-date ! A FlexoProcess contains all the data needed by the <I>workflow processor</I> to
* execute an instance of a process. In other words, a FlexoProcess contains all the information about the structure of a single workflow.<BR>
* <B>Note : </B> The <I>process instance</I> is a running instance of a FlexoProcess. The <I>workflow processor</I> is a processor that can
* run a <I>process instance</I>, so one of the most important capabilities of a <I>workflow processor</I> is the interpretation of a
* FlexoProcess.<BR>
* A FlexoProcess can be part of a FlexoWorkflow. In this case, there will be some links between the different flexo process inside the same
* workflow. For instance, a particular node of this process can be able to start one or more process instance of another process of the
* same workflow. The dual case is that the end of one or more process instances of another process can have an effect on this process.
*
* @author benoit, sylvain
*/
public final class FlexoProcess extends WKFObject implements FlexoImportableObject, ApplicationHelpEntryPoint, XMLStorageResourceData,
InspectableObject, Bindable, ExecutableWorkflowElement, MetricsValueOwner, LevelledObject, ReferenceOwner {
public static final String VISIBLE_ROLES = "visibleRoles";
static final Logger logger = Logger.getLogger(FlexoProcess.class.getPackage().getName());
public static final String ACTIVITY_CONTEXT = "ACTIVITY";
public static final String OPERATION_CONTEXT = "OPERATION";
public static final String ACTION_CONTEXT = "ACTION";
public static final String EXECUTION_CONTEXT = "EXECUTION";
private FlexoProcessResource _resource;
private String _name;
private StatusList _statusList;
private Vector<FlexoProcess> _subProcesses;
private FlexoCSS cssSheet;
private transient FlexoProcessNode _processNode;
private ActivityPetriGraph _petriGraph;
private boolean _isWebService;
private PortRegistery _registery;
private Vector<ServiceInterface> _serviceInterfaces;
private ProcessBindingModel _bindingModel;
private String acronym;
private Vector<SubProcessNode> _subProcessNodes;
private Vector<AbstractNode> allAbstractNodes = null;
private Vector<WKFNode> allNodes = null;
private Date lastUpdate;
/* Key: String, Value: FlexoModelObject */
private BidiMap nameForNodeMap = new DualHashBidiMap();
// Not Serialized
private DefaultServiceInterface _portRegistryInterface;
private transient ProcessStatistics statistics;
public static FlexoActionizer<AddStatus, WKFObject, WKFObject> addStatusActionizer;
public static FlexoActionizer<WKFDelete, WKFObject, WKFObject> deleteActionizer;
private Vector<MetricsValue> metricsValues;
private Vector<FlexoModelObjectReference<Role>> visibleRoles;
public static FlexoActionizer<AddProcessMetricsValue, FlexoProcess, WKFObject> addMetricsActionizer;
public static FlexoActionizer<DeleteMetricsValue, MetricsValue, MetricsValue> deleteMetricsActionizer;
// ==========================================================================
// ============================= Constructor
// ================================
// ==========================================================================
public FlexoProcess(FlexoProcessBuilder builder) {
this(builder.getProject());
builder.process = this;
_resource = builder.resource;
_name = new String(builder.defaultProcessName);
initializeDeserialization(builder);
}
private FlexoProcess(FlexoProject project) {
super(project);
setProcess(this);
_subProcessNodes = new Vector<SubProcessNode>();
_serviceInterfaces = new Vector<ServiceInterface>();
metricsValues = new Vector<MetricsValue>();
visibleRoles = new Vector<FlexoModelObjectReference<Role>>();
}
/**
* Creates a new FlexoProcess with default values (public API outside XML serialization)
*
* @param workflow
* @throws DuplicateResourceException
*/
public FlexoProcess(String processName, FlexoWorkflow workflow) throws DuplicateResourceException {
this(workflow.getProject());
_name = processName;
}
/**
* Creates and returns a newly created root process
*
* @return a newly created workflow
* @throws InvalidFileNameException
*/
public static FlexoProcess createNewRootProcess(FlexoWorkflow workflow) {
if (workflow.getRootProcess() == null) {
try {
FlexoProcess returned = createNewProcess(workflow, null, workflow.getWorkflowName(), true);
workflow.setRootProcess(returned);
return returned;
} catch (DuplicateResourceException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Cannot create root process !");
}
return null;
} catch (InvalidFileNameException e) {
e.printStackTrace();
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Cannot create root process because " + workflow.getWorkflowName() + " is not a valid file name");
}
return null;
}
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Cannot create root process: a root process is already declared");
}
return null;
}
}
/**
* Creates and returns a newly created process
*
* @param isRoot
* TODO
*
* @return a newly created workflow
* @throws DuplicateResourceException
* @throws InvalidFileNameException
*/
// TODO: Move that in a FlexoAction !!!!
public static FlexoProcess createNewProcess(FlexoWorkflow workflow, FlexoProcess parentProcess, String processName, boolean isRoot)
throws DuplicateResourceException, InvalidFileNameException {
if (processWithSimilarNameExists(workflow, null, ToolBox.getJavaName(processName))) {
throw new InvalidFileNameException("A process with similar name exists");
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("BEGIN createNewProcess()");
}
FlexoProject project = workflow.getProject();
if (workflow.getLocalFlexoProcessWithName(processName) != null) {
throw new DuplicateResourceException("PROCESS." + processName);
}
FlexoProcess newProcess = new FlexoProcess(processName, workflow);
ProcessDMEntity e = project.getDataModel().getProcessInstanceRepository().getProcessDMEntity(newProcess);
if (e != null && logger.isLoggable(Level.SEVERE)) {
logger.severe("Dm entity for process " + processName + "already exists.");
}
FlexoProcessResource processRes = createProcessResource(parentProcess, processName, workflow, newProcess, false);
project.registerResource(processRes);
if (isRoot) {
workflow.setRootProcess(newProcess);
}
initProcessObjects(newProcess);
if (logger.isLoggable(Level.FINE)) {
logger.fine("END createNewProcess()");
}
return newProcess;
}
/**
* @param process
*/
public static void initProcessObjects(FlexoProcess process) {
// TODO: Use FlexoActions !!!
process.isImported = false;
process.createsProcessDMEntityIfRequired();
process.createsAutoGeneratedProcessBusinessDataDMEntityIfRequired();
process.updateMetricsValues();
process.setStatusList(new StatusList(process, true));
ActivityPetriGraph.createNewActivityPetriGraph(process);
NewPort _newPort = new NewPort(process, process.findNextInitialName("NEW_PORT", NewPort.getDefaultInitialName()));
_newPort.setIndexValue(0);
process.getPortRegistery().addToNewPorts(_newPort);
DeletePort _deletePort = new DeletePort(process, process.findNextInitialName("DELETE_PORT", DeletePort.getDefaultInitialName()));
_deletePort.setIndexValue(1);
process.getPortRegistery().addToDeletePorts(_deletePort);
OutPort _processTerminated = new OutPort(process,
process.findNextInitialName("PROCESS_TERMINATED", OutPort.getDefaultInitialName()));
_processTerminated.setIndexValue(2);
process.getPortRegistery().addToOutPorts(_processTerminated);
// ActivityNode begin = (ActivityNode) process.getActivityPetriGraph()
// .getAllBeginNodes().firstElement();
// ActivityNode end = (ActivityNode) process.getActivityPetriGraph()
// .getAllEndNodes().firstElement();
// new OperationPetriGraph(begin);
// new OperationPetriGraph(end);
EventNode begin = process.getActivityPetriGraph().getAllEventNodes().firstElement();
EventNode end = process.getActivityPetriGraph().getAllEventNodes().lastElement();
// FlexoPreCondition beginCondition = new FlexoPreCondition(begin, begin
// .getOperationPetriGraph().getAllBeginNodes().firstElement());
// FlexoPreCondition endCondition = new FlexoPreCondition(end, end
// .getOperationPetriGraph().getAllBeginNodes().firstElement());
try {
FlexoPostCondition<?, ?> newBeginPostCondition = new InternalMessageInEdge(_newPort, begin, process);
newBeginPostCondition.updateMetricsValues();
_newPort.addToOutgoingPostConditions(newBeginPostCondition);
} catch (InvalidEdgeException e1) {
e1.printStackTrace();
}
try {
FlexoPostCondition<?, ?> deleteEndPostCondition = new InternalMessageInEdge(_deletePort, end, process);
deleteEndPostCondition.updateMetricsValues();
_deletePort.addToOutgoingPostConditions(deleteEndPostCondition);
} catch (InvalidEdgeException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
FlexoPostCondition<?, ?> processTerminatedPostCondition = new InternalMessageOutEdge(end, _processTerminated);
processTerminatedPostCondition.updateMetricsValues();
processTerminatedPostCondition.setName(FlexoLocalization.localizedForKey("process_terminated"));
end.addToOutgoingPostConditions(processTerminatedPostCondition);
} catch (InvalidEdgeException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
process.getPortRegistery().setIsVisible(false);
}
/**
* @param workflow
* @param parentProcess
* @param processName
* @param project
* @param processResFile
* @param newProcess
* @return
* @throws InvalidFileNameException
*/
private static FlexoProcessResource createProcessResource(FlexoProcess parentProcess, String processName, FlexoWorkflow workflow,
FlexoProcess newProcess, boolean isImported) throws InvalidFileNameException {
FlexoProject project = workflow.getProject();
FlexoWorkflowResource workflowRes = workflow.getFlexoResource();
File processFile = ProjectRestructuration.getExpectedProcessFile(project, processName);
FlexoProjectFile processResFile = new FlexoProjectFile(processFile, project);
if (!processResFile.nameIsValid()) {
processResFile.fixName();
}
FlexoProcessNode newProcessNode = new FlexoProcessNode(processName, newProcess, workflow);
if (parentProcess == null) {
if (isImported) {
workflow.addToImportedRootNodeProcesses(newProcessNode);
} else {
workflow.addToTopLevelNodeProcesses(newProcessNode);
}
} else {
if (isImported && !parentProcess.isImported()) {
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Trying to add an imported process to an non-imported process!");
}
} else if (!isImported && parentProcess.isImported()) {
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Trying to add an non-imported process to an imported process!");
}
}
parentProcess.addToSubProcesses(newProcess);
// parentProcess.getProcessNode().addToSubProcesses(newProcessNode);
}
FlexoProcessResource processRes = null;
try {
processRes = new FlexoProcessResource(project, newProcess, workflowRes, processResFile);
} catch (InvalidFileNameException e1) {
boolean ok = false;
for (int i = 0; i < 10000 && !ok; i++) {
try {
processFile = ProjectRestructuration.getExpectedProcessFile(project, FileUtils.getValidFileName(processName) + i);
processResFile = new FlexoProjectFile(processFile, project);
processRes = new FlexoProcessResource(project, newProcess, workflowRes, processResFile);
ok = true;
} catch (InvalidFileNameException e2) {
}
}
if (!ok) {
processFile = ProjectRestructuration.getExpectedProcessFile(project,
FileUtils.getValidFileName(processName) + newProcess.getFlexoID());
processResFile = new FlexoProjectFile(processFile, project);
processResFile.setProject(project);
processRes = new FlexoProcessResource(project, newProcess, workflowRes, processResFile);
}
}
if (processRes == null) {
throw new InvalidFileNameException(processResFile.getRelativePath());
}
return processRes;
}
public static FlexoProcess createImportedProcessFromProcess(FlexoWorkflow workflow, PPMProcess process)
throws InvalidFileNameException, DuplicateResourceException {
FlexoProject project = workflow.getProject();
FlexoProcess newFIP = workflow.getRecursivelyImportedProcessWithURI(process.getUri());
FlexoProcess parentProcess = null;
if (process.getParentProcess() != null) {
parentProcess = workflow.getRecursivelyImportedProcessWithURI(process.getParentProcess().getUri());
if (parentProcess == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find parent process: " + process.getParentProcess().getName());
}
}
}
if (newFIP != null) {
if (parentProcess != null) {
parentProcess.getProcessNode().addToSubProcesses(newFIP.getProcessNode());
}
try {
newFIP.updateFromObject(process);
} catch (Exception e) {
e.printStackTrace();
}
return newFIP;
}
FlexoProcess fip = new FlexoProcess(workflow.getProject());
fip.isImported = true;
try {
fip.updateFromObject(process);
} catch (Exception e) {
// Should not happen for imported processes
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("setName threw an exception for imported FlexoProcess!!!");
}
e.printStackTrace();
}
FlexoProcessResource resource = createProcessResource(parentProcess, process.getName(), workflow, fip, true);
String name = resource.getName();
if (project.resourceForKey(resource.getResourceType(), name) != null) {
name = name + "FromServer";
}
int attempt = 1;
String base = name;
while (project.resourceForKey(resource.getResourceType(), name) != null) {
name = base + "_" + String.valueOf(attempt);
attempt++;
}
if (!resource.getName().equals(name)) {
resource.setName(name);
}
project.registerResource(resource);
fip.setFlexoResource(resource);
if (process.getSubProcesses() != null) {
for (int i = 0; i < process.getSubProcesses().length; i++) {
PPMProcess sub = process.getSubProcesses()[i];
createImportedProcessFromProcess(workflow, sub);
}
}
return fip;
}
// Temporary flag to prevent unuseful code from being executed.
private boolean isImported = false;
@Override
public boolean isImported() {
if (getProcessNode() != null) {
return getProcessNode().isImported();
}
return isImported;
}
@Override
public Class<? extends PPMObject> getEquivalentPPMClass() {
return PPMProcess.class;
}
public void updateFromObject(PPMProcess process) throws Exception {
super.updateFromObject(process);
}
public PPMProcess getEquivalentPPMProcess() {
return getEquivalentPPMProcess(true);
}
public PPMProcess getEquivalentPPMProcess(boolean includeChildren) {
PPMProcess process = new PPMProcess();
copyObjectAttributesInto(process);
if (includeChildren) {
int i = 0;
PPMProcess[] subs = new PPMProcess[getSubProcesses().size()];
for (FlexoProcess sub : getSubProcesses()) {
subs[i] = sub.getEquivalentPPMProcess(includeChildren);
i++;
}
process.setSubProcesses(subs);
}
return process;
}
public boolean isEquivalentTo(PPMProcess p) {
return isEquivalentTo(p, true);
}
public boolean isEquivalentTo(PPMProcess p, boolean compareChildren) {
if (!super.isEquivalentTo(p)) {
return false;
}
/*
* if (getParentProcess()==null && p.getParentProcess()!=null) return false; else if(getParentProcess()!=null &&
* p.getParentProcess()==null) return false; else if (getParentProcess()!=null && p.getParentProcess()!=null &&
* !(getParentProcess().getURI().equals(p.getParentProcess().getUri()))) { return false; }
*/
if (compareChildren) {
boolean ok = getSubProcesses().size() != 0 && p.getSubProcesses() != null
&& p.getSubProcesses().length == getSubProcesses().size() || getSubProcesses().size() == 0
&& (p.getSubProcesses() == null || p.getSubProcesses().length == 0);
for (int i = 0; ok && i < getSubProcesses().size(); i++) {
FlexoProcess fip = getSubProcesses().get(i);
if (p.getSubProcesses() == null || p.getSubProcesses().length <= i) {
ok = false;
} else {
ok &= fip.isEquivalentTo(p.getSubProcesses()[i], compareChildren);
}
ok &= fip.getParentProcess() == this;
}
if (!ok) {
return false;
}
}
return true;
}
@Override
public void setIsDeletedOnServer(boolean isDeletedOnServer) {
super.setIsDeletedOnServer(isDeletedOnServer);
for (FlexoProcess sub : getSubProcesses()) {
sub.setIsDeletedOnServer(isDeletedOnServer);
}
}
// ==========================================================================
// ===================== Resource managing
// ==================================
// ==========================================================================
@Override
public FlexoProcessResource getFlexoResource() {
return _resource;
}
/**
* Overrides getXMLMapping
*
* @see org.openflexo.foundation.wkf.WKFObject#getXMLMapping()
*/
@Override
public XMLMapping getXMLMapping() {
return getProject().getXmlMappings().getWKFMapping();
}
@Override
public FlexoXMLStorageResource getFlexoXMLFileResource() {
return _resource;
}
@Override
public void setFlexoResource(FlexoResource resource) {
_resource = (FlexoProcessResource) resource;
}
/**
* Save this object using ResourceManager scheme
*
* Overrides
*
* @see org.openflexo.foundation.rm.FlexoResourceData#save()
* @see org.openflexo.foundation.rm.FlexoResourceData#save()
*/
@Override
public void save() throws SaveResourceException {
_resource.saveResourceData();
}
public void clearCachedObjects() {
allAbstractNodes = null;
allNodes = null;
}
/**
* Implements
*
* @see org.openflexo.foundation.rm.FlexoResourceData#receiveRMNotification(org.openflexo.foundation.rm.RMNotification) Receive a
* notification that has been propagated by the ResourceManager scheme and coming from a modification on an other resource
*
* Handles ComponentNameChanged notifications
*
* @see org.openflexo.foundation.rm.FlexoResourceData#receiveRMNotification(org.openflexo.foundation.rm.RMNotification)
*/
@Override
public void receiveRMNotification(RMNotification aNotification) {
if (aNotification instanceof ComponentNameChanged) {
ComponentNameChanged notification = (ComponentNameChanged) aNotification;
for (OperationNode operation : getAllEmbeddedOperationNodes()) {
if (operation.getComponentInstance() != null) {
OperationComponentInstance ci = operation.getComponentInstance();
if (ci.getComponentName().equals(notification.oldValue())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Process " + getName() + " Updating component instance " + notification.component.getName()
+ " for " + operation.getName());
}
ci.notifyComponentNameChanged(notification.component);
}
}
if (operation.getTabOperationComponentInstance() != null) {
TabComponentInstance ci = operation.getTabOperationComponentInstance();
if (ci.getComponentName().equals(notification.oldValue())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Process " + getName() + " Updating tab component instance " + notification.component.getName()
+ " for " + operation.getName());
}
ci.notifyComponentNameChanged(notification.component);
}
}
}
for (ActionNode action : getAllEmbeddedActionNodes()) {
if (action.getTabActionComponentInstance() != null) {
TabComponentInstance ci = action.getTabActionComponentInstance();
if (ci.getComponentName().equals(notification.oldValue())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Process " + getName() + " Updating component instance " + notification.component.getName()
+ " for " + action.getName());
}
ci.notifyComponentNameChanged(notification.component);
}
}
}
}
if (aNotification instanceof ComponentDeleteRequest) {
ComponentDeleteRequest notification = (ComponentDeleteRequest) aNotification;
for (Enumeration<OperationNode> en = getAllEmbeddedOperationNodes().elements(); en.hasMoreElements();) {
OperationNode node = en.nextElement();
if (node.getComponentInstance() != null) {
OperationComponentInstance ci = node.getComponentInstance();
if (ci.getComponentName().equals(notification.component.getComponentName())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Receive a deletion request for " + notification.component.getComponentName() + " in " + getName());
}
notification.addToWarnings(notification.component.getComponentName() + " is used by operation : " + node.getName());
}
}
if (node.getTabOperationComponentInstance() != null) {
TabComponentInstance ci = node.getTabOperationComponentInstance();
if (ci.getComponentName().equals(notification.component.getComponentName())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Receive a deletion request for " + notification.component.getComponentName() + " in " + getName());
}
notification.addToWarnings(notification.component.getComponentName() + " is used by operation : " + node.getName());
}
}
}
// We don't check action nodes
}
if (aNotification instanceof ComponentDeleted) {
ComponentDeleted notification = (ComponentDeleted) aNotification;
for (Enumeration<OperationNode> en = getAllEmbeddedOperationNodes().elements(); en.hasMoreElements();) {
OperationNode node = en.nextElement();
if (node.getTabOperationComponentInstance() != null) {
TabComponentInstance ci = node.getTabOperationComponentInstance();
if (ci.getComponentName().equals(notification.component.getComponentName())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Operation named " + node.getName() + " has received a deletion request for "
+ notification.component.getComponentName() + " in " + getName());
}
node.removeTabComponentInstance();
}
}
if (node.getComponentInstance() != null) {
OperationComponentInstance ci = node.getComponentInstance();
if (ci.getComponentName().equals(notification.component.getComponentName())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Operation named " + node.getName() + " has received a deletion request for "
+ notification.component.getComponentName() + " in " + getName());
}
node.removeComponentInstance();
}
}
}
for (ActionNode action : getAllEmbeddedActionNodes()) {
if (action.getTabActionComponentInstance() != null) {
TabComponentInstance ci = action.getTabActionComponentInstance();
if (ci.getComponentName().equals(notification.oldValue())) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Process " + getName() + " Updating component instance " + notification.component.getName()
+ " for " + action.getName());
}
action.removeTabComponentInstance();
}
}
}
}
}
// ==========================================================================
// ============================= Accessors
// ==================================
// ==========================================================================
@Override
public String getFullyQualifiedName() {
FlexoProcess current = this;
String returned = "" + getName();
while (current.getParentProcess() != null) {
returned = current.getParentProcess().getName() + "." + returned;
current = current.getParentProcess();
}
return returned;
}
/*
* public FlexoPetriGraph getPetriGraph(String context) { return getActivityPetriGraph(); }
*
* public void setPetriGraph(FlexoPetriGraph aPetriGraph, String context) { setActivityPetriGraph((ActivityPetriGraph) aPetriGraph); }
*/
public ActivityPetriGraph getActivityPetriGraph() {
return _petriGraph;
}
public void setActivityPetriGraph(ActivityPetriGraph aPetriGraph) {
_petriGraph = aPetriGraph;
if (_petriGraph != null) {
_petriGraph.setContainer(this, ACTIVITY_CONTEXT);
}
}
/**
* @return
* @deprecated use getWorkflow().getRoleList()
*/
@Deprecated
public RoleList getRoleList() {
return getWorkflow().getRoleList();
}
/**
* DEPRECATED: we will use this to add all roles defined in supplied role list to workflow role list
*
* @param list
* @deprecated
*/
@Deprecated
public void setRoleList(RoleList list) {
for (Role role : list.getRoles()) {
try {
getRoleList().addToRoles(role, true);
} catch (DuplicateRoleException e) {
logger.warning("DuplicateRoleException: " + e);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Duplicate role: " + role.getName(), e);
}
}
}
}
public StatusList getStatusList() {
return getStatusList(!isImported());
}
protected StatusList getStatusList(boolean createIfMissing) {
if (_statusList == null && createIfMissing) {
if (!isDeserializing()) {
setStatusList(new StatusList(this, true));
} else {
setStatusList(new StatusList(this, false));
}
}
return _statusList;
}
public void setStatusList(StatusList list) {
_statusList = list;
setChanged();
notifyAttributeModification("statusList", null, _statusList);
}
protected void notifyStatusListUpdated() {
setChanged();
notifyObservers(new WKFAttributeDataModification("statusList.defaultStatus", null, null));
}
/**
* @return
* @deprecated
*/
@Deprecated
public FlexoCSS getCalculatedCssSheet() {
if (cssSheet == null) {
if (isTopLevelProcess()) {
return getProject().getCssSheet();
} else {
return getParentProcess().getCalculatedCssSheet();
}
} else {
return cssSheet;
}
}
/**
* @return
* @deprecated
*/
@Deprecated
public FlexoCSS getCssSheet() {
return cssSheet;
}
/**
* @deprecated
*/
@Deprecated
public void setCssSheet(FlexoCSS cssSheet) {
FlexoCSS old = this.cssSheet;
this.cssSheet = cssSheet;
setChanged();
notifyAttributeModification("cssSheet", old, cssSheet);
}
/*
* public String getComponentPrefix() { return componentPrefix; }
*
*
* public void setComponentPrefix(String componentPrefix) { this.componentPrefix = componentPrefix; }
*/
@Override
public void updateMetricsValues() {
getWorkflow().updateMetricsForProcess(this);
}
@Override
public Vector<MetricsValue> getMetricsValues() {
return metricsValues;
}
public void setMetricsValues(Vector<MetricsValue> metricsValues) {
this.metricsValues = metricsValues;
setChanged();
}
@Override
public void addToMetricsValues(MetricsValue value) {
if (value.getMetricsDefinition() != null) {
metricsValues.add(value);
value.setOwner(this);
setChanged();
notifyObservers(new MetricsValueAdded(value, "metricsValues"));
}
}
@Override
public void removeFromMetricsValues(MetricsValue value) {
metricsValues.remove(value);
value.setOwner(null);
setChanged();
notifyObservers(new MetricsValueRemoved(value, "metricsValues"));
}
public void addMetrics() {
if (addMetricsActionizer != null) {
addMetricsActionizer.run(this, null);
}
}
public void deleteMetrics(MetricsValue value) {
if (deleteMetricsActionizer != null) {
deleteMetricsActionizer.run(value, null);
}
}
public Vector<FlexoModelObjectReference<Role>> getVisibleRoles() {
return visibleRoles;
}
public void setVisibleRoles(Vector<FlexoModelObjectReference<Role>> visibleRoles) {
this.visibleRoles = visibleRoles;
setChanged();
}
public void addToVisibleRoles(FlexoModelObjectReference<Role> value) {
if (value != null) {
visibleRoles.add(value);
value.setOwner(this);
setChanged();
notifyAttributeModification(VISIBLE_ROLES, null, value);
}
}
public void removeFromVisibleRoles(FlexoModelObjectReference<Role> value) {
visibleRoles.remove(value);
value.setOwner(null);
value.delete();
setChanged();
notifyAttributeModification(VISIBLE_ROLES, value, null);
}
@Override
public void objectDeleted(FlexoModelObjectReference<?> reference) {
if (visibleRoles.contains(reference)) {
removeFromVisibleRoles((FlexoModelObjectReference<Role>) reference);
}
}
@Override
public void notifyObjectLoaded(FlexoModelObjectReference<?> reference) {
}
@Override
public void objectCantBeFound(FlexoModelObjectReference<?> reference) {
objectDeleted(reference);
}
@Override
public void objectSerializationIdChanged(FlexoModelObjectReference<?> reference) {
setChanged();
}
@Override
public String getInspectorName() {
if (isImported()) {
return Inspectors.WKF.IMPORTED_PROCESS;
}
return Inspectors.WKF.FLEXO_PROCESS_INSPECTOR;
}
// ==========================================================================
// ============================= Instance Methods
// ===========================
// ==========================================================================
/**
* Same as getParentProcess(), but used in an interactive context (inspector)
*/
/*
* public FlexoProcess getInteractiveParentProcess() { return getParentProcess(); }
*/
/**
* Same as setParentProcess(), but used in an interactive context (inspector) In this case, just throw an ProcessMovingConfirmation that
* will be caught by a controller which has the responsability to continue process if confirmation was given.
*/
/*
* public void setInteractiveParentProcess(FlexoProcess aNewParentProcess) { if (aNewParentProcess != getInteractiveParentProcess()) {
* throw new ProcessMovingConfirmation(this, aNewParentProcess); } }
*/
/**
* Return the parent process of this process
*
* @return FlexoProcess
*/
public FlexoProcess getParentProcess() {
if (_processNode != null) {
if (_processNode.getFatherProcessNode() != null) {
return _processNode.getFatherProcessNode().getProcess();
} else {
// This is a top-level process
return null;
}
}
return null;
}
/**
* Sets the parent process of this process (move)
*
*/
public void setParentProcess(FlexoProcess aNewParentProcess) throws InvalidParentProcessException, InvalidProcessReferencesException {
if (getParentProcess() != aNewParentProcess) {
if (aNewParentProcess != null && this.getIsWebService()) {
throw new InvalidParentProcessException(this, aNewParentProcess);
}
boolean isImported = isImported();
if (!isImported && !isAcceptableAsParentProcess(aNewParentProcess)) {
throw new InvalidParentProcessException(this, aNewParentProcess);
}
if (aNewParentProcess == null) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Making process " + this + " context free");
}
} else {
if (logger.isLoggable(Level.INFO)) {
logger.info("Moving process " + this + " under process " + aNewParentProcess);
}
}
FlexoProcessNode newParentProcessNode = aNewParentProcess != null ? aNewParentProcess.getProcessNode() : null;
if (newParentProcessNode != null) {
newParentProcessNode.addToSubProcesses(getProcessNode());
} else {
if (isImported) {
getWorkflow().addToImportedRootNodeProcesses(getProcessNode());
} else {
getWorkflow().addToTopLevelNodeProcesses(getProcessNode());
}
}
if (getProcessDMEntity() != null) {
getProcessDMEntity().updateParentProcessPropertyIfRequired();
}
if (!isImported()) {
validateAfterMoving();
}
}
}
public boolean isAcceptableAsParentProcess(FlexoProcess aProcess) {
return isProcessHierarchyValidForNewParentProcess(aProcess);
}
private boolean isProcessHierarchyValidForNewParentProcess(FlexoProcess aNewParentProcess) {
return !isImported() && !isAncestorOf(aNewParentProcess) && (aNewParentProcess == null || !aNewParentProcess.isImported());
}
private void validateAfterMoving() throws InvalidProcessReferencesException {
ValidationReport report = getWorkflow().validate(getProcessMovingValidationModel());
if (report.getErrorNb() > 0) {
throw new InvalidProcessReferencesException(this, report);
}
}
private ProcessMovingValidationModel processMovingValidationModel;
public ProcessMovingValidationModel getProcessMovingValidationModel() {
if (processMovingValidationModel == null && getProject() != null) {
processMovingValidationModel = new ProcessMovingValidationModel(getProject());
}
return processMovingValidationModel;
}
private static class ProcessMovingValidationModel extends ValidationModel {
public ProcessMovingValidationModel(FlexoProject project) {
super(project, project.getTargetType());
registerRule(new FlexoProcess.ProcessHierarchyIsConsistent());
registerRule(new SubProcessNode.SubProcessReferenceMustBeValid());
registerRule(new ComponentInstance.DefinedBindingsMustBeValid());
// Notify that the validation model is complete and that inheritance
// computation could be performed
update();
}
/**
* Return a boolean indicating if validation of supplied object must be notified
*
* @param next
* @return a boolean
*/
@Override
protected boolean shouldNotifyValidation(Validable next) {
return next instanceof FlexoWorkflow || next instanceof FlexoProcess;
}
/**
* Overrides fixAutomaticallyIfOneFixProposal
*
* @see org.openflexo.foundation.validation.ValidationModel#fixAutomaticallyIfOneFixProposal()
*/
@Override
public boolean fixAutomaticallyIfOneFixProposal() {
return false;
}
}
public boolean isTopLevelProcess() {
return getParentProcess() == null;
}
public boolean isRootProcess() {
return isTopLevelProcess() && getWorkflow().getRootProcess() == this;
}
public boolean isAncestorOf(FlexoProcess anOtherProcess) {
FlexoProcess current = anOtherProcess;
while (current != null) {
if (current == this) {
return true;
}
current = current.getParentProcess();
}
return false;
}
/**
* Return all sub-processes of this process, as a Vector of FlexoProcess
*
* @return a Vector of FlexoProcess
*/
public Vector<FlexoProcess> getSubProcesses() {
if (logger.isLoggable(Level.FINE)) {
logger.fine("getSubProcesses() for " + getName());
}
_subProcesses = rebuildSubProcesses();
return _subProcesses;
}
public boolean isSingleSubProcess() {
boolean hasAtLeastOne = false;
for (SubProcessNode subProcessNode : getSubProcessNodes()) {
if (!subProcessNode.isSingle()) {
return false;
}
hasAtLeastOne = true;
}
return hasAtLeastOne;
}
public Vector<FlexoProcess> getSortedSubProcesses() {
Vector<FlexoProcess> reply = new Vector<FlexoProcess>();
Enumeration<FlexoProcessNode> en = getProcessNode().getSortedSubprocesses();
while (en.hasMoreElements()) {
reply.add(en.nextElement().getProcess());
}
return reply;
}
public void addToSubProcesses(FlexoProcess aProcess) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Adding process " + aProcess.getName() + " as subprocess of " + getName());
}
getProcessNode().addToSubProcesses(aProcess.getProcessNode());
rebuildSubProcesses();
if (aProcess.getProcessDMEntity() != null) {
aProcess.getProcessDMEntity().createParentProcessPropertyIfRequired();
}
setChanged();
notifyObservers(new ProcessInserted(aProcess, this));
if (logger.isLoggable(Level.INFO)) {
logger.info("DONE. Adding process " + aProcess.getName() + " as subprocess of " + getName());
}
}
public void removeFromSubProcesses(FlexoProcess aProcess) {
getProcessNode().removeFromSubProcesses(aProcess.getProcessNode());
rebuildSubProcesses();
setChanged();
notifyObservers(new ProcessRemoved(this, getParentProcess()));
}
/**
* Return all sub-processes of this process, as a Vector of FlexoProcess
*
* @return a Vector of FlexoProcess
*/
protected Vector<FlexoProcess> rebuildSubProcesses() {
if (_subProcesses != null) {
_subProcesses.clear();
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("rebuildSubProcesses() for " + getName());
}
if (getProcessNode() == null || getProcessNode().getSubProcesses() == null) {
return new Vector<FlexoProcess>();
}
_subProcesses = new Vector<FlexoProcess>();
Enumeration en = getProcessNode().getSubProcesses().elements();
while (en.hasMoreElements()) {
FlexoProcess subProcess = ((FlexoProcessNode) en.nextElement()).getProcess();
if (subProcess != null) {
_subProcesses.add(subProcess);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Sub-process: " + subProcess.getName());
}
}
}
return _subProcesses;
}
@Override
public double getWidth(String context) {
return getWidth(context, 1000.0);
}
@Override
public double getHeight(String context) {
return getHeight(context, 1000.0);
}
public double getScale(String context, double defaultValue) {
return _doubleGraphicalPropertyForKey("scale_" + context, defaultValue);
}
public void setScale(String context, double value) {
boolean wasNull = !hasGraphicalPropertyForKey("scale_" + context);
double oldValue = getScale(context, value);
if (logger.isLoggable(Level.FINE)) {
logger.fine("setScale from " + oldValue + " to " + value + " wasNull=" + wasNull);
}
if (wasNull || value != oldValue) {
_setGraphicalPropertyForKey(value, "scale_" + context);
setChanged();
}
}
/**
* Return all OperationNode contained in this process
*
* @return a Vector of OperationNode
*/
public Vector<OperationNode> getAllEmbeddedOperationNodes() {
Vector<OperationNode> v = new Vector<OperationNode>();
if (isImported()) {
return v;
}
if (_petriGraph != null) {
for (AbstractActivityNode activity : _petriGraph.getAllEmbeddedAbstractActivityNodes()) {
v.addAll(activity.getAllEmbeddedOperationNodes());
}
return v;
}
if (logger.isLoggable(Level.WARNING)) {
logger.warning("_petriGraph is null for process:" + getName());
}
return v;
}
/**
* Return all OperationNode contained in this process that are associated with a WOComponent
*
* @return a Vector of OperationNode
*/
public List<OperationNode> getAllOperationNodesWithComponent() {
List<OperationNode> retval = new Vector<OperationNode>();
for (OperationNode operation : getAllEmbeddedOperationNodes()) {
if (operation.hasWOComponent()) {
retval.add(operation);
}
}
return retval;
}
public OperationNode getOperationNodeWithFlexoID(long flexoID) {
for (OperationNode operation : getAllEmbeddedOperationNodes()) {
if (operation != null) {
if (operation.getFlexoID() == flexoID) {
return operation;
}
}
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Could not find operation with flexoID " + flexoID);
}
return null;
}
/**
* Return all OperationNode contained in this process
*
* @return a Vector of OperationNode
*/
public Vector<WKFArtefact> getAllEmbeddedArtefacts() {
return _petriGraph.getAllEmbeddedArtefacts();
}
/**
* Return all WOComponents contained in this process
*
* @return a Vector of ComponentDefinition
*/
/*
* public Vector<ComponentDefinition> getAllComponents() { Vector<ComponentDefinition> answer = new Vector<ComponentDefinition>();
* answer.addAll(getAllOperationComponents()); answer.addAll(getAllThumnailComponents()); return answer; }
*/
public Vector<OperationComponentInstance> getAllComponentInstances() {
Vector<OperationComponentInstance> answer = new Vector<OperationComponentInstance>();
for (OperationNode operation : getAllEmbeddedOperationNodes()) {
if (operation.getComponentInstance() != null && operation.getComponentInstance().getComponentDefinition() != null) {
answer.add(operation.getComponentInstance());
}
}
return answer;
}
/**
* Return all thumnail components contained in this process
*
* @return a Vector of ThumbnailComponentDefinition
*/
public Vector<TabComponentDefinition> getAllThumnailComponents() {
/*
* Vector answer = new Vector(); Enumeration en = getAllOperationNodes().elements(); OperationNode cur = null;
* while(en.hasMoreElements()){ cur = (OperationNode)en.nextElement(); if(cur.getComponentDefinition()!=null){
* answer.addAll(cur.getComponentDefinition ().getThumbnailsComponentList()); } }
*/
return getProject().getFlexoComponentLibrary().getTabComponentList();
}
/**
* Return all ActionNode contained in this process
*
* @return a Vector of ActionNode
*/
public Vector<ActionNode> getAllEmbeddedActionNodes() {
if (_petriGraph != null) {
Vector<ActionNode> v = new Vector<ActionNode>();
for (AbstractActivityNode a : _petriGraph.getAllEmbeddedAbstractActivityNodes()) {
for (OperationNode o : a.getAllEmbeddedOperationNodes()) {
v.addAll(o.getAllEmbeddedActionNodes());
}
}
return v;
} else {
return new Vector<ActionNode>();
}
}
@Override
public String toString() {
return getName();
}
@Override
public String getName() {
return _name;
}
public String getProcessInstanceEntityName() {
return getProcessInstanceEntityName(_name);
}
public String getProcessInstanceEntityName(String aProcessName) {
return beautifyName(aProcessName) + "ProcessInstance";
}
public static String beautifyName(String name) {
if (name == null) {
return null;
}
if (name.matches(JavaUtils.JAVA_CLASS_NAME_REGEXP)) {
return name;
}
Matcher m = JavaUtils.JAVA_VARIABLE_ACCEPTABLE_PATTERN.matcher(name);
StringBuffer sb = new StringBuffer();
int i = 0;
while (m.find()) {
int n = m.start() - i;
for (int j = 0; j < n; j++) {
sb.append('_');
}
sb.append(ToolBox.capitalize(m.group(), true));
i = m.start() + m.end();
}
if (sb.length() == 0 || sb.charAt(0) >= '0' && sb.charAt(0) <= '9') {
sb.insert(0, '_');
}
return sb.toString();
}
private static boolean processWithSimilarNameExists(FlexoWorkflow workflow, FlexoProcess thisProcess, String nameCandidate) {
String javaNameCandidate = ToolBox.getJavaName(nameCandidate);
for (FlexoProcess p : workflow.getAllFlexoProcesses()) {
if (p != thisProcess) {
String processJavaName = ToolBox.getJavaName(p.getName());
if (processJavaName.equals(javaNameCandidate)) {
return true;
}
}
}
return false;
}
@Override
public void setName(String newName) throws DuplicateResourceException, InvalidNameException {
if (logger.isLoggable(Level.FINE)) {
logger.fine("FlexoProcess.setName() with " + newName + " was: " + _name);
}
if (!newName.equals(_name) || _name == null) {
if (getWorkflow() != null && processWithSimilarNameExists(getWorkflow(), this, ToolBox.getJavaName(newName))) {
throw new InvalidNameException("A process with similar name exists");
}
if (getProject() != null && getFlexoResource() != null && !isDeserializing()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("renameResource() with " + newName);
}
try {
getProject().renameResource(getFlexoResource(), newName);
} catch (DuplicateResourceException e) {
if (!isImported()) {
setChanged(false);
notifyObserversAsReentrantModification(new NameChanged(_name, _name));
throw e;
} else if (logger.isLoggable(Level.WARNING)) {
logger.warning("Duplicate resource thrown on imported process: " + newName);
}
}
if (getProcessNode() != null) {
getProcessNode().setChanged();// Workflow needs to be saved
// again
}
}
if (!isDeserializing() && getProcessDMEntity() != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("rename process entity with " + getProcessInstanceEntityName(newName));
}
getProcessDMEntity().setName(getProcessInstanceEntityName(newName));
}
String oldName = _name;
_name = newName;
/*
* if (getProcessNode() != null) { if (logger.isLoggable(Level.FINE)) logger.fine("rename process node with " + newName);
* getProcessNode().setName(newName); }
*/
setChanged();
notifyObservers(new NameChanged(oldName, newName));
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("setName() ignored");
}
}
}
public void createsAutoGeneratedProcessBusinessDataDMEntityIfRequired() {
if (!isImported() && getBusinessDataType() == null) {
getProject().getDataModel().getProcessBusinessDataRepository().getAutoGeneratedProcessBusinessDataDMEntity(this);
}
}
public ProcessDMEntity createsProcessDMEntityIfRequired() {
if (!isImported()) {
return getProcessDMEntity();
}
return null;
}
private ProcessDMEntity _processDMEntity = null;
public ProcessDMEntity getProcessDMEntity() {
if (_processDMEntity == null && !isImported()) {
if (getProject() != null) {
DMModel dmModel = getProject().getDataModel();
ProcessInstanceRepository processInstanceRepository = dmModel.getProcessInstanceRepository();
_processDMEntity = processInstanceRepository.getProcessDMEntity(this);
// logger.info("************ getProcessNode()="+getProcessNode());
if (_processDMEntity == null) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Creates entry for process " + getName() + " in ProcessInstanceRepository");
}
_processDMEntity = new ProcessDMEntity(getProject().getDataModel(), this);
getProject().getDataModel().getProcessInstanceRepository().registerEntity(_processDMEntity);
}
_processDMEntity.setProcess(this);
}
}
return _processDMEntity;
}
/*
* public BindingVariable getBusinessData() { if (_businessData == null) { _businessData = new
* BindingVariable(this,getProject().getDataModel()); } return _businessData; }
*
* public void setBusinessData(BindingVariable businessData) { _businessData = businessData; }
*/
public DMProperty getBusinessDataProperty() {
ProcessDMEntity processDMEntity = getProcessDMEntity();
if (processDMEntity != null) {
return processDMEntity.getBusinessDataProperty();
}
return null;
}
public String getBusinessDataVariableName() {
if (getBusinessDataProperty() != null) {
return getBusinessDataProperty().getName();
}
return null;
}
public void setBusinessDataVariableName(String aName) throws InvalidNameException, DuplicatePropertyNameException {
if (aName == null) {
return;
}
if (ReservedKeyword.contains(aName)) {
throw new InvalidNameException();
}
if (getBusinessDataProperty() != null) {
getBusinessDataProperty().setName(aName);
} else if (getProcessDMEntity() != null) {
if (!aName.trim().equals("")) {
getProcessDMEntity().createBusinessDataProperty(aName);
}
}
}
public DMEntity getBusinessDataType() {
if (getBusinessDataProperty() != null) {
return getBusinessDataProperty().getType().getBaseEntity();
}
return null;
}
public void setBusinessDataType(DMEntity aType) {
if (getBusinessDataProperty() != null) {
getBusinessDataProperty().setType(DMType.makeResolvedDMType(aType));
} else if (getProcessDMEntity() != null) {
getProcessDMEntity().createBusinessDataProperty(aType);
setChanged();
notifyAttributeModification("businessDataVariableName", null, getBusinessDataProperty());
}
if (aType != null && !aType.hasPropertyNamed("status")) {
if (aType instanceof DMEOEntity) {
DMEOAttribute statusAttribute;
try {
statusAttribute = DMEOAttribute.createsNewDMEOAttribute(aType.getDMModel(), (DMEOEntity) aType, "status", false, true,
DMPropertyImplementationType.PUBLIC_ACCESSORS_PRIVATE_FIELD);
statusAttribute.setPrototype(aType.getDMModel().getPrototypeNamed("str100"));
statusAttribute.setColumnName("PROCESS_STATUS");
((DMEOEntity) aType).registerProperty(statusAttribute);
} catch (EOAccessException e) {
// Ok this sucks.
logger.log(Level.SEVERE, "Could not create status attribute in business data class", e);
}
} else {
aType.createDMProperty("status", DMType.makeResolvedDMType(String.class, getProject()),
DMPropertyImplementationType.PUBLIC_ACCESSORS_ONLY);
}
}
setChanged();
notifyAttributeModification("businessDataType", null, aType);
}
@Override
public BindingModel getBindingModel() {
if (_bindingModel == null) {
_bindingModel = new ProcessBindingModel();
}
return _bindingModel;
}
public class ProcessBindingModel extends BindingModel {
private ProcessBindingVariable _processInstance;
ProcessBindingModel() {
super();
_processInstance = new ProcessBindingVariable();
}
@Override
public int getBindingVariablesCount() {
return 1;
}
@Override
public BindingVariable getBindingVariableAt(int index) {
return getProcessInstanceBindingVariable();
}
public BindingVariable getProcessInstanceBindingVariable() {
return _processInstance;
}
@Override
public boolean allowsNewBindingVariableCreation() {
return false;
}
public class ProcessBindingVariable extends BindingVariable {
private DMType _processBindingVariableType = null;
ProcessBindingVariable() {
super(FlexoProcess.this, FlexoProcess.this.getProject().getDataModel(), FlexoLocalization
.localizedForKey("access_to_the_current_process_instance"));
setVariableName("processInstance");
}
@Override
public DMType getType() {
if (_processBindingVariableType == null || _processBindingVariableType.getKindOfType() != DMType.KindOfType.RESOLVED
|| _processBindingVariableType.getBaseEntity() != getProcessDMEntity()) {
_processBindingVariableType = DMType.makeResolvedDMType(getProcessDMEntity());
}
return _processBindingVariableType;
}
}
}
public FlexoProcessNode getProcessNode() {
return _processNode;
}
public void setProcessNode(FlexoProcessNode processNode) {
_processNode = processNode;
rebuildSubProcesses();
}
/**
* Return all abstract node at all levels for this process
*
* @return a Vector of AbstractNode
*/
public Vector<AbstractNode> getAllAbstractNodes() {
if (allAbstractNodes == null) {
allAbstractNodes = new Vector<AbstractNode>();
if (getPortRegistery() != null) {
allAbstractNodes.addAll(getPortRegistery().getAllPorts());
}
appendAllAbstractNodesOfPetriGraph(getActivityPetriGraph(), allAbstractNodes);
/*
* allAbstractNodes.addAll(getAllActivities()); if (getPortRegistery() != null) {
* allAbstractNodes.addAll(getPortRegistery().getAllPorts()); } for (Enumeration e = getAllSubProcessNodes().elements();
* e.hasMoreElements();) { SubProcessNode node = (SubProcessNode) e.nextElement(); if (node.getPortMapRegistery() != null) {
* allAbstractNodes .addAll(node.getPortMapRegistery().getPortMaps()); } }
*
* // Don't do this, this will be done while adding getAllDeepOperatorNodes() // All activity-level operator nodes were recorded
* twice !!!!!!
*
* // allAbstractNodes.addAll(getAllOperatorNodes());
*
* if (_petriGraph != null) { allAbstractNodes.addAll(_petriGraph.getAllOperationNodes());
* allAbstractNodes.addAll(_petriGraph.getAllActionNodes()); allAbstractNodes.addAll(_petriGraph.getAllDeepOperatorNodes()); }
*/
}
return allAbstractNodes;
}
private void appendAllAbstractNodesOfPetriGraph(FlexoPetriGraph pg, Vector<AbstractNode> returned) {
for (AbstractNode n : pg.getNodes()) {
appendAllAbstractNodes(n, returned);
}
}
private void appendAllAbstractNodes(AbstractNode node, Vector<AbstractNode> returned) {
returned.add(node);
if (node instanceof FlexoNode) {
returned.addAll(((FlexoNode) node).getPreConditions());
}
if (node instanceof SubProcessNode) {
if (((SubProcessNode) node).getPortMapRegistery() != null) {
returned.addAll(((SubProcessNode) node).getPortMapRegistery().getPortMaps());
}
}
if (node instanceof AbstractActivityNode && ((AbstractActivityNode) node).hasContainedPetriGraph()) {
appendAllAbstractNodesOfPetriGraph(((AbstractActivityNode) node).getContainedPetriGraph(), returned);
}
if (node instanceof OperationNode && ((OperationNode) node).hasContainedPetriGraph()) {
appendAllAbstractNodesOfPetriGraph(((OperationNode) node).getContainedPetriGraph(), returned);
}
if (node instanceof SelfExecutableNode && ((SelfExecutableNode) node).hasExecutionPetriGraph()) {
appendAllAbstractNodesOfPetriGraph(((SelfExecutableNode) node).getExecutionPetriGraph(), returned);
}
if (node instanceof LOOPOperator && ((LOOPOperator) node).hasExecutionPetriGraph()) {
appendAllAbstractNodesOfPetriGraph(((LOOPOperator) node).getExecutionPetriGraph(), returned);
}
}
/**
* Return all abstract node at all levels for this process
*
* @return a Vector of AbstractNode
*/
public Vector<WKFNode> getAllNodes() {
if (allNodes == null) {
allNodes = new Vector<WKFNode>();
if (getPortRegistery() != null) {
allNodes.addAll(getPortRegistery().getAllPorts());
}
appendAllNodesOfPetriGraph(getActivityPetriGraph(), allNodes);
/*
* allAbstractNodes.addAll(getAllActivities()); if (getPortRegistery() != null) {
* allAbstractNodes.addAll(getPortRegistery().getAllPorts()); } for (Enumeration e = getAllSubProcessNodes().elements();
* e.hasMoreElements();) { SubProcessNode node = (SubProcessNode) e.nextElement(); if (node.getPortMapRegistery() != null) {
* allAbstractNodes .addAll(node.getPortMapRegistery().getPortMaps()); } }
*
* // Don't do this, this will be done while adding getAllDeepOperatorNodes() // All activity-level operator nodes were recorded
* twice !!!!!!
*
* // allAbstractNodes.addAll(getAllOperatorNodes());
*
* if (_petriGraph != null) { allAbstractNodes.addAll(_petriGraph.getAllOperationNodes());
* allAbstractNodes.addAll(_petriGraph.getAllActionNodes()); allAbstractNodes.addAll(_petriGraph.getAllDeepOperatorNodes()); }
*/
}
return allNodes;
}
private void appendAllNodesOfPetriGraph(FlexoPetriGraph pg, Vector<WKFNode> returned) {
for (AbstractNode n : pg.getNodes()) {
appendAllNodes(n, returned);
}
returned.addAll(pg.getArtefacts());
}
private void appendAllNodes(WKFNode node, Vector<WKFNode> returned) {
returned.add(node);
if (node instanceof FlexoNode) {
returned.addAll(((FlexoNode) node).getPreConditions());
}
if (node instanceof SubProcessNode) {
if (((SubProcessNode) node).getPortMapRegistery() != null) {
returned.addAll(((SubProcessNode) node).getPortMapRegistery().getPortMaps());
}
}
if (node instanceof AbstractActivityNode && ((AbstractActivityNode) node).hasContainedPetriGraph()) {
appendAllNodesOfPetriGraph(((AbstractActivityNode) node).getContainedPetriGraph(), returned);
}
if (node instanceof OperationNode && ((OperationNode) node).hasContainedPetriGraph()) {
appendAllNodesOfPetriGraph(((OperationNode) node).getContainedPetriGraph(), returned);
}
if (node instanceof SelfExecutableNode && ((SelfExecutableNode) node).hasExecutionPetriGraph()) {
appendAllNodesOfPetriGraph(((SelfExecutableNode) node).getExecutionPetriGraph(), returned);
}
if (node instanceof LOOPOperator && ((LOOPOperator) node).hasExecutionPetriGraph()) {
appendAllNodesOfPetriGraph(((LOOPOperator) node).getExecutionPetriGraph(), returned);
}
}
/**
* Return all activities for this process
*
* @return a Vector of AbstractActivityNode
*/
public Vector<AbstractActivityNode> getAllAbstractActivityNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllAbstractActivityNodes();
} else {
return new Vector<AbstractActivityNode>();
}
}
public Vector<AbstractActivityNode> getAllMeaningFullActivityNodes() {
Vector<AbstractActivityNode> all = getAllAbstractActivityNodes();
Vector<AbstractActivityNode> reply = new Vector<AbstractActivityNode>();
for (AbstractActivityNode node : all) {
if (!node.isBeginOrEndNode() && node.getName().trim().length() > 0) {
if (!node.getDontGenerate()) {
reply.add(node);
}
}
}
return reply;
}
public Vector<SubProcessNode> getAllMeaningSubProcessNodes() {
Vector<AbstractActivityNode> all = getAllAbstractActivityNodes();
Vector<SubProcessNode> reply = new Vector<SubProcessNode>();
for (AbstractActivityNode node : all) {
if (!node.isBeginOrEndNode() && node.getName().trim().length() > 0) {
if (node instanceof SubProcessNode) {
reply.add((SubProcessNode) node);
}
}
}
return reply;
}
public Vector<AbstractActivityNode> getAllEmbeddedAbstractActivityNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllEmbeddedAbstractActivityNodes();
} else {
return new Vector<AbstractActivityNode>();
}
}
public Vector<PetriGraphNode> getAllAbstractActivityNodesAndActivityOperators() {
if (_petriGraph != null) {
Vector<PetriGraphNode> v = new Vector<PetriGraphNode>();
v.addAll(_petriGraph.getAllEmbeddedAbstractActivityNodes());
v.addAll(_petriGraph.getAllEmbeddedOperatorsOfSameLevel());
return v;
} else {
return new Vector<PetriGraphNode>();
}
}
public Vector<PetriGraphNode> getAllAbstractActivityNodesAndActivityOperatorsWithEvents() {
if (_petriGraph != null) {
Vector<PetriGraphNode> v = new Vector<PetriGraphNode>();
v.addAll(_petriGraph.getAllEmbeddedNodesOfClass(AbstractActivityNode.class));
v.addAll(_petriGraph.getAllEmbeddedNodesOfClassOfSameLevel(OperatorNode.class));
v.addAll(_petriGraph.getAllEmbeddedNodesOfClassOfSameLevel(EventNode.class));
return v;
} else {
return new Vector<PetriGraphNode>();
}
}
/**
* Return all activities of the underlying petri graph.
*
* @return a Vector of ActivityNode
*/
public Vector<ActivityNode> getAllActivityNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllActivityNodes();
} else {
return new Vector<ActivityNode>();
}
}
public AbstractActivityNode getAbstractActivityNodeNamed(String name) {
Enumeration<AbstractActivityNode> en = getAllEmbeddedAbstractActivityNodes().elements();
while (en.hasMoreElements()) {
AbstractActivityNode node = en.nextElement();
if (node.getName().equals(name)) {
return node;
}
}
if (logger.isLoggable(Level.WARNING)) {
logger.warning("AbstractActivity named " + name + " could not be found in process " + getProcess().getName());
}
return null;
}
public EventNode getEventNodeNamed(String name) {
Enumeration<EventNode> en = getAllEventNodes().elements();
while (en.hasMoreElements()) {
EventNode node = en.nextElement();
if (node.getName().equals(name)) {
return node;
}
}
if (logger.isLoggable(Level.WARNING)) {
logger.warning("AbstractActivity named " + name + " could not be found in process " + getProcess().getName());
}
return null;
}
/**
* Return all sub-processes for this process
*
* @return a Vector of SubProcessNode
*/
public Vector<SubProcessNode> getAllSubProcessNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllSubProcessNodes();
} else {
return new Vector<SubProcessNode>();
}
}
public Vector<SubProcessNode> getAllProcessInstances() {
return getWorkflow().getAllSubProcessNodeUsingProcess(this);
}
/**
* Return a vector of all BEGIN_NODE of the underlying Petri Graph
*
* @return Vector of Begin nodes
*/
public Vector<FlexoNode> getAllBeginNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllBeginNodes();
} else {
return new Vector<FlexoNode>();
}
}
/**
* Return a vector of all END_NODE of the underlying Petri Graph
*
* @return Vector of end nodes
*/
public Vector<FlexoNode> getAllEndNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllEndNodes();
} else {
return new Vector<FlexoNode>();
}
}
/**
* Return a vector of all OPERATOR of the underlying Petri Graph
*
* @return Vector of ActivityNode
*/
public Vector<OperatorNode> getAllOperatorNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllOperatorNodes();
} else {
return new Vector<OperatorNode>();
}
}
public Vector<OperatorNode> getAllEmbeddedOperatorNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllEmbeddedOperators();
} else {
return new Vector<OperatorNode>();
}
}
/**
* Return a vector of all Event nodes of the underlying Petri Graph
*
* @return Vector of EventNode
*/
public Vector<EventNode> getAllEventNodes() {
// TODO: optimize me later !!!
if (_petriGraph != null) {
return _petriGraph.getAllEventNodes();
} else {
return new Vector<EventNode>();
}
}
public Vector<FlexoPostCondition<?, ?>> getAllPostConditions() {
Vector<FlexoPostCondition<?, ?>> returned = new Vector<FlexoPostCondition<?, ?>>() {
@Override
public synchronized boolean addAll(Collection<? extends FlexoPostCondition<?, ?>> c) {
for (FlexoPostCondition<?, ?> edge : c) {
if (!contains(edge)) {
add(edge);
}
}
return true;
}
};
for (AbstractNode n : getAllAbstractNodes()) {
returned.addAll(n.getOutgoingPostConditions());
returned.addAll(n.getIncomingPostConditions());
}
return returned;
}
public Vector<WKFAssociation> getAllAssociations() {
Vector<WKFAssociation> returned = new Vector<WKFAssociation>() {
@Override
public synchronized boolean addAll(Collection<? extends WKFAssociation> c) {
for (WKFAssociation edge : c) {
if (!contains(edge)) {
add(edge);
}
}
return true;
}
};
for (WKFNode n : getAllNodes()) {
returned.addAll(n.getOutgoingAssociations());
returned.addAll(n.getIncomingAssociations());
}
return returned;
}
public Vector<MessageEdge<?, ?>> getAllMessageEdges() {
// logger.info("getAllMessageEdges for process "+getName());
Vector<MessageEdge<?, ?>> returned = new Vector<MessageEdge<?, ?>>();
for (FlexoPostCondition<?, ?> e : getAllPostConditions()) {
if (e instanceof MessageEdge) {
returned.add((MessageEdge<?, ?>) e);
// logger.info("Found "+e.getDerivedNameFromStartingObject()+" to "+e.getDerivedNameFromEndingObject());
}
}
return returned;
}
/**
* Returns the level of a FlexoProcess (which is {@link FlexoLevel.PROCESS} ).
*
* @see org.openflexo.foundation.wkf.LevelledObject#getLevel()
*/
@Override
public FlexoLevel getLevel() {
return FlexoLevel.PROCESS;
}
// ==========================================================================
// ================================= Delete ===============================
// ==========================================================================
@Override
public final void delete() {
if (isImported()) {
isImported = true;// This is important, because it allows to do some
}
// tests on this deleted object
if (logger.isLoggable(Level.FINE)) {
logger.fine("delete: FlexoProcess " + getName());
}
for (FlexoProcess p : new Vector<FlexoProcess>(getSubProcesses())) {
p.delete();
}
Vector<SubProcessNode> allBoundSubProcessNodes = new Vector<SubProcessNode>(getSubProcessNodes());
for (Enumeration<SubProcessNode> e = allBoundSubProcessNodes.elements(); e.hasMoreElements();) {
SubProcessNode subProcessNode = e.nextElement();
subProcessNode.setSubProcess(null);
if (logger.isLoggable(Level.INFO)) {
logger.info("Set subprocess to null for " + subProcessNode.getName());
}
}
/*
* FlexoProcessNode processNode = getProcessNode(); if (processNode != null) { processNode.delete(); processNode = null; }
*/
if (_petriGraph != null) {
_petriGraph.delete();
}
FlexoProcess parentProcess = getParentProcess();
if (getFlexoResource() != null) {
getFlexoResource().delete();
}
if (getProcessDMEntity() != null) {
getProcessDMEntity().delete();
}
if (getProcessNode() != null) {
getProcessNode().delete();
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Process " + getName() + " has no process node associated!");
}
}
FlexoProcessImageBuilder.deleteSnapshot(this);
super.delete();
if (nameForNodeMap != null) {
nameForNodeMap.clear();
}
nameForNodeMap = null;
setChanged();
notifyObservers(new ProcessRemoved(this, parentProcess));
deleteObservers();
}
/**
* Build and return a vector of all the objects that will be deleted during process deletion
*
* @param aVector
* of DeletableObject
*/
@Override
public Vector<WKFObject> getAllEmbeddedDeleted() {
return getAllEmbeddedWKFObjects();
}
/**
* Return a Vector of all embedded WKFObjects
*
* @return a Vector of WKFObject instances
*/
@Override
public Vector<WKFObject> getAllEmbeddedWKFObjects() {
Vector<WKFObject> returned = new Vector<WKFObject>();
returned.add(this);
if (_petriGraph != null) {
returned.addAll(_petriGraph.getAllEmbeddedWKFObjects());
}
if (getPortRegistery() != null) {
returned.addAll(getPortRegistery().getAllEmbeddedWKFObjects());
}
if (getServiceInterfaces() != null) {
Enumeration en = getServiceInterfaces().elements();
while (en.hasMoreElements()) {
ServiceInterface service = (ServiceInterface) en.nextElement();
returned.addAll(service.getAllEmbeddedWKFObjects());
}
}
if (getStatusList() != null) {
returned.addAll(getStatusList().getAllEmbeddedWKFObjects());
}
returned.addAll(getMetricsValues());
return returned;
}
/**
* Return a vector of all embedded objects on which the validation will be performed
*
* @return a Vector of Validable objects
*/
@Override
public Vector<Validable> getAllEmbeddedValidableObjects() {
Vector<Validable> returned = new Vector<Validable>();
returned.addAll(getAllEmbeddedWKFObjects());
for (OperationNode operation : getAllEmbeddedOperationNodes()) {
if (operation.getComponentInstance() != null) {
returned.add(operation.getComponentInstance());
}
}
return returned;
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextInitialName(String baseName) {
return nextInitialName(baseName, getFullyQualifiedName() + "." + baseName);
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextInitialName(String prefix, String baseName) {
return nextInitialName(baseName, getFullyQualifiedName() + "." + prefix + "." + baseName);
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextNonAmbigousNameForNode(String baseName, AbstractNode aNode) {
if (aNode instanceof PetriGraphNode) {
if (aNode instanceof AbstractActivityNode) {
return findNextInitialName(baseName);
}
if (aNode instanceof OperationNode) {
return findNextInitialName(baseName, ((OperationNode) aNode).getAbstractActivityNode());
}
if (aNode instanceof ActionNode) {
return findNextInitialName(baseName, ((ActionNode) aNode).getOperationNode());
}
} else if (aNode instanceof OperatorNode) {
if (aNode.getLevel() == FlexoLevel.ACTIVITY) {
return findNextInitialName(baseName);
}
if (aNode.getLevel() == FlexoLevel.OPERATION) {
return findNextInitialName(baseName, ((OperatorNode) aNode).getAbstractActivityNode());
}
if (aNode.getLevel() == FlexoLevel.ACTION) {
return findNextInitialName(baseName, ((OperatorNode) aNode).getOperationNode());
}
} else if (aNode instanceof FlexoPort) {
return findNextInitialName(baseName);
} else if (aNode instanceof FlexoPortMap) {
return findNextInitialName(baseName, ((FlexoPortMap) aNode).getSubProcessNode());
}
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Unexpected type " + aNode.getClass().getName());
}
return null;
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextInitialName(String baseName, WKFObject node) {
if (node instanceof AbstractNode) {
return findNextNonAmbigousNameForNode(baseName, (AbstractNode) node);
}
return baseName;
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextInitialName(String baseName, AbstractActivityNode activityNode) {
if (activityNode == null) {
return baseName;
}
return nextInitialName(baseName, getFullyQualifiedName() + "." + activityNode.getName() + "." + baseName);
}
/**
* @param baseName
* @param node
* @return
*/
public String findNextInitialName(String baseName, OperationNode operationNode) {
if (operationNode == null) {
return baseName;
}
return nextInitialName(baseName, getFullyQualifiedName() + "." + operationNode.getAbstractActivityNode().getName() + "."
+ operationNode.getName() + "." + baseName);
}
/**
* @param fullQualifiedBaseName
* @param node
* @return
*/
private String nextInitialName(String baseName, String fullQualifiedBaseName) {
// Scrum 1.3.2: request to remove disambiguation of node names
/*
* Vector allNodes = getAllAbstractNodes();
*
* boolean found = false; int i = 0; String tryWith = fullQualifiedBaseName; String returnedName = baseName;
*
* if (logger.isLoggable(Level.FINE)) logger.fine("findNextInitialName() for " + fullQualifiedBaseName);
*
* while (!found) { boolean alreadyExists = false; if (logger.isLoggable(Level.FINE)) logger.fine("look " + tryWith); for
* (Enumeration e = allNodes.elements(); (e.hasMoreElements() && !(alreadyExists));) { String next = ((AbstractNode)
* e.nextElement()).getFullyQualifiedName(); if (logger.isLoggable(Level.FINE)) logger.fine(" > already " + next); if
* (next.equalsIgnoreCase(tryWith)) { alreadyExists = true; } } alreadyExists |= getName().equalsIgnoreCase(returnedName); if
* (alreadyExists) { i++; tryWith = fullQualifiedBaseName + "-" + i; returnedName = baseName + "-" + i; } else { found = true; } }
* if (logger.isLoggable(Level.FINE)) logger.fine("findNextInitialName() return " + tryWith); return returnedName;
*/
return baseName;
}
public PortRegistery getPortRegistery() {
if (_registery == null && !isImported()) {
_registery = new PortRegistery(this);
// TODO: following must be put in some finalizer
/*
* _registery.setX(250,WKFRepresentableObject.BASIC_PROCESS_EDITOR);
* _registery.setY(60,WKFRepresentableObject.BASIC_PROCESS_EDITOR); _registery
* .setWidth(80,WKFRepresentableObject.BASIC_PROCESS_EDITOR); _registery
* .setHeight(20,WKFRepresentableObject.BASIC_PROCESS_EDITOR); _registery.setX(250,WKFRepresentableObject.SWIMMING_LANE_EDITOR);
* _registery.setY(60,WKFRepresentableObject.SWIMMING_LANE_EDITOR); _registery
* .setWidth(80,WKFRepresentableObject.SWIMMING_LANE_EDITOR); _registery
* .setHeight(20,WKFRepresentableObject.SWIMMING_LANE_EDITOR);
*/
}
return _registery;
}
public void setPortRegistery(PortRegistery registery) {
_registery = registery;
if (registery.getProcess() != this) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("there is a problem!");
}
}
_registery.setProcess(this);
}
public DefaultServiceInterface getPortRegisteryInterface() {
if (getPortRegistery() != null && _portRegistryInterface == null) {
try {
_portRegistryInterface = new DefaultServiceInterface(this);
_portRegistryInterface.updateFromPortRegistery();
} catch (FlexoException f) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception should not arise");
}
f.printStackTrace();
}
}
return _portRegistryInterface;
}
public Vector<ServiceInterface> getServiceInterfaces() {
return _serviceInterfaces;
}
public void setServiceInterfaces(Vector<ServiceInterface> vector) {
_serviceInterfaces = vector;
}
public ServiceInterface addServiceInterface(String name) throws DuplicateWKFObjectException, DuplicateWSObjectException {
// will throw an exception
ServiceInterface newInterface;
try {
ServiceInterface.checkInterfaceName(this, name, null);
newInterface = new ServiceInterface(this, name);
} catch (DuplicateWKFObjectException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("An interface with the same name (" + name + ") already exist");
}
throw e;
} catch (DuplicateWSObjectException e) {
throw e;
}
addToServiceInterfaces(newInterface);
return newInterface;
}
public void addToServiceInterfaces(ServiceInterface anInterface) {
if (!_serviceInterfaces.contains(anInterface)) {
_serviceInterfaces.add(anInterface);
anInterface.setProcess(this);
setChanged();
notifyObservers(new ServiceInterfaceInserted(anInterface));
}
}
public void removeFromServiceInterfaces(ServiceInterface anInterface) {
if (_serviceInterfaces.contains(anInterface)) {
_serviceInterfaces.remove(anInterface);
setChanged();
notifyObservers(new ServiceInterfaceRemoved(anInterface));
anInterface.setProcess(null);
}
}
public ServiceInterface getServiceInterfaceNamed(String interfaceName) {
Enumeration<ServiceInterface> en = _serviceInterfaces.elements();
while (en.hasMoreElements()) {
ServiceInterface intf = en.nextElement();
if (intf.getName().equals(interfaceName)) {
return intf;
}
}
return null;
}
@Deprecated
public boolean getIsWebService() {
return _isWebService;
}
@Deprecated
public void setIsWebService(boolean isWebService) {
boolean oldValue = _isWebService;
_isWebService = isWebService;
if (isWebService != oldValue) {
notifyAttributeModification("isWebService", new Boolean(oldValue), new Boolean(isWebService));
}
}
public Vector<SubProcessNode> getSubProcessNodes() {
return _subProcessNodes;
}
public void addToSubProcessNodes(SubProcessNode node) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(getName() + ": addToSubProcessNodes() " + node.getName());
}
if (!node.getXMLResourceData().getFlexoXMLFileResource().isConverting() && !_subProcessNodes.contains(node)) {
_subProcessNodes.add(node);
addObserver(node);
}
}
public void removeFromSubProcessNodes(SubProcessNode node) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(getName() + ": removeFromSubProcessNodes() " + node.getName());
}
_subProcessNodes.remove(node);
deleteObserver(node);
}
public void notifyPostInserted(FlexoPostCondition<?, ?> post) {
setChanged();
notifyObservers(new PostInserted(post));
}
public void notifyAssociationInserted(WKFAssociation association) {
setChanged();
notifyObservers(new AssociationInserted(association));
}
/**
* We finalize here serialization since port and port registery definitions are inter-procedural !
*/
public void finalizeProcessBindings() {
if (logger.isLoggable(Level.FINE)) {
logger.fine("finalizeProcessBindings() " + getName());
}
for (Enumeration e = getAllSubProcessNodes().elements(); e.hasMoreElements();) {
SubProcessNode node = (SubProcessNode) e.nextElement();
if (node.getSubProcess() != null) {
if (logger.isLoggable(Level.FINE)) {
logger.finer("Finalize linking " + getName() + " with " + node.getSubProcess().getName());
}
if (!node.getSubProcess().isImported()) {
node.getPortMapRegistery().lookupServiceInterface();
}
} else if (node.getSubProcessName() != null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Undefined sub-process " + node.getSubProcessName() + " referenced in process " + getName());
}
node.setSubProcessName(null);
}
if (node.getSubProcess() == null && node.getPortMapRegistery() != null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Inconsistent data : PortMapRegistery defined while no sub-process is defined: remove it");
}
node.getPortMapRegistery().delete();
node.setSubProcessName(null);
}
}
// Now do it with message edges
// Vector<MessageEdge> unboundMessageEdgesToRemove = new
// Vector<MessageEdge>();
for (MessageEdge messageEdge : getAllMessageEdges()) {
messageEdge.lookupMessageDefinition();
}
}
@Override
public synchronized void setIsModified() {
if (ignoreNotifications()) {
return;
}
if (nameForNodeMap != null) {
nameForNodeMap.clear();// Any modification is capable of modify the
}
// names of the objects.
lastUpdate = null; // Reset the last update date so that it will be
// recomputed according to the new lastMemoryUpdate!
super.setIsModified();
}
/**
* This date is use to perform fine tuning resource dependancies computing
*
* @return
*/
@Override
public Date getLastUpdate() {
if (lastUpdate == null) {
lastUpdate = lastMemoryUpdate();
}
if (lastUpdate == null) {
lastUpdate = super.getLastUpdate();
}
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getAcronym() {
return acronym;
}
public void setAcronym(String acronym) {
this.acronym = acronym;
}
public static final String getTypeName() {
return "PROCESS";
}
private static final Vector<WKFObject> EMPTY_VECTOR = EmptyVector.EMPTY_VECTOR(WKFObject.class);
public void addStatus() {
if (addStatusActionizer != null) {
addStatusActionizer.run(this, EMPTY_VECTOR);
}
}
public void deleteStatus(Status object) {
if (deleteActionizer != null) {
deleteActionizer.run(object, EMPTY_VECTOR);
}
}
/**
* @return
* @deprecated
*/
@Deprecated
public Enumeration<Role> getSortedRoles() {
return getWorkflow().getSortedRoles();
}
public Enumeration<Status> getSortedStatuses() {
if (getStatusList() == null) {
return ToolBox.getEnumeration(new Status[0]);
}
disableObserving();
Status[] o = FlexoIndexManager.sortArray(getStatusList().getStatus().toArray(new Status[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
public Enumeration<EventNode> getSortedEvents() {
disableObserving();
EventNode[] o = FlexoIndexManager.sortArray(getAllEventNodes().toArray(new EventNode[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
// =========================================================
// ============= Control graph management ==================
// =========================================================
private static ControlGraphFactory<FlexoProcess> _executionComputingFactory;
public static void setExecutionComputingFactory(ControlGraphFactory<FlexoProcess> factory) {
_executionComputingFactory = factory;
}
public WorkflowControlGraph<FlexoProcess> getExecution() {
if (_executionComputingFactory != null) {
return _executionComputingFactory.getControlGraph(this);
}
return null;
}
@Override
public void setProgrammingLanguageForControlGraphComputation(ProgrammingLanguage language) {
if (getExecution() != null) {
getExecution().setProgrammingLanguage(language);
}
}
@Override
public void setInterproceduralForControlGraphComputation(boolean interprocedural) {
if (getExecution() != null) {
getExecution().setInterprocedural(interprocedural);
}
}
@Override
public String getExecutableElementName() {
return FlexoLocalization.localizedForKeyWithParams("process_($0)", getName());
}
public String getExecutionClassName() {
return ToolBox.capitalize(ToolBox.getJavaName(getName(), false, false) + "Processor");
}
public String getExecutionGroupName() {
return "org.openflexo.controlgraph." + getProject().getPrefix().toLowerCase();
}
public synchronized BidiMap getNameForNodeMap() {
if (nameForNodeMap.size() == 0) {
buildNameForNodeMap();
}
return nameForNodeMap;
}
public synchronized String getUniqueNameForNode(AbstractNode node) {
if (getNameForNodeMap().getKey(node) != null) {
return (String) getNameForNodeMap().getKey(node);
}
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Node "
+ node
+ " had no computed name meaning that it was probably not properly embedded in the FlexoProcess."
+ "I will compute its name now, but this can be source of instability in the names of the nodes. You should try to find why that node was not embedded.");
}
return computeAndStoreNameForNode(node);
}
private synchronized String computeAndStoreNameForNode(AbstractNode node) {
String base = ToolBox.uncapitalize(node.getNiceName());
String attempt = base;
if (nameForNodeMap.get(attempt) != null || ReservedKeyword.contains(attempt)) {
String nodeType = node.getNodeTypeName();
if (base.toLowerCase().indexOf(nodeType.toLowerCase()) == -1) {
base = base + nodeType;
}
base = ToolBox.uncapitalize(base);
int i = 1;
attempt = base;
while (nameForNodeMap.get(attempt) != null || ReservedKeyword.contains(attempt)) {
i++;
attempt = base + String.valueOf(i);
}
}
nameForNodeMap.put(attempt, node);
return attempt;
}
private void buildNameForNodeMap() {
Vector<AbstractNode> nodes = getActivityPetriGraph().getAllEmbeddedNodesOfClass(AbstractNode.class);
nodes.addAll(getPortRegistery().getAllPorts());
Collections.sort(nodes, new Comparator<FlexoModelObject>() {
@Override
public int compare(FlexoModelObject o1, FlexoModelObject o2) {
return o1.compareTo(o2);
}
});
for (FlexoProcess process : getWorkflow().getAllLocalFlexoProcesses()) {
nameForNodeMap.put(ToolBox.uncapitalize(ToolBox.getJavaName(process.getName())), process);
}
for (FlexoProcess process : getWorkflow().getAllImportedFlexoProcesses()) {
nameForNodeMap.put(ToolBox.uncapitalize(ToolBox.getJavaName(process.getName())), process);
}
if (getProcessDMEntity() != null) {
for (DMObject obj : getProcessDMEntity().getOrderedChildren()) {
nameForNodeMap.put(ToolBox.uncapitalize(ToolBox.getJavaName(obj.getName())), obj);
}
}
for (AbstractNode node : nodes) {
computeAndStoreNameForNode(node);
}
}
// ============================================================
// ==================== Validation ============================
// ============================================================
public static class NonRootProcessShouldBeUsed extends ValidationRule<NonRootProcessShouldBeUsed, FlexoProcess> {
public NonRootProcessShouldBeUsed() {
super(FlexoProcess.class, "non_root_process_should_be_used");
}
@Override
public ValidationIssue<NonRootProcessShouldBeUsed, FlexoProcess> applyValidation(final FlexoProcess process) {
if (!process.isRootProcess() && process.getSubProcessNodes().size() == 0
&& (!process.isImported() || process.isTopLevelProcess())) {
return new ValidationWarning<NonRootProcessShouldBeUsed, FlexoProcess>(this, process,
"process_($object.name)_is_used_nowhere");
}
return null;
}
}
public static class FlexoProcessMustHaveADefaultStatus extends ValidationRule<FlexoProcessMustHaveADefaultStatus, FlexoProcess> {
public FlexoProcessMustHaveADefaultStatus() {
super(FlexoProcess.class, "process_must_have_a_default_status");
}
@Override
public ValidationIssue<FlexoProcessMustHaveADefaultStatus, FlexoProcess> applyValidation(FlexoProcess process) {
if (process.getStatusList() != null && process.getStatusList().getDefaultStatus() == null) {
Vector<FixProposal<FlexoProcessMustHaveADefaultStatus, FlexoProcess>> v = new Vector<FixProposal<FlexoProcessMustHaveADefaultStatus, FlexoProcess>>();
Enumeration<Status> en = process.getStatusList().getStatus().elements();
while (en.hasMoreElements()) {
Status s = en.nextElement();
v.add(new SetDefaultStatus(s));
}
v.add(new CreateAndSetDefaultStatus());
return new ValidationError<FlexoProcessMustHaveADefaultStatus, FlexoProcess>(this, process,
"process_($object.name)_has_no_default_status", v);
}
return null;
}
protected static class CreateAndSetDefaultStatus extends FixProposal<FlexoProcessMustHaveADefaultStatus, FlexoProcess> {
public CreateAndSetDefaultStatus() {
super("create_and_set_default_status");
// TODO Auto-generated constructor stub
}
@Override
protected void fixAction() {
FlexoProcess p = getObject();
Status s = p.getStatusList().createNewStatus();
p.getStatusList().setDefaultStatus(s);
}
}
protected static class SetDefaultStatus extends FixProposal<FlexoProcessMustHaveADefaultStatus, FlexoProcess> {
private Status status;
public SetDefaultStatus(Status status) {
super("set_default_status_to_($status.name)");
this.status = status;
}
// Used by KVC for message
public Status getStatus() {
return status;
}
@Override
protected void fixAction() {
FlexoProcess p = getObject();
p.getStatusList().setDefaultStatus(status);
}
}
}
public static class ProcessHierarchyIsConsistent extends ValidationRule<ProcessHierarchyIsConsistent, FlexoProcess> {
public ProcessHierarchyIsConsistent() {
super(FlexoProcess.class, "process_hierarchy_must_be_consistent");
}
@Override
public ValidationIssue<ProcessHierarchyIsConsistent, FlexoProcess> applyValidation(final FlexoProcess process) {
if (!process.isImported() && !process.isAcceptableAsParentProcess(process.getParentProcess())) {
return new ValidationError<ProcessHierarchyIsConsistent, FlexoProcess>(this, process,
"process_hierarchy_for_($object.name)_is_inconsistant");
}
return null;
}
}
public static class ImportedProcessShouldExistOnServer extends ValidationRule<ImportedProcessShouldExistOnServer, FlexoProcess> {
public ImportedProcessShouldExistOnServer() {
super(FlexoProcess.class, "imported_process_should_exist_on_server");
}
@Override
public ValidationIssue<ImportedProcessShouldExistOnServer, FlexoProcess> applyValidation(final FlexoProcess process) {
if (process.isImported() && process.isDeletedOnServer()) {
return new ValidationWarning<ImportedProcessShouldExistOnServer, FlexoProcess>(this, process,
"process_($object.name)_no_longer_exists_on_server", new DeleteProcess());
}
return null;
}
public static class DeleteProcess extends FixProposal<ImportedProcessShouldExistOnServer, FlexoProcess> {
public DeleteProcess() {
super("delete_process_($object.name)");
}
@Override
protected void fixAction() {
getObject().delete();
}
}
}
public static class ProcessMustDefineBusinessDataClass extends ValidationRule<ProcessMustDefineBusinessDataClass, FlexoProcess> {
/**
* @param objectType
* @param ruleName
*/
public ProcessMustDefineBusinessDataClass() {
super(FlexoProcess.class, "process_must_define_business_data_class");
}
/**
* Overrides applyValidation
*
* @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable)
*/
@Override
public ValidationIssue<ProcessMustDefineBusinessDataClass, FlexoProcess> applyValidation(FlexoProcess process) {
if (process.getBusinessDataType() == null && !process.isRootProcess()) {
return new ValidationError<ProcessMustDefineBusinessDataClass, FlexoProcess>(this, process,
"process_must_define_a_business_data_type", new SetTypeProposal());
}
if (!process.isRootProcess()
&& (process.getBusinessDataVariableName() == null || process.getBusinessDataVariableName().trim().length() == 0)) {
return new ValidationError<ProcessMustDefineBusinessDataClass, FlexoProcess>(this, process,
"process_must_define_a_business_data_variable", new SetVariableNameProposal());
}
return null;
}
/**
* Overrides isValidForTarget
*
* @see org.openflexo.foundation.validation.ValidationRule#isValidForTarget(TargetType)
*/
@Override
public boolean isValidForTarget(TargetType targetType) {
return targetType != CodeType.PROTOTYPE;
}
public static class SetTypeProposal extends ParameteredFixProposal<ProcessMustDefineBusinessDataClass, FlexoProcess> {
private static final ParameterDefinition[] parameters = new ParameterDefinition[] { new DMEntityParameter("type", "type", null) };
/**
* @param aMessage
*/
public SetTypeProposal() {
super("set_type", parameters);
}
/**
* Overrides fixAction
*
* @see org.openflexo.foundation.validation.FixProposal#fixAction()
*/
@Override
protected void fixAction() {
DMEntity e = (DMEntity) getValueForParameter("type");
if (e != null) {
getObject().setBusinessDataType(e);
}
}
}
public static class SetVariableNameProposal extends ParameteredFixProposal<ProcessMustDefineBusinessDataClass, FlexoProcess> {
private static final ParameterDefinition[] parameters = new ParameterDefinition[] { new TextFieldParameter("name", "name", null) };
/**
* @param aMessage
*/
public SetVariableNameProposal() {
super("set_variable", parameters);
}
/**
* Overrides fixAction
*
* @see org.openflexo.foundation.validation.FixProposal#fixAction()
*/
@Override
protected void fixAction() {
String s = (String) getValueForParameter("name");
if (s != null && s.trim().length() == 0) {
try {
getObject().setBusinessDataVariableName(s);
} catch (InvalidNameException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning(e.getMessage());
}
} catch (DuplicatePropertyNameException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning(e.getMessage());
}
}
}
}
}
}
public static class BusinessDataClassMustHaveStatusProperty extends
ValidationRule<BusinessDataClassMustHaveStatusProperty, FlexoProcess> {
/**
* @param objectType
* @param ruleName
*/
public BusinessDataClassMustHaveStatusProperty() {
super(FlexoProcess.class, "business_data_class_must_have_status_property");
}
/**
* Overrides applyValidation
*
* @see org.openflexo.foundation.validation.ValidationRule#applyValidation(org.openflexo.foundation.validation.Validable)
*/
@Override
public ValidationIssue<BusinessDataClassMustHaveStatusProperty, FlexoProcess> applyValidation(FlexoProcess process) {
if (process._processDMEntity != null) {
if (process.getBusinessDataType().getProperty("status") == null) {
return new ValidationError<BusinessDataClassMustHaveStatusProperty, FlexoProcess>(this, process,
"business_data_class_must_have_status_property", process.getBusinessDataType().getIsReadOnly() ? null
: new AddPropertyStatus(process.getBusinessDataType()));
}
}
return null;
}
/**
* Overrides isValidForTarget
*
* @see org.openflexo.foundation.validation.ValidationRule#isValidForTarget(TargetType)
*/
@Override
public boolean isValidForTarget(TargetType targetType) {
return targetType != CodeType.PROTOTYPE;
}
public static class AddPropertyStatus extends FixProposal<BusinessDataClassMustHaveStatusProperty, FlexoProcess> {
private DMEntity _businessDataClass;
/**
* @param aMessage
*/
public AddPropertyStatus(DMEntity businessDataClass) {
super("create_status_property");
_businessDataClass = businessDataClass;
}
/**
* Overrides fixAction
*
* @see org.openflexo.foundation.validation.FixProposal#fixAction()
*/
@Override
protected void fixAction() {
if (_businessDataClass instanceof DMEOEntity) {
DMEOAttribute statusAttribute;
try {
statusAttribute = DMEOAttribute.createsNewDMEOAttribute(_businessDataClass.getDMModel(),
(DMEOEntity) _businessDataClass, "status", false, true,
DMPropertyImplementationType.PUBLIC_ACCESSORS_PRIVATE_FIELD);
statusAttribute.setPrototype(_businessDataClass.getDMModel().getPrototypeNamed("str100"));
statusAttribute.setColumnName("PROCESS_STATUS");
((DMEOEntity) _businessDataClass).registerProperty(statusAttribute);
} catch (EOAccessException e) {
// Ok this sucks.
throw new RuntimeException(e);
}
} else {
_businessDataClass.createDMProperty("status", DMType.makeResolvedDMType(String.class, getProject()),
DMPropertyImplementationType.PUBLIC_ACCESSORS_ONLY);
}
}
}
}
public void notifyOperationChange(OperationNode node) {
setChanged();
notifyObservers(new OperationChange(node));
}
/**
* Overrides getClassNameKey
*
* @see org.openflexo.foundation.FlexoModelObject#getClassNameKey()
*/
@Override
public String getClassNameKey() {
return "flexo_process";
}
/**
* Wheter there is within all the operations of this process at least one operation associated to a component
*
* @return
*/
public boolean hasWOComponent() {
for (AbstractActivityNode act : getAllEmbeddedAbstractActivityNodes()) {
if (act.hasWOComponent()) {
return true;
}
}
return false;
}
public int getIndex() {
if (getProcessNode() != null) {
return getProcessNode().getIndex();
}
logger.warning("Process node is null for flexo process " + this.getName());
return -1;
}
public void setIndex(int index) {
if (getProcessNode() != null) {
getProcessNode().setIndex(index);
if (getIndex() != index) {
setChanged(false);
AttributeDataModification dm = new AttributeDataModification("index", null, getIndex());
dm.setReentrant(true);
notifyObservers(dm);
}
} else {
logger.warning("Process node is null for flexo process " + this.getName());
}
}
public int getVectorIndex() {
if (getProcessNode() != null) {
return getProcessNode().getVectorIndex();
}
logger.warning("Process node is null for flexo process " + this.getName());
return -1;
}
public void setVectorIndex(int index) {
if (getProcessNode() != null) {
getProcessNode().setVectorIndex(index);
if (getVectorIndex() != index) {
setChanged(false);
AttributeDataModification dm = new AttributeDataModification("vectorIndex", null, getIndex());
dm.setReentrant(true);
notifyObservers(dm);
}
} else {
logger.warning("Process node is null for flexo process " + this.getName());
}
}
/**
* Returns a sorted vector of all the abstract activity nodes that are in the underlying activity petrigraph and the ones embedded by
* LOOPOperator and SelfExecutableNode. This is done recursively on all nodes.
*
* @return a sorted vector of all the abstract activity nodes embedded in the petri graph.
*/
public Vector<AbstractActivityNode> getAllEmbeddedSortedAbstractActivityNodes() {
if (_petriGraph != null) {
return _petriGraph.getAllEmbeddedSortedAbstractActivityNodes();
}
return new Vector<AbstractActivityNode>();
}
public Enumeration<AbstractActivityNode> getSortedActivities() {
disableObserving();
AbstractActivityNode[] o = FlexoIndexManager.sortArray(getAllAbstractActivityNodes().toArray(new AbstractActivityNode[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
public Enumeration<AbstractActivityNode> getSortedMeaningFullActivities() {
disableObserving();
AbstractActivityNode[] o = FlexoIndexManager.sortArray(getAllMeaningFullActivityNodes().toArray(new AbstractActivityNode[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
public List<SubProcessNode> getSortedSubProcessNode() {
disableObserving();
SubProcessNode[] o = FlexoIndexManager.sortArray(getAllMeaningSubProcessNodes().toArray(new SubProcessNode[0]));
enableObserving();
return Arrays.asList(o);
}
public List<AbstractActivityNode> getSortedMeaningFullActivitiesAndSubProcessNode() {
disableObserving();
AbstractActivityNode[] o = FlexoIndexManager.sortArray(getAllMeaningFullActivityNodes().toArray(new AbstractActivityNode[0]));
enableObserving();
return Arrays.asList(o);
}
public Enumeration<PetriGraphNode> getSortedActivitiesAndOperators() {
disableObserving();
PetriGraphNode[] o = FlexoIndexManager.sortArray(getAllAbstractActivityNodesAndActivityOperators().toArray(new PetriGraphNode[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
public Enumeration<PetriGraphNode> getSortedActivitiesAndOperatorsWithEvents() {
disableObserving();
PetriGraphNode[] o = FlexoIndexManager.sortArray(getAllAbstractActivityNodesAndActivityOperatorsWithEvents().toArray(
new PetriGraphNode[0]));
enableObserving();
return ToolBox.getEnumeration(o);
}
public Vector<Status> getSortedStatusesVector() {
if (getStatusList() == null) {
return new Vector<Status>();
}
disableObserving();
Vector<Status> v = new Vector<Status>(getStatusList().getStatus());
Collections.sort(v, FlexoIndexManager.INDEX_COMPARATOR);
enableObserving();
return v;
}
public boolean hasAtLeastOneStatusToDocument() {
if (getStatusList() == null) {
return false;
}
Enumeration<Status> en = getStatusList().elements();
while (en.hasMoreElements()) {
if (!en.nextElement().getDontGenerate()) {
return true;
}
}
return false;
}
public boolean hasAtLeastOneEventToDocument() {
Enumeration<EventNode> en = getAllEventNodes().elements();
while (en.hasMoreElements()) {
if (!en.nextElement().getDontGenerate()) {
return true;
}
}
return false;
}
public ProcessStatistics getStatistics() {
if (statistics == null) {
statistics = new ProcessStatistics(this);
}
return statistics;
}
@Override
public ApplicationHelpEntryPoint getParentHelpEntry() {
return getParentProcess();
}
@Override
public List<ApplicationHelpEntryPoint> getChildsHelpObjects() {
Vector<ApplicationHelpEntryPoint> reply = new Vector<ApplicationHelpEntryPoint>();
reply.addAll(getAllActivityNodes());
return reply;
}
@Override
public String getShortHelpLabel() {
return getName();
}
@Override
public String getTypedHelpLabel() {
return "Process : " + getName();
}
public void resolveObjectReferences() {
for (ActionNode node : getAllEmbeddedActionNodes()) {
node.getDisplayProcess();
node.getDisplayOperation();
}
}
public boolean oneAncestorIsNotGenerated() {
if (getDontGenerate()) {
return true;
}
if (getParentProcess() == null) {
return getDontGenerate();
}
return getParentProcess().oneAncestorIsNotGenerated();
}
public String getProcessDictionaryKey() {
return ToolBox.cleanStringForProcessDictionaryKey(getName());
}
public String getBusinessDataDictionaryKey() {
if (getBusinessDataType() != null) {
return ToolBox.cleanStringForProcessDictionaryKey(getBusinessDataType().getName());
}
return AutoGeneratedProcessBusinessDataDMEntity.getProcessBusinessDataEntityNameForProcess(this);
}
public static final String PROCESSINSTANCE_STATUS_KEY = ToolBox.cleanStringForProcessDictionaryKey("status");
public static final String PROCESSINSTANCE_CREATIONDATE_KEY = ToolBox.cleanStringForProcessDictionaryKey("creationDate");
public static final String PROCESSINSTANCE_LASTUPDATEDATE_KEY = ToolBox.cleanStringForProcessDictionaryKey("lastUpdateDate");
/**
* Return a map containing the sample value list for each key used for this process (prototype).
*
* @return a map containing the sample value list for each key used for this process (prototype)..
*/
public Map<String, List<Object>> getProcessInstanceDictionaryPrototypeSamples() {
Map<String, List<Object>> keysTable = new HashMap<String, List<Object>>();
for (IEWidget widget : getWidgetsForProcessInstanceDictionary()) {
String key = widget.getProcessInstanceDictionaryKey();
List<Object> sampleValues = new ArrayList<Object>();
if (widget instanceof IEWidgetWithValueList) {
sampleValues = ((IEWidgetWithValueList) widget).getValueList(this);
}
if (!keysTable.containsKey(key) || keysTable.get(key).size() < sampleValues.size()) {
keysTable.put(widget.getProcessInstanceDictionaryKey(), sampleValues);
}
}
if (getStatusList().size() > 0) {
// Always add status list if any
List<Object> statuses = new ArrayList<Object>();
keysTable.put(PROCESSINSTANCE_STATUS_KEY, statuses);
for (Status status : getStatusList().getStatus()) {
statuses.add(status.getName());
}
}
if (keysTable.get(PROCESSINSTANCE_CREATIONDATE_KEY) == null) {
keysTable.put(PROCESSINSTANCE_CREATIONDATE_KEY, new ArrayList<Object>());
}
if (keysTable.get(PROCESSINSTANCE_LASTUPDATEDATE_KEY) == null) {
keysTable.put(PROCESSINSTANCE_LASTUPDATEDATE_KEY, new ArrayList<Object>());
}
return keysTable;
}
/**
* Return a map with all keys found for this process with their type. Keys are created based on the screen components.
*
* @return a map with all keys found for this process with their type. Keys are created based on the screen components.
*/
public Map<String, Class<? extends Object>> getProcessInstanceDictionaryKeys() {
Map<String, Class<? extends Object>> result = new HashMap<String, Class<? extends Object>>();
for (IEWidget widget : getWidgetsForProcessInstanceDictionary()) {
String key = widget.getProcessInstanceDictionaryKey();
if (key != null) {
Class<? extends Object> type = getProcessInstanceDictionaryType(widget);
if (result.containsKey(key) && result.get(key) != type) {
type = Object.class;
}
result.put(key, type);
}
}
if (getStatusList().size() > 0) {
result.put(PROCESSINSTANCE_STATUS_KEY, String.class);
}
result.put(PROCESSINSTANCE_CREATIONDATE_KEY, Date.class);
result.put(PROCESSINSTANCE_LASTUPDATEDATE_KEY, Date.class);
return result;
}
private List<IEWidget> getWidgetsForProcessInstanceDictionary() {
Map<FlexoProcess, Set<IEWOComponent>> componentsByProcess = new HashMap<FlexoProcess, Set<IEWOComponent>>();
for (OperationComponentInstance ci : getProject().getFlexoWorkflow().getAllComponentInstances()) {
OperationNode operationNode = ci.getOperationNode();
if (operationNode != null && operationNode.hasWOComponent()) {
if (componentsByProcess.get(operationNode.getProcess()) == null) {
componentsByProcess.put(operationNode.getProcess(), new HashSet<IEWOComponent>());
}
componentsByProcess.get(operationNode.getProcess()).add(operationNode.getWOComponent());
}
}
List<IEWidget> allWidgets = new ArrayList<IEWidget>();
for (Map.Entry<FlexoProcess, Set<IEWOComponent>> entry : componentsByProcess.entrySet()) {
for (IEWOComponent woComponent : entry.getValue()) {
allWidgets.addAll(getWidgetsForProcessInstanceFromComponent(woComponent, entry.getKey()));
}
}
return allWidgets;
}
private List<IEWidget> getWidgetsForProcessInstanceFromComponent(IEWOComponent component, FlexoProcess componentProcess) {
List<IEWidget> allWidgets = new ArrayList<IEWidget>();
for (IEWidget widget : component.getAllEmbeddedIEWidgets(IEWidget.class)) {
if (widget.getIsAcceptableForProcessInstanceDictionary(componentProcess, this)) {
allWidgets.add(widget);
}
if (widget instanceof IETabWidget) {
allWidgets.addAll(getWidgetsForProcessInstanceFromComponent(((IETabWidget) widget).getTabComponent(), componentProcess));
}
}
return allWidgets;
}
/**
* Return the type used in the process instance dictionary for the specified IEWidget.
*
* @param widget
* @return the type used in the process instance dictionary for the specified IEWidget.
*/
public Class<? extends Object> getProcessInstanceDictionaryType(IEWidget widget) {
if (widget instanceof IECheckBoxWidget) {
return Boolean.class;
}
if (widget instanceof IEDropDownWidget) {
return String.class;
}
if (widget instanceof IERadioButtonWidget) {
return Boolean.class;
}
if (widget instanceof IETextAreaWidget) {
return String.class;
}
if (widget instanceof IEWysiwygWidget) {
return String.class;
}
TextFieldType fieldType = null;
if (widget instanceof IEHyperlinkWidget) {
fieldType = ((IEHyperlinkWidget) widget).getFieldType();
} else if (widget instanceof IEStringWidget) {
fieldType = ((IEStringWidget) widget).getFieldType();
} else if (widget instanceof IETextFieldWidget) {
fieldType = ((IETextFieldWidget) widget).getFieldType();
}
if (fieldType == null) {
return String.class;
}
switch (fieldType) {
case DATE:
return Date.class;
case DOUBLE:
return Double.class;
case FLOAT:
return Float.class;
case INTEGER:
return Integer.class;
case KEYVALUE:
case STATUS_LIST:
case TEXT:
default:
return String.class;
}
}
public boolean isRoleVisible(Role role) {
for (FlexoModelObjectReference<Role> r : getVisibleRoles()) {
if (r.getObject() == role) {
return true;
}
}
return false;
}
public void setRoleVisible(Role role, boolean visible) {
if (role.isCache()) {
role = role.getRole(true);
if (role == null) {
return;
}
}
if (visible && !isRoleVisible(role)) {
addToVisibleRoles(new FlexoModelObjectReference<Role>(role));
} else if (!visible) {
boolean changed = false;
Iterator<FlexoModelObjectReference<Role>> i = getVisibleRoles().iterator();
while (i.hasNext()) {
FlexoModelObjectReference<org.openflexo.foundation.wkf.Role> ref = i.next();
if (ref.getObject() == role) {
i.remove();
changed = true;
}
}
if (changed) {
setChanged();
notifyAttributeModification(VISIBLE_ROLES, role, null);
}
}
}
}