001: package net.sf.saxon.instruct;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.trans.XPathException;
005: import net.sf.saxon.type.ItemType;
006: import net.sf.saxon.type.SchemaType;
007: import net.sf.saxon.type.SimpleType;
008: import net.sf.saxon.om.Validation;
009:
010: import java.util.Iterator;
011:
012: /**
013: * An abstract class to act as a common parent for instructions that create element nodes
014: * and document nodes.
015: */
016:
017: public abstract class ParentNodeConstructor extends Instruction {
018:
019: protected Expression content;
020: private boolean lazyConstruction = false;
021: private boolean namespaceSensitiveType;
022: int validation = Validation.PRESERVE;
023: private SchemaType schemaType;
024:
025: public ParentNodeConstructor() {
026: }
027:
028: /**
029: * Indicate that lazy construction should (or should not) be used
030: * @param lazy set to true if lazy construction should be used
031: */
032:
033: public void setLazyConstruction(boolean lazy) {
034: lazyConstruction = lazy;
035: }
036:
037: /**
038: * Establish whether lazy construction is to be used
039: */
040:
041: public final boolean isLazyConstruction() {
042: return lazyConstruction;
043: }
044:
045: /**
046: * Set the schema type to be used for validation
047: */
048:
049: public void setSchemaType(SchemaType type) {
050: schemaType = type;
051: namespaceSensitiveType = (type instanceof SimpleType)
052: && ((SimpleType) type).isNamespaceSensitive();
053: }
054:
055: /**
056: * Get the schema type chosen for validation; null if not defined
057: */
058:
059: public SchemaType getSchemaType() {
060: return schemaType;
061: }
062:
063: /**
064: * Determine whether the schema type is namespace sensitive. The result is undefined if schemaType is null.
065: */
066:
067: public boolean isNamespaceSensitive() {
068: return namespaceSensitiveType;
069: }
070:
071: /**
072: * Get the validation mode for this instruction
073: * @return the validation mode, for example {@link Validation#STRICT} or {@link Validation#PRESERVE}
074: */
075: public int getValidationAction() {
076: return validation;
077: }
078:
079: /**
080: * Set the expression that constructs the content of the element
081: */
082:
083: public void setContentExpression(Expression content) {
084: this .content = content;
085: adoptChildExpression(content);
086: }
087:
088: /**
089: * Get the expression that constructs the content of the element
090: */
091:
092: public Expression getContentExpression() {
093: return content;
094: }
095:
096: /**
097: * Simplify an expression. This performs any static optimization (by rewriting the expression
098: * as a different expression). The default implementation does nothing.
099: * @return the simplified expression
100: * @throws net.sf.saxon.trans.XPathException
101: * if an error is discovered during expression rewriting
102: */
103:
104: public Expression simplify(StaticContext env) throws XPathException {
105: content = content.simplify(env);
106: return this ;
107: }
108:
109: public Expression typeCheck(StaticContext env,
110: ItemType contextItemType) throws XPathException {
111: content = content.typeCheck(env, contextItemType);
112: adoptChildExpression(content);
113: verifyLazyConstruction();
114: return this ;
115: }
116:
117: public Expression optimize(Optimizer opt, StaticContext env,
118: ItemType contextItemType) throws XPathException {
119: content = content.optimize(opt, env, contextItemType);
120: adoptChildExpression(content);
121: return this ;
122: }
123:
124: /**
125: * Handle promotion offers, that is, non-local tree rewrites.
126: * @param offer The type of rewrite being offered
127: * @throws net.sf.saxon.trans.XPathException
128: */
129:
130: protected void promoteInst(PromotionOffer offer)
131: throws XPathException {
132: if (offer.action != PromotionOffer.UNORDERED) {
133: content = doPromotion(content, offer);
134: }
135: }
136:
137: /**
138: * Get the immediate sub-expressions of this expression.
139: * @return an iterator containing the sub-expressions of this expression
140: */
141:
142: public Iterator iterateSubExpressions() {
143: return new MonoIterator(content);
144: }
145:
146: /**
147: * Determine whether this instruction creates new nodes.
148: * This implementation returns true.
149: */
150:
151: public final boolean createsNewNodes() {
152: return true;
153: }
154:
155: public int getCardinality() {
156: return StaticProperty.EXACTLY_ONE;
157: }
158:
159: /**
160: * Check that lazy construction is possible for this element
161: */
162:
163: void verifyLazyConstruction() {
164: if (!isLazyConstruction()) {
165: return;
166: }
167: // Lazy construction is not possible if the expression depends on the values of position() or last(),
168: // as we can't save these.
169: if ((getDependencies() & (StaticProperty.DEPENDS_ON_POSITION | StaticProperty.DEPENDS_ON_LAST)) != 0) {
170: setLazyConstruction(false);
171: }
172: // Lazy construction is not possible if validation is required
173: if (validation == Validation.STRICT
174: || validation == Validation.LAX || schemaType != null) {
175: setLazyConstruction(false);
176: }
177: }
178: }
179:
180: //
181: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
182: // you may not use this file except in compliance with the License. You may obtain a copy of the
183: // License at http://www.mozilla.org/MPL/
184: //
185: // Software distributed under the License is distributed on an "AS IS" basis,
186: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
187: // See the License for the specific language governing rights and limitations under the License.
188: //
189: // The Original Code is: all this file.
190: //
191: // The Initial Developer of the Original Code is Michael H. Kay.
192: //
193: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
194: //
195: // Contributor(s): none.
196: //
|