KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > instruct > SimpleContentConstructor


1 package net.sf.saxon.instruct;
2
3 import net.sf.saxon.expr.*;
4 import net.sf.saxon.om.*;
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.StringValue;
9 import net.sf.saxon.value.Cardinality;
10 import net.sf.saxon.value.AtomicValue;
11
12 import java.io.PrintStream JavaDoc;
13 import java.util.Iterator JavaDoc;
14
15 /**
16  * This class implements the rules for an XSLT simple content constructor, which are used in constructing
17  * the string value of an attribute node, text node, comment node, etc, from the value of the select
18  * expression or the contained sequence constructor.
19  */

20
21 public class SimpleContentConstructor extends ComputedExpression {
22
23     Expression select;
24     Expression separator;
25     boolean isSingleton = false;
26     boolean isAtomic = false;
27
28     public SimpleContentConstructor(Expression select, Expression separator) {
29         this.select = select;
30         this.separator = separator;
31         adoptChildExpression(select);
32         adoptChildExpression(separator);
33     }
34
35     /**
36      * Compute the cardinality of the result of the expression.
37      * @return the cardinality, @link {StaticProperty.EXACTLY_ONE}
38      */

39
40     protected int computeCardinality() {
41         return StaticProperty.EXACTLY_ONE;
42
43     }
44
45     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
46         select = select.typeCheck(env, contextItemType);
47         separator = separator.typeCheck(env, contextItemType);
48         if (!Cardinality.allowsMany(select.getCardinality())) {
49             isSingleton = true;
50         }
51         if (Type.isSubType(select.getItemType(), Type.ANY_ATOMIC_TYPE)) {
52             isAtomic = true;
53         }
54         return this;
55     }
56
57     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
58         select = select.optimize(opt, env, contextItemType);
59         separator = separator.optimize(opt, env, contextItemType);
60         return this;
61     }
62
63     /**
64      * Determine the data type of the expression, if possible. All expression return
65      * sequences, in general; this method determines the type of the items within the
66      * sequence, assuming that (a) this is known in advance, and (b) it is the same for
67      * all items in the sequence.
68      * <p/>
69      * <p>This method should always return a result, though it may be the best approximation
70      * that is available at the time.</p>
71      *
72      * @return a value such as Type.STRING, Type.BOOLEAN, Type.NUMBER,
73      * Type.NODE, or Type.ITEM (meaning not known at compile time)
74      */

75
76     public ItemType getItemType() {
77         return Type.STRING_TYPE;
78     }
79
80     /**
81      * Diagnostic print of expression structure. The expression is written to the System.err
82      * output stream
83      *
84      * @param level indentation level for this expression
85      * @param pool NamePool used to expand any names appearing in the expression
86      * @param out Output destination
87      */

88
89     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
90         out.println(ExpressionTool.indent(level) + "construct simple content");
91         select.display(level+1, pool, out);
92         separator.display(level+1, pool, out);
93     }
94
95     /**
96      * Simplify an expression. This performs any static optimization (by rewriting the expression
97      * as a different expression). The default implementation does nothing.
98      *
99      * @return the simplified expression
100      * @throws net.sf.saxon.trans.XPathException
101      * if an error is discovered during expression
102      * rewriting
103      */

104
105     public Expression simplify(StaticContext env) throws XPathException {
106         select = select.simplify(env);
107         if (select instanceof AtomicValue) {
108             return select;
109         }
110         separator = separator.simplify(env);
111         return this;
112     }
113
114      /**
115      * Get the immediate sub-expressions of this expression. Default implementation
116      * returns a zero-length array, appropriate for an expression that has no
117      * sub-expressions.
118      *
119      * @return an iterator containing the sub-expressions of this expression
120      */

121
122     public Iterator JavaDoc iterateSubExpressions() {
123         return new PairIterator(select, separator);
124     }
125
126     /**
127      * Offer promotion for this subexpression. The offer will be accepted if the subexpression
128      * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
129      * By default the offer is not accepted - this is appropriate in the case of simple expressions
130      * such as constant values and variable references where promotion would give no performance
131      * advantage. This method is always called at compile time.
132      *
133      * @param offer details of the offer, for example the offer to move
134      * expressions that don't depend on the context to an outer level in
135      * the containing expression
136      * @return if the offer is not accepted, return this expression unchanged.
137      * Otherwise return the result of rewriting the expression to promote
138      * this subexpression
139      * @throws net.sf.saxon.trans.XPathException
140      * if any error is detected
141      */

