Coverage Report - net.sourceforge.jeuclid.converter.Processor
 
Classes in this File Line Coverage Branch Coverage Complexity
Processor
0%
0/51
0%
0/14
2,333
Processor$SingletonHolder
0%
0/4
N/A
2,333
 
 1  
 /*
 2  
  * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 /* $Id: Processor.java,v 5a7becda9147 2009/10/23 10:57:54 max $ */
 18  
 
 19  
 package net.sourceforge.jeuclid.converter;
 20  
 
 21  
 import java.io.IOException;
 22  
 
 23  
 import javax.xml.transform.Result;
 24  
 import javax.xml.transform.Source;
 25  
 import javax.xml.transform.Transformer;
 26  
 import javax.xml.transform.TransformerException;
 27  
 import javax.xml.transform.TransformerFactory;
 28  
 import javax.xml.transform.dom.DOMResult;
 29  
 import javax.xml.transform.dom.DOMSource;
 30  
 
 31  
 import net.sourceforge.jeuclid.LayoutContext;
 32  
 import net.sourceforge.jeuclid.context.LayoutContextImpl;
 33  
 import net.sourceforge.jeuclid.converter.ConverterPlugin.DocumentWithDimension;
 34  
 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
 35  
 import net.sourceforge.jeuclid.elements.generic.MathImpl;
 36  
 import net.sourceforge.jeuclid.parser.Parser;
 37  
 
 38  
 import org.apache.commons.logging.Log;
 39  
 import org.apache.commons.logging.LogFactory;
 40  
 import org.w3c.dom.Element;
 41  
 import org.w3c.dom.Node;
 42  
 import org.w3c.dom.NodeList;
 43  
 import org.xml.sax.SAXException;
 44  
 
 45  
 /**
 46  
  * Contains the actual processing routines.
 47  
  * <p>
 48  
  * To use this class obtain an instance of the Processor singleton instance.
 49  
  * Then use the {@link #process(Source, Result)} function to process your
 50  
  * Document.
 51  
  * <p>
 52  
  * This will replace all occurrences of MathML within fo:instream tags by the
 53  
  * equivalent SVG code. It will also add a baseline-shift attribute so that the
 54  
  * formula is in line with the rest of the text.
 55  
  * 
 56  
  * @version $Revision: 5a7becda9147 $
 57  
  */
 58  0
 public final class Processor {
 59  
 
 60  0
     private static final class SingletonHolder {
 61  0
         private static final Processor INSTANCE = new Processor();
 62  
 
 63  0
         private SingletonHolder() {
 64  0
         }
 65  
     }
 66  
 
 67  
     /**
 68  
      * Logger for this class
 69  
      */
 70  0
     private static final Log LOGGER = LogFactory.getLog(Processor.class);
 71  
 
 72  
     // private static final String NAMESPACE_HTML =
 73  
     // "http://www.w3.org/1999/xhtml";
 74  
 
 75  
     private final Transformer transformer;
 76  
 
 77  
     /**
 78  
      * Default constructor.
 79  
      */
 80  0
     protected Processor() {
 81  
         Transformer t;
 82  
         try {
 83  0
             t = TransformerFactory.newInstance().newTransformer();
 84  0
         } catch (final TransformerException e) {
 85  0
             t = null;
 86  0
             Processor.LOGGER.warn(e.getMessage());
 87  0
             assert false;
 88  0
         }
 89  0
         this.transformer = t;
 90  0
     }
 91  
 
 92  
     /**
 93  
      * Retrieve the processor singleton object.
 94  
      * 
 95  
      * @return the Processor.
 96  
      */
 97  
     public static Processor getInstance() {
 98  0
         return Processor.SingletonHolder.INSTANCE;
 99  
     }
 100  
 
 101  
     /**
 102  
      * use {@link #getInstance()} instead.
 103  
      * 
 104  
      * @return see {@link #getInstance()}
 105  
      * @throws TransformerException
 106  
      *             see {@link #getInstance()}
 107  
      * @deprecated use {@link #getInstance()} instead.
 108  
      */
 109  
     @Deprecated
 110  
     public static Processor getProcessor() throws TransformerException {
 111  0
         return Processor.getInstance();
 112  
     }
 113  
 
 114  
     /**
 115  
      * Pre-process a .fo file.
 116  
      * 
 117  
      * @param inputSource
 118  
      *            Input File
 119  
      * @param result
 120  
      *            Output File
 121  
      * @param context
 122  
      *            LayoutContext.
 123  
      * @throws TransformerException
 124  
      *             an error occurred during the processing.
 125  
      */
 126  
     public void process(final Source inputSource, final Result result,
 127  
             final LayoutContext context) throws TransformerException {
 128  0
         Processor.LOGGER.info("Processing " + inputSource.getSystemId()
 129  
                 + " to " + result.getSystemId());
 130  
         try {
 131  0
             final Node doc = Parser.getInstance().parse(inputSource);
 132  0
             this.processSubtree(doc, context);
 133  0
             final DOMSource source = new DOMSource(doc);
 134  0
             this.transformer.transform(source, result);
 135  0
         } catch (final IOException e) {
 136  0
             throw new TransformerException("IOException", e);
 137  0
         } catch (final SAXException e) {
 138  0
             throw new TransformerException("SAXException", e);
 139  0
         }
 140  0
     }
 141  
 
 142  
     /**
 143  
      * Pre-process a .fo file.
 144  
      * 
 145  
      * @param inputSource
 146  
      *            Input File
 147  
      * @param result
 148  
      *            Output File
 149  
      * @throws TransformerException
 150  
      *             an error occurred during the processing.
 151  
      */
 152  
     public void process(final Source inputSource, final Result result)
 153  
             throws TransformerException {
 154  0
         this.process(inputSource, result, LayoutContextImpl
 155  
                 .getDefaultLayoutContext());
 156  0
     }
 157  
 
 158  
     private void processSubtree(final Node node, final LayoutContext context) {
 159  0
         if (AbstractJEuclidElement.URI.equals(node.getNamespaceURI())
 160  
                 && MathImpl.ELEMENT.equals(node.getLocalName())) {
 161  
 
 162  0
             final DocumentWithDimension svgdocdim = Converter
 163  
                     .getInstance()
 164  
                     .convert(
 165  
                             node,
 166  
                             net.sourceforge.jeuclid.converter.Converter.TYPE_SVG,
 167  
                             context);
 168  
 
 169  0
             final float baselinePercent = -(svgdocdim.getBaseline() / (float) svgdocdim
 170  
                     .getDimension().getHeight()) * 100f;
 171  
 
 172  0
             final Node parent = node.getParentNode();
 173  0
             if ("http://www.w3.org/1999/XSL/Format".equals(parent
 174  
                     .getNamespaceURI())
 175  
                     && "instream-foreign-object".equals(parent.getLocalName())) {
 176  0
                 final Element pElement = (Element) parent;
 177  0
                 pElement
 178  
                         .setAttribute("alignment-adjust", baselinePercent + "%");
 179  
             }
 180  0
             this.safeReplaceChild(parent, node, svgdocdim.getDocument()
 181  
                     .getFirstChild());
 182  0
         } else {
 183  0
             this.processChildren(node, context);
 184  
             // TODO: This is an IE-Fix, but does not work yet.
 185  
             // final Node parent = node.getParentNode();
 186  
             // if ((parent != null)
 187  
             // && (Processor.NAMESPACE_HTML.equals(parent
 188  
             // .getNamespaceURI()))
 189  
             // && ("html".equals(parent.getLocalName()))
 190  
             // && ("head".equals(node.getLocalName()))) {
 191  
             // ((Element) parent).setAttribute("xmlns:svg",
 192  
             // "http://www.w3.org/2000/svg");
 193  
             // final Document ownerDoc = node.getOwnerDocument();
 194  
             // final Element objectElement = ownerDoc
 195  
             // .createElement("object");
 196  
             // objectElement.setAttribute("id", "AdobeSVG");
 197  
             // objectElement.setAttribute("classid",
 198  
             // "clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2");
 199  
             // node.appendChild(objectElement);
 200  
             // final ProcessingInstruction pi = ownerDoc
 201  
             // .createProcessingInstruction("import",
 202  
             // "namespace=\"svg\" implementation=\"#AdobeSVG\"");
 203  
             // node.appendChild(pi);
 204  
             // }
 205  
         }
 206  0
     }
 207  
 
 208  
     private void safeReplaceChild(final Node parent, final Node oldChild,
 209  
             final Node newChild) {
 210  
         try {
 211  0
             final DOMSource source = new DOMSource(newChild);
 212  0
             final DOMResult result = new DOMResult(parent);
 213  
 
 214  0
             this.transformer.transform(source, result);
 215  0
         } catch (final TransformerException e) {
 216  0
             Processor.LOGGER.warn("TranformerException: " + e.getMessage());
 217  0
         }
 218  0
         parent.removeChild(oldChild);
 219  0
     }
 220  
 
 221  
     private void processChildren(final Node node, final LayoutContext context) {
 222  0
         final NodeList childList = node.getChildNodes();
 223  0
         if (childList != null) {
 224  0
             for (int i = 0; i < childList.getLength(); i++) {
 225  0
                 final Node child = childList.item(i);
 226  0
                 this.processSubtree(child, context);
 227  
             }
 228  
         }
 229  0
     }
 230  
 
 231  
 }