| /* |
| * 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. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.fo; |
| |
| // Java |
| import java.awt.geom.Point2D; |
| import java.util.HashMap; |
| |
| import javax.xml.parsers.DocumentBuilderFactory; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| import org.xml.sax.Attributes; |
| import org.xml.sax.Locator; |
| |
| import org.apache.fop.apps.FOPException; |
| import org.apache.fop.datatypes.Length; |
| import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; |
| |
| /** |
| * Abstract class modelling generic, non-XSL-FO XML objects. Such objects are |
| * stored in a DOM. |
| */ |
| public abstract class XMLObj extends FONode implements ObjectBuiltListener { |
| |
| private static final String XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/"; |
| |
| // temp reference for attributes |
| private Attributes attr = null; |
| |
| /** DOM element representing this node */ |
| protected Element element; |
| |
| /** DOM document containing this node */ |
| protected Document doc; |
| |
| /** Name of the node */ |
| protected String name; |
| |
| /** |
| * Base constructor |
| * |
| * @param parent {@link FONode} that is the parent of this object |
| */ |
| public XMLObj(FONode parent) { |
| super(parent); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <br>Here, blocks XSL-FO's from having non-FO parents. |
| */ |
| protected void validateChildNode(Locator loc, String nsURI, String localName) |
| throws ValidationException { |
| if (FO_URI.equals(nsURI)) { |
| invalidChildError(loc, nsURI, localName); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void processNode(String elementName, Locator locator, |
| Attributes attlist, PropertyList propertyList) throws FOPException { |
| setLocator(locator); |
| name = elementName; |
| attr = attlist; |
| } |
| |
| /** |
| * @return DOM document representing this foreign XML |
| */ |
| public Document getDOMDocument() { |
| return doc; |
| } |
| |
| /** |
| * Returns the dimensions of the generated area in pts. |
| * |
| * @param view Point2D instance to receive the dimensions |
| * @return the requested dimensions in pts. |
| */ |
| public Point2D getDimension(Point2D view) { |
| return null; |
| } |
| |
| /** |
| * Retrieve the intrinsic alignment-adjust of the child element. |
| * |
| * @return the intrinsic alignment-adjust. |
| */ |
| public Length getIntrinsicAlignmentAdjust() { |
| return null; |
| } |
| |
| /** {@inheritDoc} */ |
| public String getLocalName() { |
| return name; |
| } |
| |
| private static HashMap ns = new HashMap(); |
| static { |
| ns.put("xlink", "http://www.w3.org/1999/xlink"); |
| } |
| |
| /** |
| * Add an element to the DOM document |
| * @param doc DOM document to which to add an element |
| * @param parent the parent element of the element that is being added |
| */ |
| public void addElement(Document doc, Element parent) { |
| this.doc = doc; |
| element = doc.createElementNS(getNamespaceURI(), name); |
| |
| setAttributes(element, attr); |
| attr = null; |
| parent.appendChild(element); |
| } |
| |
| private static void setAttributes(Element element, Attributes attr) { |
| for (int count = 0; count < attr.getLength(); count++) { |
| String rf = attr.getValue(count); |
| String qname = attr.getQName(count); |
| int idx = qname.indexOf(":"); |
| if (idx == -1) { |
| element.setAttribute(qname, rf); |
| } else { |
| String pref = qname.substring(0, idx); |
| String tail = qname.substring(idx + 1); |
| if (pref.equals("xmlns")) { |
| ns.put(tail, rf); |
| } else { |
| element.setAttributeNS((String)ns.get(pref), tail, rf); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Add the top-level element to the DOM document |
| * |
| * @param doc DOM document |
| * @param svgRoot non-XSL-FO element to be added as the root of this document |
| */ |
| public void buildTopLevel(Document doc, Element svgRoot) { |
| // build up the info for the top level element |
| setAttributes(element, attr); |
| } |
| |
| /** |
| * Create an empty DOM document |
| * |
| * @return DOM document |
| */ |
| public Document createBasicDocument() { |
| doc = null; |
| |
| element = null; |
| try { |
| DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); |
| fact.setNamespaceAware(true); |
| doc = fact.newDocumentBuilder().newDocument(); |
| Element el = doc.createElementNS(getNamespaceURI(), name); |
| doc.appendChild(el); |
| |
| element = doc.getDocumentElement(); |
| buildTopLevel(doc, element); |
| if (!element.hasAttributeNS(XMLNS_NAMESPACE_URI, "xmlns")) { |
| element.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns", |
| getNamespaceURI()); |
| } |
| |
| } catch (Exception e) { |
| //TODO this is ugly because there may be subsequent failures like NPEs |
| log.error("Error while trying to instantiate a DOM Document", e); |
| } |
| return doc; |
| } |
| |
| /** {@inheritDoc} */ |
| protected void addChildNode(FONode child) { |
| if (child instanceof XMLObj) { |
| ((XMLObj)child).addElement(doc, element); |
| } else { |
| // in theory someone might want to embed some defined |
| // xml (eg. fo) inside the foreign xml |
| // they could use a different namespace |
| log.debug("Invalid element: " + child.getName() + " inside foreign xml markup"); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected void characters(char[] data, int start, int length, |
| PropertyList pList, Locator locator) throws FOPException { |
| super.characters(data, start, length, pList, locator); |
| String str = new String(data, start, length); |
| org.w3c.dom.Text text = doc.createTextNode(str); |
| element.appendChild(text); |
| } |
| |
| /** {@inheritDoc} */ |
| public void notifyObjectBuilt(Object obj) { |
| this.doc = (Document)obj; |
| this.element = this.doc.getDocumentElement(); |
| } |
| |
| } |
| |