package jadex.bpmn.model;
import jadex.bridge.IArgument;
import jadex.bridge.IModelInfo;
import jadex.bridge.ModelInfo;
import jadex.commons.ICacheableModel;
import jadex.commons.SReflect;
import jadex.commons.SUtil;
import jadex.javaparser.IParsedExpression;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
/**
* Java representation of a bpmn model for xml description.
*/
public class MBpmnModel extends MAnnotationElement implements ICacheableModel//, ILoadableComponentModel
{
//-------- constants --------
/** Constant for task. */
public static final String TASK = "Task";
/** Constant for sub process. */
public static final String SUBPROCESS = "SubProcess";
/** Constant for gateway parallel. */
public static final String GATEWAY_PARALLEL = "GatewayParallel";
/** Constant for gateway data based exclusive. */
public static final String GATEWAY_DATABASED_EXCLUSIVE = "GatewayDataBasedExclusive";
/** Constant for event start empty. */
public static final String EVENT_START_EMPTY = "EventStartEmpty";
/** Constant for event start message. */
public static final String EVENT_START_MESSAGE = "EventStartMessage";
/** Constant for event start timer. */
public static final String EVENT_START_TIMER = "EventStartTimer";
/** Constant for event start rule. */
public static final String EVENT_START_RULE = "EventStartRule";
/** Constant for event start signal. */
public static final String EVENT_START_SIGNAL = "EventStartSignal";
/** Constant for event start multiple. */
public static final String EVENT_START_MULTIPLE = "EventStartMultiple";
/** Constant for event end empty. */
public static final String EVENT_END_EMPTY = "EventEndEmpty";
/** Constant for event end error. */
public static final String EVENT_END_ERROR = "EventEndError";
/** Constant for event end message. */
public static final String EVENT_END_MESSAGE = "EventEndMessage";
/** Constant for event start empty. */
public static final String EVENT_INTERMEDIATE_EMPTY = "EventIntermediateEmpty";
/** Constant for event intermediate error. */
public static final String EVENT_INTERMEDIATE_ERROR = "EventIntermediateError";
/** Constant for event intermediate rule. */
public static final String EVENT_INTERMEDIATE_RULE = "EventIntermediateRule";
/** Constant for event intermediate signal. */
public static final String EVENT_INTERMEDIATE_SIGNAL = "EventIntermediateSignal";
/** Constant for event intermediate message. */
public static final String EVENT_INTERMEDIATE_MESSAGE = "EventIntermediateMessage";
/** Constant for event intermediate timer. */
public static final String EVENT_INTERMEDIATE_TIMER = "EventIntermediateTimer";
/** Constant for event intermediate multiple. */
public static final String EVENT_INTERMEDIATE_MULTIPLE = "EventIntermediateMultiple";
//-------- attributes --------
/** The suspend flag. */
protected Boolean suspend;
/** The master flag. */
protected Boolean master;
/** The daemon flag. */
protected Boolean daemon;
/** The autoshutdown flag. */
protected Boolean autoshutdown;
/** The pools. */
protected List pools;
/** The artifacts. */
protected List artifacts;
/** The messages. */
protected List messages;
//-------- init structures --------
/** The cached edges of the model. */
protected Map alledges;
/** The cached activities of the model. */
protected Map allactivities;
/** The association sources. */
protected Map associationsources;
/** The association targets. */
protected Map associationtargets;
/** The messaging edges. */
protected Map allmessagingedges;
//-------- added structures --------
// /** The name of the model. */
// protected String name;
// /** The package. */
// protected String packagename;
// /** The description. */
// protected String description;
// /** The properties. */
// protected Map properties;
/** The imports. */
protected List imports;
/** The context variables (name -> [class, initexpression]). */
protected Map variables;
// /** The arguments. */
// protected List arguments;
//
// /** The results. */
// protected List results;
//-------- model management --------
// /** The filename. */
// protected String filename;
/** The last modified date. */
protected long lastmodified;
/** The last check date. */
protected long lastchecked;
// /** The classloader. */
// protected ClassLoader classloader;
/** The model info. */
protected ModelInfo modelinfo;
//-------- methods --------
/**
* Create a new model.
*/
public MBpmnModel()
{
this.modelinfo = new ModelInfo();
}
/**
* Init the model info.
*/
public void initModelInfo()
{
List names = new ArrayList();
for(Iterator it=getAllActivities().values().iterator(); it.hasNext(); )
{
names.add(((MActivity)it.next()).getBreakpointId());
}
addProperty("debugger.breakpoints", names);
addMethodInfos(getModelInfo().getProperties(), "remote_excluded", new String[]{"getServiceProvider"});
modelinfo.setConfigurations(getConfigurations());
modelinfo.setStartable(true);
}
/**
* Add method info.
*/
public static void addMethodInfos(Map props, String type, String[] names)
{
Object ex = props.get(type);
if(ex!=null)
{
List newex = new ArrayList();
for(Iterator it=SReflect.getIterator(ex); it.hasNext(); )
{
newex.add(it.next());
}
for(int i=0; i<names.length; i++)
{
newex.add(names[i]);
}
}
else
{
props.put(type, names);
}
}
/**
* Get the pools.
* @return The pools.
*/
public List getPools()
{
return pools;
}
/**
* Add a pool.
* @param pool The pool.
*/
public void addPool(MPool pool)
{
if(pools==null)
pools = new ArrayList();
pools.add(pool);
}
/**
* Remove a pool.
* @param pool The pool.
*/
public void removePool(MPool pool)
{
if(pools!=null)
pools.remove(pool);
}
/**
* Get the pools.
* @return The pools.
*/
public MPool getPool(String name)
{
MPool ret = name==null? (MPool)pools.get(0): null;
for(int i=0; i<pools.size() && ret==null; i++)
{
MPool tmp = (MPool)pools.get(i);
if(tmp.getName().equals(name))
ret = tmp;
}
return ret;
}
/**
* Get the artifacts.
* @return The artifacts.
*/
public List getArtifacts()
{
return artifacts;
}
/**
* Add an artifact.
* @param artifact The artifact.
*/
public void addArtifact(MArtifact artifact)
{
if(artifacts==null)
artifacts = new ArrayList();
artifacts.add(artifact);
}
/**
* Remove an artifact.
* @param artifact The artifact.
*/
public void removeArtifact(MArtifact artifact)
{
if(artifacts!=null)
artifacts.remove(artifact);
}
/**
* Get the message edges.
* @return The message edges.
*/
public List getMessagingEdges()
{
return messages;
}
/**
* Add a message edge.
* @param message The message edfe.
*/
public void addMessagingEdge(MMessagingEdge message)
{
if(messages==null)
messages = new ArrayList();
messages.add(message);
}
/**
* Remove a message edge.
* @param message The message.
*/
public void removeMessagingEdge(MMessagingEdge message)
{
if(messages!=null)
messages.remove(message);
}
//-------- helper init methods --------
/**
* Get all message edges.
* @return The message edges (id -> edge).
*/
public Map getAllMessagingEdges()
{
if(this.allmessagingedges==null)
{
this.allmessagingedges = new HashMap();
List messages = getMessagingEdges();
if(messages!=null)
{
for(int i=0; i<messages.size(); i++)
{
MMessagingEdge msg = (MMessagingEdge)messages.get(i);
allmessagingedges.put(msg.getId(), msg);
}
}
}
return allmessagingedges;
}
/**
* Get all sequence edges.
* @return The sequence edges (id -> edge).
*/
public Map getAllSequenceEdges()
{
if(this.alledges==null)
{
this.alledges = new HashMap();
// todo: hierarchical search also in lanes of pools?!
List pools = getPools();
if(pools!=null)
{
for(int i=0; i<pools.size(); i++)
{
MPool tmp = (MPool)pools.get(i);
addEdges(tmp.getSequenceEdges(), alledges);
List acts = tmp.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
if(acts.get(j) instanceof MSubProcess)
{
getAllEdges((MSubProcess)acts.get(j), alledges);
}
}
}
}
}
}
return alledges;
}
/**
* Get all activities.
* @return The activities (id -> activity).
*/
public Map getAllActivities()
{
if(this.allactivities==null)
{
this.allactivities = new HashMap();
List pools = getPools();
if(pools!=null)
{
for(int i=0; i<pools.size(); i++)
{
MPool tmp = (MPool)pools.get(i);
List acts = tmp.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
MActivity mact = (MActivity)acts.get(j);
allactivities.put(mact.getId(), acts.get(j));
if(mact instanceof MSubProcess)
{
addAllSubActivities((MSubProcess)mact, allactivities);
}
}
}
}
}
}
return allactivities;
}
/**
* Add all subactivities.
*/
public void addAllSubActivities(MSubProcess proc, Map activities)
{
List acts = proc.getActivities();
if(acts!=null)
{
for(int i=0; i<acts.size(); i++)
{
MActivity mact = (MActivity)acts.get(i);
allactivities.put(mact.getId(), acts.get(i));
if(mact instanceof MSubProcess)
{
addAllSubActivities((MSubProcess)mact, activities);
}
}
}
}
/**
* Internal get all edges.
* @param sub The subprocess.
* @param edges The edges (results will be added to this).
*/
protected void getAllEdges(MSubProcess sub, Map edges)
{
addEdges(sub.getSequenceEdges(), edges);
List acts = sub.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
if(acts.get(j) instanceof MSubProcess)
{
getAllEdges((MSubProcess)acts.get(j), edges);
}
}
}
}
/**
* Add edges to the result map.
* @param tmp The list of edges.
* @param edges The result map (id -> edge).
*/
protected void addEdges(List tmp, Map edges)
{
if(tmp!=null)
{
for(int i=0; i<tmp.size(); i++)
{
MSequenceEdge edge = (MSequenceEdge)tmp.get(i);
edges.put(edge.getId(), edge);
}
}
}
/**
* Get all association targets.
* @return A map of association targets (association id -> target).
*/
public Map getAllAssociationTargets()
{
if(this.associationtargets==null)
{
this.associationtargets = new HashMap();
// Add pools
List pools = getPools();
if(pools!=null)
{
for(int i=0; i<pools.size(); i++)
{
MPool pool = (MPool)pools.get(i);
addAssociations(pool.getAssociationsDescription(), pool, associationtargets);
// Add lanes
List lanes = pool.getLanes();
if(lanes!=null)
{
for(int j=0; j<lanes.size(); j++)
{
MLane lane = (MLane)lanes.get(j);
addAssociations(lane.getAssociationsDescription(), lane, associationtargets);
}
}
// Add activities
List acts = pool.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
MActivity act = (MActivity)acts.get(j);
addActivityTargets(act);
}
}
}
}
// Add edges
Map edges = getAllSequenceEdges();
for(Iterator it=edges.values().iterator(); it.hasNext(); )
{
MSequenceEdge edge = (MSequenceEdge)it.next();
addAssociations(edge.getAssociationsDescription(), edge, associationtargets);
}
}
return associationtargets;
}
/**
* Internal add activity targets.
* @param act The activity.
*/
protected void addActivityTargets(MActivity act)
{
addAssociations(act.getAssociationsDescription(), act, associationtargets);
if(act instanceof MSubProcess)
{
List acts = ((MSubProcess)act).getActivities();
if(acts!=null)
{
for(int i=0; i<acts.size(); i++)
{
MActivity subact = (MActivity)acts.get(i);
addActivityTargets(subact);
}
}
}
}
/**
* Internal add associations.
* @param target The target.
* @param targets The targets result map.
*/
protected boolean addAssociations(String assosdesc, MIdElement target, Map targets)
{
boolean ret = false;
// String assosdesc = target.getAssociationsDescription();
if(assosdesc!=null)
{
StringTokenizer stok = new StringTokenizer(assosdesc);
while(stok.hasMoreElements() && !ret)
{
String assoid = stok.nextToken();
targets.put(assoid, target);
}
}
return ret;
}
/**
* Get all association sources.
* @return The map of association sources (association id -> source).
*/
public Map getAllAssociationSources()
{
if(this.associationsources==null)
{
this.associationsources = new HashMap();
addArtifacts(getArtifacts(), associationsources);
List pools = getPools();
if(pools!=null)
{
for(int i=0; i<pools.size(); i++)
{
MPool pool = (MPool)pools.get(i);
addArtifacts(pool.getArtifacts(), associationsources);
// Search subprocesses
List acts = pool.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
Object act = acts.get(j);
if(act instanceof MSubProcess)
{
addSubProcesses((MSubProcess)act, associationsources);
}
}
}
}
}
}
return associationsources;
}
/**
* Add sub processes.
* @param subproc The sub process.
* @param sources The sources result map.
*/
protected void addSubProcesses(MSubProcess subproc, Map sources)
{
List artifacts = subproc.getArtifacts();
addArtifacts(artifacts, sources);
List acts = subproc.getActivities();
if(acts!=null)
{
for(int j=0; j<acts.size(); j++)
{
Object act = acts.get(j);
if(act instanceof MSubProcess)
{
addSubProcesses(((MSubProcess)act), sources);
}
}
}
}
/**
* Add artifacts.
* @param artifacts The list of artifacts.
* @param sources The sources result map (association id -> art).
*/
protected MArtifact addArtifacts(List artifacts, Map sources)
{
MArtifact ret = null;
if(artifacts!=null)
{
for(int i=0; i<artifacts.size() && ret==null; i++)
{
MArtifact art = (MArtifact)artifacts.get(i);
List assos = art.getAssociations();
if(assos!=null)
{
for(int j=0; j<assos.size(); j++)
{
MAssociation asso = (MAssociation)assos.get(j);
sources.put(asso.getId(), art);
}
}
}
}
return ret;
}
/**
* Get the name of the model.
* @return The name of the model.
*/
public String getName()
{
return modelinfo.getName();
}
/**
* Set the name of the model.
* @param name The name to set.
*/
public void setName(String name)
{
modelinfo.setName(name);
}
/**
* Get the full model name (package.name)
* @return The full name.
* /
public String getFullName()
{
String pkg = getPackage();
return pkg!=null && pkg.length()>0? pkg+"."+getName(): getName();
}*/
/**
* Get all start activities of the model.
* @return A non-empty List of start activities or null, if none.
*/
public List getStartActivities()
{
List ret = null;
for(int i=0; pools!=null && i<pools.size(); i++)
{
MPool pool = (MPool) pools.get(i);
List tmp = pool.getStartActivities();
if(tmp!=null)
{
if(ret!=null)
ret.addAll(tmp);
else
ret = tmp;
}
}
return ret;
}
/**
* Get all imports.
* @return The imports.
*/
public String[] getAllImports()
{
List ret = new ArrayList();
if(modelinfo.getPackage()!=null)
ret.add(modelinfo.getPackage()+".*");
if(imports!=null)
ret.addAll(imports);
return (String[])ret.toArray(new String[ret.size()]);
}
/**
* Set the imports.
* @param imports The imports.
* /
public void setImports(String[] imports)
{
this.imports = imports;
}*/
/**
* Add an import.
* @param import The import statement.
*/
public void addImport(String imp)
{
if(imports==null)
imports = new ArrayList();
this.imports.add(imp);
}
/**
* Get the package name.
* @return The package name.
* /
public String getPackage()
{
return modelinfo.getPackage();
}*/
/**
* Set the package name.
* @param packagename The package name to set.
*/
public void setPackage(String packagename)
{
modelinfo.setPackage(packagename);
}
/**
* Get a string representation of this AGR space type.
* @return A string representation of this AGR space type.
*/
public String toString()
{
StringBuffer sbuf = new StringBuffer();
sbuf.append(SReflect.getInnerClassName(getClass()));
sbuf.append("(name=");
sbuf.append(getName());
sbuf.append(")");
return sbuf.toString();
}
//-------- static part --------
/**
* Get all start activities form the supplied set of activities.
* Start activities are those without incoming edges.
* @return A non-empty List of start activities or null, if none.
*/
public static List getStartActivities(List activities)
{
List ret = null;
if (activities != null)
{
for(Iterator it=activities.iterator(); it.hasNext(); )
{
MActivity activity = (MActivity) it.next();
if(activity.getIncomingSequenceEdges()==null || activity.getIncomingSequenceEdges().isEmpty())
{
if(ret==null)
{
ret = new ArrayList();
}
ret.add(activity);
}
}
}
return ret;
}
/**
* Add a context variable declaration.
* @param name The variable name.
* @param clazz The type of the variable
* @param exp An initialization expression (if any).
*/
public void addContextVariable(String name, Class clazz, IParsedExpression exp)
{
if(variables==null)
variables = new HashMap();
variables.put(name, new Object[]{clazz, exp});
}
/**
* Remove a context variable declaration.
* @param name The variable name.
*/
public void removeContextVariable(String name)
{
if(variables!=null)
{
variables.remove(name);
if(variables.isEmpty())
{
variables = null;
}
}
}
/**
* Get the declared context variables.
* @return A set of variable names.
*/
public Set getContextVariables()
{
return variables!=null ? variables.keySet() : Collections.EMPTY_SET;
}
/**
* Get the class of a declared context variable.
* @param name The variable name.
* @return The class of the variable.
*/
public Class getContextVariableClass(String name)
{
return (Class)((Object[])variables.get(name))[0];
}
/**
* Get the initialization expression of a declared context variable.
* @param name The variable name.
* @return The initialization expression (if any).
*/
public IParsedExpression getContextVariableExpression(String name)
{
return (IParsedExpression)((Object[])variables.get(name))[1];
}
/**
* Get the filename.
* @return The filename.
* /
public String getFilename()
{
return modelinfo.getFilename();
}*/
/**
* Set the filename.
* @param filename The filename to set.
*/
public void setFilename(String filename)
{
modelinfo.setFilename(filename);
}
/**
* Get the lastmodified date.
* @return The lastmodified date.
*/
public long getLastModified()
{
return this.lastmodified;
}
/**
* Set the lastmodified date.
* @param lastmodified The lastmodified date to set.
*/
public void setLastModified(long lastmodified)
{
this.lastmodified = lastmodified;
}
/**
* Get the last checked date.
* @return The last checked date
*/
public long getLastChecked()
{
return this.lastchecked;
}
/**
* Set the last checked date.
* @param lastchecked The last checked date to set.
*/
public void setLastChecked(long lastchecked)
{
this.lastchecked = lastchecked;
}
/**
* Get the configurations.
* @return The configuration.
*/
protected String[] getConfigurations()
{
// Todo: more in configuration than just pools/lanes?
String[] ret;
List pools = getPools();
if(pools!=null)
{
List aret = new ArrayList();
if(pools.size()>1)
{
aret.add("All");
}
for(int i=0; i<pools.size(); i++)
{
MPool pool = (MPool)pools.get(i);
aret.add(pool.getName());
List lanes = pool.getLanes();
if(lanes!=null)
{
for(int j=0; j<lanes.size(); j++)
{
MLane lane = (MLane)lanes.get(j);
String name = lane.getName();
while(lane.getLane()!=null)
{
lane = lane.getLane();
name = lane.getName() + "." + name;
}
aret.add(pool.getName()+"."+name);
}
ret = (String[])aret.toArray(new String[aret.size()]);
}
}
ret = (String[])aret.toArray(new String[aret.size()]);
}
else
{
ret = SUtil.EMPTY_STRING_ARRAY;
}
return ret;
}
// /**
// * Is the model startable.
// * @return True, if startable.
// */
// public boolean isStartable()
// {
// return true;
// }
/**
* Set the description.
* @param description The description to set.
*/
public void setDescription(String description)
{
modelinfo.setDescription(description);
}
/**
* Get the model description.
* @return The model description.
* /
public String getDescription()
{
// todo: implement me
// use description from artifact, or from property field of special editor
return modelinfo.getDescription();
}*/
/**
* Add an argument.
* @param argument The argument.
*/
public void addArgument(IArgument argument)
{
modelinfo.addArgument(argument);
}
/**
* Get the arguments.
* @return The arguments.
* /
public IArgument[] getArguments()
{
return modelinfo.getArguments();
}*/
/**
* Get the report.
* @return The report.
* /
public IReport getReport()
{
return modelinfo.getReport();
}*/
/**
* Get the properties.
* Arbitrary properties that can e.g. be used to
* define kernel-specific settings to configure tools.
* @return The properties.
* /
public Map getProperties()
{
if(properties==null)
{
Map props = new HashMap();
List names = new ArrayList();
for(Iterator it=getAllActivities().values().iterator(); it.hasNext(); )
{
names.add(((MActivity)it.next()).getBreakpointId());
}
props.put("debugger.breakpoints", names);
this.properties = props;
}
return this.properties;
}*/
/**
* Add a property.
*/
public void addProperty(String name, Object value)
{
modelinfo.addProperty(name, value);
}
/**
* Return the class loader corresponding to the micro agent class.
* /
public ClassLoader getClassLoader()
{
return modelinfo.getClassLoader();
}*/
/**
* Add a result.
* @param result The result.
*/
public void addResult(IArgument result)
{
modelinfo.addResult(result);
}
/**
* Get the results.
* @return The results.
* /
public IArgument[] getResults()
{
return modelinfo.getResults();
}*/
/**
* Set the classloader.
* @param classloader The classloader to set.
*/
public void setClassloader(ClassLoader classloader)
{
modelinfo.setClassloader(classloader);
}
/**
* Get the model info.
* @return The model info.
*/
public IModelInfo getModelInfo()
{
return modelinfo;
}
/**
* Get the master.
* @return the master.
*/
public Boolean getMaster()
{
return master;
}
/**
* Set the master.
* @param master The master to set.
*/
public void setMaster(Boolean master)
{
this.master = master;
}
/**
* Get the daemon.
* @return the daemon.
*/
public Boolean getDaemon()
{
return daemon;
}
/**
* Set the daemon.
* @param daemon The daemon to set.
*/
public void setDaemon(Boolean daemon)
{
this.daemon = daemon;
}
/**
* Get the autoshutdown.
* @return the autoshutdown.
*/
public Boolean getAutoShutdown()
{
return autoshutdown;
}
/**
* Set the autoshutdown.
* @param autoshutdown The autoshutdown to set.
*/
public void setAutoShutdown(Boolean autoshutdown)
{
this.autoshutdown = autoshutdown;
}
/**
* Get the suspend.
* @return the suspend.
*/
public Boolean getSuspend()
{
return suspend;
}
/**
* Set the suspend.
* @param suspend The suspend to set.
*/
public void setSuspend(Boolean suspend)
{
this.suspend = suspend;
}
}