📄 scxmlserializer.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.scxml.io;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml.SCXMLHelper;
import org.apache.commons.scxml.model.Action;
import org.apache.commons.scxml.model.Assign;
import org.apache.commons.scxml.model.Cancel;
import org.apache.commons.scxml.model.Data;
import org.apache.commons.scxml.model.Datamodel;
import org.apache.commons.scxml.model.Else;
import org.apache.commons.scxml.model.ElseIf;
import org.apache.commons.scxml.model.Exit;
import org.apache.commons.scxml.model.ExternalContent;
import org.apache.commons.scxml.model.Finalize;
import org.apache.commons.scxml.model.History;
import org.apache.commons.scxml.model.If;
import org.apache.commons.scxml.model.Initial;
import org.apache.commons.scxml.model.Invoke;
import org.apache.commons.scxml.model.Log;
import org.apache.commons.scxml.model.NamespacePrefixesHolder;
import org.apache.commons.scxml.model.OnEntry;
import org.apache.commons.scxml.model.OnExit;
import org.apache.commons.scxml.model.Parallel;
import org.apache.commons.scxml.model.Param;
import org.apache.commons.scxml.model.SCXML;
import org.apache.commons.scxml.model.Send;
import org.apache.commons.scxml.model.State;
import org.apache.commons.scxml.model.Transition;
import org.apache.commons.scxml.model.TransitionTarget;
import org.apache.commons.scxml.model.Var;
import org.w3c.dom.Node;
/**
* <p>Utility class for serializing the Commons SCXML Java object
* model. Class uses the visitor pattern to trace through the
* object heirarchy. Used primarily for testing, debugging and
* visual verification.</p>
*
* <b>NOTE:</b> This serializer makes the following assumptions about the
* original SCXML document(s) parsed to create the object model:
* <ul>
* <li>The default document namespace is the SCXML namespace:
* <i>http://www.w3.org/2005/07/scxml</i></li>
* <li>The Commons SCXML namespace
* ( <i>http://commons.apache.org/scxml</i> ), if needed, uses the
* "<i>cs</i>" prefix</li>
* <li>All namespace prefixes needed throughout the document are
* declared on the document root element (<scxml>)</li>
* </ul>
*/
public class SCXMLSerializer {
/** The indent to be used while serializing an SCXML object. */
private static final String INDENT = " ";
/** The JAXP transformer. */
private static final Transformer XFORMER = getTransformer();
/** The SCXML namespace. */
private static final String NAMESPACE_SCXML =
"http://www.w3.org/2005/07/scxml";
/** The Commons SCXML namespace. */
private static final String NAMESPACE_COMMONS_SCXML =
"http://commons.apache.org/scxml";
/**
* Serialize this SCXML object (primarily for debugging).
*
* @param scxml
* The SCXML to be serialized
* @return String The serialized SCXML
*/
public static String serialize(final SCXML scxml) {
StringBuffer b =
new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n").
append("<scxml xmlns=\"").append(NAMESPACE_SCXML).
append("\"").append(serializeNamespaceDeclarations(scxml)).
append(" version=\"").append(scxml.getVersion()).
append("\" initial=\"").append(scxml.getInitial()).
append("\">\n");
if (XFORMER == null) {
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLSerializer.class);
log.warn("SCXMLSerializer: DOM serialization pertinent to"
+ " the document will be skipped since a suitable"
+ " JAXP Transformer could not be instantiated.");
}
b.append(INDENT).append("<!-- http://commons.apache.org/scxml -->\n");
Datamodel dm = scxml.getDatamodel();
if (dm != null) {
serializeDatamodel(b, dm, INDENT);
}
Map c = scxml.getChildren();
Iterator i = c.keySet().iterator();
while (i.hasNext()) {
TransitionTarget tt = (TransitionTarget) c.get(i.next());
if (tt instanceof State) {
serializeState(b, (State) tt, INDENT);
} else {
serializeParallel(b, (Parallel) tt, INDENT);
}
}
b.append("</scxml>\n");
return b.toString();
}
/**
* Serialize this State object.
*
* @param b The buffer to append the serialization to
* @param s The State to serialize
* @param indent The indent for this XML element
*/
public static void serializeState(final StringBuffer b,
final State s, final String indent) {
b.append(indent).append("<state");
serializeTransitionTargetAttributes(b, s);
boolean f = s.isFinal();
if (f) {
b.append(" final=\"true\"");
}
b.append(">\n");
Initial ini = s.getInitial();
if (ini != null) {
serializeInitial(b, ini, indent + INDENT);
}
List h = s.getHistory();
if (h != null) {
serializeHistory(b, h, indent + INDENT);
}
Datamodel dm = s.getDatamodel();
if (dm != null) {
serializeDatamodel(b, dm, indent + INDENT);
}
serializeOnEntry(b, s, indent + INDENT);
List t = s.getTransitionsList();
for (int i = 0; i < t.size(); i++) {
serializeTransition(b, (Transition) t.get(i), indent + INDENT);
}
Parallel p = s.getParallel(); //TODO: Remove in v1.0
Invoke inv = s.getInvoke();
if (p != null) {
serializeParallel(b, p, indent + INDENT);
} else if (inv != null) {
serializeInvoke(b , inv, indent + INDENT);
} else {
Map c = s.getChildren();
Iterator j = c.keySet().iterator();
while (j.hasNext()) {
TransitionTarget tt = (TransitionTarget) c.get(j.next());
if (tt instanceof State) {
serializeState(b, (State) tt, indent + INDENT);
} else if (tt instanceof Parallel) {
serializeParallel(b, (Parallel) tt, indent + INDENT);
}
}
}
serializeOnExit(b, s, indent + INDENT);
b.append(indent).append("</state>\n");
}
/**
* Serialize this Parallel object.
*
* @param b The buffer to append the serialization to
* @param p The Parallel to serialize
* @param indent The indent for this XML element
*/
public static void serializeParallel(final StringBuffer b,
final Parallel p, final String indent) {
b.append(indent).append("<parallel");
serializeTransitionTargetAttributes(b, p);
b.append(">\n");
serializeOnEntry(b, p, indent + INDENT);
Set s = p.getChildren();
Iterator i = s.iterator();
while (i.hasNext()) {
serializeState(b, (State) i.next(), indent + INDENT);
}
serializeOnExit(b, p, indent + INDENT);
b.append(indent).append("</parallel>\n");
}
/**
* Serialize this Invoke object.
*
* @param b The buffer to append the serialization to
* @param i The Invoke to serialize
* @param indent The indent for this XML element
*/
public static void serializeInvoke(final StringBuffer b,
final Invoke i, final String indent) {
b.append(indent).append("<invoke");
String ttype = i.getTargettype();
String src = i.getSrc();
String srcexpr = i.getSrcexpr();
if (ttype != null) {
b.append(" targettype=\"").append(ttype).append("\"");
}
// Prefer src
if (src != null) {
b.append(" src=\"").append(src).append("\"");
} else if (srcexpr != null) {
b.append(" srcexpr=\"").append(srcexpr).append("\"");
}
b.append(">\n");
List params = i.params();
for (Iterator iter = params.iterator(); iter.hasNext();) {
Param p = (Param) iter.next();
b.append(indent).append(INDENT).append("<param name=\"").
append(p.getName()).append("\" expr=\"").
append(SCXMLHelper.escapeXML(p.getExpr())).append("\"/>\n");
}
Finalize f = i.getFinalize();
if (f != null) {
b.append(indent).append(INDENT).append("<finalize>\n");
serializeActions(b, f.getActions(), indent + INDENT + INDENT);
b.append(indent).append(INDENT).append("</finalize>\n");
}
b.append(indent).append("</invoke>\n");
}
/**
* Serialize this Initial object.
*
* @param b The buffer to append the serialization to
* @param i The Initial to serialize
* @param indent The indent for this XML element
*/
public static void serializeInitial(final StringBuffer b, final Initial i,
final String indent) {
b.append(indent).append("<initial");
serializeTransitionTargetAttributes(b, i);
b.append(">\n");
serializeTransition(b, i.getTransition(), indent + INDENT);
b.append(indent).append("</initial>\n");
}
/**
* Serialize the History.
*
* @param b The buffer to append the serialization to
* @param l The List of History objects to serialize
* @param indent The indent for this XML element
*/
public static void serializeHistory(final StringBuffer b, final List l,
final String indent) {
if (l.size() > 0) {
for (int i = 0; i < l.size(); i++) {
History h = (History) l.get(i);
b.append(indent).append("<history");
serializeTransitionTargetAttributes(b, h);
if (h.isDeep()) {
b.append(" type=\"deep\"");
} else {
b.append(" type=\"shallow\"");
}
b.append(">\n");
serializeTransition(b, h.getTransition(), indent + INDENT);
b.append(indent).append("</history>\n");
}
}
}
/**
* Serialize this Transition object.
*
* @param b The buffer to append the serialization to
* @param t The Transition to serialize
* @param indent The indent for this XML element
*/
public static void serializeTransition(final StringBuffer b,
final Transition t, final String indent) {
b.append(indent).append("<transition");
if (!SCXMLHelper.isStringEmpty(t.getEvent())) {
b.append(" event=\"").append(t.getEvent()).append("\"");
}
if (!SCXMLHelper.isStringEmpty(t.getCond())) {
b.append(" cond=\"").append(SCXMLHelper.escapeXML(t.getCond())).
append("\"");
}
boolean next = !SCXMLHelper.isStringEmpty(t.getNext());
if (next) {
b.append(" target=\"" + t.getNext() + "\"");
}
b.append(">\n");
boolean exit = serializeActions(b, t.getActions(), indent + INDENT);
if (!next && !exit) {
serializeTarget(b, t, indent + INDENT);
}
b.append(indent).append("</transition>\n");
}
/**
* Serialize this Transition's Target.
*
*
* @param b The buffer to append the serialization to
* @param t The Transition whose Target needs to be serialized
* @param indent The indent for this XML element
*
* @deprecated Inline <target> element has been deprecated
* in the SCXML WD
*/
public static void serializeTarget(final StringBuffer b,
final Transition t, final String indent) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -