001: package net.sf.saxon.instruct;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.om.*;
005: import net.sf.saxon.trans.DynamicError;
006: import net.sf.saxon.trans.StaticError;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.type.ItemType;
009: import net.sf.saxon.type.Type;
010: import net.sf.saxon.type.TypeHierarchy;
011:
012: import java.io.PrintStream;
013: import java.util.Iterator;
014:
015: /**
016: * Common superclass for XSLT instructions whose content template produces a text
017: * value: xsl:attribute, xsl:comment, xsl:processing-instruction, xsl:namespace,
018: * and xsl:text
019: */
020:
021: public abstract class SimpleNodeConstructor extends Instruction {
022:
023: protected Expression select = null;
024:
025: public SimpleNodeConstructor() {
026: }
027:
028: public void setSelect(Expression select) throws StaticError {
029: this .select = select;
030: adoptChildExpression(select);
031: }
032:
033: public Expression getSelect() {
034: return select;
035: }
036:
037: /**
038: * Determine whether this instruction creates new nodes.
039: * This implementation returns true.
040: */
041:
042: public final boolean createsNewNodes() {
043: return true;
044: }
045:
046: public Expression simplify(StaticContext env) throws XPathException {
047: if (select != null) {
048: select = select.simplify(env);
049: }
050: return this ;
051: }
052:
053: /**
054: * Get the static properties of this expression (other than its type). The result is
055: * bit-signficant. These properties are used for optimizations. In general, if
056: * property bit is set, it is true, but if it is unset, the value is unknown.
057: *
058: * @return a set of flags indicating static properties of this expression
059: */
060:
061: public int computeSpecialProperties() {
062: return super .computeSpecialProperties()
063: | StaticProperty.SINGLE_DOCUMENT_NODESET;
064: }
065:
066: public abstract void localTypeCheck(StaticContext env,
067: ItemType contextItemType) throws XPathException;
068:
069: /**
070: * The analyze() method is called in XQuery, where node constructors
071: * are implemented as Expressions. In this case the required type for the
072: * select expression is a single string.
073: * @param env The static context for the query
074: * @return the rewritten expression
075: * @throws XPathException if any static errors are found in this expression
076: * or any of its children
077: */
078:
079: public Expression typeCheck(StaticContext env,
080: ItemType contextItemType) throws XPathException {
081: localTypeCheck(env, contextItemType);
082:
083: if (select != null) {
084: final TypeHierarchy th = env.getNamePool()
085: .getTypeHierarchy();
086: select = select.typeCheck(env, contextItemType);
087: if (select.getItemType(th).isAtomicType()) {
088: select = new Atomizer(select, env.getConfiguration());
089: }
090: if (!th.isSubType(select.getItemType(th), Type.STRING_TYPE)) {
091: select = new AtomicSequenceConverter(select,
092: Type.STRING_TYPE);
093: }
094: adoptChildExpression(select);
095: }
096: return this ;
097: }
098:
099: public Expression optimize(Optimizer opt, StaticContext env,
100: ItemType contextItemType) throws XPathException {
101: if (select != null) {
102: select = select.optimize(opt, env, contextItemType);
103: adoptChildExpression(select);
104: }
105: return this ;
106: }
107:
108: public Iterator iterateSubExpressions() {
109: return new MonoIterator(select);
110: }
111:
112: /**
113: * Expand the stylesheet elements subordinate to this one, returning the result
114: * as a string. The expansion must not generate any element or attribute nodes.
115: * @param context The dynamic context for the transformation
116: */
117:
118: public CharSequence expandChildren(XPathContext context)
119: throws XPathException {
120: Item item = select.evaluateItem(context);
121: if (item == null) {
122: return "";
123: } else {
124: return item.getStringValueCS();
125: }
126: }
127:
128: /**
129: * Evaluate as an expression. We rely on the fact that when these instructions
130: * are generated by XQuery, there will always be a valueExpression to evaluate
131: * the content
132: */
133:
134: public Item evaluateItem(XPathContext context)
135: throws XPathException {
136: String content = (select == null ? "" : select
137: .evaluateAsString(context));
138: content = checkContent(content, context);
139: try {
140: final TypeHierarchy th = context.getNamePool()
141: .getTypeHierarchy();
142: Orphan o = new Orphan(context.getConfiguration());
143: o.setNodeKind((short) getItemType(th).getPrimitiveType());
144: o.setStringValue(content);
145: o.setNameCode(evaluateNameCode(context));
146: return o;
147: } catch (SkipInstructionException skip) {
148: // error recovery path
149: return null;
150: }
151: }
152:
153: /**
154: * Check the content of the node, and adjust it if necessary. The checks depend on the node kind.
155: * @param data the supplied content
156: * @param context the dynamic context
157: * @return the original content, unless adjustments are needed
158: * @throws DynamicError if the content is invalid
159: */
160:
161: protected String checkContent(String data, XPathContext context)
162: throws DynamicError {
163: return data;
164: }
165:
166: protected int evaluateNameCode(XPathContext context)
167: throws XPathException, XPathException {
168: return -1;
169: }
170:
171: public SequenceIterator iterate(XPathContext context)
172: throws XPathException {
173: return SingletonIterator.makeIterator(evaluateItem(context));
174: }
175:
176: /**
177: * Display this instruction as an expression, for diagnostics
178: */
179:
180: public void display(int level, NamePool pool, PrintStream out) {
181: if (select != null) {
182: select.display(level, pool, out);
183: }
184: }
185:
186: /**
187: * Offer promotion for subexpressions. The offer will be accepted if the subexpression
188: * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
189: * By default the offer is not accepted - this is appropriate in the case of simple expressions
190: * such as constant values and variable references where promotion would give no performance
191: * advantage. This method is always called at compile time.
192: *
193: * @param offer details of the offer, for example the offer to move
194: * expressions that don't depend on the context to an outer level in
195: * the containing expression
196: * @exception XPathException if any error is detected
197: */
198:
199: protected void promoteInst(PromotionOffer offer)
200: throws XPathException {
201: if (select != null) {
202: select = doPromotion(select, offer);
203: }
204: super .promoteInst(offer);
205: }
206:
207: }
208:
209: //
210: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
211: // you may not use this file except in compliance with the License. You may obtain a copy of the
212: // License at http://www.mozilla.org/MPL/
213: //
214: // Software distributed under the License is distributed on an "AS IS" basis,
215: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
216: // See the License for the specific language governing rights and limitations under the License.
217: //
218: // The Original Code is: all this file.
219: //
220: // The Initial Developer of the Original Code is Michael H. Kay.
221: //
222: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
223: //
224: // Contributor(s): none.
225: //
|