KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.instruct;
2
3 import net.sf.saxon.Configuration;
4 import net.sf.saxon.Controller;
5 import net.sf.saxon.event.Receiver;
6 import net.sf.saxon.expr.*;
7 import net.sf.saxon.om.*;
8 import net.sf.saxon.pattern.ContentTypeTest;
9 import net.sf.saxon.pattern.NodeKindTest;
10 import net.sf.saxon.style.StandardNames;
11 import net.sf.saxon.trans.DynamicError;
12 import net.sf.saxon.trans.StaticError;
13 import net.sf.saxon.trans.XPathException;
14 import net.sf.saxon.type.*;
15 import net.sf.saxon.value.QNameValue;
16 import net.sf.saxon.value.StringValue;
17 import net.sf.saxon.value.SequenceType;
18 import net.sf.saxon.value.AtomicValue;
19
20 import java.io.PrintStream JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Iterator JavaDoc;
23
24
25 /**
26  * An instruction representing an xsl:element element in an XSLT stylesheet,
27  * or a computed element constructor in XQuery. (In both cases, if the element name
28  * is expressed as a compile-time expression, then a FixedElement instruction
29  * is used instead.)
30  * @see FixedElement
31  */

32
33 public class ComputedElement extends ElementCreator {
34
35     private Expression elementName;
36     private Expression namespace = null;
37     private NamespaceResolver nsContext;
38     private boolean allowNameAsQName;
39     private ItemType itemType;
40
41     /**
42      * Create an instruction that creates a new element node
43      *
44      * @param elementName Expression that evaluates to produce the name of the
45      * element node as a lexical QName
46      * @param namespace Expression that evaluates to produce the namespace URI of
47      * the element node. Set to null if the namespace is to be deduced from the prefix
48      * of the elementName.
49      * @param nsContext Saved copy of the static namespace context for the instruction.
50      * Can be set to null if namespace is supplied.
51      * @param schemaType The required schema type for the content
52      * @param allowQName
53      */

54     public ComputedElement(Expression elementName,
55                            Expression namespace,
56                            NamespaceResolver nsContext,
57                            SchemaType schemaType,
58                            int validation,
59                            boolean inheritNamespaces,
60                            boolean allowQName) {
61         this.elementName = elementName;
62         this.namespace = namespace;
63         this.nsContext = nsContext;
64         setSchemaType(schemaType);
65         this.validation = validation;
66         this.inheritNamespaces = inheritNamespaces;
67         this.allowNameAsQName = allowQName;
68         adoptChildExpression(elementName);
69         adoptChildExpression(namespace);
70     }
71
72     public Expression simplify(StaticContext env) throws XPathException {
73         elementName = elementName.simplify(env);
74         if (namespace != null) {
75             namespace = namespace.simplify(env);
76         }
77         Configuration config = env.getConfiguration();
78         setLazyConstruction(config.isLazyConstructionMode());
79
80         if (getSchemaType() != null) {
81             itemType = new ContentTypeTest(Type.ELEMENT, getSchemaType(), config);
82             getSchemaType().analyzeContentExpression(content, Type.ELEMENT, env);
83         } else if (validation == Validation.STRIP || !config.isSchemaAware(Configuration.XML_SCHEMA)) {
84             itemType = new ContentTypeTest(Type.ELEMENT,
85                     BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_UNTYPED),
86                     config);
87         } else {
88             // paradoxically, we know less about the type if validation="strict" is specified!
89
// We know that it won't be untyped, but we have no way of representing that.
90
itemType = NodeKindTest.ELEMENT;
91         }
92         return super.simplify(env);
93     }
94
95     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
96         elementName = elementName.typeCheck(env, contextItemType);
97         adoptChildExpression(elementName);
98         RoleLocator role = new RoleLocator(RoleLocator.INSTRUCTION, "element/name", 0, null);
99         role.setSourceLocator(this);
100         if (allowNameAsQName) {
101             // Can only happen in XQuery
102
elementName = TypeChecker.staticTypeCheck(elementName,
103                     SequenceType.SINGLE_ATOMIC, false, role, env);
104         } else {
105             elementName = TypeChecker.staticTypeCheck(elementName,
106                     SequenceType.SINGLE_STRING, false, role, env);
107         }
108         if (namespace != null) {
109             namespace = namespace.typeCheck(env, contextItemType);
110             adoptChildExpression(namespace);
111
112             role = new RoleLocator(RoleLocator.INSTRUCTION, "attribute/namespace", 0, null);
113             role.setSourceLocator(this);
114             namespace = TypeChecker.staticTypeCheck(
115                     namespace, SequenceType.SINGLE_STRING, false, role, env);
116         }
117         return super.typeCheck(env, contextItemType);
118     }
119
120     /**
121      * Get the item type of the value returned by this instruction
122      *
123      * @return the item type
124      */

125
126     public ItemType getItemType() {
127         if (itemType == null) {
128             return super.getItemType();
129         }
130         return itemType;
131     }
132
133     public Iterator JavaDoc iterateSubExpressions() {
134         ArrayList JavaDoc list = new ArrayList JavaDoc(8);
135         list.add(content);
136         list.add(elementName);
137         if (namespace != null) {
138             list.add(namespace);
139         }
140         return list.iterator();
141     }
142
143     /**
144      * Offer promotion for subexpressions. The offer will be accepted if the subexpression
145      * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
146      * By default the offer is not accepted - this is appropriate in the case of simple expressions
147      * such as constant values and variable references where promotion would give no performance
148      * advantage. This method is always called at compile time.
149      *
150      * @param offer details of the offer, for example the offer to move
151      * expressions that don't depend on the context to an outer level in
152      * the containing expression
153      * @throws net.sf.saxon.trans.XPathException if any error is detected
154      */

155
156     protected void promoteInst(PromotionOffer offer) throws XPathException {
157         elementName = doPromotion(elementName, offer);
158         if (namespace != null) {
159             namespace = doPromotion(namespace, offer);
160         }
161         super.promoteInst(offer);
162     }
163
164     /**
165      * Check that any elements and attributes constructed or returned by this expression are acceptable
166      * in the content model of a given complex type. It's always OK to say yes, since the check will be
167      * repeated at run-time. The process of checking element and attribute constructors against the content
168      * model of a complex type also registers the type of content expected of those constructors, so the
169      * static validation can continue recursively.
170      */

171
172     public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException {
173         if (parentType instanceof SimpleType) {
174             StaticError err = new StaticError(
175                     "Elements are not permitted here: the containing element has the simple type " + parentType.getDescription());
176             err.setIsTypeError(true);
177             err.setLocator(this);
178             throw err;
179         } else if (((ComplexType)parentType).isSimpleContent()) {
180             StaticError err = new StaticError(
181                     "Elements are not permitted here: the containing element has a complex type with simple content");
182             err.setIsTypeError(true);
183             err.setLocator(this);
184             throw err;
185         }
186         // NOTE: we could in principle check that if all the elements permitted in the content of the parentType
187
// themselves have a simple type (not uncommon, perhaps) then this element must not have element content.
188
}
189
190
191     /**
192      * Callback from the superclass ElementCreator to get the nameCode
193      * for the element name
194      *
195      * @param context The evaluation context (not used)
196      * @return the name code for the element name
197      */

198
199     public int getNameCode(XPathContext context)
200             throws XPathException, XPathException {
201
202         Controller controller = context.getController();
203         NamePool pool = controller.getNamePool();
204
205         String JavaDoc prefix;
206         String JavaDoc localName;
207         String JavaDoc uri;
208
209         // name needs to be evaluated at run-time
210
AtomicValue nameValue = (AtomicValue)elementName.evaluateItem(context);
211         nameValue = nameValue.getPrimitiveValue();
212         if (nameValue instanceof StringValue) {
213             // this will always be the case in XSLT
214
CharSequence JavaDoc rawName = nameValue.getStringValueCS();
215             try {
216                 String JavaDoc[] parts = Name.getQNameParts(rawName);
217                 prefix = parts[0];
218                 localName = parts[1];
219             } catch (QNameException err) {
220                 DynamicError err1 = new DynamicError("Invalid element name. " + err.getMessage(), this);
221                 err1.setErrorCode((isXSLT(context) ? "XTDE0820" : "XQDY0074"));
222                 err1.setXPathContext(context);
223                 throw dynamicError(this, err1, context);
224             }
225         } else if (nameValue instanceof QNameValue && allowNameAsQName) {
226             // this is allowed in XQuery
227
localName = ((QNameValue)nameValue).getLocalName();
228             uri = ((QNameValue)nameValue).getNamespaceURI();
229             namespace = new StringValue(uri);
230             prefix = ((QNameValue)nameValue).getPrefix();
231         } else {
232             DynamicError err = new DynamicError("Computed element name has incorrect type");
233             err.setErrorCode((isXSLT(context) ? "XTDE0820" : "XPTY0004"));
234             err.setIsTypeError(true);
235             err.setXPathContext(context);
236             throw dynamicError(this, err, context);
237         }
238
239         if (namespace == null) {
240             uri = nsContext.getURIForPrefix(prefix, true);
241             if (uri == null) {
242                 DynamicError err = new DynamicError("Undeclared prefix in element name: " + prefix, this);
243                 err.setErrorCode((isXSLT(context) ? "XTDE0830" : "XQDY0074"));
244                 err.setXPathContext(context);
245                 throw dynamicError(this, err, context);
246             }
247
248         } else {
249             uri = namespace.evaluateAsString(context);
250             if (uri.equals("")) {
251                 // there is a special rule for this case in the specification;
252
// we force the element to go in the null namespace
253
prefix = "";
254             }
255             if (prefix.equals("xmlns")) {
256                 // this isn't a legal prefix so we mustn't use it
257
prefix = "x-xmlns";
258             }
259         }
260
261         return pool.allocate(prefix, uri, localName);
262
263     }
264
265     /**
266      * Callback to output namespace nodes for the new element.
267      *
268      * @param context The execution context
269      * @param out the Receiver where the namespace nodes are to be written
270      * @throws XPathException
271      */

272     protected void outputNamespaceNodes(XPathContext context, Receiver out)
273             throws XPathException {
274         // do nothing
275
}
276
277
278     /**
279      * Get the name of this instruction for diagnostic and tracing purposes
280      */

281
282     public int getInstructionNameCode() {
283         return StandardNames.XSL_ELEMENT;
284     }
285
286     /**
287      * Display this instruction as an expression, for diagnostics
288      */

289
290     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
291         out.println(ExpressionTool.indent(level) + "element ");
292         out.println(ExpressionTool.indent(level + 1) + "name");
293         elementName.display(level + 2, pool, out);
294         out.println(ExpressionTool.indent(level + 1) + "content");
295         content.display(level + 1, pool, out);
296     }
297 }
298
299 //
300
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
301
// you may not use this file except in compliance with the License. You may obtain a copy of the
302
// License at http://www.mozilla.org/MPL/
303
//
304
// Software distributed under the License is distributed on an "AS IS" basis,
305
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
306
// See the License for the specific language governing rights and limitations under the License.
307
//
308
// The Original Code is: all this file.
309
//
310
// The Initial Developer of the Original Code is Michael H. Kay.
311
//
312
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
313
//
314
// Contributor(s): none.
315
//
316
Popular Tags