001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.Item;
004: import net.sf.saxon.om.NamePool;
005: import net.sf.saxon.om.QNameException;
006: import net.sf.saxon.om.NameChecker;
007: import net.sf.saxon.style.StandardNames;
008: import net.sf.saxon.trans.StaticError;
009: import net.sf.saxon.trans.XPathException;
010: import net.sf.saxon.type.AtomicType;
011: import net.sf.saxon.type.ItemType;
012: import net.sf.saxon.type.Type;
013: import net.sf.saxon.type.TypeHierarchy;
014: import net.sf.saxon.value.*;
015:
016: import java.io.PrintStream;
017: import java.util.Iterator;
018:
019: /**
020: * This class supports casting a string to a QName or a notation.
021: */
022:
023: public class CastAsQName extends ComputedExpression {
024:
025: private Expression operand;
026: private AtomicType targetType;
027:
028: public CastAsQName(Expression s, AtomicType target) {
029: operand = s;
030: targetType = target;
031: }
032:
033: public Expression analyze(StaticContext env,
034: ItemType contextItemType) throws XPathException {
035: if (operand instanceof StringValue) {
036: try {
037: CharSequence arg = ((StringValue) operand)
038: .getStringValueCS();
039: String parts[] = env.getConfiguration()
040: .getNameChecker().getQNameParts(arg);
041: String uri;
042: if ("".equals(parts[0])) {
043: uri = "";
044: } else {
045: uri = env.getURIForPrefix(parts[0]);
046: if (uri == null) {
047: StaticError e = new StaticError("Prefix '"
048: + parts[0] + "' has not been declared");
049: throw e;
050: }
051: }
052: final NameChecker checker = env.getConfiguration()
053: .getNameChecker();
054: final TypeHierarchy th = env.getNamePool()
055: .getTypeHierarchy();
056: if (targetType.getFingerprint() == StandardNames.XS_QNAME) {
057: return new QNameValue(parts[0], uri, parts[1],
058: checker);
059: } else if (th.isSubType(targetType, Type.QNAME_TYPE)) {
060: QNameValue q = new QNameValue(parts[0], uri,
061: parts[1], checker);
062: AtomicValue av = targetType.makeDerivedValue(q,
063: arg, true);
064: if (av instanceof ValidationErrorValue) {
065: throw ((ValidationErrorValue) av)
066: .getException();
067: }
068: return av;
069: } else {
070: NotationValue n = new NotationValue(parts[0], uri,
071: parts[1], checker);
072: AtomicValue av = targetType.makeDerivedValue(n,
073: arg, true);
074: if (av instanceof ValidationErrorValue) {
075: throw ((ValidationErrorValue) av)
076: .getException();
077: }
078: return av;
079: }
080: } catch (QNameException err) {
081: StaticError e = new StaticError(err);
082: throw e;
083: }
084: } else {
085: StaticError err = new StaticError(
086: "The argument of a QName constructor must be a string literal");
087: throw err;
088: }
089: }
090:
091: public Expression typeCheck(StaticContext env,
092: ItemType contextItemType) throws XPathException {
093: if (operand instanceof StringValue) {
094: try {
095: CharSequence arg = ((StringValue) operand)
096: .getStringValueCS();
097: String parts[] = env.getConfiguration()
098: .getNameChecker().getQNameParts(arg);
099: String uri;
100: if ("".equals(parts[0])) {
101: uri = "";
102: } else {
103: uri = env.getURIForPrefix(parts[0]);
104: if (uri == null) {
105: StaticError e = new StaticError("Prefix '"
106: + parts[0] + "' has not been declared");
107: throw e;
108: }
109: }
110: final NameChecker checker = env.getConfiguration()
111: .getNameChecker();
112: final TypeHierarchy th = env.getNamePool()
113: .getTypeHierarchy();
114: if (targetType.getFingerprint() == StandardNames.XS_QNAME) {
115: return new QNameValue(parts[0], uri, parts[1],
116: checker);
117: } else if (th.isSubType(targetType, Type.QNAME_TYPE)) {
118: QNameValue q = new QNameValue(parts[0], uri,
119: parts[1], checker);
120: AtomicValue av = targetType.makeDerivedValue(q,
121: arg, true);
122: if (av instanceof ValidationErrorValue) {
123: throw ((ValidationErrorValue) av)
124: .getException();
125: }
126: return av;
127: } else {
128: NotationValue n = new NotationValue(parts[0], uri,
129: parts[1], checker);
130: AtomicValue av = targetType.makeDerivedValue(n,
131: arg, true);
132: if (av instanceof ValidationErrorValue) {
133: throw ((ValidationErrorValue) av)
134: .getException();
135: }
136: return av;
137: }
138: } catch (QNameException err) {
139: StaticError e = new StaticError(err);
140: throw e;
141: }
142: } else {
143: StaticError err = new StaticError(
144: "The argument of a QName constructor must be a string literal");
145: throw err;
146: }
147: }
148:
149: /**
150: * Perform optimisation of an expression and its subexpressions.
151: * <p/>
152: * <p>This method is called after all references to functions and variables have been resolved
153: * to the declaration of the function or variable, and after all type checking has been done.</p>
154: *
155: * @param opt the optimizer in use. This provides access to supporting functions; it also allows
156: * different optimization strategies to be used in different circumstances.
157: * @param env the static context of the expression
158: * @param contextItemType the static type of "." at the point where this expression is invoked.
159: * The parameter is set to null if it is known statically that the context item will be undefined.
160: * If the type of the context item is not known statically, the argument is set to
161: * {@link net.sf.saxon.type.Type#ITEM_TYPE}
162: * @return the original expression, rewritten if appropriate to optimize execution
163: * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
164: * (typically a type error)
165: */
166:
167: public Expression optimize(Optimizer opt, StaticContext env,
168: ItemType contextItemType) throws XPathException {
169: operand = operand.optimize(opt, env, contextItemType);
170: if (operand instanceof Value) {
171: return Value.asValue(evaluateItem(env
172: .makeEarlyEvaluationContext()));
173: }
174: return this ;
175: }
176:
177: public Expression promote(PromotionOffer offer)
178: throws XPathException {
179: return super .promote(offer);
180: }
181:
182: public int computeCardinality() {
183: return StaticProperty.EXACTLY_ONE;
184: }
185:
186: public ItemType getItemType(TypeHierarchy th) {
187: return targetType;
188: }
189:
190: /**
191: * Determine the special properties of this expression
192: * @return {@link StaticProperty#NON_CREATIVE}.
193: */
194:
195: public int computeSpecialProperties() {
196: int p = super .computeSpecialProperties();
197: return p | StaticProperty.NON_CREATIVE;
198: }
199:
200: public int getIntrinsicDependencies() {
201: return 0;
202: }
203:
204: public Iterator iterateSubExpressions() {
205: return new MonoIterator(operand);
206: }
207:
208: public Item evaluateItem(XPathContext context)
209: throws XPathException {
210: throw new UnsupportedOperationException(
211: "A QName constructor cannot be evaluated at run-time");
212: }
213:
214: public void display(int level, NamePool pool, PrintStream out) {
215: out.println(ExpressionTool.indent(level) + "cast as QName");
216: operand.display(level + 1, pool, out);
217: }
218: }
219: //
220: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
221: // you may not use this file except in compliance with the License. You may obtain a copy of the
222: // License at http://www.mozilla.org/MPL/
223: //
224: // Software distributed under the License is distributed on an "AS IS" basis,
225: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
226: // See the License for the specific language governing rights and limitations under the License.
227: //
228: // The Original Code is: all this file.
229: //
230: // The Initial Developer of the Original Code is Michael H. Kay.
231: //
232: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
233: //
234: // Contributor(s): none.
235: //
|