All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jvoicexml.xml.XmlDocument Maven / Gradle / Ivy

The newest version!
/*
 * JVoiceXML - A free VoiceXML implementation.
 *
 * Copyright (C) 2005-2017 JVoiceXML group - http://jvoicexml.sourceforge.net
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

package org.jvoicexml.xml;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.UserDataHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * An XML Document abstract base class.
 *
 * 

* VoiceXML is designed for creating audio dialogs that feature synthesized * speech, digitized audio, recognition of spoken and DTMF key input, recording * of spoken input, telephony and mixed initiative conversations. Its major goal * is to bring the advantages of web-based development and content delivery to * interactive voice response applications. *

* *

* Objects of this class can create such VoiceXML documents or parse them. *

* *

* The encoding can be controlled via the * jvoicexml.xml.encoding environment property. The default * value is UTF-8. *

*

* Entities are not resolved by default. The bahavior can be controlled via * the system property org.jvoicexml.resolveEntities. *

* @author Steve Doyle * @author Dirk Schnelle-Walka */ public abstract class XmlDocument implements Document, Serializable { /** The serial version UID. */ private static final long serialVersionUID = 2293026699195796236L; /** The encapsulated document, implemented as a delegate. */ private transient Document document; /** * The document builder to use. Unfortunately, SAX parsing is not thread * safe, so we store the builder in a thread local variable. */ private static final ThreadLocal LOCAL_BUILDER = new ThreadLocal() { @Override protected DocumentBuilder initialValue() { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // Configure the factory to ignore comments factory.setIgnoringComments(true); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); final EntityResolver resolver = new IgnoringEntityResolver(); boolean resolveEntities = Boolean.getBoolean("org.jvoicexml.xml.resolveEntities"); if (!resolveEntities) { builder.setEntityResolver(resolver); } } catch (ParserConfigurationException e) { e.printStackTrace(); } return builder; }; }; /** * Creates an empty XML document. * * @throws ParserConfigurationException * Error creating the document builder. */ public XmlDocument() throws ParserConfigurationException { // Check if there is a document type specified. final DocumentType prototype = getDoctype(); final DocumentBuilder builder = LOCAL_BUILDER.get(); if (prototype == null) { // If there is none, simply create a new document as usual. document = builder.newDocument(); if (document != null) { final Node root = createRootNode(); appendChild(root); } } else { // otherwise create a document with the given doctype as a // prototype final DOMImplementation impl = builder.getDOMImplementation(); final DocumentType type = impl.createDocumentType(prototype.getName(), prototype.getPublicId(), prototype.getSystemId()); document = impl.createDocument(getDefaultNamespaceURI(), prototype.getName(), type); } } /** * Constructs a new XML document from the given input source. * * @param source * Input source for a single XML document. * @throws ParserConfigurationException * Error creating the document builder. * @throws SAXException * Error parsing the input source. * @throws IOException * Error reading the input source. */ public XmlDocument(final InputSource source) throws ParserConfigurationException, SAXException, IOException { final DocumentBuilder builder = LOCAL_BUILDER.get(); document = builder.parse(source); } /** * Construct a new XML document with the given document. * * @param doc * Encapsulated document. */ public XmlDocument(final Document doc) { Document current = doc; while (current instanceof XmlDocument) { final XmlDocument xmldocument = (XmlDocument) current; current = xmldocument.getDocument(); if (current == null) { current = xmldocument; break; } } document = current; } /** * Retrieves the encapsulated document. * @return The encapsulated document. */ public final Document getDocument() { Document current = document; while (current instanceof XmlDocument) { final XmlDocument xmldocument = (XmlDocument) current; current = xmldocument.getDocument(); if (current == null) { return xmldocument; } } return document; } /** * Retrieves the node factory for child node lists. * @return Node factory for child node lists. * * @since 0.5 */ protected abstract XmlNodeFactory getXmlNodefactory(); /** * Create the root node of the document. * * @return Root node */ protected abstract Node createRootNode(); /** * Adds the node newChild to the end of the list of children * of this node. * * @param newChild * The node to add.If it is a DocumentFragment object, * the entire contents of the document fragment are moved into the * child list of this node * @return The node added. */ public final Node appendChild(final Node newChild) { final Node insertChild; if (newChild instanceof XmlNode) { final XmlNode xmlNode = (XmlNode) newChild; insertChild = xmlNode.getNode(); } else { insertChild = newChild; } return document.appendChild(insertChild); } /** * Returns a duplicate of this node, i.e., serves as a generic copy * constructor for nodes. * * @param deep * If true, recursively clone the subtree under the * specified node; if false, clone only the node * itself (and its attributes, if it is an Element). * @return The duplicate node. */ public final Node cloneNode(final boolean deep) { return document.cloneNode(deep); } /** * Creates an Attr of the given name. * * @param name * The name of the attribute. * @return A new Attr object with the nodeName * attribute set to name, and localName, * prefix, and namespaceURI set to * null. The value of the attribute is the empty * string. */ public final Attr createAttribute(final String name) { return document.createAttribute(name); } /** * Creates an attribute of the given qualified name and namespace URI. * * @param namespaceURI * The namespace URI of the attribute to create. * @param qualifiedName * The qualified name of the attribute to instantiate. * @return A new Attr object with the following attributes: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
AttributeValue
Node.nodeNamequalifiedName
Node.namespaceURInamespaceURI
Node.prefixprefix, extracted from * qualifiedName, or null if there is * no prefix
Node.localNamelocal name, extracted from * qualifiedName
Attr.name qualifiedName
Node.nodeValuethe empty string
*/ public final Attr createAttributeNS(final String namespaceURI, final String qualifiedName) { return document.createAttributeNS(namespaceURI, qualifiedName); } /** * Creates a CDATASection node whose value is the specified * string. * * @param data * The data for the CDATASection contents. * @return The new CDATASection object. */ public final CDATASection createCDATASection(final String data) { return document.createCDATASection(data); } /** * Creates a Comment node given the specified string. * * @param data * The data for the node. * @return The new Comment object. */ public final Comment createComment(final String data) { return document.createComment(data); } /** * Creates an empty DocumentFragment object. * * @return A new DocumentFragment. */ public final DocumentFragment createDocumentFragment() { return document.createDocumentFragment(); } /** * Creates an element of the type specified. * * @param tagName * The name of the element type to instantiate. For XML, this is * case-sensitive. For HTML, the tagName parameter may * be provided in any case, but it must be mapped to the canonical * uppercase form by the DOM implementation. * @return A new Element object with the * nodeName attribute set to tagName, * and localName, prefix, and * namespaceURI set to null. */ public final Element createElement(final String tagName) { return document.createElement(tagName); } /** * Creates an element of the given qualified name and namespace URI. * * @param namespaceURI * The namespace URI of the element to create. * @param qualifiedName * The qualified name of the element type to instantiate. * @return A new Element object with the following * attributes: * * * * * * * * * * * * * * * * * * * * * * * * *
AttributeValue
Node.nodeName qualifiedName
Node.namespaceURI namespaceURI
Node.prefixprefix, extracted from * qualifiedName, or null if there is * no prefix
Node.localNamelocal name, extracted from * qualifiedName
Element.tagName qualifiedName
*/ public final Element createElementNS(final String namespaceURI, final String qualifiedName) { return document.createElementNS(namespaceURI, qualifiedName); } /** * Creates an EntityReference object. * * @param name * The name of the entity to reference. * @return The new EntityReference object. */ public final EntityReference createEntityReference(final String name) { return document.createEntityReference(name); } /** * Creates a ProcessingInstruction node given the specified * name and data strings. * * @param target * The target part of the processing instruction. * @param data * The data for the node. * @return The new ProcessingInstruction object. */ public final ProcessingInstruction createProcessingInstruction( final String target, final String data) { return document.createProcessingInstruction(target, data); } /** * Creates a Text node given the specified string. * * @param data * The data for the node. * @return The new Text object. */ public final Text createTextNode(final String data) { return document.createTextNode(data); } /** * A NamedNodeMap containing the attributes of this node (if * it is an Element) or null otherwise. * * @return NamedNodeMap */ public final NamedNodeMap getAttributes() { return document.getAttributes(); } /** * A NodeList that contains all children of this node. * * @return NodeList */ public final NodeList getChildNodes() { final NodeList children = document.getChildNodes(); return getXmlNodeList(children); } /** * Retrieves the Document Type Declaration associated with this document. * null if there is none * * @return the associated document type * @see DocumentType */ public DocumentType getDoctype() { if (document == null) { return null; } return document.getDoctype(); } /** * This is a convenience attribute that allows direct access to the child * node that is the root element of the document. * * @return Element */ public final Element getDocumentElement() { return document.getDocumentElement(); } /** * Returns the Element whose ID is given by * elementId. * * @param elementId * The unique id value for an element. * @return The matching element. */ public final Element getElementById(final String elementId) { return document.getElementById(elementId); } /** * Returns a NodeList of all the Elements with * a given tag name in the order in which they are encountered in a preorder * traversal of the Document tree. * * @param tagname * The name of the tag to match on. The special value "*" matches all * tags. * @return A new NodeList object containing all the matched * Elements. */ public final NodeList getElementsByTagName(final String tagname) { final NodeList list = document.getElementsByTagName(tagname); return getXmlNodeList(list); } /** * Returns a NodeList of all the Elements with * a given local name and namespace URI in the order in which they are * encountered in a preorder traversal of the Document tree. * * @param namespaceURI * The namespace URI of the elements to match on. The special value * "*" matches all namespaces. * @param localName * The local name of the elements to match on. The special value "*" * matches all local names. * @return A new NodeList object containing all the matched * Elements. */ public final NodeList getElementsByTagNameNS(final String namespaceURI, final String localName) { return getXmlNodeList(document.getElementsByTagNameNS(namespaceURI, localName)); } /** * Get the XmlNode object corresponding to the node. * * @param node - * Node to convert to an XmlNode * @return XmlNode representing the node. */ protected final Node getXmlNode(final Node node) { final XmlNodeFactory factory = getXmlNodefactory(); return factory.getXmlNode(node); } /** * Get the XmlNodeList object corresponding to the nodelist. * * @param nodeList - * Node to convert to an XmlNodeList * @return XmlNodeList representing the node. */ protected abstract NodeList getXmlNodeList(final NodeList nodeList); /** * The first child of this node. * * @return Node */ public final Node getFirstChild() { return getXmlNode(document.getFirstChild()); } /** * The DOMImplementation object that handles this document. * * @return DOMImplementation */ public final DOMImplementation getImplementation() { return document.getImplementation(); } /** * The last child of this node. * * @return Node */ public final Node getLastChild() { return getXmlNode(document.getLastChild()); } /** * Returns the local part of the qualified name of this node. * * @return String */ public final String getLocalName() { return document.getLocalName(); } /** * The namespace URI of this node, or null if it is * unspecified. * * @return String */ public final String getNamespaceURI() { if (document == null) { return getDefaultNamespaceURI(); } return document.getNamespaceURI(); } /** * Retrieves the default namespace. * @return the default namespace, never null. * @since 0.7.5 */ protected abstract String getDefaultNamespaceURI(); /** * The node immediately following this node. * * @return Node */ public final Node getNextSibling() { return getXmlNode(document.getNextSibling()); } /** * The name of this node, depending on its type; see the table above. * * @return String */ public final String getNodeName() { return document.getNodeName(); } /** * A code representing the type of the underlying object, as defined above. * * @return short */ public final short getNodeType() { return document.getNodeType(); } /** * The value of this node, depending on its type; see the table above. * * @return String */ public final String getNodeValue() { return document.getNodeValue(); } /** * The Document object associated with this node. * * @return Document */ public final Document getOwnerDocument() { return document.getOwnerDocument(); } /** * The parent of this node. * * @return Node */ public final Node getParentNode() { return getXmlNode(document.getParentNode()); } /** * The namespace prefix of this node, or null if it is * unspecified. * * @return String */ public final String getPrefix() { return document.getPrefix(); } /** * The node immediately preceding this node. * * @return Node */ public final Node getPreviousSibling() { return getXmlNode(document.getPreviousSibling()); } /** * Returns whether this node (if it is an element) has any attributes. * * @return true if this node has any attributes, * false otherwise. */ public final boolean hasAttributes() { return document.hasAttributes(); } /** * Returns whether this node has any children. * * @return true if this node has any children, * false otherwise. */ public final boolean hasChildNodes() { return document.hasChildNodes(); } /** * Imports a node from another document to this document. * * @param importedNode * The node to import. * @param deep * If true, recursively import the subtree under the * specified node; if false, import only the node * itself, as explained above. This has no effect on * Attr , EntityReference, and * Notation nodes. * @return The imported node that belongs to this Document. */ public final Node importNode(final Node importedNode, final boolean deep) { return document.importNode(importedNode, deep); } /** * An attribute specifying the encoding used for this document at the time * of the parsing. * * @return String */ public final String getInputEncoding() { return document.getInputEncoding(); } /** * An attribute specifying, as part of the XML * declaration, the encoding of this document. * * @return String */ public final String getXmlEncoding() { return document.getXmlEncoding(); } /** * An attribute specifying, as part of the XML * declaration, whether this document is standalone. * * @return boolean */ public final boolean getXmlStandalone() { return document.getXmlStandalone(); } /** * An attribute specifying, as part of the XML * declaration, whether this document is standalone. * * @param xmlStandalone * boolean */ public final void setXmlStandalone(final boolean xmlStandalone) { document.setXmlStandalone(xmlStandalone); } /** * An attribute specifying, as part of the XML * declaration, the version number of this document. * * @return String */ public final String getXmlVersion() { return document.getXmlVersion(); } /** * An attribute specifying, as part of the XML * declaration, the version number of this document. * * @param xmlVersion * String */ public final void setXmlVersion(final String xmlVersion) { document.setXmlVersion(xmlVersion); } /** * An attribute specifying whether error checking is enforced or not. * * @return boolean */ public final boolean getStrictErrorChecking() { return document.getStrictErrorChecking(); } /** * An attribute specifying whether error checking is enforced or not. * * @param strictErrorChecking * boolean */ public final void setStrictErrorChecking( final boolean strictErrorChecking) { document.setStrictErrorChecking(strictErrorChecking); } /** * The location of the document or null if undefined or if * the Document was created using * DOMImplementation.createDocument. * * @return String */ public final String getDocumentURI() { return document.getDocumentURI(); } /** * The location of the document or null if undefined or if * the Document was created using * DOMImplementation.createDocument. * * @param documentURI * String */ public final void setDocumentURI(final String documentURI) { document.setDocumentURI(documentURI); } /** * Attempts to adopt a node from another document to this document. * * @param source * The node to move into this document. * @return The adopted node, or null if this operation fails, * such as when the source node comes from a different * implementation. */ public final Node adoptNode(final Node source) { return document.adoptNode(getRawNode(source)); } /** * The configuration used when Document.normalizeDocument() * is invoked. * * @return DOMConfiguration */ public final DOMConfiguration getDomConfig() { return document.getDomConfig(); } /** * This method acts as if the document was going through a save and load * cycle, putting the document in a "normal" form. */ public final void normalizeDocument() { document.normalizeDocument(); } /** * Rename an existing node of type ELEMENT_NODE or * ATTRIBUTE_NODE. * * @param n * The node to rename. * @param namespaceURI * The new namespace URI. * @param qualifiedName * The new qualified name. * @return The renamed node. This is either the specified node or the new * node that was created to replace the specified node. */ public final Node renameNode(final Node n, final String namespaceURI, final String qualifiedName) { return document.renameNode(getRawNode(n), namespaceURI, qualifiedName); } /** * Inserts the node newChild before the existing child node * refChild. * * @param newChild * The node to insert. * @param refChild * The reference node, i.e., the node before which the new node must * be inserted. * @return The node being inserted. */ public final Node insertBefore(final Node newChild, final Node refChild) { return document .insertBefore(getRawNode(newChild), getRawNode(refChild)); } /** * Tests whether the DOM implementation implements a specific feature and * that feature is supported by this node. * * @param feature * The name of the feature to test. This is the same name which can * be passed to the method hasFeature on * DOMImplementation. * @param version * This is the version number of the feature to test. In Level 2, * version 1, this is the string "2.0". If the version is not * specified, supporting any version of the feature will cause the * method to return true. * @return Returns true if the specified feature is supported * on this node, false otherwise. */ public final boolean isSupported(final String feature, final String version) { return document.isSupported(feature, version); } /** * Puts all Text nodes in the full depth of the sub-tree * underneath this Node, including attribute nodes, into a * "normal" form where only structure (e.g., elements, comments, processing * instructions, CDATA sections, and entity references) separates * Text nodes, i.e., there are neither adjacent * Text nodes nor empty Text nodes. * */ public final void normalize() { document.normalize(); } /** * Removes the child node indicated by oldChild from the list * of children, and returns it. * * @param oldChild * The node being removed. * @return The node removed. */ public final Node removeChild(final Node oldChild) { return document.removeChild(getRawNode(oldChild)); } /** * Replaces the child node oldChild with * newChild in the list of children, and returns the * oldChild node. * * @param newChild * The new node to put in the child list. * @param oldChild * The node being replaced in the list. * @return The node replaced. */ public final Node replaceChild(final Node newChild, final Node oldChild) { return document .replaceChild(getRawNode(newChild), getRawNode(oldChild)); } /** * The value of this node, depending on its type; see the table above. * * @param nodeValue * String */ public final void setNodeValue(final String nodeValue) { document.setNodeValue(nodeValue); } /** * The namespace prefix of this node, or null if it is * unspecified. * * @param prefix * String */ public final void setPrefix(final String prefix) { document.setPrefix(prefix); } /** * The absolute base URI of this node or null if the * implementation wasn't able to obtain an absolute URI. * * @return String */ public final String getBaseURI() { return document.getBaseURI(); } /** * Compares the reference node, i.e. * * @param other * The node to compare against the reference node. * @return Returns how the node is positioned relatively to the reference * node. */ public final short compareDocumentPosition(final Node other) { return document.compareDocumentPosition(getRawNode(other)); } /** * This attribute returns the text content of this node and its descendants. * * @return String */ public final String getTextContent() { return document.getTextContent(); } /** * This attribute returns the text content of this node and its descendants. * * @param textContent * String */ public final void setTextContent(final String textContent) { document.setTextContent(textContent); } /** * Returns whether this node is the same node as the given one. * * @param other * The node to test against. * @return Returns true if the nodes are the same, * false otherwise. */ public final boolean isSameNode(final Node other) { return document.isSameNode(getRawNode(other)); } /** * Look up the prefix associated to the given namespace URI, starting from * this node. * * @param namespaceURI * The namespace URI to look for. * @return Returns an associated namespace prefix if found or * null if none is found. If more than one prefix are * associated to the namespace prefix, the returned namespace prefix * is implementation dependent. */ public final String lookupPrefix(final String namespaceURI) { return document.lookupPrefix(namespaceURI); } /** * This method checks if the specified namespaceURI is the * default namespace or not. * * @param namespaceURI * The namespace URI to look for. * @return Returns true if the specified * namespaceURI is the default namespace, * false otherwise. */ public final boolean isDefaultNamespace(final String namespaceURI) { return document.isDefaultNamespace(namespaceURI); } /** * Look up the namespace URI associated to the given prefix, starting from * this node. * * @param prefix * The prefix to look for. If this parameter is null, * the method will return the default namespace URI if any. * @return Returns the associated namespace URI or null if * none is found. */ public final String lookupNamespaceURI(final String prefix) { return document.lookupNamespaceURI(prefix); } /** * Tests whether two nodes are equal. * * @param arg * The node to compare equality with. * @return Returns true if the nodes are equal, * false otherwise. */ public final boolean isEqualNode(final Node arg) { return document.isEqualNode(arg); } /** * This method returns a specialized object which implements the specialized * APIs of the specified feature and version, as specified in . * * @param feature * The name of the feature requested. Note that any plus sign "+" * prepended to the name of the feature will be ignored since it is * not significant in the context of this method. * @param version * This is the version number of the feature to test. * @return Returns an object which implements the specialized APIs of the * specified feature and version, if any, or null if * there is no object which implements interfaces associated with * that feature. If the DOMObject returned by this * method implements the Node interface, it must * delegate to the primary core Node and not return * results inconsistent with the primary core Node * such as attributes, childNodes, etc. */ public final Object getFeature(final String feature, final String version) { return document.getFeature(feature, version); } /** * Associate an object to a key on this node. * * @param key * The key to associate the object to. * @param data * The object to associate to the given key, or null * to remove any existing association to that key. * @param handler * The handler to associate to that key, or null. * @return Returns the DOMUserData previously associated to * the given key on this node, or null if there was * none. */ public final Object setUserData(final String key, final Object data, final UserDataHandler handler) { return document.setUserData(key, data, handler); } /** * Retrieves the object associated to a key on a this node. * * @param key * The key the object is associated to. * @return Returns the DOMUserData associated to the given * key on this node, or null if there was none. */ public final Object getUserData(final String key) { return document.getUserData(key); } /** * Returns the contents of this object as an XML formatted string. * * @return XML representation of this object. * * @exception IOException * Error writing to the writer. */ public final String toXml() throws IOException { final ByteArrayOutputStream out = new ByteArrayOutputStream(); final Result result = new StreamResult(out); final TransformerFactory transformerFactory = TransformerFactory.newInstance(); try { final Transformer transformer = transformerFactory.newTransformer(); final String encoding = System.getProperty("jvoicexml.xml.encoding", "UTF-8"); transformer.setOutputProperty(OutputKeys.ENCODING, encoding); transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); final DocumentType type = getDoctype(); if (type != null) { transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, type.getPublicId()); transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, type.getSystemId()); } final Source source = new DOMSource(document); transformer.transform(source, result); return out.toString(encoding); } catch (TransformerException e) { throw new IOException(e.getMessage(), e); } } /** * {@inheritDoc} * * Creates a representation as an XML string. If this is not possible * for some reason, the conventional {@link Object#toString()} creation * is used. * * @since 0.3 */ @Override public final String toString() { try { return toXml(); } catch (java.io.IOException ioe) { return super.toString(); } } /** * Get the raw node encapsulated by the specified node. If the specified * node is a raw node then it is returned. * * @param arg * The node that may be wrapping a raw node. * @return The raw node. */ private Node getRawNode(final Node arg) { final Node rawNode; if (arg instanceof VoiceXmlNode) { final VoiceXmlNode voiceXmlNode = (VoiceXmlNode) arg; rawNode = voiceXmlNode.getNode(); } else { rawNode = arg; } return rawNode; } /** * Writes the state of the object for its particular class so that the * corresponding {@link #readObject(java.io.ObjectInputStream)} * method can restore it. * @param out the stream to write to * @throws IOException * if an error occurs while writing to the stream */ private void writeObject(final ObjectOutputStream out) throws IOException { final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); final Result result = new StreamResult(buffer); final TransformerFactory transformerFactory = TransformerFactory.newInstance(); try { final Transformer transformer = transformerFactory.newTransformer(); final String encoding = System.getProperty("jvoicexml.xml.encoding", "UTF-8"); transformer.setOutputProperty(OutputKeys.ENCODING, encoding); final Source source = new DOMSource(this); transformer.transform(source, result); } catch (TransformerException e) { throw new IOException(e.getMessage(), e); } out.writeLong(buffer.size()); out.write(buffer.toByteArray()); } /** * Reads from the stream and restores the classes fields. * @param in the stream to read from * @throws IOException * if an error occurs while reading from the stream * @throws ClassNotFoundException * if a dependent class could not be found */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { final int size = (int) in.readLong(); final byte[] buffer = new byte[size]; int num = 0; do { num += in.read(buffer, num, size - num); } while (num < size); final ByteArrayInputStream stream = new ByteArrayInputStream(buffer); final InputSource source = new InputSource(stream); final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // Configure the factory to ignore comments factory.setIgnoringComments(true); try { final DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.parse(source); } catch (SAXException e) { throw new IOException(e.getMessage(), e); } catch (ParserConfigurationException e) { throw new IOException(e.getMessage(), e); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy