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