📄 scxmlparser.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.IOException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ExtendedBaseRules;
import org.apache.commons.digester.NodeCreateRule;
import org.apache.commons.digester.ObjectCreateRule;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.SetNextRule;
import org.apache.commons.digester.SetPropertiesRule;
import org.apache.commons.digester.WithDefaultsRulesWrapper;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.scxml.PathResolver;
import org.apache.commons.scxml.SCXMLHelper;
import org.apache.commons.scxml.env.URLResolver;
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.CustomAction;
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.Event;
import org.apache.commons.scxml.model.Executable;
import org.apache.commons.scxml.model.Exit;
import org.apache.commons.scxml.model.ExternalContent;
import org.apache.commons.scxml.model.Final;
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.ModelException;
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.PathResolverHolder;
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.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
* <p>The SCXMLParser provides the ability to parse a SCXML document into
* the Java object model provided in the model package.</p>
* <p>The SCXMLParser can be used for:</p>
* <ol>
* <li>Parse a SCXML file into the Commons SCXML Java object model.</li>
* <li>Obtain a SCXML Parser for further customization of the default
* ruleset.</li>
* </ol>
*
* <p>If switching from {@link SCXMLDigester}, changes need to be made to
* the SCXML documents, such as:</p>
* <ul>
* <li>A <parallel> should not be wrapped in a <state> element
* unless otherwise necessary</li>
* <li><var> and <exit> elements continue to be supported by
* Commons SCXML, but in the Commons SCXML namespace:
* <code>http://commons.apache.org/scxml</code></li>
* <li><event> is now supported</li>
* </ul>
* <p>See latest version of the SCXML Working Draft for more details.</p>
*
* <p><b>NOTE:</b> The SCXMLParser assumes that the SCXML document to be
* parsed is well-formed and correct. If that assumption does not hold,
* any subsequent behavior is undefined.</p>
*
* @since 0.7
*/
public final class SCXMLParser {
/**
* The SCXML namespace that this Digester is built for. Any document
* that is intended to be parsed by this digester <b>must</b>
* bind the SCXML elements to this namespace.
*/
private static final String NAMESPACE_SCXML =
"http://www.w3.org/2005/07/scxml";
/**
* The namespace that defines any custom actions defined by the Commons
* SCXML implementation. Any document that intends to use these custom
* actions needs to ensure that they are in the correct namespace. Use
* of actions in this namespace makes the document non-portable across
* implementations.
*/
private static final String NAMESPACE_COMMONS_SCXML =
"http://commons.apache.org/scxml";
//---------------------- PUBLIC METHODS ----------------------//
/**
* <p>API for standalone usage where the SCXML document is a URL.</p>
*
* @param scxmlURL
* a canonical absolute URL to parse (relative URLs within the
* top level document are to be resovled against this URL).
* @param errHandler
* The SAX ErrorHandler
*
* @return SCXML The SCXML object corresponding to the file argument
*
* @throws IOException Underlying Digester parsing threw an IOException
* @throws SAXException Underlying Digester parsing threw a SAXException
* @throws ModelException If the resulting document model has flaws
*
* @see ErrorHandler
* @see PathResolver
*/
public static SCXML parse(final URL scxmlURL,
final ErrorHandler errHandler)
throws IOException, SAXException, ModelException {
if (scxmlURL == null) {
throw new IllegalArgumentException(ERR_NULL_URL);
}
return parse(scxmlURL, errHandler, null);
}
/**
* <p>API for standalone usage where the SCXML document is a URI.
* A PathResolver must be provided.</p>
*
* @param pathResolver
* The PathResolver for this context
* @param documentRealPath
* The String pointing to the absolute (real) path of the
* SCXML document
* @param errHandler
* The SAX ErrorHandler
*
* @return SCXML The SCXML object corresponding to the file argument
*
* @throws IOException Underlying Digester parsing threw an IOException
* @throws SAXException Underlying Digester parsing threw a SAXException
* @throws ModelException If the resulting document model has flaws
*
* @see ErrorHandler
* @see PathResolver
*/
public static SCXML parse(final String documentRealPath,
final ErrorHandler errHandler, final PathResolver pathResolver)
throws IOException, SAXException, ModelException {
return parse(documentRealPath, errHandler, pathResolver, null);
}
/**
* <p>API for standalone usage where the SCXML document is an
* InputSource. This method may be used when the SCXML document is
* packaged in a Java archive, or part of a compound document
* where the SCXML root is available as a
* <code>org.w3c.dom.Element</code> or via a <code>java.io.Reader</code>.
* </p>
*
* <p><em>Note:</em> Since there is no path resolution, the SCXML document
* must not have external state sources.</p>
*
* @param documentInputSource
* The InputSource for the SCXML document
* @param errHandler
* The SAX ErrorHandler
*
* @return SCXML The SCXML object corresponding to the file argument
*
* @throws IOException Underlying Digester parsing threw an IOException
* @throws SAXException Underlying Digester parsing threw a SAXException
* @throws ModelException If the resulting document model has flaws
*
* @see ErrorHandler
*/
public static SCXML parse(final InputSource documentInputSource,
final ErrorHandler errHandler)
throws IOException, SAXException, ModelException {
if (documentInputSource == null) {
throw new IllegalArgumentException(ERR_NULL_ISRC);
}
return parse(documentInputSource, errHandler, null);
}
/**
* <p>API for standalone usage where the SCXML document is a URL, and
* the document uses custom actions.</p>
*
* @param scxmlURL
* a canonical absolute URL to parse (relative URLs within the
* top level document are to be resovled against this URL).
* @param errHandler
* The SAX ErrorHandler
* @param customActions
* The list of {@link CustomAction}s this digester
* instance will process, can be null or empty
*
* @return SCXML The SCXML object corresponding to the file argument
*
* @throws IOException Underlying Digester parsing threw an IOException
* @throws SAXException Underlying Digester parsing threw a SAXException
* @throws ModelException If the resulting document model has flaws
*
* @see ErrorHandler
* @see PathResolver
*/
public static SCXML parse(final URL scxmlURL,
final ErrorHandler errHandler, final List customActions)
throws IOException, SAXException, ModelException {
SCXML scxml = null;
Digester scxmlParser = SCXMLParser
.newInstance(null, new URLResolver(scxmlURL), customActions);
scxmlParser.setErrorHandler(errHandler);
try {
scxml = (SCXML) scxmlParser.parse(scxmlURL.toString());
} catch (RuntimeException rte) {
// Intercept runtime exceptions, only to log them with a
// sensible error message about failure in document parsing
MessageFormat msgFormat = new MessageFormat(ERR_DOC_PARSE_FAIL);
String errMsg = msgFormat.format(new Object[] {
String.valueOf(scxmlURL), rte.getMessage()
});
org.apache.commons.logging.Log log = LogFactory.
getLog(SCXMLParser.class);
log.error(errMsg, rte);
throw rte;
}
if (scxml != null) {
ModelUpdater.updateSCXML(scxml);
}
return scxml;
}
/**
* <p>API for standalone usage where the SCXML document is a URI.
* A PathResolver must be provided.</p>
*
* @param pathResolver
* The PathResolver for this context
* @param documentRealPath
* The String pointing to the absolute (real) path of the
* SCXML document
* @param errHandler
* The SAX ErrorHandler
* @param customActions
* The list of {@link CustomAction}s this digester
* instance will process, can be null or empty
*
* @return SCXML The SCXML object corresponding to the file argument
*
* @throws IOException Underlying Digester parsing threw an IOException
* @throws SAXException Underlying Digester parsing threw a SAXException
* @throws ModelException If the resulting document model has flaws
*
* @see ErrorHandler
* @see PathResolver
*/
public static SCXML parse(final String documentRealPath,
final ErrorHandler errHandler, final PathResolver pathResolver,
final List customActions)
throws IOException, SAXException, ModelException {
if (documentRealPath == null) {
throw new IllegalArgumentException(ERR_NULL_PATH);
}
SCXML scxml = null;
Digester scxmlParser = SCXMLParser.newInstance(null, pathResolver,
customActions);
scxmlParser.setErrorHandler(errHandler);
try {
scxml = (SCXML) scxmlParser.parse(documentRealPath);
} catch (RuntimeException rte) {
// Intercept runtime exceptions, only to log them with a
// sensible error message about failure in document parsing
MessageFormat msgFormat = new MessageFormat(ERR_DOC_PARSE_FAIL);
String errMsg = msgFormat.format(new Object[] {
documentRealPath, rte.getMessage()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -