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 javax.xml.transform.*;
064: import javax.xml.transform.dom.*;
065: import javax.xml.transform.stream.*;
066: import java.util.*;
067: import java.text.*;
068: import java.io.*;
069: import xflow.util.*;
070: import xflow.common.*;
071: import org.apache.log4j.Logger;
072:
073: public class XflowGraphSerializer {
074:
075: private static Logger log = Logger
076: .getLogger(XflowGraphSerializer.class);
077: private static String template = "<xflow><nodes></nodes><transitions></transitions></xflow>";
078:
079: public static String serialize(DirectedGraph dg)
080: throws XflowException {
081:
082: String graphName = dg.getName();
083: String result = null;
084: try {
085: DocumentBuilderFactory factory = DocumentBuilderFactory
086: .newInstance();
087: DocumentBuilder builder = factory.newDocumentBuilder();
088:
089: StringReader sreader = new StringReader(template);
090: InputSource is = new InputSource(sreader);
091: Document doc = builder.parse(is);
092:
093: NodeList els = doc.getElementsByTagName("xflow");
094: Element xflowEl = (Element) els.item(0);
095: xflowEl.setAttribute("name", graphName);
096:
097: els = doc.getElementsByTagName("nodes");
098: Element nodesEl = (Element) els.item(0);
099:
100: // Serialize nodes
101: Vector gnodes = dg.getAllNodes();
102: for (int i = 0; i < gnodes.size(); i++) {
103: xflow.common.Node gnode = (xflow.common.Node) gnodes
104: .elementAt(i);
105: String nodeName = gnode.getNodeName();
106: String nodeType = gnode.getNodeType();
107: Element nodeEl = doc.createElement("node");
108: nodesEl.appendChild(nodeEl);
109: nodeEl.setAttribute("id", nodeName);
110: nodeEl.setAttribute("type", nodeType);
111: if (nodeType.equals(xflow.common.Node.CONTAINER)) {
112: String containee = gnode.getContainee();
113: nodeEl.setAttribute("containee", containee);
114: int containeeVersion = gnode.getContaineeVersion();
115: if (containeeVersion != -1) {
116: nodeEl.setAttribute("containeeVersion", ""
117: + containeeVersion);
118: }
119: }
120: if (nodeType.equals(xflow.common.Node.PROCESS)) {
121: int timeoutMinutes = gnode.getTimeoutMinutes();
122: if (timeoutMinutes != -1) {
123: nodeEl.setAttribute("timeoutMinutes", ""
124: + timeoutMinutes);
125: }
126: String timeoutHandler = gnode.getTimeoutHandler();
127: if (timeoutHandler != null) {
128: nodeEl.setAttribute("timeoutHandler",
129: timeoutHandler);
130: }
131: }
132: }
133:
134: // Serialize transitions
135: els = doc.getElementsByTagName("transitions");
136: Element transitionsEl = (Element) els.item(0);
137:
138: xflow.common.Node rootNode = dg.getRootNode();
139: serializeTransitions(doc, transitionsEl, rootNode);
140:
141: result = serialize(doc.getDocumentElement());
142: } catch (Exception e) {
143: throw new XflowException(e.getMessage());
144: }
145: return result;
146: }
147:
148: public static String serialize(Element element)
149: throws XflowException {
150:
151: String serialized = null;
152:
153: try {
154: element.normalize();
155:
156: // Use a Transformer for output
157: TransformerFactory tFactory = TransformerFactory
158: .newInstance();
159: Transformer transformer = tFactory.newTransformer();
160:
161: DOMSource source = new DOMSource(element);
162: StringWriter writer = new StringWriter();
163: StreamResult result = new StreamResult(writer);
164: transformer.transform(source, result);
165: serialized = writer.toString();
166: } catch (Exception e) {
167: throw new XflowException(e.getMessage());
168: }
169:
170: return serialized;
171: }
172:
173: private static void serializeTransitions(Document doc,
174: Element transitionsEl, xflow.common.Node gnode) {
175:
176: Vector destinations = gnode.getDestinations();
177: for (int i = 0; i < destinations.size(); i++) {
178: Destination d = (Destination) destinations.elementAt(i);
179: Element transEl = doc.createElement("transition");
180: transitionsEl.appendChild(transEl);
181: transEl.setAttribute("from", gnode.getNodeName());
182: transEl.setAttribute("to", d.node.getNodeName());
183: if (d.rule != null) {
184: Element ruleEl = doc.createElement("rule");
185: Text textEl = doc.createTextNode(d.rule);
186: ruleEl.appendChild(textEl);
187: transEl.appendChild(ruleEl);
188: }
189:
190: serializeTransitions(doc, transitionsEl, d.node);
191: }
192: }
193:
194: // Simple test
195: public static void main(String[] args) throws XflowException {
196:
197: DirectedGraph dg = new DirectedGraph("test");
198: xflow.common.Node gnode1 = new xflow.common.Node("Start",
199: xflow.common.Node.START);
200: xflow.common.Node gnode2 = new xflow.common.Node("P1",
201: xflow.common.Node.PROCESS);
202: gnode2.setTimeoutMinutes(12);
203: gnode2.setTimeoutHandler("MyHandler");
204: xflow.common.Node gnode3 = new xflow.common.Node("P2",
205: xflow.common.Node.PROCESS);
206: xflow.common.Node gnode4 = new xflow.common.Node("P3",
207: xflow.common.Node.CONTAINER);
208: gnode4.setContainee("MyContainee");
209: xflow.common.Node gnode5 = new xflow.common.Node("End",
210: xflow.common.Node.END);
211:
212: dg.setRootNode(gnode1);
213: gnode1.addDestination(gnode2, null);
214: gnode2.addDestination(gnode3, null);
215: gnode3.addDestination(gnode4, null);
216: gnode4.addDestination(gnode5,
217: "//book/detail/inventory[@copies > 50]");
218:
219: System.out.println(dg.toXML());
220: }
221: }
|