001: package net.sf.saxon.sort;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.om.NamePool;
006: import net.sf.saxon.om.SequenceIterator;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.type.AnyItemType;
009: import net.sf.saxon.type.ItemType;
010: import net.sf.saxon.type.Type;
011: import net.sf.saxon.type.TypeHierarchy;
012: import net.sf.saxon.value.EmptySequence;
013: import net.sf.saxon.value.ObjectValue;
014: import net.sf.saxon.value.Value;
015:
016: import java.io.PrintStream;
017: import java.util.Iterator;
018:
019: /**
020: * A TupleSorter is an expression that sorts a stream of tuples. It is used
021: * to implement XQuery FLWR expressions.
022: */
023: public class TupleSorter extends ComputedExpression implements
024: MappingFunction {
025:
026: private Expression base;
027: private FixedSortKeyDefinition[] sortKeys;
028:
029: // Although this class uses the FixedSortKeyDefinition class to define the sort keys,
030: // the actual sort key expression in the FixedSortKeyDefinition is not used. This is because
031: // the sort key is instead defined as one of the members of the tuple delivered by the
032: // TupleSorter. Therefore, the sort key expression is not managed as a child of this expression.
033:
034: public TupleSorter(Expression base, FixedSortKeyDefinition[] keys) {
035: this .base = base;
036: this .sortKeys = keys;
037: adoptChildExpression(base);
038: }
039:
040: public Expression simplify(StaticContext env) throws XPathException {
041: base = base.simplify(env);
042: return this ;
043: }
044:
045: public Expression typeCheck(StaticContext env,
046: ItemType contextItemType) throws XPathException {
047: base = base.typeCheck(env, contextItemType);
048: return this ;
049: }
050:
051: public Expression optimize(Optimizer opt, StaticContext env,
052: ItemType contextItemType) throws XPathException {
053: base = base.optimize(opt, env, contextItemType);
054: if (base instanceof EmptySequence) {
055: return base;
056: }
057: return this ;
058: }
059:
060: public ItemType getItemType(TypeHierarchy th) {
061: return AnyItemType.getInstance();
062: // TODO: we can do better than this, but we need more information
063: }
064:
065: public int computeCardinality() {
066: return StaticProperty.ALLOWS_ZERO_OR_MORE;
067: }
068:
069: public Iterator iterateSubExpressions() {
070: return new MonoIterator(base);
071: }
072:
073: /**
074: * Promote this expression if possible
075: */
076:
077: public Expression promote(PromotionOffer offer)
078: throws XPathException {
079: Expression exp = offer.accept(this );
080: if (exp != null) {
081: return exp;
082: } else {
083: base = base.promote(offer);
084: return this ;
085: }
086: }
087:
088: public SequenceIterator iterate(XPathContext context)
089: throws XPathException {
090: SequenceIterator iter = new SortedTupleIterator(context, base
091: .iterate(context), sortKeys);
092: MappingIterator mapper = new MappingIterator(iter, this ,
093: context);
094: return mapper;
095: }
096:
097: public boolean effectiveBooleanValue(XPathContext context)
098: throws XPathException {
099: // so long as the sequence is homogeneous (all atomic values or all nodes), the EBV
100: // of the sorted sequence is the same as the EBV of the base sequence. Only if it is
101: // heterogeneous do we need to do the sort in order to calculate the EBV.
102: final TypeHierarchy th = context.getNamePool()
103: .getTypeHierarchy();
104: ItemType type = base.getItemType(th);
105: if (type == Type.ITEM_TYPE) {
106: return super .effectiveBooleanValue(context);
107: } else {
108: return base.effectiveBooleanValue(context);
109: }
110: }
111:
112: public void display(int level, NamePool pool, PrintStream out) {
113: out.println(ExpressionTool.indent(level) + "TupleSorter");
114: base.display(level + 1, pool, out);
115: }
116:
117: /**
118: * Mapping function to map the wrapped objects returned by the SortedTupleIterator
119: * into real items. This is done because each tuple may actually represent a sequence
120: * of underlying values that share the same sort key.
121: */
122:
123: public Object map(Item item, XPathContext context)
124: throws XPathException {
125: ObjectValue tuple = (ObjectValue) item;
126: Object o = tuple.getObject();
127: if (o == null) {
128: return o;
129: }
130: if (o instanceof Item) {
131: return o;
132: }
133: Value value = (Value) o;
134: return value.iterate(context);
135: }
136:
137: }
138:
139: //
140: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
141: // you may not use this file except in compliance with the License. You may obtain a copy of the
142: // License at http://www.mozilla.org/MPL/
143: //
144: // Software distributed under the License is distributed on an "AS IS" basis,
145: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
146: // See the License for the specific language governing rights and limitations under the License.
147: //
148: // The Original Code is: all this file.
149: //
150: // The Initial Developer of the Original Code is Michael H. Kay
151: //
152: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
153: //
154: // Contributor(s): none
155: //
|