KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > dom > DOMEnvelope


1 package net.sf.saxon.dom;
2
3 import net.sf.saxon.Configuration;
4 import net.sf.saxon.event.PipelineConfiguration;
5 import net.sf.saxon.event.Receiver;
6 import net.sf.saxon.event.Sender;
7 import net.sf.saxon.expr.XPathContext;
8 import net.sf.saxon.om.*;
9 import net.sf.saxon.trans.DynamicError;
10 import net.sf.saxon.trans.XPathException;
11 import net.sf.saxon.value.SequenceExtent;
12 import net.sf.saxon.value.Value;
13 import org.w3c.dom.Node JavaDoc;
14 import org.w3c.dom.NodeList JavaDoc;
15
16 import javax.xml.transform.Result JavaDoc;
17 import javax.xml.transform.Source JavaDoc;
18 import javax.xml.transform.dom.DOMSource JavaDoc;
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.List JavaDoc;
23
24 /**
25  * DOMEnvelope is an object model representation in which DOM interfaces are wrapped around
26  * Saxon NodeInfo nodes: that is, it implements the DOM on top of a Saxon tree implementation
27  * such as the TinyTree or standard tree.
28  */

29
30 //TODO: this class has been supplied to a user (Pier Fumagalli) for testing. If it works, the code in
31
//DOMObjectModel that handles a NodeOverNodeInfo wrapper is redundant and can be removed.
32

