001    /*
002     * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    /* $Id: MathMLSerializer.java,v 2bab6eb875e8 2010/08/11 16:45:50 max $ */
018    
019    package net.sourceforge.jeuclid;
020    
021    import java.io.StringWriter;
022    
023    import javax.annotation.concurrent.ThreadSafe;
024    import javax.xml.transform.OutputKeys;
025    import javax.xml.transform.Transformer;
026    import javax.xml.transform.TransformerException;
027    import javax.xml.transform.TransformerFactory;
028    import javax.xml.transform.dom.DOMSource;
029    import javax.xml.transform.stream.StreamResult;
030    
031    import org.apache.commons.logging.Log;
032    import org.apache.commons.logging.LogFactory;
033    import org.w3c.dom.Node;
034    
035    /**
036     * Utility class to serialize DOM documents back into Strings.
037     * <p>
038     * This class can be used to generate String representations for an existing DOM
039     * Tree. The functionality is not restricted to JEuclid, and can be used for
040     * other DOM trees as well. In this case, you should set the addDoctype
041     * parameter to false.
042     * 
043     * @version $Revision: 2bab6eb875e8 $
044     */
045    @ThreadSafe
046    public final class MathMLSerializer {
047    
048        /**
049         * Logger for this class
050         */
051        private static final Log LOGGER = LogFactory.getLog(MathMLSerializer.class);
052    
053        private MathMLSerializer() {
054            // empty on purpose
055        }
056    
057        /**
058         * Serialize a document back into a String.
059         * 
060         * @param doc
061         *            a DOM model of a document, or a node in a document
062         * @param addDoctype
063         *            if true, extra attributes such as docType will be set. This
064         *            ensures maximum MathML compatibility. Use only with MathML DOM
065         *            trees.
066         * @param format
067         *            if true, result will be nicely formatted.
068         * @return the document serialized to a string
069         * @see #serializeDocument(Node, boolean, boolean, boolean)
070         */
071        public static String serializeDocument(final Node doc,
072                final boolean addDoctype, final boolean format) {
073            return MathMLSerializer.serializeDocument(doc, addDoctype, format,
074                    false);
075        }
076    
077        /**
078         * Serialize a document back into a String.
079         * 
080         * @param doc
081         *            a DOM model of a document.
082         * @param addDoctype
083         *            if true, extra attributes such as docType will be set. This
084         *            ensures maximum MathML compatibility. Use only with MathML DOM
085         *            trees.
086         * @param format
087         *            if true, result will be nicely formatted.
088         * @param omitXMLDecl
089         *            if true, there will be no XML declaration.
090         * @return the document serialized to a string
091         */
092        public static String serializeDocument(final Node doc,
093                final boolean addDoctype, final boolean format,
094                final boolean omitXMLDecl) {
095            final StringWriter writer = new StringWriter();
096            try {
097                final Transformer transformer = TransformerFactory.newInstance()
098                        .newTransformer();
099                final DOMSource source = new DOMSource(doc);
100                final StreamResult result = new StreamResult(writer);
101    
102                if (addDoctype) {
103                    transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
104                            ResourceEntityResolver.MML2_PUBLICID);
105                    transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
106                            ResourceEntityResolver.MML2_SYSTEMID);
107                    transformer.setOutputProperty(OutputKeys.MEDIA_TYPE,
108                            Constants.MATHML_MIMETYPE);
109                }
110                MathMLSerializer.boolToProperty(format, OutputKeys.INDENT,
111                        transformer);
112                MathMLSerializer.boolToProperty(omitXMLDecl,
113                        OutputKeys.OMIT_XML_DECLARATION, transformer);
114                transformer.transform(source, result);
115            } catch (final TransformerException e) {
116                MathMLSerializer.LOGGER.warn(e.getMessage(), e);
117            }
118            return writer.toString();
119    
120        }
121    
122        private static void boolToProperty(final boolean bool, final String key,
123                final Transformer transformer) {
124            if (bool) {
125                transformer.setOutputProperty(key, "yes");
126            } else {
127                transformer.setOutputProperty(key, "no");
128            }
129        }
130    
131    }