📄 scxmlparser.java
字号:
* @param scxml The root document, if this one is src'ed in
*/
private static void addPseudoStatePropertiesRules(final String xp,
final ExtendedBaseRules scxmlRules, final List customActions,
final PathResolver pr, final SCXML scxml) {
scxmlRules.add(xp, new SetPropertiesRule(new String[] {"id"},
new String[] {"id"}));
scxmlRules.add(xp, new DigestSrcAttributeRule(scxml, customActions,
pr));
}
/**
* Add Digester rules for all <transition> elements.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param setNextMethod The method name for adding this transition
* to its parent (defined by the SCXML Java object model).
* @param pr The {@link PathResolver} for this document
* @param customActions The list of custom actions this digester needs
* to be able to process
*/
private static void addTransitionRules(final String xp,
final ExtendedBaseRules scxmlRules, final String setNextMethod,
final PathResolver pr, final List customActions) {
scxmlRules.add(xp, new ObjectCreateRule(Transition.class));
scxmlRules.add(xp, new SetPropertiesRule(
new String[] {"event", "cond", "target"},
new String[] {"event", "cond", "next"}));
scxmlRules.add(xp, new SetCurrentNamespacesRule());
addActionRules(xp, scxmlRules, pr, customActions);
// Add <exit> custom action rule in Commons SCXML namespace
scxmlRules.setNamespaceURI(NAMESPACE_COMMONS_SCXML);
scxmlRules.add(xp + XPF_EXT, new Rule() {
public void end(final String namespace, final String name) {
Transition t = (Transition) getDigester().peek(1);
TransitionTarget tt = (TransitionTarget) getDigester().
peek(2);
if (tt instanceof Initial) {
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.warn("Ignored <exit> action in <initial>");
} else {
State exitState = new State();
exitState.setFinal(true);
t.getTargets().add(exitState);
}
}
});
scxmlRules.setNamespaceURI(NAMESPACE_SCXML);
scxmlRules.add(xp, new SetNextRule(setNextMethod));
}
/**
* Add Digester rules for all <onentry> and <onexit>
* elements.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param pr The {@link PathResolver} for this document
* @param customActions The list of custom actions this digester needs
* to be able to process
*/
private static void addHandlerRules(final String xp,
final ExtendedBaseRules scxmlRules, final PathResolver pr,
final List customActions) {
scxmlRules.add(xp + XPF_ONEN, new ObjectCreateRule(OnEntry.class));
addActionRules(xp + XPF_ONEN, scxmlRules, pr, customActions);
scxmlRules.add(xp + XPF_ONEN, new SetNextRule("setOnEntry"));
scxmlRules.add(xp + XPF_ONEX, new ObjectCreateRule(OnExit.class));
addActionRules(xp + XPF_ONEX, scxmlRules, pr, customActions);
scxmlRules.add(xp + XPF_ONEX, new SetNextRule("setOnExit"));
}
/**
* Add Digester rules for all actions ("executable" elements).
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param pr The {@link PathResolver} for this document
* @param customActions The list of custom actions this digester needs
* to be able to process
*/
private static void addActionRules(final String xp,
final ExtendedBaseRules scxmlRules, final PathResolver pr,
final List customActions) {
// Actions in SCXML namespace
addActionRulesTuple(xp + XPF_ASN, scxmlRules, Assign.class);
scxmlRules.add(xp + XPF_ASN, new SetPathResolverRule(pr));
addActionRulesTuple(xp + XPF_EVT, scxmlRules, Event.class);
addSendRulesTuple(xp + XPF_SND, scxmlRules);
addActionRulesTuple(xp + XPF_CAN, scxmlRules, Cancel.class);
addActionRulesTuple(xp + XPF_LOG, scxmlRules, Log.class);
// Actions in Commons SCXML namespace
scxmlRules.setNamespaceURI(NAMESPACE_COMMONS_SCXML);
addActionRulesTuple(xp + XPF_VAR, scxmlRules, Var.class);
addActionRulesTuple(xp + XPF_EXT, scxmlRules, Exit.class);
// Reset namespace
scxmlRules.setNamespaceURI(NAMESPACE_SCXML);
}
/**
* Add custom action rules, if any custom actions are provided.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param customActions The list of custom actions this digester needs
* to be able to process
*/
private static void addCustomActionRules(final String xp,
final ExtendedBaseRules scxmlRules, final List customActions) {
if (customActions == null || customActions.size() == 0) {
return;
}
for (int i = 0; i < customActions.size(); i++) {
Object item = customActions.get(i);
if (item == null || !(item instanceof CustomAction)) {
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.warn(ERR_CUSTOM_ACTION_TYPE);
} else {
CustomAction ca = (CustomAction) item;
scxmlRules.setNamespaceURI(ca.getNamespaceURI());
String xpfLocalName = STR_SLASH + ca.getLocalName();
Class klass = ca.getActionClass();
if (SCXMLHelper.implementationOf(klass,
ExternalContent.class)) {
addCustomActionRulesTuple(xp + xpfLocalName, scxmlRules,
klass, true);
} else {
addCustomActionRulesTuple(xp + xpfLocalName, scxmlRules,
klass, false);
}
}
}
scxmlRules.setNamespaceURI(NAMESPACE_SCXML);
}
/**
* Add Digester rules that are specific to the <send> action
* element.
*
* @param xp The Digester style XPath expression of <send> element
* @param scxmlRules The rule set to be used for digestion
*/
private static void addSendRulesTuple(final String xp,
final ExtendedBaseRules scxmlRules) {
addActionRulesTuple(xp, scxmlRules, Send.class);
try {
scxmlRules.add(xp, new ParseExternalContentRule());
} catch (ParserConfigurationException pce) {
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.error(ERR_PARSER_CFG_SEND, pce);
}
}
/**
* Add Digester rules for a simple custom action (no body content).
*
* @param xp The path to the custom action element
* @param scxmlRules The rule set to be used for digestion
* @param klass The <code>Action</code> class implementing the custom
* action.
* @param bodyContent Whether the custom rule has body content
* that should be parsed using
* <code>NodeCreateRule</code>
*/
private static void addCustomActionRulesTuple(final String xp,
final ExtendedBaseRules scxmlRules, final Class klass,
final boolean bodyContent) {
addActionRulesTuple(xp, scxmlRules, klass);
if (bodyContent) {
try {
scxmlRules.add(xp, new ParseExternalContentRule());
} catch (ParserConfigurationException pce) {
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.error(ERR_PARSER_CFG_CUSTOM, pce);
}
}
}
/**
* Add Digester rules for all <if> elements.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param pr The {@link PathResolver} for this document
* @param customActions The list of custom actions this digester needs
* to be able to process
*/
private static void addIfRules(final String xp,
final ExtendedBaseRules scxmlRules, final PathResolver pr,
final List customActions) {
addActionRulesTuple(xp, scxmlRules, If.class);
addActionRules(xp, scxmlRules, pr, customActions);
addActionRulesTuple(xp + XPF_EIF, scxmlRules, ElseIf.class);
addActionRulesTuple(xp + XPF_ELS, scxmlRules, Else.class);
}
/**
* Add Digester rules that are common across all actions elements.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param klass The class in the Java object model to be instantiated
* in the ObjectCreateRule for this action
*/
private static void addActionRulesTuple(final String xp,
final ExtendedBaseRules scxmlRules, final Class klass) {
addSimpleRulesTuple(xp, scxmlRules, klass, null, null, "addAction");
scxmlRules.add(xp, new SetExecutableParentRule());
scxmlRules.add(xp, new SetCurrentNamespacesRule());
}
/**
* Add the run of the mill Digester rules for any element.
*
* @param xp The Digester style XPath expression of the parent
* XML element
* @param scxmlRules The rule set to be used for digestion
* @param klass The class in the Java object model to be instantiated
* in the ObjectCreateRule for this action
* @param args The attributes to be mapped into the object model
* @param props The properties that args get mapped to
* @param addMethod The method that the SetNextRule should call
*/
private static void addSimpleRulesTuple(final String xp,
final ExtendedBaseRules scxmlRules, final Class klass,
final String[] args, final String[] props,
final String addMethod) {
scxmlRules.add(xp, new ObjectCreateRule(klass));
if (args == null) {
scxmlRules.add(xp, new SetPropertiesRule());
} else {
scxmlRules.add(xp, new SetPropertiesRule(args, props));
}
scxmlRules.add(xp, new SetNextRule(addMethod));
}
/**
* Discourage instantiation since this is a utility class.
*/
private SCXMLParser() {
super();
}
/**
* Custom digestion rule for establishing necessary associations of this
* TransitionTarget with the root SCXML object.
* These include: <br>
* 1) Updation of the SCXML object's global targets Map <br>
* 2) Obtaining a handle to the SCXML object's NotificationRegistry <br>
*/
private static class UpdateModelRule extends Rule {
/**
* The root SCXML object.
*/
private SCXML scxml;
/**
* Constructor.
* @param scxml The root SCXML object
*/
UpdateModelRule(final SCXML scxml) {
super();
this.scxml = scxml;
}
/**
* @see Rule#end(String, String)
*/
public final void end(final String namespace, final String name) {
if (scxml == null) {
scxml = (SCXML) getDigester()
.peek(getDigester().getCount() - 1);
}
TransitionTarget tt = (TransitionTarget) getDigester().peek();
scxml.addTarget(tt);
}
}
/**
* Custom digestion rule for setting Executable parent of Action elements.
*/
private static class SetExecutableParentRule extends Rule {
/**
* Constructor.
*/
SetExecutableParentRule() {
super();
}
/**
* @see Rule#end(String, String)
*/
public final void end(final String namespace, final String name) {
Action child = (Action) getDigester().peek();
for (int i = 1; i < getDigester().getCount() - 1; i++) {
Object ancestor = getDigester().peek(i);
if (ancestor instanceof Executable) {
child.setParent((Executable) ancestor);
return;
}
}
}
}
/**
* Custom digestion rule for parsing bodies of
* <code>ExternalContent</code> elements.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -