001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.graph.def;
023:
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029:
030: import org.dom4j.Element;
031: import org.jbpm.JbpmException;
032: import org.jbpm.graph.exe.ExecutionContext;
033: import org.jbpm.jpdl.xml.JpdlXmlReader;
034: import org.jbpm.jpdl.xml.Parsable;
035:
036: /**
037: * brings hierarchy into the elements of a process definition by creating a
038: * parent-child relation between {@link GraphElement}s.
039: */
040: public class SuperState extends Node implements Parsable,
041: NodeCollection {
042:
043: private static final long serialVersionUID = 1L;
044:
045: protected List nodes = null;
046: transient Map nodesMap = null;
047:
048: public SuperState() {
049: }
050:
051: public SuperState(String name) {
052: super (name);
053: }
054:
055: // event types //////////////////////////////////////////////////////////////
056:
057: public static final String[] supportedEventTypes = new String[] {
058: Event.EVENTTYPE_NODE_ENTER, Event.EVENTTYPE_NODE_LEAVE,
059: Event.EVENTTYPE_TASK_CREATE, Event.EVENTTYPE_TASK_ASSIGN,
060: Event.EVENTTYPE_TASK_START, Event.EVENTTYPE_TASK_END,
061: Event.EVENTTYPE_TRANSITION, Event.EVENTTYPE_BEFORE_SIGNAL,
062: Event.EVENTTYPE_AFTER_SIGNAL,
063: Event.EVENTTYPE_SUPERSTATE_ENTER,
064: Event.EVENTTYPE_SUPERSTATE_LEAVE,
065: Event.EVENTTYPE_SUBPROCESS_CREATED,
066: Event.EVENTTYPE_SUBPROCESS_END, Event.EVENTTYPE_TIMER };
067:
068: public String[] getSupportedEventTypes() {
069: return supportedEventTypes;
070: }
071:
072: // xml //////////////////////////////////////////////////////////////////////
073:
074: public void read(Element element, JpdlXmlReader jpdlReader) {
075: jpdlReader.readNodes(element, this );
076: }
077:
078: // behaviour ////////////////////////////////////////////////////////////////
079:
080: public void execute(ExecutionContext executionContext) {
081: if ((nodes == null) || (nodes.size() == 0)) {
082: throw new JbpmException(
083: "transition enters superstate +"
084: + this
085: + "' and it there is no first child-node to delegate to");
086: }
087: Node startNode = (Node) nodes.get(0);
088: startNode.enter(executionContext);
089: }
090:
091: // nodes ////////////////////////////////////////////////////////////////////
092:
093: // javadoc description in NodeCollection
094: public List getNodes() {
095: return nodes;
096: }
097:
098: // javadoc description in NodeCollection
099: public Map getNodesMap() {
100: if ((nodesMap == null) && (nodes != null)) {
101: nodesMap = new HashMap();
102: Iterator iter = nodes.iterator();
103: while (iter.hasNext()) {
104: Node node = (Node) iter.next();
105: nodesMap.put(node.getName(), node);
106: }
107: }
108: return nodesMap;
109: }
110:
111: // javadoc description in NodeCollection
112: public Node getNode(String name) {
113: return (Node) getNodesMap().get(name);
114: }
115:
116: // javadoc description in NodeCollection
117: public boolean hasNode(String name) {
118: return getNodesMap().containsKey(name);
119: }
120:
121: // javadoc description in NodeCollection
122: public Node addNode(Node node) {
123: if (node == null)
124: throw new IllegalArgumentException(
125: "can't add a null node to a superstate");
126: if (nodes == null)
127: nodes = new ArrayList();
128: nodes.add(node);
129: node.super State = this ;
130: nodesMap = null;
131: return node;
132: }
133:
134: // javadoc description in NodeCollection
135: public Node removeNode(Node node) {
136: Node removedNode = null;
137: if (node == null)
138: throw new IllegalArgumentException(
139: "can't remove a null node from a superstate");
140: if (nodes != null) {
141: if (nodes.remove(node)) {
142: removedNode = node;
143: removedNode.super State = null;
144: nodesMap = null;
145: }
146: }
147: return removedNode;
148: }
149:
150: // javadoc description in NodeCollection
151: public void reorderNode(int oldIndex, int newIndex) {
152: if ((nodes != null) && (Math.min(oldIndex, newIndex) >= 0)
153: && (Math.max(oldIndex, newIndex) < nodes.size())) {
154: Object o = nodes.remove(oldIndex);
155: nodes.add(newIndex, o);
156: } else {
157: throw new IndexOutOfBoundsException(
158: "couldn't reorder element from index '" + oldIndex
159: + "' to index '" + newIndex
160: + "' in nodeList '" + nodes + "'");
161: }
162: }
163:
164: // javadoc description in NodeCollection
165: public String generateNodeName() {
166: return ProcessDefinition.generateNodeName(nodes);
167: }
168:
169: // javadoc description in NodeCollection
170: public Node findNode(String hierarchicalName) {
171: return ProcessDefinition.findNode(this , hierarchicalName);
172: }
173:
174: /**
175: * recursively checks if the given node is one of the descendants of this supernode.
176: */
177: public boolean containsNode(Node node) {
178: boolean containsNode = false;
179: SuperState parent = node.getSuperState();
180: while ((!containsNode) && (parent != null)) {
181: if (this .equals(parent)) {
182: containsNode = true;
183: } else {
184: parent = parent.getSuperState();
185: }
186: }
187: return containsNode;
188: }
189:
190: // other ////////////////////////////////////////////////////////////////////
191:
192: public GraphElement getParent() {
193: GraphElement parent = processDefinition;
194: if (super State != null) {
195: parent = super State;
196: }
197: return parent;
198: }
199:
200: public boolean isSuperStateNode() {
201: return true;
202: }
203: }
|