1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xpath.internal.objects;
23
24import com.sun.org.apache.xml.internal.dtm.DTM;
25import com.sun.org.apache.xml.internal.dtm.DTMIterator;
26import com.sun.org.apache.xml.internal.utils.XMLString;
27import com.sun.org.apache.xpath.internal.Expression;
28import com.sun.org.apache.xpath.internal.ExpressionNode;
29import com.sun.org.apache.xpath.internal.XPathContext;
30import com.sun.org.apache.xpath.internal.axes.RTFIterator;
31
32import org.w3c.dom.NodeList;
33
34/**
35 * This class represents an XPath result tree fragment object, and is capable of
36 * converting the RTF to other types, such as a string.
37 * @xsl.usage general
38 */
39public class XRTreeFrag extends XObject implements Cloneable
40{
41    static final long serialVersionUID = -3201553822254911567L;
42  private DTMXRTreeFrag m_DTMXRTreeFrag;
43  private int m_dtmRoot = DTM.NULL;
44  protected boolean m_allowRelease = false;
45
46
47  /**
48   * Create an XRTreeFrag Object.
49   *
50   */
51  public XRTreeFrag(int root, XPathContext xctxt, ExpressionNode parent)
52  {
53    super(null);
54    exprSetParent(parent);
55    initDTM(root, xctxt);
56  }
57
58  /**
59   * Create an XRTreeFrag Object.
60   *
61   */
62  public XRTreeFrag(int root, XPathContext xctxt)
63  {
64    super(null);
65   initDTM(root, xctxt);
66  }
67
68  private final void initDTM(int root, XPathContext xctxt){
69    m_dtmRoot = root;
70    final DTM dtm = xctxt.getDTM(root);
71    if(dtm != null){
72      m_DTMXRTreeFrag = xctxt.getDTMXRTreeFrag(xctxt.getDTMIdentity(dtm));
73    }
74  }
75
76  /**
77   * Return a java object that's closest to the representation
78   * that should be handed to an extension.
79   *
80   * @return The object that this class wraps
81   */
82  public Object object()
83  {
84    if (m_DTMXRTreeFrag.getXPathContext() != null)
85      return new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeIterator((DTMIterator)(new com.sun.org.apache.xpath.internal.NodeSetDTM(m_dtmRoot, m_DTMXRTreeFrag.getXPathContext().getDTMManager())));
86    else
87      return super.object();
88  }
89
90  /**
91   * Create an XRTreeFrag Object.
92   *
93   */
94  public XRTreeFrag(Expression expr)
95  {
96    super(expr);
97  }
98
99  /**
100   * Specify if it's OK for detach to release the iterator for reuse.
101   *
102   * @param allowRelease true if it is OK for detach to release this iterator
103   * for pooling.
104   */
105  public void allowDetachToRelease(boolean allowRelease)
106  {
107    m_allowRelease = allowRelease;
108  }
109
110  /**
111   * Detaches the <code>DTMIterator</code> from the set which it iterated
112   * over, releasing any computational resources and placing the iterator
113   * in the INVALID state. After <code>detach</code> has been invoked,
114   * calls to <code>nextNode</code> or <code>previousNode</code> will
115   * raise a runtime exception.
116   *
117   * In general, detach should only be called once on the object.
118   */
119  public void detach(){
120    if(m_allowRelease){
121        m_DTMXRTreeFrag.destruct();
122      setObject(null);
123    }
124  }
125
126  /**
127   * Tell what kind of class this is.
128   *
129   * @return type CLASS_RTREEFRAG
130   */
131  public int getType()
132  {
133    return CLASS_RTREEFRAG;
134  }
135
136  /**
137   * Given a request type, return the equivalent string.
138   * For diagnostic purposes.
139   *
140   * @return type string "#RTREEFRAG"
141   */
142  public String getTypeString()
143  {
144    return "#RTREEFRAG";
145  }
146
147  /**
148   * Cast result object to a number.
149   *
150   * @return The result tree fragment as a number or NaN
151   */
152  public double num()
153    throws javax.xml.transform.TransformerException
154  {
155
156    XMLString s = xstr();
157
158    return s.toDouble();
159  }
160
161  /**
162   * Cast result object to a boolean.  This always returns true for a RTreeFrag
163   * because it is treated like a node-set with a single root node.
164   *
165   * @return true
166   */
167  public boolean bool()
168  {
169    return true;
170  }
171
172  private XMLString m_xmlStr = null;
173
174  /**
175   * Cast result object to an XMLString.
176   *
177   * @return The document fragment node data or the empty string.
178   */
179  public XMLString xstr()
180  {
181    if(null == m_xmlStr)
182      m_xmlStr = m_DTMXRTreeFrag.getDTM().getStringValue(m_dtmRoot);
183
184    return m_xmlStr;
185  }
186
187  /**
188   * Cast result object to a string.
189   *
190   * @return The string this wraps or the empty string if null
191   */
192  public void appendToFsb(com.sun.org.apache.xml.internal.utils.FastStringBuffer fsb)
193  {
194    XString xstring = (XString)xstr();
195    xstring.appendToFsb(fsb);
196  }
197
198
199  /**
200   * Cast result object to a string.
201   *
202   * @return The document fragment node data or the empty string.
203   */
204  public String str()
205  {
206    String str = m_DTMXRTreeFrag.getDTM().getStringValue(m_dtmRoot).toString();
207
208    return (null == str) ? "" : str;
209  }
210
211  /**
212   * Cast result object to a result tree fragment.
213   *
214   * @return The document fragment this wraps
215   */
216  public int rtf()
217  {
218    return m_dtmRoot;
219  }
220
221  /**
222   * Cast result object to a DTMIterator.
223   * dml - modified to return an RTFIterator for
224   * benefit of EXSLT object-type function in
225   * {@link com.sun.org.apache.xalan.internal.lib.ExsltCommon}.
226   * @return The document fragment as a DTMIterator
227   */
228  public DTMIterator asNodeIterator()
229  {
230    return new RTFIterator(m_dtmRoot, m_DTMXRTreeFrag.getXPathContext().getDTMManager());
231  }
232
233  /**
234   * Cast result object to a nodelist. (special function).
235   *
236   * @return The document fragment as a nodelist
237   */
238  public NodeList convertToNodeset()
239  {
240
241    if (m_obj instanceof NodeList)
242      return (NodeList) m_obj;
243    else
244      return new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList(asNodeIterator());
245  }
246
247  /**
248   * Tell if two objects are functionally equal.
249   *
250   * @param obj2 Object to compare this to
251   *
252   * @return True if the two objects are equal
253   *
254   * @throws javax.xml.transform.TransformerException
255   */
256  public boolean equals(XObject obj2)
257  {
258
259    try
260    {
261      if (XObject.CLASS_NODESET == obj2.getType())
262      {
263
264        // In order to handle the 'all' semantics of
265        // nodeset comparisons, we always call the
266        // nodeset function.
267        return obj2.equals(this);
268      }
269      else if (XObject.CLASS_BOOLEAN == obj2.getType())
270      {
271        return bool() == obj2.bool();
272      }
273      else if (XObject.CLASS_NUMBER == obj2.getType())
274      {
275        return num() == obj2.num();
276      }
277      else if (XObject.CLASS_NODESET == obj2.getType())
278      {
279        return xstr().equals(obj2.xstr());
280      }
281      else if (XObject.CLASS_STRING == obj2.getType())
282      {
283        return xstr().equals(obj2.xstr());
284      }
285      else if (XObject.CLASS_RTREEFRAG == obj2.getType())
286      {
287
288        // Probably not so good.  Think about this.
289        return xstr().equals(obj2.xstr());
290      }
291      else
292      {
293        return super.equals(obj2);
294      }
295    }
296    catch(javax.xml.transform.TransformerException te)
297    {
298      throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(te);
299    }
300  }
301
302}
303