KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > InstanceOfExpression


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.Item;
3 import net.sf.saxon.om.NamePool;
4 import net.sf.saxon.om.SequenceIterator;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.ItemType;
7 import net.sf.saxon.type.Type;
8 import net.sf.saxon.value.*;
9
10 import java.io.PrintStream JavaDoc;
11
12 /**
13 * InstanceOf Expression: implements "Expr instance of data-type"
14 */

15
16 public final class InstanceOfExpression extends UnaryExpression {
17
18     ItemType targetType;
19     int targetCardinality;
20
21     public InstanceOfExpression(Expression source, SequenceType target) {
22         super(source);
23         targetType = target.getPrimaryType();
24         if (targetType == null) {
25             throw new IllegalArgumentException JavaDoc("Primary item type must not be null");
26         }
27         targetCardinality = target.getCardinality();
28     }
29
30     /**
31     * Type-check the expression
32     * @return the checked expression
33     */

34
35     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
36         operand = operand.typeCheck(env, contextItemType);
37         if (operand instanceof Value) {
38             return (AtomicValue)evaluateItem(null);
39         }
40
41         // See if we can get the answer by static analysis.
42

43         if (Cardinality.subsumes(targetCardinality, operand.getCardinality())) {
44             int relation = Type.relationship(operand.getItemType(), targetType);
45             if (relation == Type.SAME_TYPE || relation == Type.SUBSUMED_BY) {
46                 return BooleanValue.TRUE;
47             } else if (relation == Type.DISJOINT) {
48                 // if the item types are disjoint, the result might still be true if both sequences are empty
49
if (!Cardinality.allowsZero(targetCardinality) || !Cardinality.allowsZero(operand.getCardinality())) {
50                     return BooleanValue.FALSE;
51                 }
52             }
53         }
54         return this;
55     }
56
57     /**
58      * Perform optimisation of an expression and its subexpressions.
59      * <p/>
60      * <p>This method is called after all references to functions and variables have been resolved
61      * to the declaration of the function or variable, and after all type checking has been done.</p>
62      *
63      * @param opt the optimizer in use. This provides access to supporting functions; it also allows
64      * different optimization strategies to be used in different circumstances.
65      * @param env the static context of the expression
66      * @param contextItemType the static type of "." at the point where this expression is invoked.
67      * The parameter is set to null if it is known statically that the context item will be undefined.
68      * If the type of the context item is not known statically, the argument is set to
69      * {@link net.sf.saxon.type.Type#ITEM_TYPE}
70      * @return the original expression, rewritten if appropriate to optimize execution
71      * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
72      * (typically a type error)
73      */

74
75     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
76         Expression e = super.optimize(opt, env, contextItemType);
77         if (e != this) {
78             return e;
79         }
80         if (Cardinality.subsumes(targetCardinality, operand.getCardinality())) {
81             int relation = Type.relationship(operand.getItemType(), targetType);
82             if (relation == Type.SAME_TYPE || relation == Type.SUBSUMED_BY) {
83                 return BooleanValue.TRUE;
84             } else if (relation == Type.DISJOINT) {
85                 // if the item types are disjoint, the result might still be true if both sequences are empty
86
if (!Cardinality.allowsZero(targetCardinality) || !Cardinality.allowsZero(operand.getCardinality())) {
87                     return BooleanValue.FALSE;
88                 }
89             }
90         }
91         return this;
92     }
93
94
95     /**
96      * Is this expression the same as another expression?
97      */

98
99     public boolean equals(Object JavaDoc other) {
100         return super.equals(other) &&
101                 targetType == ((InstanceOfExpression)other).targetType &&
102                 targetCardinality == ((InstanceOfExpression)other).targetCardinality;
103     }
104
105      /**
106      * Determine the cardinality
107      */

108
109     public int computeCardinality() {
110         return StaticProperty.EXACTLY_ONE;
111     }
112
113     /**
114     * Determine the data type of the result of the InstanceOf expression
115     */

116
117     public ItemType getItemType() {
118         return Type.BOOLEAN_TYPE;
119     }
120
121     /**
122     * Evaluate the expression
123     */

124
125     public Item evaluateItem(XPathContext context) throws XPathException {
126         return BooleanValue.get(effectiveBooleanValue(context));
127     }
128
129     /**
130     * Evaluate the expression as a boolean
131     */

132
133     public boolean effectiveBooleanValue(XPathContext context) throws XPathException {
134         SequenceIterator iter = operand.iterate(context);
135         int count = 0;
136         while (true) {
137             Item item = iter.next();
138             if (item == null) break;
139             count++;
140             if (!targetType.matchesItem(item)) {
141                 return false;
142             }
143             if (count==2 && !Cardinality.allowsMany(targetCardinality)) {
144                 return false;
145             }
146         }
147         if (count==0 && ((targetCardinality & StaticProperty.ALLOWS_ZERO)==0)) {
148             return false;
149         }
150         return true;
151     }
152
153     /**
154      * Give a string representation of the operator for use in diagnostics
155      * @return the operator, as a string
156      */

157
158     protected String JavaDoc displayOperator(NamePool pool) {
159         return "instance of " + targetType.toString(pool) + Cardinality.getOccurrenceIndicator(targetCardinality);
160     }
161
162     /**
163     * Diagnostic print of expression structure
164     */

165
166     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
167         out.println(ExpressionTool.indent(level) + "instance of" );
168         operand.display(level+1, pool, out);
169         out.println(ExpressionTool.indent(level+1) +
170                 targetType.toString(pool) +
171                 Cardinality.getOccurrenceIndicator(targetCardinality));
172     }
173
174 }
175
176 //
177
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
178
// you may not use this file except in compliance with the License. You may obtain a copy of the
179
// License at http://www.mozilla.org/MPL/
180
//
181
// Software distributed under the License is distributed on an "AS IS" basis,
182
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
183
// See the License for the specific language governing rights and limitations under the License.
184
//
185
// The Original Code is: all this file.
186
//
187
// The Initial Developer of the Original Code is Michael H. Kay
188
//
189
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
190
//
191
// Contributor(s): none.
192
//
193
Popular Tags