KickJava   Java API By Example, From Geeks To Geeks.

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


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.trans.DynamicError;
5 import net.sf.saxon.trans.StaticError;
6 import net.sf.saxon.trans.XPathException;
7 import net.sf.saxon.type.AtomicType;
8 import net.sf.saxon.type.ItemType;
9 import net.sf.saxon.type.Type;
10 import net.sf.saxon.type.BuiltInAtomicType;
11 import net.sf.saxon.value.*;
12
13 /**
14 * Cast Expression: implements "cast as data-type ( expression )". It also allows an internal
15 * cast, which has the same semantics as a user-requested cast, but maps an empty sequence to
16 * an empty sequence.
17 */

18
19 public final class CastExpression extends UnaryExpression {
20
21     private AtomicType targetType;
22     private AtomicType targetPrimitiveType;
23     private boolean allowEmpty = false;
24     private boolean derived = false;
25
26
27
28     public CastExpression(Expression source, AtomicType target, boolean allowEmpty) {
29         super(source);
30         this.allowEmpty = allowEmpty;
31         targetType = target;
32         targetPrimitiveType = (AtomicType)target.getPrimitiveItemType();
33         derived = (targetType.getFingerprint() != targetPrimitiveType.getFingerprint());
34         adoptChildExpression(source);
35     }
36
37     /**
38      * Handle a cast to QName or NOTATION. The argument must be a string literal.
39      */

40
41     public AtomicValue doQNameCast(StaticContext env) throws XPathException {
42         if (!(operand instanceof StringValue)) {
43             throw new StaticError("The argument of a QName or NOTATION constructor must be a string literal");
44         }
45         return QNameValue.castToQName((StringValue)operand, targetType, env);
46     }
47
48
49     /**
50     * Simplify the expression
51     * @return the simplified expression
52     */

53
54      public Expression simplify(StaticContext env) throws XPathException {
55         if ((targetType instanceof BuiltInAtomicType) && !env.isAllowedBuiltInType(targetType)) {
56             // this is checked here because the ConstructorFunctionLibrary doesn't have access to the static
57
// context at bind time
58
env.issueWarning("The type " + targetType.getDisplayName() + " is not recognized by a Basic XSLT Processor. " +
59                                 "Saxon permits it for the time being.", this);
60         }
61         operand = operand.simplify(env);
62         if (operand instanceof AtomicValue) {
63             return typeCheck(env, Type.ITEM_TYPE);
64         }
65         return this;
66     }
67
68     /**
69     * Type-check the expression
70     */

71
72     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
73         operand = operand.typeCheck(env, contextItemType);
74         SequenceType atomicType = SequenceType.makeSequenceType(Type.ANY_ATOMIC_TYPE, getCardinality());
75
76         RoleLocator role = new RoleLocator(RoleLocator.TYPE_OP, "cast as", 0, null);
77         role.setSourceLocator(this);
78         operand = TypeChecker.staticTypeCheck(operand, atomicType, false, role, env);
79
80         if (Type.isSubType(operand.getItemType(), targetType)) {
81             return operand;
82             // It's not entirely clear that the spec permits this. Perhaps we should change the type label?
83
// On the other hand, it's generally true that any expression defined to return an X
84
// is allowed to return a subtype of X.
85
}
86         if (targetType.isNamespaceSensitive()) {
87             return new CastAsQName(operand, targetType).analyze(env, contextItemType);
88         }
89         if (operand instanceof AtomicValue) {
90             return (AtomicValue)evaluateItem(null);
91         }
92         // TODO: check statically that the cast of the supplied value to the required type is an allowed cast.
93
return this;
94     }
95
96
97     /**
98     * Get the static cardinality of the expression
99     */

100
101     public int computeCardinality() {
102         return (allowEmpty ? StaticProperty.ALLOWS_ZERO_OR_ONE : StaticProperty.EXACTLY_ONE);
103     }
104
105     /**
106     * Get the static type of the expression
107     */

108
109     public ItemType getItemType() {
110         return targetType;
111     }
112
113     /**
114      * Determine the special properties of this expression
115      * @return {@link StaticProperty#NON_CREATIVE}.
116      */

117
118     public int computeSpecialProperties() {
119         int p = super.computeSpecialProperties();
120         return p | StaticProperty.NON_CREATIVE;
121     }
122
123     /**
124     * Evaluate the expression
125     */

126
127     public Item evaluateItem(XPathContext context) throws XPathException {
128         AtomicValue value = (AtomicValue)operand.evaluateItem(context);
129         if (value==null) {
130             if (allowEmpty) {
131                 return null;
132             } else {
133                 DynamicError e = new DynamicError("Cast does not allow an empty sequence");
134                 e.setXPathContext(context);
135                 throw e;
136             }
137         }
138         AtomicValue result = value.convert(targetPrimitiveType, context, true);
139         if (result instanceof ValidationErrorValue) {
140             XPathException err = ((ValidationErrorValue)result).getException();
141             String JavaDoc code = err.getErrorCodeLocalPart();
142             dynamicError(err.getMessage(), code, context);
143         }
144         if (derived) {
145             result = result.convert(targetType, context, true);
146             if (result instanceof ValidationErrorValue) {
147                 XPathException err = ((ValidationErrorValue)result).getException();
148                 String JavaDoc code = err.getErrorCodeLocalPart();
149                 dynamicError(err.getMessage(), code, context);
150             }
151         }
152         return result;
153     }
154
155     /**
156      * Is this expression the same as another expression?
157      */

158
159     public boolean equals(Object JavaDoc other) {
160         return super.equals(other) &&
161                 targetType == ((CastExpression)other).targetType &&
162                 allowEmpty == ((CastExpression)other).allowEmpty;
163     }
164
165     /**
166      * Give a string representation of the operator for use in diagnostics
167      * @return the operator, as a string
168      */

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