KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > objects > XRTreeFrag


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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: XRTreeFrag.java,v 1.30 2004/02/17 04:34:38 minchau Exp $
18  */

19 package org.apache.xpath.objects;
20
21 import org.apache.xml.dtm.DTM;
22 import org.apache.xml.dtm.DTMIterator;
23 import org.apache.xml.utils.XMLString;
24 import org.apache.xpath.Expression;
25 import org.apache.xpath.ExpressionNode;
26 import org.apache.xpath.XPathContext;
27 import org.apache.xpath.axes.RTFIterator;
28
29 import org.w3c.dom.NodeList JavaDoc;
30
31 /**
32  * This class represents an XPath result tree fragment object, and is capable of
33  * converting the RTF to other types, such as a string.
34  * @xsl.usage general
35  */

36 public class XRTreeFrag extends XObject implements Cloneable JavaDoc
37 {
38   DTM m_dtm;
39   int m_dtmRoot;
40   XPathContext m_xctxt;
41   boolean m_allowRelease = false;
42
43 // /**
44
// * Create an XRTreeFrag Object.
45
// *
46
// * @param frag Document fragment this will wrap
47
// */
48
// public XRTreeFrag(DTMIterator frag)
49
// {
50
// super(frag);
51
//
52
// // Obviously, this constructor should be avoided when possible.
53
// m_dtmRoot = frag.cloneWithReset().nextNode();
54
// }
55

56   /**
57    * Create an XRTreeFrag Object.
58    *
59    * @param frag Document fragment this will wrap
60    */

61   public XRTreeFrag(int root, XPathContext xctxt, ExpressionNode parent)
62   {
63     super(null);
64     
65     // Obviously, this constructor should be avoided when possible.
66
exprSetParent(parent);
67     m_dtmRoot = root;
68     m_xctxt = xctxt;
69     m_dtm = xctxt.getDTM(root);
70   }
71   
72   /**
73    * Create an XRTreeFrag Object.
74    *
75    * @param frag Document fragment this will wrap
76    */

77   public XRTreeFrag(int root, XPathContext xctxt)
78   {
79     super(null);
80     
81     // Obviously, this constructor should be avoided when possible.
82
m_dtmRoot = root;
83     m_xctxt = xctxt;
84     m_dtm = xctxt.getDTM(root);
85   }
86
87   
88   /**
89    * Return a java object that's closest to the representation
90    * that should be handed to an extension.
91    *
92    * @return The object that this class wraps
93    */

94   public Object JavaDoc object()
95   {
96     if (m_xctxt != null)
97       return new org.apache.xml.dtm.ref.DTMNodeIterator((DTMIterator)(new org.apache.xpath.NodeSetDTM(m_dtmRoot, m_xctxt.getDTMManager())));
98     else
99       return super.object();
100   }
101   
102   /**
103    * Create an XRTreeFrag Object.
104    *
105    * @param frag Document fragment this will wrap
106    */

107   public XRTreeFrag(Expression expr)
108   {
109     super(expr);
110   }
111   
112   /**
113    * Release any resources this object may have by calling destruct().
114    * %ISSUE% This release will occur asynchronously. Resources it manipulates
115    * MUST be thread-safe!
116    *
117    * @throws Throwable
118    */

119   protected void finalize() throws Throwable JavaDoc
120   {
121     try
122     {
123       destruct();
124     }
125     finally
126     {
127       super.finalize(); // Always use this.
128
}
129   }
130   
131   /**
132    * Specify if it's OK for detach to release the iterator for reuse.
133    *
134    * @param allowRelease true if it is OK for detach to release this iterator
135    * for pooling.
136    */

137   public void allowDetachToRelease(boolean allowRelease)
138   {
139     m_allowRelease = allowRelease;
140   }
141
142   /**
143    * Detaches the <code>DTMIterator</code> from the set which it iterated
144    * over, releasing any computational resources and placing the iterator
145    * in the INVALID state. After <code>detach</code> has been invoked,
146    * calls to <code>nextNode</code> or <code>previousNode</code> will
147    * raise a runtime exception.
148    *
149    * In general, detach should only be called once on the object.
150    */

151   public void detach()
152   {
153     if(m_allowRelease)
154     {
155         // %REVIEW% Do we actually _need_ detach, now that DTM RTF
156
// storage is managed as a stack?
157
// See #destruct() for a comment about this next check.
158
int ident = m_xctxt.getDTMIdentity(m_dtm);
159       DTM foundDTM = m_xctxt.getDTM(ident);
160       if(foundDTM == m_dtm)
161       {
162         m_xctxt.release(m_dtm, true);
163         m_dtm = null;
164         m_xctxt = null;
165       }
166       m_obj = null;
167     }
168   }
169   
170   /**
171    * Forces the object to release it's resources. This is more harsh than
172    * detach(). You can call destruct as many times as you want.
173    */

174   public void destruct()
175   {
176     if(null != m_dtm)
177     {
178       // For this next check, see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7622.
179
// What happens if you don't do this this check:
180
// 1) Transform#1 creates an XRTreeFrag. This has a reference to a DTM, that in turn
181
// is registered with a DTMManager. The DTM will need to be deleted from the
182
// DTMManager when the XRTreeFrag is deleted. The XRTreeFrag also contains a
183
// reference to the XPathContext.
184
// 2) Transform#1 completes. The XPathContext is reset... namely the a bunch
185
// of structures are reset or rebuilt, including DTMManagerDefault#m_dtms.
186
// BUT, the XRTreeFrags are still hanging around, waiting to unregister themselves.
187
// 3) Transform#2 starts humming along. It builds a XRTreeFrag and installs that
188
// RTF DTM into DTMManagerDefault#m_dtms[2].
189
// 4) The finalizer thread wakes and decides to delete some of those old XRTreeFrags
190
// from Transform#1.
191
// 5) The XRTreeFrag#finalize() method references through the XPathContext, and
192
// deletes what it thinks is it's DTM from DTMManagerDefault#m_dtms[2] (via
193
// getDTMIdentity(dtm)).
194
// 6) Transform#2 tries to reference DTMManagerDefault#m_dtms[2], finds it is
195
// null, and chaos results.
196
int ident = m_xctxt.getDTMIdentity(m_dtm);
197       DTM foundDTM = m_xctxt.getDTM(ident);
198       if(foundDTM == m_dtm)
199       {
200         m_xctxt.release(m_dtm, true);
201         m_dtm = null;
202         m_xctxt = null;
203       }
204     }
205     m_obj = null;
206  }
207
208   /**
209    * Tell what kind of class this is.
210    *
211    * @return type CLASS_RTREEFRAG
212    */

213   public int getType()
214   {
215     return CLASS_RTREEFRAG;
216   }
217
218   /**
219    * Given a request type, return the equivalent string.
220    * For diagnostic purposes.
221    *
222    * @return type string "#RTREEFRAG"
223    */

224   public String JavaDoc getTypeString()
225   {
226     return "#RTREEFRAG";
227   }
228
229   /**
230    * Cast result object to a number.
231    *
232    * @return The result tree fragment as a number or NaN
233    */

234   public double num()
235     throws javax.xml.transform.TransformerException JavaDoc
236   {
237
238     XMLString s = xstr();
239
240     return s.toDouble();
241   }
242
243   /**
244    * Cast result object to a boolean. This always returns true for a RTreeFrag
245    * because it is treated like a node-set with a single root node.
246    *
247    * @return true
248    */

249   public boolean bool()
250   {
251     return true;
252   }
253   
254   private XMLString m_xmlStr = null;
255   
256   /**
257    * Cast result object to an XMLString.
258    *
259    * @return The document fragment node data or the empty string.
260    */

261   public XMLString xstr()
262   {
263     if(null == m_xmlStr)
264       m_xmlStr = m_dtm.getStringValue(m_dtmRoot);
265     
266     return m_xmlStr;
267   }
268   
269   /**
270    * Cast result object to a string.
271    *
272    * @return The string this wraps or the empty string if null
273    */

274   public void appendToFsb(org.apache.xml.utils.FastStringBuffer fsb)
275   {
276     XString xstring = (XString)xstr();
277     xstring.appendToFsb(fsb);
278   }
279
280
281   /**
282    * Cast result object to a string.
283    *
284    * @return The document fragment node data or the empty string.
285    */

286   public String JavaDoc str()
287   {
288     String JavaDoc str = m_dtm.getStringValue(m_dtmRoot).toString();
289
290     return (null == str) ? "" : str;
291   }
292
293   /**
294    * Cast result object to a result tree fragment.
295    *
296    * @return The document fragment this wraps
297    */

298   public int rtf()
299   {
300     return m_dtmRoot;
301   }
302
303   /**
304    * Cast result object to a DTMIterator.
305    * dml - modified to return an RTFIterator for
306    * benefit of EXSLT object-type function in
307    * {@link org.apache.xalan.lib.ExsltCommon}.
308    * @return The document fragment as a DTMIterator
309    */

310   public DTMIterator asNodeIterator()
311   {
312     return new RTFIterator(m_dtmRoot, m_xctxt.getDTMManager());
313   }
314
315   /**
316    * Cast result object to a nodelist. (special function).
317    *
318    * @return The document fragment as a nodelist
319    */

320   public NodeList JavaDoc convertToNodeset()
321   {
322
323     if (m_obj instanceof NodeList JavaDoc)
324       return (NodeList JavaDoc) m_obj;
325     else
326       return new org.apache.xml.dtm.ref.DTMNodeList(asNodeIterator());
327   }
328
329   /**
330    * Tell if two objects are functionally equal.
331    *
332    * @param obj2 Object to compare this to
333    *
334    * @return True if the two objects are equal
335    *
336    * @throws javax.xml.transform.TransformerException
337    */

338   public boolean equals(XObject obj2)
339   {
340
341     try
342     {
343       if (XObject.CLASS_NODESET == obj2.getType())
344       {
345   
346         // In order to handle the 'all' semantics of
347
// nodeset comparisons, we always call the
348
// nodeset function.
349
return obj2.equals(this);
350       }
351       else if (XObject.CLASS_BOOLEAN == obj2.getType())
352       {
353         return bool() == obj2.bool();
354       }
355       else if (XObject.CLASS_NUMBER == obj2.getType())
356       {
357         return num() == obj2.num();
358       }
359       else if (XObject.CLASS_NODESET == obj2.getType())
360       {
361         return xstr().equals(obj2.xstr());
362       }
363       else if (XObject.CLASS_STRING == obj2.getType())
364       {
365         return xstr().equals(obj2.xstr());
366       }
367       else if (XObject.CLASS_RTREEFRAG == obj2.getType())
368       {
369   
370         // Probably not so good. Think about this.
371
return xstr().equals(obj2.xstr());
372       }
373       else
374       {
375         return super.equals(obj2);
376       }
377     }
378     catch(javax.xml.transform.TransformerException JavaDoc te)
379     {
380       throw new org.apache.xml.utils.WrappedRuntimeException(te);
381     }
382   }
383
384 }
385
Popular Tags