33 public class DOMEnvelope implements ExternalObjectModel, Serializable JavaDoc {
34
35     public DOMEnvelope() {}
36
37      /**
38      * Test whether this object model recognizes a given node as one of its own
39      */

40
41     public boolean isRecognizedNode(Object JavaDoc object) {
42          return object instanceof NodeOverNodeInfo;
43     }
44
45     /**
46      * Test whether this object model recognizes a given class as representing a
47      * node in that object model. This method will generally be called at compile time.
48      *
49      * @param nodeClass A class that possibly represents nodes
50      * @return true if the class is used to represent nodes in this object model
51      */

52
53     public boolean isRecognizedNodeClass(Class JavaDoc nodeClass) {
54         return NodeOverNodeInfo.class.isAssignableFrom(nodeClass);
55     }
56
57     /**
58      * Test whether this object model recognizes a given class as representing a
59      * list of nodes in that object model. This method will generally be called at compile time.
60      *
61      * @param nodeClass A class that possibly represents nodes
62      * @return true if the class is used to represent nodes in this object model
63      */

64
65     public boolean isRecognizedNodeListClass(Class JavaDoc nodeClass) {
66         return NodeList JavaDoc.class.isAssignableFrom(nodeClass);
67     }
68
69     /**
70      * Test whether this object model recognizes a particular kind of JAXP Result object,
71      * and if it does, return a Receiver that builds an instance of this data model from
72      * a sequence of events. If the Result is not recognised, return null.
73      * <p>
74      * This implementation always returns null: it is not possible to construct an instance
75      * of this object model implementation directly as the result of a JAXP transformation.
76      */

77
78     public Receiver getDocumentBuilder(Result JavaDoc result) throws XPathException {
79         return null;
80     }
81
82     /**
83      * Test whether this object model recognizes a particular kind of JAXP Source object,
84      * and if it does, send the contents of the document to a supplied Receiver, and return true.
85      * Otherwise, return false.
86      * <p>
87      * This implementation returns true only if the source is a DOMSource whose contained node is a
88      * a "NodeOverNodeInfo".
89      */

90
91     public boolean sendSource(Source JavaDoc source, Receiver receiver, PipelineConfiguration pipe) throws XPathException {
92         if (source instanceof DOMSource JavaDoc) {
93             Node JavaDoc startNode = ((DOMSource JavaDoc)source).getNode();
94             if (startNode instanceof NodeOverNodeInfo) {
95                 NodeInfo base = ((NodeOverNodeInfo)startNode).getUnderlyingNodeInfo();
96                 Sender driver = new Sender(pipe);
97                 driver.send(base, receiver);
98                 return true;
99             }
100         }
101         return false;
102     }
103
104     /**
105      * Wrap or unwrap a node using this object model to return the corresponding Saxon node. If the supplied
106      * source does not belong to this object model, return null
107      */

108
109     public NodeInfo unravel(Source JavaDoc source, Configuration config) {
110
111         if (source instanceof DOMSource JavaDoc) {
112             NodeInfo start;
113             Node JavaDoc dsnode = ((DOMSource JavaDoc)source).getNode();
114             if (dsnode instanceof NodeOverNodeInfo) {
115                 // Supplied source is a DOM Node wrapping a Saxon node: unwrap it
116
start = ((NodeOverNodeInfo)dsnode).getUnderlyingNodeInfo();
117                 return start;
118             }
119         }
120         return null;
121     }
122
123     /**
124      * Convert a Java object to an XPath value. If the supplied object is recognized as a representation
125      * of a value using this object model, the object model should convert the value to an XPath value
126      * and return this as the result. If not, it should return null. If the object is recognized but cannot
127      * be converted, an exception should be thrown
128      */

129
130     public Value convertObjectToXPathValue(Object JavaDoc object, Configuration config) throws XPathException {
131         if (object instanceof NodeList JavaDoc) {
132             NodeList JavaDoc list = ((NodeList JavaDoc)object);
133             NodeInfo[] nodes = new NodeInfo[list.getLength()];
134             for (int i=0; i<list.getLength(); i++) {
135                 if (list.item(i) instanceof NodeOverNodeInfo) {
136                     nodes[i] = ((NodeOverNodeInfo)list.item(i)).getUnderlyingNodeInfo();
137                 } else {
138                     return null;
139                 }
140             }
141             return new SequenceExtent(nodes);
142
143             // Note, we accept the nodes in the order returned by the function; there
144
// is no requirement that this should be document order.
145
} else if (object instanceof NodeOverNodeInfo) {
146             return Value.asValue(((NodeOverNodeInfo)object).getUnderlyingNodeInfo());
147         } else {
148             return null;
149         }
150     }
151
152     /**
153      * Convert an XPath value to an object in this object model. If the supplied value can be converted
154      * to an object in this model, of the specified class, then the conversion should be done and the
155      * resulting object returned. If the value cannot be converted, the method should return null. Note
156      * that the supplied class might be a List, in which case the method should inspect the contents of the
157      * Value to see whether they belong to this object model.
158      * @throws net.sf.saxon.trans.XPathException if the target class is explicitly associated with this object model, but the
159      * supplied value cannot be converted to the appropriate class
160      */

161
162     public Object JavaDoc convertXPathValueToObject(Value value, Class JavaDoc target, XPathContext context) throws XPathException {
163         // We accept the object if (a) the target class is Node, Node[], or NodeList,
164
// or (b) the supplied object is a node, or sequence of nodes, that wrap DOM nodes,
165
// provided that the target class is Object or a collection class
166
boolean requireDOM =
167                 (Node JavaDoc.class.isAssignableFrom(target) || (target == NodeList JavaDoc.class) ||
168                 (target.isArray() && Node JavaDoc.class.isAssignableFrom(target.getComponentType())));
169
170         // Note: we allow the declared type of the method argument to be a subclass of Node. If the actual
171
// node supplied is the wrong kind of node, this will result in a Java exception.
172

173         boolean allowDOM =
174                 (target == Object JavaDoc.class || target.isAssignableFrom(ArrayList JavaDoc.class) ||
175                 target.isAssignableFrom(HashSet JavaDoc.class) ||
176                 (target.isArray() && target.getComponentType() == Object JavaDoc.class));
177         if (!(requireDOM || allowDOM)) {
178             return null;
179         }
180         List JavaDoc nodes = new ArrayList JavaDoc(20);
181
182         SequenceIterator iter = value.iterate(context);
183         while (true) {
184             Item item = iter.next();
185             if (item == null) {
186                 break;
187             }
188             if (item instanceof VirtualNode) {
189                 Object JavaDoc o = ((VirtualNode)item).getUnderlyingNode();
190                 if (o instanceof Node JavaDoc) {
191                     nodes.add(o);
192                 } else {
193                     if (requireDOM) {
194                         DynamicError err = new DynamicError("Extension function required class " + target.getName() +
195                                 "; supplied value of class " + item.getClass().getName() +
196                                 " could not be converted");
197                         throw err;
198                     };
199                 }
200             } else if (requireDOM) {
201                 if (item instanceof NodeInfo) {
202                     nodes.add(NodeOverNodeInfo.wrap((NodeInfo)item));
203                 } else {
204                     DynamicError err = new DynamicError("Extension function required class " + target.getName() +
205                                 "; supplied value of class " + item.getClass().getName() +
206                                 " could not be converted");
207                     throw err;
208                 }
209             } else {
210                 return null; // DOM Nodes are not actually required; let someone else try the conversion
211
}
212         }
213
214         if (nodes.size() == 0 && !requireDOM) {
215             return null; // empty sequence supplied - try a different mapping
216
}
217         if (Node JavaDoc.class.isAssignableFrom(target)) {
218             if (nodes.size() != 1) {
219                 DynamicError err = new DynamicError("Extension function requires a single DOM Node" +
220                                 "; supplied value contains " + nodes.size() + " nodes");
221                 throw err;
222             }
223             return nodes.get(0);
224             // could fail if the node is of the wrong kind
225
} else if (target == NodeList JavaDoc.class) {
226             return new DOMNodeList(nodes);
227         } else if (target.isArray() && target.getComponentType() == Node JavaDoc.class) {
228             Node JavaDoc[] array = new Node JavaDoc[nodes.size()];
229             nodes.toArray(array);
230             return array;
231         } else if (target.isAssignableFrom(ArrayList JavaDoc.class)) {
232             return nodes;
233         } else if (target.isAssignableFrom(HashSet JavaDoc.class)) {
234             return new HashSet JavaDoc(nodes);
235         } else {
236             // after all this work, give up
237
return null;
238         }
239     }
240
241     /**
242      * Wrap a document node in the external object model in a document wrapper that implements
243      * the Saxon DocumentInfo interface. (However, if the supplied object is a wrapper for a Saxon
244      * NodeInfo object, which is the case for this object model, then we <i>unwrap</i> it).
245      * @param node a node (any node) in the third party document
246      * @param baseURI the base URI of the node (supply "" if unknown)
247      * @param config the Saxon configuration (which among other things provides access to the NamePool)
248      * @return the wrapper, which must implement DocumentInfo
249      */

250
251     public DocumentInfo wrapDocument(Object JavaDoc node, String JavaDoc baseURI, Configuration config) {
252         if (node instanceof DocumentOverNodeInfo) {
253             return (DocumentInfo)((DocumentOverNodeInfo)node).getUnderlyingNodeInfo();
254         }
255         if (node instanceof NodeOverNodeInfo) {
256             return ((NodeOverNodeInfo)node).getUnderlyingNodeInfo().getDocumentRoot();
257         }
258         throw new IllegalArgumentException JavaDoc("Unknown node class " + node.getClass());
259     }
260
261     /**
262      * Wrap a node in the external object model in a wrapper that implements
263      * the Saxon NodeInfo interface. (However, if the supplied object is a wrapper for a Saxon
264      * NodeInfo object, which is the case for this object model, then we <i>unwrap</i> it).
265      * @param document the document wrapper, as a DocumentInfo object
266      * @param node the node to be wrapped. This must be a node within the document wrapped by the
267      * DocumentInfo provided in the first argument
268      * @return the wrapper for the node, as an instance of VirtualNode
269      */

270
271     public NodeInfo wrapNode(DocumentInfo document, Object JavaDoc node) {
272         if (node instanceof NodeOverNodeInfo) {
273             return ((NodeOverNodeInfo)node).getUnderlyingNodeInfo();
274         }
275         throw new IllegalArgumentException JavaDoc("Unknown node class " + node.getClass());
276     }
277
278     /**
279      * Convert a sequence of values to a NODELIST, as defined in the JAXP XPath API spec. This method
280      * is used when the evaluate() request specifies the return type as NODELIST, regardless of the
281      * actual results of the expression. If the sequence contains things other than nodes, the fallback
282      * is to return the sequence as a Java List object. The method can return null to invoke fallback
283      * behaviour.
284      */

285
286     public Object JavaDoc convertToNodeList(SequenceExtent extent) {
287         return null;
288     }
289 }
290
291
292 //
293
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
294
// you may not use this file except in compliance with the License. You may obtain a copy of the
295
// License at http://www.mozilla.org/MPL/
296
//
297
// Software distributed under the License is distributed on an "AS IS" basis,
298
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
299
// See the License for the specific language governing rights and limitations under the License.
300
//
301
// The Original Code is: all this file.
302
//
303
// The Initial Developer of the Original Code is Michael H. Kay.
304
//
305
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
306
//
307
// Contributor(s): Gunther Schadow (changes to allow access to public fields; also wrapping
308
// of extensions and mapping of null to empty sequence).
309
//
310
Popular Tags