1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: DOM2Helper.java 468655 2006-10-28 07:12:06Z minchau $
20 */
21package org.apache.xml.utils;
22
23import java.io.IOException;
24
25import javax.xml.parsers.DocumentBuilder;
26import javax.xml.parsers.DocumentBuilderFactory;
27import javax.xml.parsers.ParserConfigurationException;
28import javax.xml.transform.TransformerException;
29
30import org.w3c.dom.Attr;
31import org.w3c.dom.Document;
32import org.w3c.dom.Element;
33import org.w3c.dom.Node;
34
35import org.xml.sax.InputSource;
36
37/**
38 * @deprecated Since the introduction of the DTM, this class will be removed.
39 * This class provides a DOM level 2 "helper", which provides services currently
40 * not provided be the DOM standard.
41 */
42public class DOM2Helper extends DOMHelper
43{
44
45  /**
46   * Construct an instance.
47   */
48  public DOM2Helper(){}
49
50  /**
51   * Check node to see if it was created by a DOM implementation
52   * that this helper is intended to support. This is currently
53   * disabled, and assumes all nodes are acceptable rather than checking
54   * that they implement org.apache.xerces.dom.NodeImpl.
55   *
56   * @param node The node to be tested.
57   *
58   * @throws TransformerException if the node is not one which this
59   * DOM2Helper can support. If we return without throwing the exception,
60   * the node is compatable.
61   * @xsl.usage internal
62   */
63  public void checkNode(Node node) throws TransformerException
64  {
65
66    // if(!(node instanceof org.apache.xerces.dom.NodeImpl))
67    //  throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_CANNOT_HANDLE_NODES, new Object[]{((Object)node).getClass()})); //"DOM2Helper can not handle nodes of type"
68    //+((Object)node).getClass());
69  }
70
71  /**
72   * Returns true if the DOM implementation handled by this helper
73   * supports the SAX ContentHandler interface.
74   *
75   * @return true (since Xerces does).
76   */
77  public boolean supportsSAX()
78  {
79    return true;
80  }
81
82  /** Field m_doc: Document Node for the document this helper is currently
83   * accessing or building
84   * @see #setDocument
85   * @see #getDocument
86   *  */
87  private Document m_doc;
88
89  /**
90   * Specify which document this helper is currently operating on.
91   *
92   * @param doc The DOM Document node for this document.
93   * @see #getDocument
94   */
95  public void setDocument(Document doc)
96  {
97    m_doc = doc;
98  }
99
100  /**
101   * Query which document this helper is currently operating on.
102   *
103   * @return The DOM Document node for this document.
104   * @see #setDocument
105   */
106  public Document getDocument()
107  {
108    return m_doc;
109  }
110
111  /**
112   * Parse an XML document.
113   *
114   * <p>Right now the Xerces DOMParser class is used.  This needs
115   * fixing, either via jaxp, or via some other, standard method.</p>
116   *
117   * <p>The application can use this method to instruct the SAX parser
118   * to begin parsing an XML document from any valid input
119   * source (a character stream, a byte stream, or a URI).</p>
120   *
121   * <p>Applications may not invoke this method while a parse is in
122   * progress (they should create a new Parser instead for each
123   * additional XML document).  Once a parse is complete, an
124   * application may reuse the same Parser object, possibly with a
125   * different input source.</p>
126   *
127   * @param source The input source for the top-level of the
128   *        XML document.
129   *
130   * @throws TransformerException if any checked exception is thrown.
131   * @xsl.usage internal
132   */
133  public void parse(InputSource source) throws TransformerException
134  {
135
136    try
137    {
138
139      // I guess I should use JAXP factory here... when it's legal.
140      // org.apache.xerces.parsers.DOMParser parser
141      //  = new org.apache.xerces.parsers.DOMParser();
142      DocumentBuilderFactory builderFactory =
143        DocumentBuilderFactory.newInstance();
144
145      builderFactory.setNamespaceAware(true);
146      builderFactory.setValidating(true);
147
148      DocumentBuilder parser = builderFactory.newDocumentBuilder();
149
150      /*
151      // domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", getShouldExpandEntityRefs()? false : true);
152      if(m_useDOM2getNamespaceURI)
153      {
154      parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
155      parser.setFeature("http://xml.org/sax/features/namespaces", true);
156      }
157      else
158      {
159      parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
160      }
161
162      parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
163      */
164
165      parser.setErrorHandler(
166        new org.apache.xml.utils.DefaultErrorHandler());
167
168      // if(null != m_entityResolver)
169      // {
170      // System.out.println("Setting the entity resolver.");
171      //  parser.setEntityResolver(m_entityResolver);
172      // }
173      setDocument(parser.parse(source));
174    }
175    catch (org.xml.sax.SAXException se)
176    {
177      throw new TransformerException(se);
178    }
179    catch (ParserConfigurationException pce)
180    {
181      throw new TransformerException(pce);
182    }
183    catch (IOException ioe)
184    {
185      throw new TransformerException(ioe);
186    }
187
188    // setDocument(((org.apache.xerces.parsers.DOMParser)parser).getDocument());
189  }
190
191  /**
192   * Given an XML ID, return the element. This requires assistance from the
193   * DOM and parser, and is meaningful only in the context of a DTD
194   * or schema which declares attributes as being of type ID. This
195   * information may or may not be available in all parsers, may or
196   * may not be available for specific documents, and may or may not
197   * be available when validation is not turned on.
198   *
199   * @param id The ID to search for, as a String.
200   * @param doc The document to search within, as a DOM Document node.
201   * @return DOM Element node with an attribute of type ID whose value
202   * uniquely matches the requested id string, or null if there isn't
203   * such an element or if the DOM can't answer the question for other
204   * reasons.
205   */
206  public Element getElementByID(String id, Document doc)
207  {
208    return doc.getElementById(id);
209  }
210
211  /**
212   * Figure out whether node2 should be considered as being later
213   * in the document than node1, in Document Order as defined
214   * by the XPath model. This may not agree with the ordering defined
215   * by other XML applications.
216   * <p>
217   * There are some cases where ordering isn't defined, and neither are
218   * the results of this function -- though we'll generally return true.
219   * <p>
220   * TODO: Make sure this does the right thing with attribute nodes!!!
221   *
222   * @param node1 DOM Node to perform position comparison on.
223   * @param node2 DOM Node to perform position comparison on .
224   *
225   * @return false if node2 comes before node1, otherwise return true.
226   * You can think of this as
227   * <code>(node1.documentOrderPosition &lt;= node2.documentOrderPosition)</code>.
228   */
229  public static boolean isNodeAfter(Node node1, Node node2)
230  {
231
232    // Assume first that the nodes are DTM nodes, since discovering node
233    // order is massivly faster for the DTM.
234    if(node1 instanceof DOMOrder && node2 instanceof DOMOrder)
235    {
236      int index1 = ((DOMOrder) node1).getUid();
237      int index2 = ((DOMOrder) node2).getUid();
238
239      return index1 <= index2;
240    }
241    else
242    {
243
244      // isNodeAfter will return true if node is after countedNode
245      // in document order. The base isNodeAfter is sloooow (relatively).
246      return DOMHelper.isNodeAfter(node1, node2);
247    }
248  }
249
250  /**
251   * Get the XPath-model parent of a node.  This version takes advantage
252   * of the DOM Level 2 Attr.ownerElement() method; the base version we
253   * would otherwise inherit is prepared to fall back on exhaustively
254   * walking the document to find an Attr's parent.
255   *
256   * @param node Node to be examined
257   *
258   * @return the DOM parent of the input node, if there is one, or the
259   * ownerElement if the input node is an Attr, or null if the node is
260   * a Document, a DocumentFragment, or an orphan.
261   */
262  public static Node getParentOfNode(Node node)
263  {
264          Node parent=node.getParentNode();
265          if(parent==null && (Node.ATTRIBUTE_NODE == node.getNodeType()) )
266           parent=((Attr) node).getOwnerElement();
267          return parent;
268  }
269
270  /**
271   * Returns the local name of the given node, as defined by the
272   * XML Namespaces specification. This is prepared to handle documents
273   * built using DOM Level 1 methods by falling back upon explicitly
274   * parsing the node name.
275   *
276   * @param n Node to be examined
277   *
278   * @return String containing the local name, or null if the node
279   * was not assigned a Namespace.
280   */
281  public String getLocalNameOfNode(Node n)
282  {
283
284    String name = n.getLocalName();
285
286    return (null == name) ? super.getLocalNameOfNode(n) : name;
287  }
288
289  /**
290   * Returns the Namespace Name (Namespace URI) for the given node.
291   * In a Level 2 DOM, you can ask the node itself. Note, however, that
292   * doing so conflicts with our decision in getLocalNameOfNode not
293   * to trust the that the DOM was indeed created using the Level 2
294   * methods. If Level 1 methods were used, these two functions will
295   * disagree with each other.
296   * <p>
297   * TODO: Reconcile with getLocalNameOfNode.
298   *
299   * @param n Node to be examined
300   *
301   * @return String containing the Namespace URI bound to this DOM node
302   * at the time the Node was created.
303   */
304  public String getNamespaceOfNode(Node n)
305  {
306    return n.getNamespaceURI();
307  }
308
309  /** Field m_useDOM2getNamespaceURI is a compile-time flag which
310   *  gates some of the parser options used to build a DOM -- but
311   * that code is commented out at this time and nobody else
312   * references it, so I've commented this out as well. */
313  //private boolean m_useDOM2getNamespaceURI = false;
314}
315