001: /*
002: * ====================================================================
003: *
004: * XFLOW - Process Management System
005: * Copyright (C) 2003 Rob Tan
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions, and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions, and the disclaimer that follows
017: * these conditions in the documentation and/or other materials
018: * provided with the distribution.
019: *
020: * 3. The name "XFlow" must not be used to endorse or promote products
021: * derived from this software without prior written permission. For
022: * written permission, please contact rcktan@yahoo.com
023: *
024: * 4. Products derived from this software may not be called "XFlow", nor
025: * may "XFlow" appear in their name, without prior written permission
026: * from the XFlow Project Management (rcktan@yahoo.com)
027: *
028: * In addition, we request (but do not require) that you include in the
029: * end-user documentation provided with the redistribution and/or in the
030: * software itself an acknowledgement equivalent to the following:
031: * "This product includes software developed by the
032: * XFlow Project (http://xflow.sourceforge.net/)."
033: * Alternatively, the acknowledgment may be graphical using the logos
034: * available at http://xflow.sourceforge.net/
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE XFLOW AUTHORS OR THE PROJECT
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: * ====================================================================
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the XFlow Project and was originally
052: * created by Rob Tan (rcktan@yahoo.com)
053: * For more information on the XFlow Project, please see:
054: * <http://xflow.sourceforge.net/>.
055: * ====================================================================
056: */
057:
058: package xflow.util;
059:
060: import org.w3c.dom.*;
061: import org.xml.sax.*;
062: import javax.xml.parsers.*;
063: import java.util.*;
064: import java.text.*;
065: import java.io.*;
066: import xflow.util.*;
067: import xflow.common.*;
068: import org.apache.log4j.Logger;
069:
070: public class XflowXMLParser {
071:
072: private static Logger log = Logger.getLogger(XflowXMLParser.class);
073:
074: public static DirectedGraph parse(String xml) throws XflowException {
075:
076: String graphName = null;
077: DirectedGraph rgraph = null;
078:
079: HashMap pm = new HashMap();
080: HashMap rootc = new HashMap();
081:
082: // Parse the xml string
083: try {
084: DocumentBuilderFactory factory = DocumentBuilderFactory
085: .newInstance();
086: DocumentBuilder builder = factory.newDocumentBuilder();
087:
088: StringReader sreader = new StringReader(xml);
089: InputSource is = new InputSource(sreader);
090: Document doc = builder.parse(is);
091:
092: NodeList els = doc.getElementsByTagName("xflow");
093: Element el = (Element) els.item(0);
094: if (el != null) {
095: graphName = el.getAttribute("name");
096: if (graphName == null) {
097: throw new XflowException(
098: "xflow name attribute not found in XML file.");
099: }
100: rgraph = new DirectedGraph(graphName);
101: } else {
102: throw new XflowException(
103: "<xflow> element not found in XML file.");
104: }
105:
106: els = doc.getElementsByTagName("node");
107: int count = els.getLength();
108: for (int i = 0; i < count; i++) {
109: el = (Element) els.item(i);
110: String nodeName = el.getAttribute("id");
111: if (nodeName == null) {
112: throw new XflowException("node id is not defined.");
113: }
114: String nodeType = el.getAttribute("type");
115: if (nodeType == null) {
116: throw new XflowException(
117: "node type is not defined.");
118: }
119: xflow.common.Node gnode = new xflow.common.Node(
120: nodeName, nodeType);
121:
122: String timeOut = el.getAttribute("timeoutMinutes");
123: if (timeOut != null && !timeOut.equals("")) {
124: Integer dTimeOut = new Integer(timeOut);
125: gnode.setTimeoutMinutes(dTimeOut.intValue());
126: String timeOutHandler = el
127: .getAttribute("timeoutHandler");
128: if (timeOutHandler != null) {
129: gnode.setTimeoutHandler(timeOutHandler);
130: }
131: }
132: log.info("Putting: " + nodeName + " : "
133: + gnode.getNodeName() + " "
134: + gnode.getNodeType());
135: pm.put(nodeName, gnode);
136: if (nodeType.equals(xflow.common.Node.CONTAINER)) {
137: String containee = el.getAttribute("containee");
138: if (containee == null) {
139: throw new XflowException(
140: "Containee not defined for container process");
141: }
142: gnode.setContainee(containee);
143: }
144: }
145:
146: els = doc.getElementsByTagName("transition");
147: count = els.getLength();
148: for (int i = 0; i < count; i++) {
149: el = (Element) els.item(i);
150: String fromNodeName = el.getAttribute("from");
151: String toNodeName = el.getAttribute("to");
152: rootc.put(toNodeName, toNodeName);
153: xflow.common.Node fromNode = (xflow.common.Node) pm
154: .get(fromNodeName);
155: xflow.common.Node toNode = (xflow.common.Node) pm
156: .get(toNodeName);
157:
158: log.info(fromNode.getNodeName() + " to "
159: + toNode.getNodeName());
160: NodeList els2 = el.getElementsByTagName("rule");
161: Element e = (Element) els2.item(0);
162: String rule = null;
163: if (e != null) {
164: org.w3c.dom.Node node = e.getFirstChild();
165: rule = node.getNodeValue();
166: log.info(rule);
167: }
168:
169: fromNode.addDestination(toNode, rule);
170: }
171:
172: } catch (Exception e) {
173: throw new XflowException(e.getMessage());
174: }
175:
176: try {
177: String rootNodeId = findRootNodeId(pm, rootc);
178: if (rootNodeId == null) {
179: throw new XflowException("No root node in graph");
180: }
181: xflow.common.Node rootNode = (xflow.common.Node) pm
182: .get(rootNodeId);
183: rgraph.setRootNode(rootNode);
184: rootNode.traverse();
185: } catch (Exception e) {
186: throw new XflowException(e.getMessage());
187: }
188:
189: return rgraph;
190: }
191:
192: public static String findRootNodeId(HashMap pm, HashMap rootc)
193: throws Exception {
194:
195: String result = null;
196:
197: Iterator itr = pm.keySet().iterator();
198: while (itr.hasNext()) {
199: String nid = (String) itr.next();
200: if (rootc.get(nid) == null) {
201: if (result == null) {
202: result = nid;
203: } else {
204: throw new Exception(
205: "Graph has more than one root node");
206: }
207: }
208: }
209: return result;
210: }
211:
212: // Simple test
213: public static void main(String[] args) throws Exception {
214: String xml = "<xflow name=\"Test\"><nodes><node id=\"StartNode\" type=\"Start\"/><node id=\"P1\" type=\"Process\"/><node id=\"EndNode\" type=\"End\"/></nodes><transitions><transition from=\"StartNode\" to=\"P1\"/><transition from=\"P1\" to=\"EndNode\"/></transitions></xflow>";
215: DirectedGraph g = parse(xml);
216: g.getRootNode().traverse();
217: }
218: }
|