📄 scxmlparser.java
字号:
* @see ExternalContent
*/
private static class ParseExternalContentRule extends NodeCreateRule {
/**
* Constructor.
* @throws ParserConfigurationException A JAXP configuration error
*/
ParseExternalContentRule()
throws ParserConfigurationException {
super();
}
/**
* @see Rule#end(String, String)
*/
public final void end(final String namespace, final String name) {
Element bodyElement = (Element) getDigester().pop();
NodeList childNodes = bodyElement.getChildNodes();
List externalNodes = ((ExternalContent) getDigester().
peek()).getExternalNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
externalNodes.add(childNodes.item(i));
}
}
}
/**
* Custom digestion rule for parsing bodies of <data> elements.
*/
private static class ParseDataRule extends NodeCreateRule {
/**
* The PathResolver used to resolve the src attribute to the
* SCXML document it points to.
* @see PathResolver
*/
private PathResolver pr;
/**
* The "src" attribute, retained to check if body content is legal.
*/
private String src;
/**
* The "expr" attribute, retained to check if body content is legal.
*/
private String expr;
/**
* The XML tree for this data, parse as a Node, obtained from
* either the "src" or the "expr" attributes.
*/
private Node attrNode;
/**
* Constructor.
*
* @param pr The <code>PathResolver</code>
* @throws ParserConfigurationException A JAXP configuration error
*/
ParseDataRule(final PathResolver pr)
throws ParserConfigurationException {
super();
this.pr = pr;
}
/**
* @see Rule#begin(String, String, Attributes)
*/
public final void begin(final String namespace, final String name,
final Attributes attributes) throws Exception {
super.begin(namespace, name, attributes);
src = attributes.getValue("src");
expr = attributes.getValue("expr");
if (!SCXMLHelper.isStringEmpty(src)) {
String path = null;
if (pr == null) {
path = src;
} else {
path = pr.resolvePath(src);
}
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.
newInstance();
DocumentBuilder db = dbFactory.newDocumentBuilder();
attrNode = db.parse(path);
} catch (Throwable t) { // you read that correctly
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.error(t.getMessage(), t);
}
return;
}
}
/**
* @see Rule#end(String, String)
*/
public final void end(final String namespace, final String name) {
Node bodyNode = (Node) getDigester().pop();
Data data = ((Data) getDigester().peek());
// Prefer "src" over "expr", "expr" over child nodes
// "expr" can only be evaluated at execution time
if (!SCXMLHelper.isStringEmpty(src)) {
data.setNode(attrNode);
} else if (SCXMLHelper.isStringEmpty(expr)) {
// both "src" and "expr" are empty
data.setNode(bodyNode);
}
}
}
/**
* Custom digestion rule for external sources, that is, the src attribute of
* the <state> element.
*/
private static class DigestSrcAttributeRule extends Rule {
/**
* The PathResolver used to resolve the src attribute to the
* SCXML document it points to.
* @see PathResolver
*/
private PathResolver pr;
/**
* The root document.
*/
private SCXML root;
/**
* The list of custom actions the parent document is capable of
* processing (and hence, the child should be, by transitivity).
* @see CustomAction
*/
private List customActions;
/**
* Constructor.
* @param pr The PathResolver
* @param customActions The list of custom actions this digester needs
* to be able to process
*
* @see PathResolver
* @see CustomAction
*/
DigestSrcAttributeRule(final List customActions,
final PathResolver pr) {
super();
this.customActions = customActions;
this.pr = pr;
}
/**
* Constructor.
* @param root The root document, if this one is src'ed in
* @param pr The PathResolver
* @param customActions The list of custom actions this digester needs
* to be able to process
*
* @see PathResolver
* @see CustomAction
*/
DigestSrcAttributeRule(final SCXML root,
final List customActions, final PathResolver pr) {
super();
this.root = root;
this.customActions = customActions;
this.pr = pr;
}
/**
* @see Rule#begin(String, String, Attributes)
*/
public final void begin(final String namespace, final String name,
final Attributes attributes) throws ModelException {
String src = attributes.getValue("src");
if (SCXMLHelper.isStringEmpty(src)) {
return;
}
// 1) Digest the external SCXML file
Digester digester = getDigester();
SCXML scxml = (SCXML) digester.peek(digester.getCount() - 1);
SCXML parent = root;
if (parent == null) {
parent = scxml;
}
String path;
PathResolver nextpr = null;
if (pr == null) {
path = src;
} else {
path = pr.resolvePath(src);
nextpr = pr.getResolver(src);
}
String[] fragments = path.split("#", 2);
String location = fragments[0];
String fragment = null;
if (fragments.length > 1) {
fragment = fragments[1];
}
Digester externalSrcDigester;
if (fragment != null) {
// Cannot pull in all targets just yet, i.e. null parent
externalSrcDigester = newInstance(null, nextpr,
customActions);
} else {
externalSrcDigester = newInstance(parent, nextpr,
customActions);
}
SCXML externalSCXML = null;
try {
externalSCXML = (SCXML) externalSrcDigester.parse(location);
} catch (Exception e) {
MessageFormat msgFormat =
new MessageFormat(ERR_STATE_SRC);
String errMsg = msgFormat.format(new Object[] {
path
});
throw new ModelException(errMsg + " : " + e.getMessage(), e);
}
// 2) Adopt the children and datamodel
if (externalSCXML == null) {
return;
}
State s = (State) digester.peek();
if (fragment == null) {
// All targets pulled in since its not a src fragment
Initial ini = new Initial();
Transition t = new Transition();
t.setNext(externalSCXML.getInitial());
ini.setTransition(t);
s.setInitial(ini);
Map children = externalSCXML.getChildren();
Iterator childIter = children.values().iterator();
while (childIter.hasNext()) {
s.addChild((TransitionTarget) childIter.next());
}
s.setDatamodel(externalSCXML.getDatamodel());
} else {
// Need to pull in descendent targets
Object source = externalSCXML.getTargets().get(fragment);
if (source == null) {
MessageFormat msgFormat =
new MessageFormat(ERR_STATE_SRC_FRAGMENT);
String errMsg = msgFormat.format(new Object[] {
path
});
throw new ModelException(errMsg);
}
if (source instanceof State) {
State include = (State) source;
s.setOnEntry(include.getOnEntry());
s.setOnExit(include.getOnExit());
s.setDatamodel(include.getDatamodel());
List histories = include.getHistory();
for (int i = 0; i < histories.size(); i++) {
History h = (History) histories.get(i);
s.addHistory(h);
parent.addTarget(h);
}
Iterator childIter = include.getChildren().values().iterator();
while (childIter.hasNext()) {
TransitionTarget tt = (TransitionTarget) childIter.next();
s.addChild(tt);
parent.addTarget(tt);
addTargets(parent, tt);
}
s.setInvoke(include.getInvoke());
s.setFinal(include.isFinal());
if (include.getInitial() != null) {
s.setInitial(include.getInitial());
}
Iterator transIter = include.getTransitionsList().iterator();
while (transIter.hasNext()) {
s.addTransition((Transition) transIter.next());
}
} else {
MessageFormat msgFormat =
new MessageFormat(ERR_STATE_SRC_FRAGMENT_TARGET);
String errMsg = msgFormat.format(new Object[] {
path
});
throw new ModelException(errMsg);
}
}
}
/**
* Add all the nested targets from given target to given parent state machine.
*
* @param parent The state machine
* @param tt The transition target to import
*/
private static void addTargets(final SCXML parent, final TransitionTarget tt) {
Iterator histIter = tt.getHistory().iterator();
while (histIter.hasNext()) {
History h = (History) histIter.next();
parent.addTarget(h);
}
if (tt instanceof State) {
Iterator childIter = ((State) tt).getChildren().values().iterator();
while (childIter.hasNext()) {
TransitionTarget child = (TransitionTarget) childIter.next();
parent.addTarget(child);
addTargets(parent, child);
}
} else if (tt instanceof Parallel) {
Iterator childIter = ((Parallel) tt).getChildren().iterator();
while (childIter.hasNext()) {
TransitionTarget child = (TransitionTarget) childIter.next();
parent.addTarget(child);
addTargets(parent, child);
}
}
}
}
/**
* Custom digestion rule for setting PathResolver for runtime retrieval.
*/
private static class SetPathResolverRule extends Rule {
/**
* The PathResolver to set
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -