KickJava   Java API By Example, From Geeks To Geeks.

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


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: XObject.java,v 1.25 2004/02/17 04:34:38 minchau Exp $
18  */

19 package org.apache.xpath.objects;
20
21 import java.io.Serializable JavaDoc;
22
23 import org.apache.xalan.res.XSLMessages;
24 import org.apache.xml.dtm.DTM;
25 import org.apache.xml.dtm.DTMIterator;
26 import org.apache.xml.utils.XMLString;
27 import org.apache.xpath.Expression;
28 import org.apache.xpath.ExpressionOwner;
29 import org.apache.xpath.NodeSetDTM;
30 import org.apache.xpath.XPathContext;
31 import org.apache.xpath.XPathException;
32 import org.apache.xpath.XPathVisitor;
33 import org.apache.xpath.res.XPATHErrorResources;
34
35 import org.w3c.dom.DocumentFragment JavaDoc;
36 import org.w3c.dom.NodeList JavaDoc;
37 import org.w3c.dom.traversal.NodeIterator;
38
39 /**
40  * This class represents an XPath object, and is capable of
41  * converting the object to various types, such as a string.
42  * This class acts as the base class to other XPath type objects,
43  * such as XString, and provides polymorphic casting capabilities.
44  * @xsl.usage general
45  */

46 public class XObject extends Expression implements Serializable JavaDoc, Cloneable JavaDoc
47 {
48
49   /**
50    * The java object which this object wraps.
51    * @serial
52    */

53   protected Object JavaDoc m_obj; // This may be NULL!!!
54

55   /**
56    * Create an XObject.
57    */

58   public XObject(){}
59
60   /**
61    * Create an XObject.
62    *
63    * @param obj Can be any object, should be a specific type
64    * for derived classes, or null.
65    */

66   public XObject(Object JavaDoc obj)
67   {
68     m_obj = obj;
69   }
70
71   /**
72    * For support of literal objects in xpaths.
73    *
74    * @param xctxt The XPath execution context.
75    *
76    * @return This object.
77    *
78    * @throws javax.xml.transform.TransformerException
79    */

80   public XObject execute(XPathContext xctxt)
81           throws javax.xml.transform.TransformerException JavaDoc
82   {
83     return this;
84   }
85
86   /**
87    * Specify if it's OK for detach to release the iterator for reuse.
88    * This function should be called with a value of false for objects that are
89    * stored in variables.
90    * Calling this with a value of false on a XNodeSet will cause the nodeset
91    * to be cached.
92    *
93    * @param allowRelease true if it is OK for detach to release this iterator
94    * for pooling.
95    */

96   public void allowDetachToRelease(boolean allowRelease){}
97
98   /**
99    * Detaches the <code>DTMIterator</code> from the set which it iterated
100    * over, releasing any computational resources and placing the iterator
101    * in the INVALID state. After <code>detach</code> has been invoked,
102    * calls to <code>nextNode</code> or <code>previousNode</code> will
103    * raise a runtime exception.
104    */

105   public void detach(){}
106
107   /**
108    * Forces the object to release it's resources. This is more harsh than
109    * detach().
110    */

111   public void destruct()
112   {
113
114     if (null != m_obj)
115     {
116       allowDetachToRelease(true);
117       detach();
118
119       m_obj = null;
120     }
121   }
122   
123   /**
124    * Reset for fresh reuse.
125    */

126   public void reset()
127   {
128   }
129
130   /**
131    * Directly call the
132    * characters method on the passed ContentHandler for the
133    * string-value. Multiple calls to the
134    * ContentHandler's characters methods may well occur for a single call to
135    * this method.
136    *
137    * @param ch A non-null reference to a ContentHandler.
138    *
139    * @throws org.xml.sax.SAXException
140    */

141   public void dispatchCharactersEvents(org.xml.sax.ContentHandler JavaDoc ch)
142           throws org.xml.sax.SAXException JavaDoc
143   {
144     xstr().dispatchCharactersEvents(ch);
145   }
146
147   /**
148    * Create the right XObject based on the type of the object passed. This
149    * function can not make an XObject that exposes DOM Nodes, NodeLists, and
150    * NodeIterators to the XSLT stylesheet as node-sets.
151    *
152    * @param val The java object which this object will wrap.
153    *
154    * @return the right XObject based on the type of the object passed.
155    */

156   static public XObject create(Object JavaDoc val)
157   {
158     return XObjectFactory.create(val);
159   }
160   
161   /**
162    * Create the right XObject based on the type of the object passed.
163    * This function <emph>can</emph> make an XObject that exposes DOM Nodes, NodeLists, and
164    * NodeIterators to the XSLT stylesheet as node-sets.
165    *
166    * @param val The java object which this object will wrap.
167    * @param xctxt The XPath context.
168    *
169    * @return the right XObject based on the type of the object passed.
170    */

171   static public XObject create(Object JavaDoc val, XPathContext xctxt)
172   {
173     return XObjectFactory.create(val, xctxt);
174   }
175
176   /** Constant for NULL object type */
177   public static final int CLASS_NULL = -1;
178
179   /** Constant for UNKNOWN object type */
180   public static final int CLASS_UNKNOWN = 0;
181
182   /** Constant for BOOLEAN object type */
183   public static final int CLASS_BOOLEAN = 1;
184
185   /** Constant for NUMBER object type */
186   public static final int CLASS_NUMBER = 2;
187
188   /** Constant for STRING object type */
189   public static final int CLASS_STRING = 3;
190
191   /** Constant for NODESET object type */
192   public static final int CLASS_NODESET = 4;
193
194   /** Constant for RESULT TREE FRAGMENT object type */
195   public static final int CLASS_RTREEFRAG = 5;
196
197   /** Represents an unresolved variable type as an integer. */
198   public static final int CLASS_UNRESOLVEDVARIABLE = 600;
199
200   /**
201    * Tell what kind of class this is.
202    *
203    * @return CLASS_UNKNOWN
204    */

205   public int getType()
206   {
207     return CLASS_UNKNOWN;
208   }
209
210   /**
211    * Given a request type, return the equivalent string.
212    * For diagnostic purposes.
213    *
214    * @return type string "#UNKNOWN" + object class name
215    */

216   public String JavaDoc getTypeString()
217   {
218     return "#UNKNOWN (" + object().getClass().getName() + ")";
219   }
220
221   /**
222    * Cast result object to a number. Always issues an error.
223    *
224    * @return 0.0
225    *
226    * @throws javax.xml.transform.TransformerException
227    */

228   public double num() throws javax.xml.transform.TransformerException JavaDoc
229   {
230
231     error(XPATHErrorResources.ER_CANT_CONVERT_TO_NUMBER,
232           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a number");
233

234     return 0.0;
235   }
236   
237   /**
238    * Cast result object to a number, but allow side effects, such as the
239    * incrementing of an iterator.
240    *
241    * @return numeric value of the string conversion from the
242    * next node in the NodeSetDTM, or NAN if no node was found
243    */

244   public double numWithSideEffects() throws javax.xml.transform.TransformerException JavaDoc
245   {
246     return num();
247   }
248
249   /**
250    * Cast result object to a boolean. Always issues an error.
251    *
252    * @return false
253    *
254    * @throws javax.xml.transform.TransformerException
255    */

256   public boolean bool() throws javax.xml.transform.TransformerException JavaDoc
257   {
258
259     error(XPATHErrorResources.ER_CANT_CONVERT_TO_NUMBER,
260           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a number");
261

262     return false;
263   }
264   
265   /**
266    * Cast result object to a boolean, but allow side effects, such as the
267    * incrementing of an iterator.
268    *
269    * @return True if there is a next node in the nodeset
270    */

271   public boolean boolWithSideEffects() throws javax.xml.transform.TransformerException JavaDoc
272   {
273     return bool();
274   }
275
276
277   /**
278    * Cast result object to a string.
279    *
280    * @return The string this wraps or the empty string if null
281    */

282   public XMLString xstr()
283   {
284     return XMLStringFactoryImpl.getFactory().newstr(str());
285   }
286
287   /**
288    * Cast result object to a string.
289    *
290    * @return The object as a string
291    */

292   public String JavaDoc str()
293   {
294     return (m_obj != null) ? m_obj.toString() : "";
295   }
296
297   /**
298    * Return the string representation of the object
299    *
300    *
301    * @return the string representation of the object
302    */

303   public String JavaDoc toString()
304   {
305     return str();
306   }
307
308   /**
309    * Cast result object to a result tree fragment.
310    *
311    * @param support XPath context to use for the conversion
312    *
313    * @return the objec as a result tree fragment.
314    */

315   public int rtf(XPathContext support)
316   {
317
318     int result = rtf();
319
320     if (DTM.NULL == result)
321     {
322       DTM frag = support.createDocumentFragment();
323
324       // %OPT%
325
frag.appendTextChild(str());
326
327       result = frag.getDocument();
328     }
329
330     return result;
331   }
332   
333   /**
334    * Cast result object to a result tree fragment.
335    *
336    * @param support XPath context to use for the conversion
337    *
338    * @return the objec as a result tree fragment.
339    */

340   public DocumentFragment JavaDoc rtree(XPathContext support)
341   {
342     DocumentFragment JavaDoc docFrag = null;
343     int result = rtf();
344
345     if (DTM.NULL == result)
346     {
347       DTM frag = support.createDocumentFragment();
348
349       // %OPT%
350
frag.appendTextChild(str());
351
352       docFrag = (DocumentFragment JavaDoc)frag.getNode(frag.getDocument());
353     }
354     else
355     {
356       DTM frag = support.getDTM(result);
357       docFrag = (DocumentFragment JavaDoc)frag.getNode(frag.getDocument());
358     }
359
360     return docFrag;
361   }
362   
363   
364   /**
365    * For functions to override.
366    *
367    * @return null
368    */

369   public DocumentFragment JavaDoc rtree()
370   {
371     return null;
372   }
373
374   /**
375    * For functions to override.
376    *
377    * @return null
378    */

379   public int rtf()
380   {
381     return DTM.NULL;
382   }
383
384   /**
385    * Return a java object that's closest to the representation
386    * that should be handed to an extension.
387    *
388    * @return The object that this class wraps
389    */

390   public Object JavaDoc object()
391   {
392     return m_obj;
393   }
394
395   /**
396    * Cast result object to a nodelist. Always issues an error.
397    *
398    * @return null
399    *
400    * @throws javax.xml.transform.TransformerException
401    */

402   public DTMIterator iter() throws javax.xml.transform.TransformerException JavaDoc
403   {
404
405     error(XPATHErrorResources.ER_CANT_CONVERT_TO_NODELIST,
406           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a NodeList!");
407

408     return null;
409   }
410   
411   /**
412    * Get a fresh copy of the object. For use with variables.
413    *
414    * @return This object, unless overridden by subclass.
415    */

416   public XObject getFresh()
417   {
418     return this;
419   }
420
421   
422   /**
423    * Cast result object to a nodelist. Always issues an error.
424    *
425    * @return null
426    *
427    * @throws javax.xml.transform.TransformerException
428    */

429   public NodeIterator nodeset() throws javax.xml.transform.TransformerException JavaDoc
430   {
431
432     error(XPATHErrorResources.ER_CANT_CONVERT_TO_NODELIST,
433           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a NodeList!");
434

435     return null;
436   }
437   
438   /**
439    * Cast result object to a nodelist. Always issues an error.
440    *
441    * @return null
442    *
443    * @throws javax.xml.transform.TransformerException
444    */

445   public NodeList JavaDoc nodelist() throws javax.xml.transform.TransformerException JavaDoc
446   {
447
448     error(XPATHErrorResources.ER_CANT_CONVERT_TO_NODELIST,
449           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a NodeList!");
450

451     return null;
452   }
453
454
455   /**
456    * Cast result object to a nodelist. Always issues an error.
457    *
458    * @return The object as a NodeSetDTM.
459    *
460    * @throws javax.xml.transform.TransformerException
461    */

462   public NodeSetDTM mutableNodeset()
463           throws javax.xml.transform.TransformerException JavaDoc
464   {
465
466     error(XPATHErrorResources.ER_CANT_CONVERT_TO_MUTABLENODELIST,
467           new Object JavaDoc[]{ getTypeString() }); //"Can not convert "+getTypeString()+" to a NodeSetDTM!");
468

469     return (NodeSetDTM) m_obj;
470   }
471
472   /**
473    * Cast object to type t.
474    *
475    * @param t Type of object to cast this to
476    * @param support XPath context to use for the conversion
477    *
478    * @return This object as the given type t
479    *
480    * @throws javax.xml.transform.TransformerException
481    */

482   public Object JavaDoc castToType(int t, XPathContext support)
483           throws javax.xml.transform.TransformerException JavaDoc
484   {
485
486     Object JavaDoc result;
487
488     switch (t)
489     {
490     case CLASS_STRING :
491       result = str();
492       break;
493     case CLASS_NUMBER :
494       result = new Double JavaDoc(num());
495       break;
496     case CLASS_NODESET :
497       result = iter();
498       break;
499     case CLASS_BOOLEAN :
500       result = new Boolean JavaDoc(bool());
501       break;
502     case CLASS_UNKNOWN :
503       result = m_obj;
504       break;
505
506     // %TBD% What to do here?
507
// case CLASS_RTREEFRAG :
508
// result = rtree(support);
509
// break;
510
default :
511       error(XPATHErrorResources.ER_CANT_CONVERT_TO_TYPE,
512             new Object JavaDoc[]{ getTypeString(),
513                           Integer.toString(t) }); //"Can not convert "+getTypeString()+" to a type#"+t);
514

515       result = null;
516     }
517
518     return result;
519   }
520
521   /**
522    * Tell if one object is less than the other.
523    *
524    * @param obj2 Object to compare this to
525    *
526    * @return True if this object is less than the given object
527    *
528    * @throws javax.xml.transform.TransformerException
529    */

530   public boolean lessThan(XObject obj2)
531           throws javax.xml.transform.TransformerException JavaDoc
532   {
533
534     // In order to handle the 'all' semantics of
535
// nodeset comparisons, we always call the
536
// nodeset function. Because the arguments
537
// are backwards, we call the opposite comparison
538
// function.
539
if (obj2.getType() == XObject.CLASS_NODESET)
540       return obj2.greaterThan(this);
541
542     return this.num() < obj2.num();
543   }
544
545   /**
546    * Tell if one object is less than or equal to the other.
547    *
548    * @param obj2 Object to compare this to
549    *
550    * @return True if this object is less than or equal to the given object
551    *
552    * @throws javax.xml.transform.TransformerException
553    */

554   public boolean lessThanOrEqual(XObject obj2)
555           throws javax.xml.transform.TransformerException JavaDoc
556   {
557
558     // In order to handle the 'all' semantics of
559
// nodeset comparisons, we always call the
560
// nodeset function. Because the arguments
561
// are backwards, we call the opposite comparison
562
// function.
563
if (obj2.getType() == XObject.CLASS_NODESET)
564       return obj2.greaterThanOrEqual(this);
565
566     return this.num() <= obj2.num();
567   }
568
569   /**
570    * Tell if one object is greater than the other.
571    *
572    * @param obj2 Object to compare this to
573    *
574    * @return True if this object is greater than the given object
575    *
576    * @throws javax.xml.transform.TransformerException
577    */

578   public boolean greaterThan(XObject obj2)
579           throws javax.xml.transform.TransformerException JavaDoc
580   {
581
582     // In order to handle the 'all' semantics of
583
// nodeset comparisons, we always call the
584
// nodeset function. Because the arguments
585
// are backwards, we call the opposite comparison
586
// function.
587
if (obj2.getType() == XObject.CLASS_NODESET)
588       return obj2.lessThan(this);
589
590     return this.num() > obj2.num();
591   }
592
593   /**
594    * Tell if one object is greater than or equal to the other.
595    *
596    * @param obj2 Object to compare this to
597    *
598    * @return True if this object is greater than or equal to the given object
599    *
600    * @throws javax.xml.transform.TransformerException
601    */

602   public boolean greaterThanOrEqual(XObject obj2)
603           throws javax.xml.transform.TransformerException JavaDoc
604   {
605
606     // In order to handle the 'all' semantics of
607
// nodeset comparisons, we always call the
608
// nodeset function. Because the arguments
609
// are backwards, we call the opposite comparison
610
// function.
611
if (obj2.getType() == XObject.CLASS_NODESET)
612       return obj2.lessThanOrEqual(this);
613
614     return this.num() >= obj2.num();
615   }
616
617   /**
618    * Tell if two objects are functionally equal.
619    *
620    * @param obj2 Object to compare this to
621    *
622    * @return True if this object is equal to the given object
623    *
624    * @throws javax.xml.transform.TransformerException
625    */

626   public boolean equals(XObject obj2)
627   {
628
629     // In order to handle the 'all' semantics of
630
// nodeset comparisons, we always call the
631
// nodeset function.
632
if (obj2.getType() == XObject.CLASS_NODESET)
633       return obj2.equals(this);
634
635     if (null != m_obj)
636     {
637       return m_obj.equals(obj2.m_obj);
638     }
639     else
640     {
641       return obj2.m_obj == null;
642     }
643   }
644
645   /**
646    * Tell if two objects are functionally not equal.
647    *
648    * @param obj2 Object to compare this to
649    *
650    * @return True if this object is not equal to the given object
651    *
652    * @throws javax.xml.transform.TransformerException
653    */

654   public boolean notEquals(XObject obj2)
655           throws javax.xml.transform.TransformerException JavaDoc
656   {
657
658     // In order to handle the 'all' semantics of
659
// nodeset comparisons, we always call the
660
// nodeset function.
661
if (obj2.getType() == XObject.CLASS_NODESET)
662       return obj2.notEquals(this);
663
664     return !equals(obj2);
665   }
666
667   /**
668    * Tell the user of an error, and probably throw an
669    * exception.
670    *
671    * @param msg Error message to issue
672    *
673    * @throws javax.xml.transform.TransformerException
674    */

675   protected void error(String JavaDoc msg)
676           throws javax.xml.transform.TransformerException JavaDoc
677   {
678     error(msg, null);
679   }
680
681   /**
682    * Tell the user of an error, and probably throw an
683    * exception.
684    *
685    * @param msg Error message to issue
686    * @param args Arguments to use in the message
687    *
688    * @throws javax.xml.transform.TransformerException
689    */

690   protected void error(String JavaDoc msg, Object JavaDoc[] args)
691           throws javax.xml.transform.TransformerException JavaDoc
692   {
693
694     String JavaDoc fmsg = XSLMessages.createXPATHMessage(msg, args);
695
696     // boolean shouldThrow = support.problem(m_support.XPATHPROCESSOR,
697
// m_support.ERROR,
698
// null,
699
// null, fmsg, 0, 0);
700
// if(shouldThrow)
701
{
702       throw new XPathException(fmsg, this);
703     }
704   }
705   
706   
707   /**
708    * XObjects should not normally need to fix up variables.
709    */

710   public void fixupVariables(java.util.Vector JavaDoc vars, int globalsSize)
711   {
712     // no-op
713
}
714
715
716   /**
717    * Cast result object to a string.
718    *
719    *
720    * NEEDSDOC @param fsb
721    * @return The string this wraps or the empty string if null
722    */

723   public void appendToFsb(org.apache.xml.utils.FastStringBuffer fsb)
724   {
725     fsb.append(str());
726   }
727   
728   /**
729    * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
730    */

731   public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
732   {
733     assertion(false, "callVisitors should not be called for this object!!!");
734   }
735   /**
736    * @see Expression#deepEquals(Expression)
737    */

738   public boolean deepEquals(Expression expr)
739   {
740     if(!isSameClass(expr))
741         return false;
742         
743     // If equals at the expression level calls deepEquals, I think we're
744
// still safe from infinite recursion since this object overrides
745
// equals. I hope.
746
if(!this.equals((XObject)expr))
747         return false;
748         
749     return true;
750   }
751
752 }
753
Popular Tags