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.trans.XPathException;
006: import net.sf.saxon.type.ItemType;
007: import net.sf.saxon.value.Cardinality;
008:
009: /**
010: * A FirstItemExpression returns the first item in the sequence returned by a given
011: * base expression
012: */
013:
014: public final class FirstItemExpression extends UnaryExpression {
015:
016: /**
017: * Constructor
018: * @param base A sequence expression denoting sequence whose first item is to be returned
019: */
020:
021: public FirstItemExpression(Expression base) {
022: super (base);
023: computeStaticProperties();
024: }
025:
026: /**
027: * Perform optimisation of an expression and its subexpressions.
028: * <p/>
029: * <p>This method is called after all references to functions and variables have been resolved
030: * to the declaration of the function or variable, and after all type checking has been done.</p>
031: *
032: * @param opt the optimizer in use. This provides access to supporting functions; it also allows
033: * different optimization strategies to be used in different circumstances.
034: * @param env the static context of the expression
035: * @param contextItemType the static type of "." at the point where this expression is invoked.
036: * The parameter is set to null if it is known statically that the context item will be undefined.
037: * If the type of the context item is not known statically, the argument is set to
038: * {@link net.sf.saxon.type.Type#ITEM_TYPE}
039: * @return the original expression, rewritten if appropriate to optimize execution
040: * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
041: * (typically a type error)
042: */
043:
044: public Expression optimize(Optimizer opt, StaticContext env,
045: ItemType contextItemType) throws XPathException {
046: operand = operand.optimize(opt, env, contextItemType);
047: if (!Cardinality.allowsMany(operand.getCardinality())) {
048: return operand;
049: }
050: return this ;
051: }
052:
053: /**
054: * Promote this expression if possible
055: */
056:
057: public Expression promote(PromotionOffer offer)
058: throws XPathException {
059: Expression exp = offer.accept(this );
060: if (exp != null) {
061: return exp;
062: } else {
063: if (offer.action != PromotionOffer.UNORDERED) {
064: // we can't push the UNORDERED property down to the operand, because order is significant
065: operand = doPromotion(operand, offer);
066: }
067: return this ;
068: }
069: }
070:
071: /**
072: * Get the static cardinality
073: */
074:
075: public int computeCardinality() {
076: return operand.getCardinality() & ~StaticProperty.ALLOWS_MANY;
077: }
078:
079: /**
080: * Evaluate the expression
081: */
082:
083: public Item evaluateItem(XPathContext context)
084: throws XPathException {
085: return operand.iterate(context).next();
086: }
087:
088: /**
089: * Diagnostic print of expression structure
090: */
091:
092: public String displayOperator(NamePool pool) {
093: return "first item of";
094: }
095:
096: }
097:
098: //
099: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
100: // you may not use this file except in compliance with the License. You may obtain a copy of the
101: // License at http://www.mozilla.org/MPL/
102: //
103: // Software distributed under the License is distributed on an "AS IS" basis,
104: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
105: // See the License for the specific language governing rights and limitations under the License.
106: //
107: // The Original Code is: all this file.
108: //
109: // The Initial Developer of the Original Code is Michael H. Kay.
110: //
111: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
112: //
113: // Contributor(s): none.
114: //
|