142
143     public Expression promote(PromotionOffer offer) throws XPathException {
144         Expression exp = offer.accept(this);
145         if (exp!=null) {
146             return exp;
147         } else {
148             select = doPromotion(select, offer);
149             separator = doPromotion(separator, offer);
150             return this;
151         }
152     }
153
154     /**
155      * Evaluate an expression as a single item. This always returns either a single Item or
156      * null (denoting the empty sequence). No conversion is done. This method should not be
157      * used unless the static type of the expression is a subtype of "item" or "item?": that is,
158      * it should not be called if the expression may return a sequence. There is no guarantee that
159      * this condition will be detected.
160      *
161      * @param context The context in which the expression is to be evaluated
162      * @return the node or atomic value that results from evaluating the
163      * expression; or null to indicate that the result is an empty
164      * sequence
165      * @throws net.sf.saxon.trans.XPathException
166      * if any dynamic error occurs evaluating the
167      * expression
168      */

169
170     public Item evaluateItem(XPathContext context) throws XPathException {
171         SequenceIterator iter;
172         if (isSingleton) {
173             // optimize for this case
174
Item item = select.evaluateItem(context);
175             if (item == null || item instanceof StringValue) {
176                 return item;
177             } else if (item instanceof AtomicValue) {
178                 return ((AtomicValue)item).convert(Type.STRING, context);
179             } else {
180                 iter = SingletonIterator.makeIterator(item);
181             }
182         } else {
183             iter = select.iterate(context);
184         }
185         FastStringBuffer sb = new FastStringBuffer(1024);
186         boolean prevText = false;
187         boolean first = true;
188         CharSequence JavaDoc sep = null;
189         while (true) {
190             Item item = iter.next();
191             if (item==null) {
192                 break;
193             }
194             if (item instanceof NodeInfo) {
195                 if (((NodeInfo)item).getNodeKind() == Type.TEXT) {
196                     CharSequence JavaDoc s = item.getStringValueCS();
197                     if (s.length() > 0) {
198                         if (!first && !prevText) {
199                             if (sep == null) {
200                                 sep = separator.evaluateItem(context).getStringValueCS();
201                             }
202                             sb.append(sep);
203                         }
204                         first = false;
205                         sb.append(s);
206                         prevText = true;
207                     }
208                 } else {
209                     prevText = false;
210                     SequenceIterator iter2 = item.getTypedValue();
211                     while (true) {
212                         Item item2 = iter2.next();
213                         if (item2 == null) {
214                             break;
215                         }
216                         if (!first) {
217                             if (sep == null) {
218                                 sep = separator.evaluateItem(context).getStringValueCS();
219                             }
220                             sb.append(sep);
221                         }
222                         first = false;
223                         sb.append(item2.getStringValueCS());
224                     }
225                 }
226             } else {
227                 if (!first) {
228                     if (sep == null) {
229                         sep = separator.evaluateItem(context).getStringValueCS();
230                     }
231                     sb.append(sep);
232                 }
233                 first = false;
234                 sb.append(item.getStringValueCS());
235             }
236         }
237         return StringValue.makeStringValue(sb.condense());
238     }
239
240     /**
241      * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
242      * This method indicates which of these methods is prefered.
243      */

244
245     public int getImplementationMethod() {
246         return Expression.EVALUATE_METHOD;
247     }
248
249 }
250
251
252 //
253
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
254
// you may not use this file except in compliance with the License. You may obtain a copy of the
255
// License at http://www.mozilla.org/MPL/
256
//
257
// Software distributed under the License is distributed on an "AS IS" basis,
258
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
259
// See the License for the specific language governing rights and limitations under the License.
260
//
261
// The Original Code is: all this file.
262
//
263
// The Initial Developer of the Original Code is Michael H. Kay.
264
//
265
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
266
//
267
// Contributor(s): none.
268
//
269
Popular Tags