Source Code Cross Referenced for StyleElement.java in  » XML » XPath-Saxon » net » sf » saxon » style » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » XPath Saxon » net.sf.saxon.style 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package net.sf.saxon.style;
0002:
0003:        import net.sf.saxon.Err;
0004:        import net.sf.saxon.PreparedStylesheet;
0005:        import net.sf.saxon.Configuration;
0006:        import net.sf.saxon.event.LocationProvider;
0007:        import net.sf.saxon.expr.*;
0008:        import net.sf.saxon.instruct.*;
0009:        import net.sf.saxon.om.*;
0010:        import net.sf.saxon.pattern.*;
0011:        import net.sf.saxon.sort.SortKeyDefinition;
0012:        import net.sf.saxon.trace.InstructionInfo;
0013:        import net.sf.saxon.trace.Location;
0014:        import net.sf.saxon.trans.DynamicError;
0015:        import net.sf.saxon.trans.SaxonErrorCode;
0016:        import net.sf.saxon.trans.StaticError;
0017:        import net.sf.saxon.trans.XPathException;
0018:        import net.sf.saxon.tree.ElementWithAttributes;
0019:        import net.sf.saxon.type.*;
0020:        import net.sf.saxon.value.*;
0021:        import org.xml.sax.Locator;
0022:
0023:        import javax.xml.transform.SourceLocator;
0024:        import javax.xml.transform.TransformerConfigurationException;
0025:        import javax.xml.transform.TransformerException;
0026:        import java.math.BigDecimal;
0027:        import java.util.ArrayList;
0028:        import java.util.Iterator;
0029:        import java.util.List;
0030:        import java.util.StringTokenizer;
0031:        import java.net.URI;
0032:        import java.net.URISyntaxException;
0033:
0034:        /**
0035:         * Abstract superclass for all element nodes in the stylesheet. <BR>
0036:         * Note: this class implements Locator. The element
0037:         * retains information about its own location in the stylesheet, which is useful when
0038:         * an XSL error is found.
0039:         */
0040:
0041:        public abstract class StyleElement extends ElementWithAttributes
0042:                implements  Locator, Container, InstructionInfo {
0043:
0044:            protected short[] extensionNamespaces = null; // a list of URI codes
0045:            private short[] excludedNamespaces = null; // a list of URI codes
0046:            protected BigDecimal version = null;
0047:            protected StaticContext staticContext = null;
0048:            protected StaticError validationError = null;
0049:            protected int reportingCircumstances = REPORT_ALWAYS;
0050:            protected String defaultXPathNamespace = null;
0051:            protected String defaultCollationName = null;
0052:            private int lineNumber; // maintained here because it's more efficient
0053:            // than using the lineNumberMap
0054:            private boolean explaining = false;
0055:            // true if saxon:explain="yes"
0056:            private int objectNameCode = -1;
0057:            // for instructions that define an XSLT named object, the name of that object
0058:            private XSLStylesheet containingStylesheet;
0059:
0060:            // Conditions under which an error is to be reported
0061:
0062:            public static final int REPORT_ALWAYS = 1;
0063:            public static final int REPORT_UNLESS_FORWARDS_COMPATIBLE = 2;
0064:            public static final int REPORT_IF_INSTANTIATED = 3;
0065:            public static final int REPORT_UNLESS_FALLBACK_AVAILABLE = 4;
0066:
0067:            /**
0068:             * Constructor
0069:             */
0070:
0071:            public StyleElement() {
0072:            }
0073:
0074:            public Executable getExecutable() {
0075:                return getPrincipalStylesheet().getExecutable();
0076:            }
0077:
0078:            /**
0079:             * Get the LocationProvider allowing location identifiers to be resolved.
0080:             */
0081:
0082:            public LocationProvider getLocationProvider() {
0083:                return getExecutable().getLocationMap();
0084:            }
0085:
0086:            /**
0087:             * Get the namepool to be used at run-time, this namepool holds the names used in
0088:             * all XPath expressions and patterns
0089:             */
0090:
0091:            public NamePool getTargetNamePool() {
0092:                return getPrincipalStylesheet().getTargetNamePool();
0093:            }
0094:
0095:            /**
0096:             * Get the static context for expressions on this element
0097:             *
0098:             * @return the static context
0099:             */
0100:
0101:            public StaticContext getStaticContext() {
0102:                if (staticContext == null) {
0103:                    staticContext = new ExpressionContext(this );
0104:                }
0105:                return staticContext;
0106:            }
0107:
0108:            public int getLineNumber() {
0109:                return lineNumber;
0110:            }
0111:
0112:            public void setLineNumber(int lineNumber) {
0113:                this .lineNumber = lineNumber;
0114:            }
0115:
0116:            /**
0117:             * Determine whether saxon:explain has been set to "yes"
0118:             */
0119:
0120:            protected boolean isExplaining() {
0121:                return explaining;
0122:            }
0123:
0124:            /**
0125:             * Make this node a substitute for a temporary one previously added to the tree. See
0126:             * StyleNodeFactory for details. "A node like the other one in all things but its class".
0127:             * Note that at this stage, the node will not yet be known to its parent, though it will
0128:             * contain a reference to its parent; and it will have no children.
0129:             */
0130:
0131:            public void substituteFor(StyleElement temp) {
0132:                this .parent = temp.parent;
0133:                this .attributeList = temp.attributeList;
0134:                this .namespaceList = temp.namespaceList;
0135:                this .nameCode = temp.nameCode;
0136:                this .sequence = temp.sequence;
0137:                this .extensionNamespaces = temp.extensionNamespaces;
0138:                this .excludedNamespaces = temp.excludedNamespaces;
0139:                this .version = temp.version;
0140:                this .root = temp.root;
0141:                this .staticContext = temp.staticContext;
0142:                this .validationError = temp.validationError;
0143:                this .reportingCircumstances = temp.reportingCircumstances;
0144:                this .lineNumber = temp.lineNumber;
0145:            }
0146:
0147:            /**
0148:             * Set a validation error
0149:             */
0150:
0151:            protected void setValidationError(TransformerException reason,
0152:                    int circumstances) {
0153:                validationError = StaticError.makeStaticError(reason);
0154:                reportingCircumstances = circumstances;
0155:            }
0156:
0157:            /**
0158:             * Determine whether this node is an instruction. The default implementation says it isn't.
0159:             */
0160:
0161:            public boolean isInstruction() {
0162:                return false;
0163:            }
0164:
0165:            /**
0166:             * Determine the type of item returned by this instruction (only relevant if
0167:             * it is an instruction). Default implementation returns Type.ITEM, indicating
0168:             * that we don't know, it might be anything. Returns null in the case of an element
0169:             * such as xsl:sort or xsl:variable that can appear in a sequence constructor but
0170:             * contributes nothing to the result sequence.
0171:             *
0172:             * @return the item type returned
0173:             */
0174:
0175:            protected ItemType getReturnedItemType() {
0176:                return AnyItemType.getInstance();
0177:            }
0178:
0179:            /**
0180:             * Get the most general type of item returned by the children of this instruction
0181:             *
0182:             * @return the lowest common supertype of the item types returned by the children
0183:             */
0184:
0185:            protected ItemType getCommonChildItemType() {
0186:                final TypeHierarchy th = getNamePool().getTypeHierarchy();
0187:                ItemType t = NoNodeTest.getInstance();
0188:                AxisIterator children = iterateAxis(Axis.CHILD);
0189:                while (true) {
0190:                    NodeInfo next = (NodeInfo) children.next();
0191:                    if (next == null) {
0192:                        return t;
0193:                    }
0194:                    if (next instanceof  StyleElement) {
0195:                        ItemType ret = ((StyleElement) next)
0196:                                .getReturnedItemType();
0197:                        if (ret != null) {
0198:                            t = Type.getCommonSuperType(t, ret, th);
0199:                        }
0200:                    } else {
0201:                        t = Type.getCommonSuperType(t, NodeKindTest.TEXT, th);
0202:                    }
0203:                    if (t == AnyItemType.getInstance()) {
0204:                        return t; // no point looking any further
0205:                    }
0206:                }
0207:            }
0208:
0209:            /**
0210:             * Mark tail-recursive calls on templates and functions.
0211:             * For most instructions, this does nothing.
0212:             */
0213:
0214:            public void markTailCalls() {
0215:                // no-op
0216:            }
0217:
0218:            /**
0219:             * Determine whether this type of element is allowed to contain a sequence constructor
0220:             */
0221:
0222:            public boolean mayContainSequenceConstructor() {
0223:                return false;
0224:            }
0225:
0226:            /**
0227:             * Determine whether this type of element is allowed to contain an xsl:fallback
0228:             * instruction
0229:             */
0230:
0231:            public boolean mayContainFallback() {
0232:                return mayContainSequenceConstructor();
0233:            }
0234:
0235:            /**
0236:             * Get the containing XSLStylesheet element
0237:             */
0238:
0239:            public XSLStylesheet getContainingStylesheet() {
0240:                if (containingStylesheet == null) {
0241:                    if (this  instanceof  XSLStylesheet) {
0242:                        containingStylesheet = (XSLStylesheet) this ;
0243:                    } else {
0244:                        containingStylesheet = ((StyleElement) getParent())
0245:                                .getContainingStylesheet();
0246:                    }
0247:                }
0248:                return containingStylesheet;
0249:            }
0250:
0251:            /**
0252:             * Get the import precedence of this stylesheet element.
0253:             */
0254:
0255:            public int getPrecedence() {
0256:                return getContainingStylesheet().getPrecedence();
0257:            }
0258:
0259:            /**
0260:             * Get the URI for a namespace prefix using the in-scope namespaces for
0261:             * this element in the stylesheet
0262:             *
0263:             * @param prefix     The namespace prefix: may be the empty string
0264:             * @param useDefault True if the default namespace is to be used when the
0265:             *                   prefix is "".
0266:             * @return the namespace URI if the prefix is bound to a namespace; "" if the
0267:             * prefix ("") is bound to no namespace; null if the prefix is not bound.
0268:             */
0269:
0270:            //    public String getURIForPrefix(String prefix, boolean useDefault)  {
0271:            //        if ("".equals(prefix) && !useDefault) {
0272:            //            return "";
0273:            //        } else {
0274:            //            try {
0275:            //                short uricode = getURICodeForPrefix(prefix);
0276:            //                return getNamePool().getURIFromURICode(uricode);
0277:            //            } catch (NamespaceException e) {
0278:            //                return null;
0279:            //            }
0280:            //        }
0281:            //    }
0282:            /**
0283:             * Make a NameCode, using this Element as the context for namespace resolution, and
0284:             * registering the code in the namepool. If the name is unprefixed, the
0285:             * default namespace is <b>not</b> used.
0286:             *
0287:             * @param qname The name as written, in the form "[prefix:]localname". The name must have
0288:             *              already been validated as a syntactically-correct QName.
0289:             * @throws XPathException     if the qname is not a lexically-valid QName, or if the name
0290:             *                            is in a reserved namespace.
0291:             * @throws NamespaceException if the prefix of the qname has not been declared
0292:             */
0293:
0294:            public final int makeNameCode(String qname) throws XPathException,
0295:                    NamespaceException {
0296:
0297:                NamePool namePool = getTargetNamePool();
0298:                String[] parts;
0299:                try {
0300:                    parts = getConfiguration().getNameChecker().getQNameParts(
0301:                            qname);
0302:                } catch (QNameException err) {
0303:                    StaticError e2 = new StaticError(err.getMessage());
0304:                    e2.setErrorCode("XTSE0020");
0305:                    throw e2;
0306:                }
0307:                String prefix = parts[0];
0308:                if ("".equals(prefix)) {
0309:                    return namePool.allocate(prefix, (short) 0, qname);
0310:
0311:                } else {
0312:
0313:                    String uri = getURIForPrefix(prefix, false);
0314:                    if (uri == null) {
0315:                        throw new NamespaceException(prefix);
0316:                    }
0317:                    if (NamespaceConstant.isReserved(uri)) {
0318:                        StaticError err = new StaticError("Namespace prefix "
0319:                                + prefix + " refers to a reserved namespace");
0320:                        err.setErrorCode("XTSE0080");
0321:                        throw err;
0322:                    }
0323:                    return namePool.allocate(prefix, uri, parts[1]);
0324:                }
0325:
0326:            }
0327:
0328:            /**
0329:             * Make a NamespaceContext object representing the list of in-scope namespaces. The NamePool
0330:             * used for numeric codes in the NamespaceContext will be the target name pool.
0331:             */
0332:
0333:            public SavedNamespaceContext makeNamespaceContext() {
0334:                return new SavedNamespaceContext(getInScopeNamespaceCodes(),
0335:                        getNamePool());
0336:            }
0337:
0338:            /**
0339:             * Process the attributes of this element and all its children
0340:             */
0341:
0342:            public void processAllAttributes() throws XPathException {
0343:                staticContext = new ExpressionContext(this );
0344:                processAttributes();
0345:                AxisIterator kids = iterateAxis(Axis.CHILD);
0346:                while (true) {
0347:                    NodeInfo child = (NodeInfo) kids.next();
0348:                    if (child == null) {
0349:                        return;
0350:                    }
0351:                    if (child instanceof  StyleElement) {
0352:                        ((StyleElement) child).processAllAttributes();
0353:                        if (((StyleElement) child).explaining) {
0354:                            // saxon:explain on any element in a template/function now causes an explanation at the
0355:                            // level of the template/function
0356:                            explaining = true;
0357:                        }
0358:                    }
0359:                }
0360:            }
0361:
0362:            /**
0363:             * Get an attribute value given the Clark name of the attribute (that is,
0364:             * the name in {uri}local format).
0365:             */
0366:
0367:            public String getAttributeValue(String clarkName) {
0368:                int fp = getNamePool().allocateClarkName(clarkName);
0369:                return getAttributeValue(fp);
0370:            }
0371:
0372:            /**
0373:             * Process the attribute list for the element. This is a wrapper method that calls
0374:             * prepareAttributes (provided in the subclass) and traps any exceptions
0375:             */
0376:
0377:            public final void processAttributes() throws XPathException {
0378:                try {
0379:                    prepareAttributes();
0380:                } catch (XPathException err) {
0381:                    //            if (forwardsCompatibleModeIsEnabled()) {
0382:                    //                setValidationError(err, REPORT_IF_INSTANTIATED);
0383:                    //            } else {
0384:                    compileError(err);
0385:                    //            }
0386:                }
0387:            }
0388:
0389:            /**
0390:             * Check whether an unknown attribute is permitted.
0391:             *
0392:             * @param nc The name code of the attribute name
0393:             */
0394:
0395:            protected void checkUnknownAttribute(int nc) throws XPathException {
0396:
0397:                String attributeURI = getNamePool().getURI(nc);
0398:                String elementURI = getURI();
0399:                String clarkName = getNamePool().getClarkName(nc);
0400:
0401:                if (clarkName.equals(StandardNames.SAXON_EXPLAIN)) {
0402:                    explaining = "yes".equals(getAttributeValue(nc & 0xfffff));
0403:                }
0404:
0405:                if (forwardsCompatibleModeIsEnabled()) {
0406:                    // then unknown attributes are permitted and ignored
0407:                    return;
0408:                }
0409:
0410:                // allow xsl:extension-element-prefixes etc on an extension element
0411:
0412:                if (isInstruction()
0413:                        && clarkName.startsWith('{' + NamespaceConstant.XSLT)
0414:                        && !(elementURI.equals(NamespaceConstant.XSLT))
0415:                        && (clarkName.endsWith("}default-collation")
0416:                                || clarkName
0417:                                        .endsWith("}xpath-default-namespace")
0418:                                || clarkName
0419:                                        .endsWith("}extension-element-prefixes")
0420:                                || clarkName
0421:                                        .endsWith("}exclude-result-prefixes")
0422:                                || clarkName.endsWith("}version") || clarkName
0423:                                .endsWith("}use-when"))) {
0424:                    return;
0425:                }
0426:
0427:                // allow standard attributes on an XSLT element
0428:
0429:                if (elementURI.equals(NamespaceConstant.XSLT)
0430:                        && (clarkName == StandardNames.DEFAULT_COLLATION
0431:                                || clarkName == StandardNames.XPATH_DEFAULT_NAMESPACE
0432:                                || clarkName == StandardNames.EXTENSION_ELEMENT_PREFIXES
0433:                                || clarkName == StandardNames.EXCLUDE_RESULT_PREFIXES
0434:                                || clarkName == StandardNames.VERSION || clarkName == StandardNames.USE_WHEN)) {
0435:                    return;
0436:                }
0437:
0438:                if ("".equals(attributeURI)
0439:                        || NamespaceConstant.XSLT.equals(attributeURI)) {
0440:                    compileError("Attribute "
0441:                            + Err.wrap(getNamePool().getDisplayName(nc),
0442:                                    Err.ATTRIBUTE)
0443:                            + " is not allowed on element "
0444:                            + Err.wrap(getDisplayName(), Err.ELEMENT),
0445:                            "XTSE0010");
0446:                }
0447:            }
0448:
0449:            /**
0450:             * Set the attribute list for the element. This is called to process the attributes (note
0451:             * the distinction from processAttributes in the superclass).
0452:             * Must be supplied in a subclass
0453:             */
0454:
0455:            public abstract void prepareAttributes() throws XPathException;
0456:
0457:            /**
0458:             * Find the last child instruction of this instruction. Returns null if
0459:             * there are no child instructions, or if the last child is a text node.
0460:             */
0461:
0462:            protected StyleElement getLastChildInstruction() {
0463:                StyleElement last = null;
0464:                AxisIterator kids = iterateAxis(Axis.CHILD);
0465:                while (true) {
0466:                    NodeInfo child = (NodeInfo) kids.next();
0467:                    if (child == null) {
0468:                        return last;
0469:                    }
0470:                    if (child instanceof  StyleElement) {
0471:                        last = (StyleElement) child;
0472:                    } else {
0473:                        last = null;
0474:                    }
0475:                }
0476:            }
0477:
0478:            /**
0479:             * Make an expression in the context of this stylesheet element
0480:             */
0481:
0482:            public Expression makeExpression(String expression)
0483:                    throws XPathException {
0484:                try {
0485:                    Expression exp = ExpressionTool.make(expression,
0486:                            staticContext, 0, Token.EOF, getLineNumber());
0487:                    return exp;
0488:                } catch (XPathException err) {
0489:                    err.setLocator(this );
0490:                    compileError(err);
0491:                    //            if (!forwardsCompatibleModeIsEnabled()) {
0492:                    //                compileError(err);
0493:                    //            } else if (err.isTypeError()) {
0494:                    //                compileError(err);
0495:                    //            }
0496:                    ErrorExpression erexp = new ErrorExpression(err);
0497:                    erexp.setLocationId(allocateLocationId(getSystemId(),
0498:                            getLineNumber()));
0499:                    erexp.setParentExpression(this );
0500:                    return erexp;
0501:                }
0502:            }
0503:
0504:            /**
0505:             * Make a pattern in the context of this stylesheet element
0506:             */
0507:
0508:            public Pattern makePattern(String pattern) throws XPathException {
0509:                try {
0510:                    return Pattern.make(pattern, staticContext,
0511:                            getPrincipalStylesheet().getExecutable());
0512:                } catch (XPathException err) {
0513:                    //            if (forwardsCompatibleModeIsEnabled()) {
0514:                    //                compileWarning("Invalid pattern, ignored because in forwards-compatibility mode. " +
0515:                    //                        err.getMessage(), err.getErrorCodeLocalPart());
0516:                    //                return new NodeTestPattern(NoNodeTest.getInstance());
0517:                    //            } else {
0518:                    compileError(err);
0519:                    return new NodeTestPattern(AnyNodeTest.getInstance());
0520:                    //            }
0521:                }
0522:            }
0523:
0524:            /**
0525:             * Make an attribute value template in the context of this stylesheet element
0526:             */
0527:
0528:            public Expression makeAttributeValueTemplate(String expression)
0529:                    throws XPathException {
0530:                try {
0531:                    return AttributeValueTemplate.make(expression,
0532:                            getLineNumber(), staticContext);
0533:                } catch (XPathException err) {
0534:                    compileError(err);
0535:                    return new StringValue(expression);
0536:                }
0537:            }
0538:
0539:            /**
0540:             * Process an attribute whose value is a SequenceType
0541:             */
0542:
0543:            public SequenceType makeSequenceType(String sequenceType)
0544:                    throws XPathException {
0545:                getStaticContext();
0546:                try {
0547:                    ExpressionParser parser = new ExpressionParser();
0548:                    return parser
0549:                            .parseSequenceType(sequenceType, staticContext);
0550:                } catch (XPathException err) {
0551:                    compileError(err);
0552:                    // recovery path after reporting an error, e.g. undeclared namespace prefix
0553:                    return SequenceType.ANY_SEQUENCE;
0554:                }
0555:            }
0556:
0557:            /**
0558:             * Process the [xsl:]extension-element-prefixes attribute if there is one
0559:             *
0560:             * @param nc the Clark name  of the attribute required
0561:             */
0562:
0563:            protected void processExtensionElementAttribute(String nc)
0564:                    throws XPathException {
0565:                String ext = getAttributeValue(nc);
0566:                if (ext != null) {
0567:                    // go round twice, once to count the values and next to add them to the array
0568:                    int count = 0;
0569:                    StringTokenizer st1 = new StringTokenizer(ext);
0570:                    while (st1.hasMoreTokens()) {
0571:                        st1.nextToken();
0572:                        count++;
0573:                    }
0574:                    extensionNamespaces = new short[count];
0575:                    count = 0;
0576:                    StringTokenizer st2 = new StringTokenizer(ext);
0577:                    while (st2.hasMoreTokens()) {
0578:                        String s = st2.nextToken();
0579:                        if ("#default".equals(s)) {
0580:                            s = "";
0581:                        }
0582:                        try {
0583:                            short uriCode = getURICodeForPrefix(s);
0584:                            extensionNamespaces[count++] = uriCode;
0585:                        } catch (NamespaceException err) {
0586:                            extensionNamespaces = null;
0587:                            compileError(err.getMessage(), "XT0280");
0588:                        }
0589:                    }
0590:                }
0591:            }
0592:
0593:            /**
0594:             * Process the [xsl:]exclude-result-prefixes attribute if there is one
0595:             *
0596:             * @param nc the Clark name of the attribute required
0597:             */
0598:
0599:            protected void processExcludedNamespaces(String nc)
0600:                    throws XPathException {
0601:                String ext = getAttributeValue(nc);
0602:                if (ext != null) {
0603:                    if ("#all".equals(ext.trim())) {
0604:                        int[] codes = getInScopeNamespaceCodes();
0605:                        excludedNamespaces = new short[codes.length];
0606:                        for (int i = 0; i < codes.length; i++) {
0607:                            excludedNamespaces[i] = (short) (codes[i] & 0xffff);
0608:                        }
0609:                    } else {
0610:                        // go round twice, once to count the values and next to add them to the array
0611:                        int count = 0;
0612:                        StringTokenizer st1 = new StringTokenizer(ext);
0613:                        while (st1.hasMoreTokens()) {
0614:                            st1.nextToken();
0615:                            count++;
0616:                        }
0617:                        excludedNamespaces = new short[count];
0618:                        count = 0;
0619:                        StringTokenizer st2 = new StringTokenizer(ext);
0620:                        while (st2.hasMoreTokens()) {
0621:                            String s = st2.nextToken();
0622:                            if ("#default".equals(s)) {
0623:                                s = "";
0624:                            } else if ("#all".equals(s)) {
0625:                                compileError(
0626:                                        "In exclude-result-prefixes, cannot mix #all with other values",
0627:                                        "XTSE0020");
0628:                            }
0629:                            try {
0630:                                short uriCode = getURICodeForPrefix(s);
0631:                                excludedNamespaces[count++] = uriCode;
0632:                            } catch (NamespaceException err) {
0633:                                excludedNamespaces = null;
0634:                                compileError(err.getMessage(), "XTSE0280");
0635:                            }
0636:                        }
0637:                    }
0638:                }
0639:            }
0640:
0641:            /**
0642:             * Process the [xsl:]version attribute if there is one
0643:             *
0644:             * @param nc the Clark name of the attribute required
0645:             */
0646:
0647:            protected void processVersionAttribute(String nc)
0648:                    throws XPathException {
0649:                String v = getAttributeValue(nc);
0650:                if (v != null) {
0651:                    AtomicValue val = DecimalValue.makeDecimalValue(v, true);
0652:                    if (val instanceof  ValidationErrorValue) {
0653:                        compileError("The version attribute must be a decimal literal");
0654:                    }
0655:                    version = ((DecimalValue) val).getValue();
0656:                }
0657:            }
0658:
0659:            /**
0660:             * Get the numeric value of the version number on this element,
0661:             * or inherited from its ancestors
0662:             */
0663:
0664:            public BigDecimal getVersion() {
0665:                if (version == null) {
0666:                    NodeInfo node = getParent();
0667:                    if (node instanceof  StyleElement) {
0668:                        version = ((StyleElement) node).getVersion();
0669:                    } else {
0670:                        version = new BigDecimal("2.0"); // defensive programming
0671:                    }
0672:                }
0673:                return version;
0674:            }
0675:
0676:            /**
0677:             * Determine whether forwards-compatible mode is enabled for this element
0678:             */
0679:
0680:            public boolean forwardsCompatibleModeIsEnabled() {
0681:                return getVersion().compareTo(BigDecimal.valueOf(2)) > 0;
0682:            }
0683:
0684:            /**
0685:             * Determine whether backwards-compatible mode is enabled for this element
0686:             */
0687:
0688:            public boolean backwardsCompatibleModeIsEnabled() {
0689:                return getVersion().compareTo(BigDecimal.valueOf(2)) < 0;
0690:            }
0691:
0692:            /**
0693:             * Process the [xsl:]default-xpath-namespace attribute if there is one
0694:             *
0695:             * @param nc the Clark name of the attribute required
0696:             */
0697:
0698:            protected void processDefaultCollationAttribute(String nc)
0699:                    throws XPathException {
0700:                String v = getAttributeValue(nc);
0701:                if (v != null) {
0702:                    StringTokenizer st = new StringTokenizer(v);
0703:                    while (st.hasMoreTokens()) {
0704:                        String uri = st.nextToken();
0705:                        if (uri
0706:                                .equals(NamespaceConstant.CODEPOINT_COLLATION_URI)) {
0707:                            defaultCollationName = uri;
0708:                            return;
0709:                        } else if (uri.startsWith("http://saxon.sf.net/")) {
0710:                            defaultCollationName = uri;
0711:                            return;
0712:                        } else {
0713:                            URI collationURI;
0714:                            try {
0715:                                collationURI = new URI(uri);
0716:                                if (!collationURI.isAbsolute()) {
0717:                                    URI base = new URI(getBaseURI());
0718:                                    collationURI = base.resolve(collationURI);
0719:                                    uri = collationURI.toString();
0720:                                }
0721:                            } catch (URISyntaxException err) {
0722:                                compileError("default collation '" + uri
0723:                                        + "' is not a valid URI");
0724:                                uri = NamespaceConstant.CODEPOINT_COLLATION_URI;
0725:                            }
0726:
0727:                            if (uri.startsWith("http://saxon.sf.net/")) {
0728:                                defaultCollationName = uri;
0729:                                return;
0730:                            }
0731:
0732:                            if (getPrincipalStylesheet().getExecutable()
0733:                                    .getNamedCollation(uri) != null) {
0734:                                defaultCollationName = uri;
0735:                                return;
0736:                            }
0737:                        }
0738:                        // if not recognized, try the next URI in order
0739:                    }
0740:                    compileError(
0741:                            "No recognized collation URI found in default-collation attribute",
0742:                            "XTSE0125");
0743:                }
0744:            }
0745:
0746:            /**
0747:             * Get the default collation for this element
0748:             */
0749:
0750:            protected String getDefaultCollationName() {
0751:                StyleElement e = this ;
0752:                while (true) {
0753:                    if (e.defaultCollationName != null) {
0754:                        return e.defaultCollationName;
0755:                    }
0756:                    NodeInfo p = e.getParent();
0757:                    if (!(p instanceof  StyleElement)) {
0758:                        break;
0759:                    }
0760:                    e = (StyleElement) p;
0761:                }
0762:                return getPrincipalStylesheet().getDefaultCollationName();
0763:            }
0764:
0765:            /**
0766:             * Check whether a particular extension element namespace is defined on this node.
0767:             * This checks this node only, not the ancestor nodes.
0768:             * The implementation checks whether the prefix is included in the
0769:             * [xsl:]extension-element-prefixes attribute.
0770:             *
0771:             * @param uriCode the namespace URI code being tested
0772:             */
0773:
0774:            protected boolean definesExtensionElement(short uriCode) {
0775:                if (extensionNamespaces == null) {
0776:                    return false;
0777:                }
0778:                for (int i = 0; i < extensionNamespaces.length; i++) {
0779:                    if (extensionNamespaces[i] == uriCode) {
0780:                        return true;
0781:                    }
0782:                }
0783:                return false;
0784:            }
0785:
0786:            /**
0787:             * Check whether a namespace uri defines an extension element. This checks whether the
0788:             * namespace is defined as an extension namespace on this or any ancestor node.
0789:             *
0790:             * @param uriCode the namespace URI code being tested
0791:             */
0792:
0793:            public boolean isExtensionNamespace(short uriCode) {
0794:                NodeInfo anc = this ;
0795:                while (anc instanceof  StyleElement) {
0796:                    if (((StyleElement) anc).definesExtensionElement(uriCode)) {
0797:                        return true;
0798:                    }
0799:                    anc = anc.getParent();
0800:                }
0801:                return false;
0802:            }
0803:
0804:            /**
0805:             * Check whether this node excludes a particular namespace from the result.
0806:             * This method checks this node only, not the ancestor nodes.
0807:             *
0808:             * @param uriCode the code of the namespace URI being tested
0809:             */
0810:
0811:            protected boolean definesExcludedNamespace(short uriCode) {
0812:                if (excludedNamespaces == null) {
0813:                    return false;
0814:                }
0815:                for (int i = 0; i < excludedNamespaces.length; i++) {
0816:                    if (excludedNamespaces[i] == uriCode) {
0817:                        return true;
0818:                    }
0819:                }
0820:                return false;
0821:            }
0822:
0823:            /**
0824:             * Check whether a namespace uri defines an namespace excluded from the result.
0825:             * This checks whether the namespace is defined as an excluded namespace on this
0826:             * or any ancestor node.
0827:             *
0828:             * @param uriCode the code of the namespace URI being tested
0829:             */
0830:
0831:            public boolean isExcludedNamespace(short uriCode) {
0832:                if (uriCode == NamespaceConstant.XSLT_CODE) {
0833:                    return true;
0834:                }
0835:                if (isExtensionNamespace(uriCode)) {
0836:                    return true;
0837:                }
0838:                NodeInfo anc = this ;
0839:                while (anc instanceof  StyleElement) {
0840:                    if (((StyleElement) anc).definesExcludedNamespace(uriCode)) {
0841:                        return true;
0842:                    }
0843:                    anc = anc.getParent();
0844:                }
0845:                return false;
0846:            }
0847:
0848:            /**
0849:             * Process the [xsl:]default-xpath-namespace attribute if there is one
0850:             *
0851:             * @param nc the Clark name of the attribute required
0852:             */
0853:
0854:            protected void processDefaultXPathNamespaceAttribute(String nc) {
0855:                String v = getAttributeValue(nc);
0856:                if (v != null) {
0857:                    defaultXPathNamespace = v;
0858:                }
0859:            }
0860:
0861:            /**
0862:             * Get the default XPath namespace code applicable to this element
0863:             */
0864:
0865:            protected short getDefaultXPathNamespace() {
0866:                NodeInfo anc = this ;
0867:                while (anc instanceof  StyleElement) {
0868:                    String x = ((StyleElement) anc).defaultXPathNamespace;
0869:                    if (x != null) {
0870:                        return getTargetNamePool().allocateCodeForURI(x);
0871:                    }
0872:                    anc = anc.getParent();
0873:                }
0874:                return NamespaceConstant.NULL_CODE;
0875:                // indicates that the default namespace is the null namespace
0876:            }
0877:
0878:            /**
0879:             * Get the Schema type definition for a type named in the stylesheet (in a
0880:             * "type" attribute).
0881:             *
0882:             * @throws XPathException if the type is not declared in an
0883:             *                        imported schema, or is not a built-in type
0884:             */
0885:
0886:            public SchemaType getSchemaType(String typeAtt)
0887:                    throws XPathException {
0888:                try {
0889:                    String[] parts = getConfiguration().getNameChecker()
0890:                            .getQNameParts(typeAtt);
0891:                    String lname = parts[1];
0892:                    String uri;
0893:                    if ("".equals(parts[0])) {
0894:                        // Name is unprefixed: use the default-xpath-namespace
0895:                        short uricode = getDefaultXPathNamespace();
0896:                        uri = getTargetNamePool().getURIFromURICode(uricode);
0897:                        nameCode = getTargetNamePool().allocate(parts[0],
0898:                                uricode, lname);
0899:                    } else {
0900:                        uri = getURIForPrefix(parts[0], false);
0901:                        if (uri == null) {
0902:                            compileError(
0903:                                    "Namespace prefix for type annotation is undeclared",
0904:                                    "XTSE0280");
0905:                            return null;
0906:                        }
0907:                    }
0908:                    int nameCode = getTargetNamePool().allocate(parts[0], uri,
0909:                            lname);
0910:                    if (uri.equals(NamespaceConstant.SCHEMA)) {
0911:                        SchemaType t = BuiltInSchemaFactory
0912:                                .getSchemaType(StandardNames.getFingerprint(
0913:                                        uri, lname));
0914:                        if (t == null) {
0915:                            compileError("Unknown built-in type " + typeAtt);
0916:                            return null;
0917:                        }
0918:                        return t;
0919:                    } else if (NamespaceConstant.isXDTNamespace(uri)) {
0920:                        ItemType t = Type.getBuiltInItemType(
0921:                                NamespaceConstant.XDT, lname);
0922:                        if (t == null) {
0923:                            if ("untyped".equals(lname)) {
0924:                                compileError("Cannot validate a node as 'untyped'");
0925:                            } else {
0926:                                compileError("Unknown built-in type " + typeAtt);
0927:                            }
0928:                        }
0929:                        return (BuiltInAtomicType) t;
0930:                    }
0931:
0932:                    // not a built-in type: look in the imported schemas
0933:
0934:                    if (!getPrincipalStylesheet().isImportedSchema(uri)) {
0935:                        compileError("There is no imported schema for the namespace of type "
0936:                                + typeAtt);
0937:                        return null;
0938:                    }
0939:                    SchemaType stype = getConfiguration().getSchemaType(
0940:                            nameCode & 0xfffff);
0941:                    if (stype == null) {
0942:                        compileError("There is no type named " + typeAtt
0943:                                + " in an imported schema");
0944:                    }
0945:                    return stype;
0946:
0947:                } catch (QNameException err) {
0948:                    compileError("Invalid type name. " + err.getMessage());
0949:                }
0950:                return null;
0951:            }
0952:
0953:            /**
0954:             * Get the type annotation to use for a given schema type
0955:             */
0956:
0957:            public int getTypeAnnotation(SchemaType schemaType) {
0958:                if (schemaType != null) {
0959:                    return schemaType.getFingerprint();
0960:                } else {
0961:                    return -1;
0962:                }
0963:            }
0964:
0965:            /**
0966:             * Check that the stylesheet element is valid. This is called once for each element, after
0967:             * the entire tree has been built. As well as validation, it can perform first-time
0968:             * initialisation. The default implementation does nothing; it is normally overriden
0969:             * in subclasses.
0970:             */
0971:
0972:            public void validate() throws XPathException {
0973:            }
0974:
0975:            /**
0976:             * Hook to allow additional validation of a parent element immediately after its
0977:             * children have been validated.
0978:             */
0979:
0980:            public void postValidate() throws XPathException {
0981:            }
0982:
0983:            /**
0984:             * Type-check an expression. This is called to check each expression while the containing
0985:             * instruction is being validated. It is not just a static type-check, it also adds code
0986:             * to perform any necessary run-time type checking and/or conversion.
0987:             */
0988:
0989:            // Note: the typeCheck() call is done at the level of individual path expression; the optimize() call is done
0990:            // for a template or function as a whole. We can't do it all at the function/template level because
0991:            // the static context (e.g. namespaces) changes from one XPath expression to another.
0992:            public Expression typeCheck(String name, Expression exp)
0993:                    throws XPathException {
0994:
0995:                if (exp == null) {
0996:                    return null;
0997:                }
0998:
0999:                //ExpressionTool.makeParentReferences(exp);
1000:                if (exp instanceof  ComputedExpression) {
1001:                    ((ComputedExpression) exp).setParentExpression(this );
1002:                    // temporary, until the instruction is compiled
1003:                }
1004:
1005:                try {
1006:                    exp = exp.typeCheck(staticContext, Type.ITEM_TYPE);
1007:                    exp = ExpressionTool.resolveCallsToCurrentFunction(exp,
1008:                            getConfiguration());
1009:                    //            if (explaining) {
1010:                    //                System.err.println("Attribute '" + name + "' of element '" + getDisplayName() + "' at line " + getLineNumber() + ':');
1011:                    //                System.err.println("Static type: " +
1012:                    //                        SequenceType.makeSequenceType(exp.getItemType(), exp.getCardinality()));
1013:                    //                System.err.println("Optimized expression tree:");
1014:                    //                exp.display(10, getNamePool(), System.err);
1015:                    //            }
1016:                    if (getConfiguration().getTraceListener() != null) {
1017:                        InstructionDetails details = new InstructionDetails();
1018:                        details.setConstructType(Location.XPATH_IN_XSLT);
1019:                        details.setLineNumber(getLineNumber());
1020:                        details.setSystemId(getSystemId());
1021:                        details.setProperty("attribute-name", name);
1022:                        TraceWrapper trace = new TraceInstruction(exp, details);
1023:                        trace.setLocationId(allocateLocationId(getSystemId(),
1024:                                getLineNumber()));
1025:                        trace.setParentExpression(this );
1026:                        exp = trace;
1027:                    }
1028:                    return exp;
1029:                } catch (DynamicError err) {
1030:                    // we can't report a dynamic error such as divide by zero unless the expression
1031:                    // is actually executed.
1032:                    if (err.isTypeError()) {
1033:                        compileError(err);
1034:                        return exp;
1035:                    } else {
1036:                        ErrorExpression erexp = new ErrorExpression(err);
1037:                        erexp.setLocationId(allocateLocationId(getSystemId(),
1038:                                getLineNumber()));
1039:                        return erexp;
1040:                    }
1041:                } catch (XPathException err) {
1042:                    compileError(err);
1043:                    ErrorExpression erexp = new ErrorExpression(err);
1044:                    erexp.setLocationId(allocateLocationId(getSystemId(),
1045:                            getLineNumber()));
1046:                    return erexp;
1047:                }
1048:            }
1049:
1050:            /**
1051:             * Allocate slots in the local stack frame to range variables used in an XPath expression
1052:             *
1053:             * @param exp the XPath expression for which slots are to be allocated
1054:             */
1055:
1056:            public void allocateSlots(Expression exp) {
1057:                SlotManager slotManager = getContainingSlotManager();
1058:                if (slotManager == null) {
1059:                    throw new AssertionError(
1060:                            "Slot manager has not been allocated");
1061:                    // previous code: ExpressionTool.allocateSlots(exp, 0, null);
1062:                } else {
1063:                    int firstSlot = slotManager.getNumberOfVariables();
1064:                    int highWater = ExpressionTool.allocateSlots(exp,
1065:                            firstSlot, slotManager);
1066:                    if (highWater > firstSlot) {
1067:                        slotManager.setNumberOfVariables(highWater);
1068:                        // This algorithm is not very efficient because it never reuses
1069:                        // a slot when a variable goes out of scope. But at least it is safe.
1070:                        // Note that range variables within XPath expressions need to maintain
1071:                        // a slot until the instruction they are part of finishes, e.g. in
1072:                        // xsl:for-each.
1073:                    }
1074:                }
1075:            }
1076:
1077:            /**
1078:             * Type-check a pattern. This is called to check each pattern while the containing
1079:             * instruction is being validated. It is not just a static type-check, it also adds code
1080:             * to perform any necessary run-time type checking and/or conversion.
1081:             */
1082:
1083:            public Pattern typeCheck(String name, Pattern pattern)
1084:                    throws XPathException {
1085:                if (pattern == null) {
1086:                    return null;
1087:                }
1088:                try {
1089:                    pattern = pattern.analyze(staticContext, Type.NODE_TYPE);
1090:                    boolean usesCurrent = false;
1091:                    int current = getNamePool().allocate("",
1092:                            NamespaceConstant.FN, "current")
1093:                            & NamePool.FP_MASK;
1094:                    if (pattern instanceof  LocationPathPattern) {
1095:                        Iterator sub = pattern.iterateSubExpressions();
1096:                        while (sub.hasNext()) {
1097:                            Expression filter = (Expression) sub.next();
1098:                            if (ExpressionTool.callsFunction(filter, current)) {
1099:                                usesCurrent = true;
1100:                                break;
1101:                            }
1102:                        }
1103:                        if (usesCurrent) {
1104:                            Configuration config = getConfiguration();
1105:                            RangeVariableDeclaration decl = new RangeVariableDeclaration();
1106:                            decl.setNameCode(config.getNamePool().allocate(
1107:                                    "saxon", NamespaceConstant.SAXON,
1108:                                    "current" + hashCode()));
1109:                            decl.setVariableName("saxon:current");
1110:                            decl.setRequiredType(SequenceType.SINGLE_ITEM);
1111:                            LetExpression let = new LetExpression();
1112:                            let.setSequence(new ContextItemExpression());
1113:                            let.setVariableDeclaration(decl);
1114:                            let.setAction(EmptySequence.getInstance());
1115:                            PromotionOffer offer = new PromotionOffer(config
1116:                                    .getOptimizer());
1117:                            offer.action = PromotionOffer.REPLACE_CURRENT;
1118:                            offer.containingExpression = let;
1119:                            ((LocationPathPattern) pattern).resolveCurrent(let,
1120:                                    offer);
1121:                            allocateSlots(let);
1122:                            decl.fixupReferences(let);
1123:                        }
1124:                    }
1125:                    return pattern;
1126:                } catch (DynamicError err) {
1127:                    // we can't report a dynamic error such as divide by zero unless the pattern
1128:                    // is actually executed. We don't have an error pattern available, so we
1129:                    // construct one
1130:                    LocationPathPattern errpat = new LocationPathPattern();
1131:                    errpat.addFilter(new ErrorExpression(err));
1132:                    return errpat;
1133:                } catch (XPathException err) {
1134:                    StaticError e2 = new StaticError("Error in " + name
1135:                            + " pattern", err);
1136:                    e2.setLocator(err.getLocator());
1137:                    e2.setErrorCode(err.getErrorCodeLocalPart());
1138:                    throw e2;
1139:                }
1140:            }
1141:
1142:            /**
1143:             * Fix up references from XPath expressions. Overridden for function declarations
1144:             * and variable declarations
1145:             */
1146:
1147:            public void fixupReferences() throws XPathException {
1148:                AxisIterator kids = iterateAxis(Axis.CHILD);
1149:                while (true) {
1150:                    NodeInfo child = (NodeInfo) kids.next();
1151:                    if (child == null) {
1152:                        return;
1153:                    }
1154:                    if (child instanceof  StyleElement) {
1155:                        ((StyleElement) child).fixupReferences();
1156:                    }
1157:                }
1158:            }
1159:
1160:            /**
1161:             * Get the SlotManager for the containing Procedure definition
1162:             *
1163:             * @return the SlotManager associated with the containing Function, Template, etc,
1164:             *         or null if there is no such containing Function, Template etc.
1165:             */
1166:
1167:            public SlotManager getContainingSlotManager() {
1168:                NodeInfo node = this ;
1169:                while (true) {
1170:                    NodeInfo next = node.getParent();
1171:                    if (next instanceof  XSLStylesheet) {
1172:                        if (node instanceof  StylesheetProcedure) {
1173:                            return ((StylesheetProcedure) node)
1174:                                    .getSlotManager();
1175:                        } else {
1176:                            return null;
1177:                        }
1178:                    }
1179:                    node = next;
1180:                }
1181:            }
1182:
1183:            /**
1184:             * Recursive walk through the stylesheet to validate all nodes
1185:             */
1186:
1187:            public void validateSubtree() throws XPathException {
1188:                if (validationError != null) {
1189:                    if (reportingCircumstances == REPORT_ALWAYS) {
1190:                        compileError(validationError);
1191:                    } else if (reportingCircumstances == REPORT_UNLESS_FORWARDS_COMPATIBLE
1192:                            && !forwardsCompatibleModeIsEnabled()) {
1193:                        compileError(validationError);
1194:                    } else if (reportingCircumstances == REPORT_UNLESS_FALLBACK_AVAILABLE) {
1195:                        boolean hasFallback = false;
1196:                        AxisIterator kids = iterateAxis(Axis.CHILD);
1197:                        while (true) {
1198:                            NodeInfo child = (NodeInfo) kids.next();
1199:                            if (child == null) {
1200:                                break;
1201:                            }
1202:                            if (child instanceof  XSLFallback) {
1203:                                hasFallback = true;
1204:                            }
1205:                        }
1206:                        if (!hasFallback) {
1207:                            compileError(validationError);
1208:                        }
1209:                    }
1210:                }
1211:                try {
1212:                    validate();
1213:                } catch (XPathException err) {
1214:                    //            if (forwardsCompatibleModeIsEnabled()) {
1215:                    //                setValidationError(err, REPORT_IF_INSTANTIATED);
1216:                    //            } else {
1217:                    compileError(err);
1218:                    //            }
1219:                }
1220:
1221:                validateChildren();
1222:                postValidate();
1223:            }
1224:
1225:            /**
1226:             * Validate the children of this node, recursively. Overridden for top-level
1227:             * data elements.
1228:             */
1229:
1230:            protected void validateChildren() throws XPathException {
1231:                boolean containsInstructions = mayContainSequenceConstructor();
1232:                AxisIterator kids = iterateAxis(Axis.CHILD);
1233:                StyleElement lastChild = null;
1234:                while (true) {
1235:                    NodeInfo child = (NodeInfo) kids.next();
1236:                    if (child == null) {
1237:                        break;
1238:                    }
1239:                    if (child instanceof  StyleElement) {
1240:                        if (containsInstructions
1241:                                && !((StyleElement) child).isInstruction()
1242:                                && !isPermittedChild((StyleElement) child)) {
1243:                            ((StyleElement) child).compileError("An "
1244:                                    + getDisplayName()
1245:                                    + " element must not contain an "
1246:                                    + child.getDisplayName() + " element",
1247:                                    "XTSE0010");
1248:                        }
1249:                        ((StyleElement) child).validateSubtree();
1250:                        lastChild = (StyleElement) child;
1251:                    }
1252:                }
1253:                if (lastChild instanceof  XSLVariable
1254:                        && !(this  instanceof  XSLStylesheet)) {
1255:                    lastChild
1256:                            .compileWarning(
1257:                                    "A variable with no following sibling instructions has no effect",
1258:                                    SaxonErrorCode.SXWN9001);
1259:                }
1260:            }
1261:
1262:            /**
1263:             * Specify that certain children are permitted for this element
1264:             */
1265:
1266:            protected boolean isPermittedChild(StyleElement child) {
1267:                return false;
1268:            }
1269:
1270:            /**
1271:             * Get the principal XSLStylesheet node. This gets the principal style sheet, i.e. the
1272:             * one originally loaded, that forms the root of the import/include tree
1273:             */
1274:
1275:            protected XSLStylesheet getPrincipalStylesheet() {
1276:                XSLStylesheet sheet = getContainingStylesheet();
1277:                while (true) {
1278:                    XSLStylesheet next = sheet.getImporter();
1279:                    if (next == null) {
1280:                        return sheet;
1281:                    }
1282:                    sheet = next;
1283:                }
1284:            }
1285:
1286:            /**
1287:             * Get the PreparedStylesheet object.
1288:             *
1289:             * @return the PreparedStylesheet to which this stylesheet element belongs
1290:             */
1291:
1292:            public PreparedStylesheet getPreparedStylesheet() {
1293:                return getPrincipalStylesheet().getPreparedStylesheet();
1294:            }
1295:
1296:            /**
1297:             * Check that the stylesheet element is within a sequence constructor
1298:             *
1299:             * @throws XPathException if not within a sequence constructor
1300:             */
1301:
1302:            public void checkWithinTemplate() throws XPathException {
1303:                //        Parent elements now check their children, not the other way around
1304:                //        StyleElement parent = (StyleElement)getParent();
1305:                //        if (!parent.mayContainSequenceConstructor()) {
1306:                //            compileError("Element must be used only within a sequence constructor", "XT0010");
1307:                //        }
1308:            }
1309:
1310:            /**
1311:             * Check that among the children of this element, any xsl:sort elements precede any other elements
1312:             *
1313:             * @param sortRequired true if there must be at least one xsl:sort element
1314:             * @throws XPathException if invalid
1315:             */
1316:
1317:            protected void checkSortComesFirst(boolean sortRequired)
1318:                    throws XPathException {
1319:                AxisIterator kids = iterateAxis(Axis.CHILD);
1320:                boolean sortFound = false;
1321:                boolean nonSortFound = false;
1322:                while (true) {
1323:                    NodeInfo child = (NodeInfo) kids.next();
1324:                    if (child == null) {
1325:                        break;
1326:                    }
1327:                    if (child instanceof  XSLSort) {
1328:                        if (nonSortFound) {
1329:                            ((XSLSort) child)
1330:                                    .compileError(
1331:                                            "Within "
1332:                                                    + getDisplayName()
1333:                                                    + ", xsl:sort elements must come before other instructions",
1334:                                            "XTSE0010");
1335:                        }
1336:                        sortFound = true;
1337:                    } else if (child.getNodeKind() == Type.TEXT) {
1338:                        // with xml:space=preserve, white space nodes may still be there
1339:                        if (!Whitespace.isWhite(child.getStringValueCS())) {
1340:                            nonSortFound = true;
1341:                        }
1342:                    } else {
1343:                        nonSortFound = true;
1344:                    }
1345:                }
1346:                if (sortRequired && !sortFound) {
1347:                    compileError(getDisplayName()
1348:                            + " must have at least one xsl:sort child",
1349:                            "XTSE0010");
1350:                }
1351:            }
1352:
1353:            /**
1354:             * Convenience method to check that the stylesheet element is at the top level
1355:             *
1356:             * @throws XPathException if not at top level
1357:             */
1358:
1359:            public void checkTopLevel(String errorCode) throws XPathException {
1360:                if (errorCode == null) {
1361:                    errorCode = "XTSE0010";
1362:                }
1363:                if (!(getParent() instanceof  XSLStylesheet)) {
1364:                    compileError(
1365:                            "Element must be used only at top level of stylesheet",
1366:                            errorCode);
1367:                }
1368:            }
1369:
1370:            /**
1371:             * Convenience method to check that the stylesheet element is empty
1372:             *
1373:             * @throws XPathException if it is not empty
1374:             */
1375:
1376:            public void checkEmpty() throws XPathException {
1377:                if (hasChildNodes()) {
1378:                    compileError("Element must be empty", "XTSE0260");
1379:                }
1380:            }
1381:
1382:            /**
1383:             * Convenience method to report the absence of a mandatory attribute
1384:             *
1385:             * @throws XPathException if the attribute is missing
1386:             */
1387:
1388:            public void reportAbsence(String attribute) throws XPathException {
1389:                compileError("Element must have a \"" + attribute
1390:                        + "\" attribute", "XTSE0010");
1391:            }
1392:
1393:            /**
1394:             * Compile the instruction on the stylesheet tree into an executable instruction
1395:             * for use at run-time.
1396:             *
1397:             * @return either a ComputedExpression, or null. The value null is returned when compiling an instruction
1398:             *         that returns a no-op, or when compiling a top-level object such as an xsl:template that compiles
1399:             *         into something other than an instruction.
1400:             */
1401:
1402:            public abstract Expression compile(Executable exec)
1403:                    throws XPathException;
1404:
1405:            /**
1406:             * Compile the children of this instruction on the stylesheet tree, adding the
1407:             * subordinate instructions to the parent instruction on the execution tree.
1408:             *
1409:             * @return the array of children
1410:             */
1411:
1412:            //    public Expression compileSequenceConstructor(Executable exec, AxisIterator iter, boolean includeParams)
1413:            //            throws XPathException {
1414:            //        // TODO: the use of recursion in this method imposes a limit on the number of sibling instructions,
1415:            //        // which can prove a problem with software-generated stylesheets.
1416:            //        int lineNumber = getLineNumber();
1417:            //        NodeInfo node = (NodeInfo)iter.next();
1418:            //        if (node == null) {
1419:            //            return null;
1420:            //        }
1421:            //        if (node instanceof StyleElement) {
1422:            //            lineNumber = node.getLineNumber();  // this is to get a line number for the next text node
1423:            //        }
1424:            //        if (node.getNodeKind() == Type.TEXT) {
1425:            //            // handle literal text nodes by generating an xsl:value-of instruction
1426:            //            ValueOf text = new ValueOf(StringValue.makeStringValue(node.getStringValueCS()), false, false);
1427:            //            text.setLocationId(allocateLocationId(getSystemId(), lineNumber));
1428:            //            Expression tail = compileSequenceConstructor(exec, iter, includeParams);
1429:            //            if (tail == null) {
1430:            //                return text;
1431:            //            } else {
1432:            //                ComputedExpression e = (ComputedExpression)Block.makeBlock(text, tail);
1433:            //                e.setLocationId(allocateLocationId(getSystemId(), getLineNumber()));
1434:            //                return e;
1435:            //            }
1436:            //
1437:            //        } else if (node instanceof XSLVariable) {
1438:            //            Expression var = ((XSLVariable)node).compileLocalVariable(exec);
1439:            //            if (var == null) {
1440:            //                // this can happen if the variable declaration is redundant
1441:            //                return compileSequenceConstructor(exec, iter, includeParams);
1442:            //            } else {
1443:            //                LocalVariable lv = (LocalVariable)var;
1444:            //                Expression tail = compileSequenceConstructor(exec, iter, includeParams);
1445:            //                if (tail == null) {
1446:            //                    // this doesn't happen, because if there are no instructions following
1447:            //                    // a variable, we'll have taken the var==null path above
1448:            //                    return null;
1449:            //                } else {
1450:            //                    LetExpression let = new LetExpression();
1451:            //                    RangeVariableDeclaration rvar = new RangeVariableDeclaration();
1452:            //                    rvar.setRequiredType(lv.getRequiredType());
1453:            //                    rvar.setNameCode(lv.getNameCode());
1454:            //                    rvar.setVariableName(lv.getVariableName());
1455:            //                    rvar.setReferenceList(((XSLVariable)node).getReferenceList());
1456:            //                    let.setVariableDeclaration(rvar);
1457:            //                    let.setSequence(lv.getSelectExpression());
1458:            //                    //let.setSlotNumber(lv.getSlotNumber());
1459:            //                    let.setAction(tail);
1460:            //                    ((XSLVariable)node).fixupBinding(let);
1461:            //                    let.setLocationId(allocateLocationId(node.getSystemId(), node.getLineNumber()));
1462:            //                    if (getConfiguration().getTraceListener() != null) {
1463:            //                        TraceExpression t = new TraceExpression(let);
1464:            //                        t.setConstructType(Location.LET_EXPRESSION);
1465:            //                        t.setObjectNameCode(lv.getNameCode());
1466:            //                        t.setSystemId(node.getSystemId());
1467:            //                        t.setLineNumber(node.getLineNumber());
1468:            //                        return t;
1469:            //                    }
1470:            //                    return let;
1471:            //                }
1472:            //            }
1473:            //
1474:            //
1475:            //        } else if (node instanceof StyleElement) {
1476:            //            StyleElement snode = (StyleElement)node;
1477:            //            Expression child;
1478:            //            if (snode.validationError != null) {
1479:            //                child = fallbackProcessing(exec, snode);
1480:            //
1481:            //            } else {
1482:            //                child = snode.compile(exec);
1483:            //                if (child instanceof ComputedExpression) {
1484:            //                    ComputedExpression childi = (ComputedExpression)child;
1485:            //                    childi.setLocationId(allocateLocationId(getSystemId(), snode.getLineNumber()));
1486:            //                }
1487:            //                if (child != null) {
1488:            //                    if (includeParams || !(node instanceof XSLParam)) {
1489:            //                        if (getConfiguration().getTraceListener() != null) {
1490:            //                            TraceWrapper trace = makeTraceInstruction(snode, child);
1491:            //                            child = trace;
1492:            //                        }
1493:            //                    }
1494:            //                }
1495:            //            }
1496:            //            Expression tail = compileSequenceConstructor(exec, iter, includeParams);
1497:            //            if (tail == null) {
1498:            //                return child;
1499:            //            } else if (child == null) {
1500:            //                return tail;
1501:            //            } else {
1502:            //                ComputedExpression e = (ComputedExpression)Block.makeBlock(child, tail);
1503:            //                e.setLocationId(allocateLocationId(getSystemId(), getLineNumber()));
1504:            //                return e;
1505:            //            }
1506:            //        }
1507:            //        return null;
1508:            //    }
1509:            /**
1510:             * Compile the children of this instruction on the stylesheet tree, adding the
1511:             * subordinate instructions to the parent instruction on the execution tree.
1512:             *
1513:             * @return the array of children
1514:             */
1515:
1516:            public Expression compileSequenceConstructor(Executable exec,
1517:                    AxisIterator iter, boolean includeParams)
1518:                    throws XPathException {
1519:
1520:                Expression result = EmptySequence.getInstance();
1521:                int locationId = allocateLocationId(getSystemId(),
1522:                        getLineNumber());
1523:                while (true) {
1524:                    int lineNumber = getLineNumber();
1525:                    NodeInfo node = (NodeInfo) iter.next();
1526:                    if (node == null) {
1527:                        return result;
1528:                    }
1529:                    if (node instanceof  StyleElement) {
1530:                        lineNumber = node.getLineNumber(); // this is to get a line number for the next text node
1531:                    }
1532:                    if (node.getNodeKind() == Type.TEXT) {
1533:                        // handle literal text nodes by generating an xsl:value-of instruction
1534:                        ValueOf text = new ValueOf(StringValue
1535:                                .makeStringValue(node.getStringValueCS()),
1536:                                false, false);
1537:                        text.setLocationId(allocateLocationId(getSystemId(),
1538:                                lineNumber));
1539:                        result = Block.makeBlock(result, text);
1540:                        if (result instanceof  ComputedExpression) {
1541:                            ((ComputedExpression) result)
1542:                                    .setLocationId(locationId);
1543:                        }
1544:                        continue;
1545:
1546:                    } else if (node instanceof  XSLVariable) {
1547:                        Expression var = ((XSLVariable) node)
1548:                                .compileLocalVariable(exec);
1549:                        if (var == null || var instanceof  EmptySequence) {
1550:                            // this can happen if the variable declaration is redundant
1551:                            continue;
1552:                        } else {
1553:                            LocalVariable lv = (LocalVariable) var;
1554:                            Expression tail = compileSequenceConstructor(exec,
1555:                                    iter, includeParams);
1556:                            if (tail == null || tail instanceof  EmptySequence) {
1557:                                // this doesn't happen, because if there are no instructions following
1558:                                // a variable, we'll have taken the var==null path above
1559:                                return result;
1560:                            } else {
1561:                                LetExpression let = new LetExpression();
1562:                                RangeVariableDeclaration rvar = new RangeVariableDeclaration();
1563:                                rvar.setRequiredType(lv.getRequiredType());
1564:                                rvar.setNameCode(lv.getNameCode());
1565:                                rvar.setVariableName(lv.getVariableName());
1566:                                rvar.setReferenceList(((XSLVariable) node)
1567:                                        .getReferenceList());
1568:                                let.setVariableDeclaration(rvar);
1569:                                let.setSequence(lv.getSelectExpression());
1570:                                //let.setSlotNumber(lv.getSlotNumber());
1571:                                let.setAction(tail);
1572:                                ((XSLVariable) node).fixupBinding(let);
1573:                                let.setLocationId(allocateLocationId(node
1574:                                        .getSystemId(), node.getLineNumber()));
1575:                                if (getConfiguration().getTraceListener() != null) {
1576:                                    TraceExpression t = new TraceExpression(let);
1577:                                    t.setConstructType(Location.LET_EXPRESSION);
1578:                                    t.setObjectNameCode(lv.getNameCode());
1579:                                    t.setSystemId(node.getSystemId());
1580:                                    t.setLineNumber(node.getLineNumber());
1581:                                    result = Block.makeBlock(result, t);
1582:                                } else {
1583:                                    result = Block.makeBlock(result, let);
1584:                                }
1585:                                if (result instanceof  ComputedExpression) {
1586:                                    ((ComputedExpression) result)
1587:                                            .setLocationId(locationId);
1588:                                }
1589:                                return result;
1590:                            }
1591:                        }
1592:
1593:                    } else if (node instanceof  StyleElement) {
1594:                        StyleElement snode = (StyleElement) node;
1595:                        Expression child;
1596:                        if (snode.validationError != null) {
1597:                            child = fallbackProcessing(exec, snode);
1598:
1599:                        } else {
1600:                            child = snode.compile(exec);
1601:                            if (child instanceof  ComputedExpression) {
1602:                                ComputedExpression childi = (ComputedExpression) child;
1603:                                childi.setLocationId(allocateLocationId(
1604:                                        getSystemId(), snode.getLineNumber()));
1605:                            }
1606:                            if (child != null) {
1607:                                if (includeParams
1608:                                        || !(node instanceof  XSLParam)) {
1609:                                    if (getConfiguration().getTraceListener() != null) {
1610:                                        TraceWrapper trace = makeTraceInstruction(
1611:                                                snode, child);
1612:                                        child = trace;
1613:                                    }
1614:                                }
1615:                            }
1616:                        }
1617:                        result = Block.makeBlock(result, child);
1618:                        if (result instanceof  ComputedExpression) {
1619:                            ((ComputedExpression) result)
1620:                                    .setLocationId(locationId);
1621:                        }
1622:                    }
1623:                }
1624:            }
1625:
1626:            /**
1627:             * Create a trace instruction to wrap a real instruction
1628:             */
1629:
1630:            protected static TraceWrapper makeTraceInstruction(
1631:                    StyleElement source, Expression child) {
1632:                if (child instanceof  TraceWrapper) {
1633:                    return (TraceWrapper) child;
1634:                    // this can happen, for example, after optimizing a compile-time xsl:if
1635:                }
1636:
1637:                TraceWrapper trace = new TraceInstruction(child, source);
1638:                trace.setLocationId(source.allocateLocationId(source
1639:                        .getSystemId(), source.getLineNumber()));
1640:                return trace;
1641:            }
1642:
1643:            /**
1644:             * Perform fallback processing. Generate fallback code for an extension
1645:             * instruction that is not recognized by the implementation.
1646:             *
1647:             * @param instruction The unknown extension instruction
1648:             */
1649:
1650:            protected Expression fallbackProcessing(Executable exec,
1651:                    StyleElement instruction) throws XPathException {
1652:                // process any xsl:fallback children; if there are none,
1653:                // generate code to report the original failure reason
1654:                Expression fallback = null;
1655:                AxisIterator kids = instruction.iterateAxis(Axis.CHILD);
1656:                while (true) {
1657:                    NodeInfo child = (NodeInfo) kids.next();
1658:                    if (child == null) {
1659:                        break;
1660:                    }
1661:                    if (child instanceof  XSLFallback) {
1662:                        //fallback.setLocationId(allocateLocationId(getSystemId(), child.getLineNumber()));
1663:                        //((XSLFallback)child).compileChildren(exec, fallback, true);
1664:                        Expression b = ((XSLFallback) child)
1665:                                .compileSequenceConstructor(exec, child
1666:                                        .iterateAxis(Axis.CHILD), true);
1667:                        if (b == null) {
1668:                            b = EmptySequence.getInstance();
1669:                        }
1670:                        if (fallback == null) {
1671:                            fallback = b;
1672:                        } else {
1673:                            fallback = Block.makeBlock(fallback, b);
1674:                            if (fallback instanceof  ComputedExpression) {
1675:                                ((ComputedExpression) fallback)
1676:                                        .setLocationId(allocateLocationId(
1677:                                                getSystemId(), getLineNumber()));
1678:                            }
1679:                        }
1680:                    }
1681:                }
1682:                if (fallback != null) {
1683:                    return fallback;
1684:                } else {
1685:                    compileError(instruction.validationError);
1686:                    return EmptySequence.getInstance();
1687:                }
1688:
1689:            }
1690:
1691:            /**
1692:             * Allocate a location identifier
1693:             */
1694:
1695:            public int allocateLocationId(String systemId, int lineNumber) {
1696:                return getStaticContext().getLocationMap().allocateLocationId(
1697:                        systemId, lineNumber);
1698:            }
1699:
1700:            /**
1701:             * Construct sort keys for a SortedIterator
1702:             *
1703:             * @return an array of SortKeyDefinition objects if there are any sort keys;
1704:             *         or null if there are none.
1705:             */
1706:
1707:            protected SortKeyDefinition[] makeSortKeys() {
1708:                // handle sort keys if any
1709:
1710:                int numberOfSortKeys = 0;
1711:                AxisIterator kids = iterateAxis(Axis.CHILD);
1712:                while (true) {
1713:                    Item child = kids.next();
1714:                    if (child == null) {
1715:                        break;
1716:                    }
1717:                    if (child instanceof  XSLSort) {
1718:                        numberOfSortKeys++;
1719:                    }
1720:                }
1721:
1722:                if (numberOfSortKeys > 0) {
1723:                    SortKeyDefinition[] keys = new SortKeyDefinition[numberOfSortKeys];
1724:                    kids = iterateAxis(Axis.CHILD);
1725:                    int k = 0;
1726:                    while (true) {
1727:                        NodeInfo child = (NodeInfo) kids.next();
1728:                        if (child == null) {
1729:                            break;
1730:                        }
1731:                        if (child instanceof  XSLSort) {
1732:                            keys[k++] = ((XSLSort) child)
1733:                                    .getSortKeyDefinition();
1734:                        }
1735:                    }
1736:                    return keys;
1737:
1738:                } else {
1739:                    return null;
1740:                }
1741:            }
1742:
1743:            /**
1744:             * Get the list of attribute-sets associated with this element.
1745:             * This is used for xsl:element, xsl:copy, xsl:attribute-set, and on literal
1746:             * result elements
1747:             *
1748:             * @param use  the original value of the [xsl:]use-attribute-sets attribute
1749:             * @param list an empty list to hold the list of XSLAttributeSet elements in the stylesheet tree.
1750:             *             Or null, if these are not required.
1751:             * @return an array of AttributeList instructions representing the compiled attribute sets
1752:             */
1753:
1754:            protected AttributeSet[] getAttributeSets(String use, List list)
1755:                    throws XPathException {
1756:
1757:                if (list == null) {
1758:                    list = new ArrayList(4);
1759:                }
1760:
1761:                XSLStylesheet stylesheet = getPrincipalStylesheet();
1762:                List toplevel = stylesheet.getTopLevel();
1763:
1764:                StringTokenizer st = new StringTokenizer(use);
1765:                while (st.hasMoreTokens()) {
1766:                    String asetname = st.nextToken();
1767:                    int fprint;
1768:                    try {
1769:                        fprint = makeNameCode(asetname) & 0xfffff;
1770:                    } catch (NamespaceException err) {
1771:                        compileError(err.getMessage(), "XTSE0710");
1772:                        fprint = -1;
1773:                    } catch (XPathException err) {
1774:                        compileError(err.getMessage(), "XTSE0710");
1775:                        fprint = -1;
1776:                    }
1777:                    boolean found = false;
1778:
1779:                    // search for the named attribute set, using all of them if there are several with the
1780:                    // same name
1781:
1782:                    for (int i = 0; i < toplevel.size(); i++) {
1783:                        if (toplevel.get(i) instanceof  XSLAttributeSet) {
1784:                            XSLAttributeSet t = (XSLAttributeSet) toplevel
1785:                                    .get(i);
1786:                            if (t.getAttributeSetFingerprint() == fprint) {
1787:                                list.add(t);
1788:                                found = true;
1789:                            }
1790:                        }
1791:                    }
1792:
1793:                    if (!found) {
1794:                        compileError("No attribute-set exists named "
1795:                                + asetname, "XTSE0710");
1796:                    }
1797:                }
1798:
1799:                AttributeSet[] array = new AttributeSet[list.size()];
1800:                for (int i = 0; i < list.size(); i++) {
1801:                    XSLAttributeSet aset = (XSLAttributeSet) list.get(i);
1802:                    aset.incrementReferenceCount();
1803:                    array[i] = aset.getInstruction();
1804:                }
1805:                return array;
1806:            }
1807:
1808:            /**
1809:             * Get the list of xsl:with-param elements for a calling element (apply-templates,
1810:             * call-template, apply-imports, next-match). This method can be used to get either
1811:             * the tunnel parameters, or the non-tunnel parameters.
1812:             *
1813:             * @param tunnel true if the tunnel="yes" parameters are wanted, false to get
1814:             * @param caller
1815:             */
1816:
1817:            protected WithParam[] getWithParamInstructions(Executable exec,
1818:                    boolean tunnel, Instruction caller) throws XPathException {
1819:                int count = 0;
1820:                AxisIterator kids = iterateAxis(Axis.CHILD);
1821:                while (true) {
1822:                    NodeInfo child = (NodeInfo) kids.next();
1823:                    if (child == null) {
1824:                        break;
1825:                    }
1826:                    if (child instanceof  XSLWithParam) {
1827:                        XSLWithParam wp = (XSLWithParam) child;
1828:                        if (wp.isTunnelParam() == tunnel) {
1829:                            count++;
1830:                        }
1831:                    }
1832:                }
1833:                WithParam[] array = new WithParam[count];
1834:                count = 0;
1835:                kids = iterateAxis(Axis.CHILD);
1836:                while (true) {
1837:                    NodeInfo child = (NodeInfo) kids.next();
1838:                    if (child == null) {
1839:                        return array;
1840:                    }
1841:                    if (child instanceof  XSLWithParam) {
1842:                        XSLWithParam wp = (XSLWithParam) child;
1843:                        if (wp.isTunnelParam() == tunnel) {
1844:                            WithParam p = (WithParam) wp.compile(exec);
1845:                            p.setParentExpression(caller);
1846:                            array[count++] = p;
1847:                        }
1848:
1849:                    }
1850:                }
1851:            }
1852:
1853:            /**
1854:             * Construct an exception with diagnostic information
1855:             */
1856:
1857:            protected void compileError(TransformerException error)
1858:                    throws XPathException {
1859:
1860:                // Set the location of the error if there is not current location information,
1861:                // or if the current location information is local to the XPath expression
1862:                if (error.getLocator() == null
1863:                        || error.getLocator() instanceof  ExpressionLocation) {
1864:                    error.setLocator(this );
1865:                }
1866:                PreparedStylesheet pss = getPreparedStylesheet();
1867:                try {
1868:                    if (pss == null) {
1869:                        // it is null before the stylesheet has been fully built
1870:                        throw error;
1871:                    } else {
1872:                        pss.reportError(error);
1873:                    }
1874:                } catch (TransformerException err2) {
1875:                    if (err2.getLocator() == null) {
1876:                        err2.setLocator(this );
1877:                    }
1878:                    throw StaticError.makeStaticError(err2);
1879:                }
1880:            }
1881:
1882:            protected void compileError(String message) throws XPathException {
1883:                StaticError tce = new StaticError(message);
1884:                tce.setLocator(this );
1885:                compileError(tce);
1886:            }
1887:
1888:            /**
1889:             * Compile time error, specifying an error code
1890:             *
1891:             * @param message   the error message
1892:             * @param errorCode the error code. May be null if not known or not defined
1893:             * @throws XPathException
1894:             */
1895:
1896:            protected void compileError(String message, String errorCode)
1897:                    throws XPathException {
1898:                StaticError tce = new StaticError(message);
1899:                tce.setErrorCode(errorCode);
1900:                tce.setLocator(this );
1901:                compileError(tce);
1902:            }
1903:
1904:            protected void undeclaredNamespaceError(String prefix,
1905:                    String errorCode) throws XPathException {
1906:                if (errorCode == null) {
1907:                    errorCode = "XTSE0280";
1908:                }
1909:                compileError("Undeclared namespace prefix " + Err.wrap(prefix),
1910:                        errorCode);
1911:            }
1912:
1913:            protected void compileWarning(String message, String errorCode)
1914:                    throws XPathException {
1915:                StaticError tce = new StaticError(message);
1916:                tce.setErrorCode(errorCode);
1917:                tce.setLocator(this );
1918:                PreparedStylesheet pss = getPreparedStylesheet();
1919:                if (pss != null) {
1920:                    pss.reportWarning(tce);
1921:                }
1922:            }
1923:
1924:            /**
1925:             * Construct an exception with diagnostic information
1926:             */
1927:
1928:            protected void issueWarning(TransformerException error) {
1929:                if (error.getLocator() == null) {
1930:                    error.setLocator(this );
1931:                }
1932:                PreparedStylesheet pss = getPreparedStylesheet();
1933:                if (pss != null) {
1934:                    // it is null before the stylesheet has been fully built - ignore it
1935:                    pss.reportWarning(error);
1936:                }
1937:            }
1938:
1939:            protected void issueWarning(String message, SourceLocator locator) {
1940:                TransformerConfigurationException tce = new TransformerConfigurationException(
1941:                        message);
1942:                if (locator == null) {
1943:                    tce.setLocator(this );
1944:                } else {
1945:                    tce.setLocator(locator);
1946:                }
1947:                issueWarning(tce);
1948:            }
1949:
1950:            /**
1951:             * Test whether this is a top-level element
1952:             */
1953:
1954:            public boolean isTopLevel() {
1955:                return (getParent() instanceof  XSLStylesheet);
1956:            }
1957:
1958:            /**
1959:             * Bind a variable used in this element to the compiled form of the XSLVariable element in which it is
1960:             * declared
1961:             *
1962:             * @param fingerprint The fingerprint of the name of the variable
1963:             * @return the XSLVariableDeclaration (that is, an xsl:variable or xsl:param instruction) for the variable
1964:             * @throws net.sf.saxon.trans.StaticError if the variable has not been declared
1965:             */
1966:
1967:            public XSLVariableDeclaration bindVariable(int fingerprint)
1968:                    throws StaticError {
1969:                XSLVariableDeclaration binding = getVariableBinding(fingerprint);
1970:                if (binding == null) {
1971:                    StaticError err = new StaticError("Variable "
1972:                            + getTargetNamePool().getDisplayName(fingerprint)
1973:                            + " has not been declared");
1974:                    err.setErrorCode("XPST0008");
1975:                    throw err;
1976:                }
1977:                return binding;
1978:            }
1979:
1980:            /**
1981:             * Bind a variable used in this element to the declaration in the stylesheet
1982:             *
1983:             * @param fprint The absolute name of the variable (prefixed by namespace URI)
1984:             * @return the XSLVariableDeclaration, or null if it has not been declared
1985:             */
1986:
1987:            private XSLVariableDeclaration getVariableBinding(int fprint) {
1988:                NodeInfo curr = this ;
1989:                NodeInfo prev = this ;
1990:
1991:                // first search for a local variable declaration
1992:                if (!isTopLevel()) {
1993:                    AxisIterator preceding = curr
1994:                            .iterateAxis(Axis.PRECEDING_SIBLING);
1995:                    while (true) {
1996:                        curr = (NodeInfo) preceding.next();
1997:                        while (curr == null) {
1998:                            curr = prev.getParent();
1999:                            while (curr instanceof  XSLFallback) {
2000:                                // a local variable is not visible within a sibling xsl:fallback element
2001:                                curr = curr.getParent();
2002:                            }
2003:                            prev = curr;
2004:                            if (curr.getParent() instanceof  XSLStylesheet) {
2005:                                break; // top level
2006:                            }
2007:                            preceding = curr
2008:                                    .iterateAxis(Axis.PRECEDING_SIBLING);
2009:                            curr = (NodeInfo) preceding.next();
2010:                        }
2011:                        if (curr.getParent() instanceof  XSLStylesheet) {
2012:                            break;
2013:                        }
2014:                        if (curr instanceof  XSLVariableDeclaration) {
2015:                            XSLVariableDeclaration var = (XSLVariableDeclaration) curr;
2016:                            if (var.getVariableFingerprint() == fprint) {
2017:                                return var;
2018:                            }
2019:                        }
2020:                    }
2021:                }
2022:
2023:                // Now check for a global variable
2024:                // we rely on the search following the order of decreasing import precedence.
2025:
2026:                XSLStylesheet root = getPrincipalStylesheet();
2027:                XSLVariableDeclaration var = root.getGlobalVariable(fprint);
2028:                return var;
2029:            }
2030:
2031:            /**
2032:             * List the variables that are in scope for this stylesheet element.
2033:             * Designed for a debugger, not used by the processor.
2034:             * @return two Enumeration of Strings, the global ones [0] and the local ones [1]
2035:             */
2036:
2037:            /**
2038:             * Get a FunctionCall declared using an xsl:function element in the stylesheet
2039:             *
2040:             * @param fingerprint the fingerprint of the name of the function
2041:             * @param arity       the number of arguments in the function call. The value -1
2042:             *                    indicates that any arity will do (this is used to support the function-available() function).
2043:             * @return the XSLFunction object representing the function declaration
2044:             *         in the stylesheet, or null if no such function is defined.
2045:             */
2046:
2047:            public XSLFunction getStylesheetFunction(int fingerprint, int arity) {
2048:
2049:                // we rely on the search following the order of decreasing import precedence.
2050:
2051:                XSLStylesheet root = getPrincipalStylesheet();
2052:                List toplevel = root.getTopLevel();
2053:                for (int i = toplevel.size() - 1; i >= 0; i--) {
2054:                    Object child = toplevel.get(i);
2055:                    if (child instanceof  XSLFunction
2056:                            && ((XSLFunction) child).getFunctionFingerprint() == fingerprint
2057:                            && (arity == -1 || ((XSLFunction) child)
2058:                                    .getNumberOfArguments() == arity)) {
2059:                        XSLFunction func = (XSLFunction) child;
2060:                        return func;
2061:                    }
2062:                }
2063:                return null;
2064:            }
2065:
2066:            /**
2067:             * Get the type of construct. This will be a constant in
2068:             * class {@link Location}. This method is part of the {@link InstructionInfo} interface
2069:             */
2070:
2071:            public int getConstructType() {
2072:                return getFingerprint();
2073:            }
2074:
2075:            /**
2076:             * Get a name identifying the object of the expression, for example a function name, template name,
2077:             * variable name, key name, element name, etc. This is used only where the name is known statically.
2078:             * If there is no name, the value will be -1.
2079:             */
2080:
2081:            public int getObjectNameCode() {
2082:                return objectNameCode;
2083:            }
2084:
2085:            /**
2086:             * Get a fingerprint identifying the object of the expression, for example a function name, template name,
2087:             * variable name, key name, element name, etc. This is used only where the name is known statically.
2088:             * If there is no name, the value will be -1.
2089:             */
2090:
2091:            public int getObjectFingerprint() {
2092:                return (objectNameCode == -1 ? -1 : objectNameCode & 0xfffff);
2093:            }
2094:
2095:            /**
2096:             * Set the object name code
2097:             */
2098:
2099:            public void setObjectNameCode(int nameCode) {
2100:                objectNameCode = nameCode;
2101:            }
2102:
2103:            /**
2104:             * Get the namespace context of the instruction.
2105:             */
2106:
2107:            public NamespaceResolver getNamespaceResolver() {
2108:                return makeNamespaceContext();
2109:            }
2110:
2111:            /**
2112:             * Get the value of a particular property of the instruction. This is part of the
2113:             * {@link InstructionInfo} interface for run-time tracing and debugging. The properties
2114:             * available include all the attributes of the source instruction (named by the attribute name):
2115:             * these are all provided as string values.
2116:             *
2117:             * @param name The name of the required property
2118:             * @return The value of the requested property, or null if the property is not available
2119:             */
2120:
2121:            public Object getProperty(String name) {
2122:                return getAttributeValue(name);
2123:            }
2124:
2125:            /**
2126:             * Get an iterator over all the properties available. The values returned by the iterator
2127:             * will be of type String, and each string can be supplied as input to the getProperty()
2128:             * method to retrieve the value of the property.
2129:             */
2130:
2131:            public Iterator getProperties() {
2132:                NamePool pool = getNamePool();
2133:                List list = new ArrayList(10);
2134:                AxisIterator it = iterateAxis(Axis.ATTRIBUTE);
2135:                while (true) {
2136:                    NodeInfo a = (NodeInfo) it.next();
2137:                    if (a == null) {
2138:                        break;
2139:                    }
2140:                    list.add(pool.getClarkName(a.getNameCode()));
2141:                }
2142:                return list.iterator();
2143:            }
2144:
2145:            public String getSystemId(int locationId) {
2146:                return getSystemId();
2147:            }
2148:
2149:            public int getLineNumber(int locationId) {
2150:                return getLineNumber();
2151:            }
2152:        }
2153:
2154:        //
2155:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
2156:        // you may not use this file except in compliance with the License. You may obtain a copy of the
2157:        // License at http://www.mozilla.org/MPL/
2158:        //
2159:        // Software distributed under the License is distributed on an "AS IS" basis,
2160:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
2161:        // See the License for the specific language governing rights and limitations under the License.
2162:        //
2163:        // The Original Code is: all this file.
2164:        //
2165:        // The Initial Developer of the Original Code is Michael H. Kay.
2166:        //
2167:        // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
2168:        //
2169:        // Contributor(s):
2170:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.