001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.ExpressionTool;
005: import net.sf.saxon.instruct.Executable;
006: import net.sf.saxon.om.AttributeCollection;
007: import net.sf.saxon.om.Axis;
008: import net.sf.saxon.om.AxisIterator;
009: import net.sf.saxon.om.NodeInfo;
010: import net.sf.saxon.sort.SortExpression;
011: import net.sf.saxon.sort.SortKeyDefinition;
012: import net.sf.saxon.trans.XPathException;
013: import net.sf.saxon.type.ItemType;
014: import net.sf.saxon.type.Type;
015: import net.sf.saxon.type.TypeHierarchy;
016: import net.sf.saxon.value.EmptySequence;
017: import net.sf.saxon.value.Whitespace;
018:
019: /**
020: * Handler for xsl:perform-sort elements in stylesheet (XSLT 2.0). <br>
021: */
022:
023: public class XSLPerformSort extends StyleElement {
024:
025: Expression select = null;
026:
027: /**
028: * Determine whether this node is an instruction.
029: * @return true - it is an instruction
030: */
031:
032: public boolean isInstruction() {
033: return true;
034: }
035:
036: /**
037: * Determine the type of item returned by this instruction (only relevant if
038: * it is an instruction).
039: * @return the item type returned
040: */
041:
042: protected ItemType getReturnedItemType() {
043: if (select == null) {
044: return getCommonChildItemType();
045: } else {
046: final TypeHierarchy th = getNamePool().getTypeHierarchy();
047: return select.getItemType(th);
048: }
049: }
050:
051: /**
052: * Determine whether this type of element is allowed to contain a template-body
053: * @return true: yes, it may contain a template-body
054: */
055:
056: public boolean mayContainSequenceConstructor() {
057: return true;
058: }
059:
060: /**
061: * Specify that xsl:sort is a permitted child
062: */
063:
064: protected boolean isPermittedChild(StyleElement child) {
065: return (child instanceof XSLSort);
066: }
067:
068: public void prepareAttributes() throws XPathException {
069:
070: AttributeCollection atts = getAttributeList();
071:
072: String selectAtt = null;
073:
074: for (int a = 0; a < atts.getLength(); a++) {
075: int nc = atts.getNameCode(a);
076: String f = getNamePool().getClarkName(nc);
077: if (f == StandardNames.SELECT) {
078: selectAtt = atts.getValue(a);
079: } else {
080: checkUnknownAttribute(nc);
081: }
082: }
083:
084: if (selectAtt != null) {
085: select = makeExpression(selectAtt);
086: }
087:
088: }
089:
090: public void validate() throws XPathException {
091: checkWithinTemplate();
092: checkSortComesFirst(true);
093:
094: if (select != null) {
095: // if there is a select attribute, check that there are no children other than xsl:sort and xsl:fallback
096: AxisIterator kids = iterateAxis(Axis.CHILD);
097: while (true) {
098: NodeInfo child = (NodeInfo) kids.next();
099: if (child == null) {
100: break;
101: }
102: if (child instanceof XSLSort
103: || child instanceof XSLFallback) {
104: // no action
105: } else if (child.getNodeKind() == Type.TEXT
106: && !Whitespace
107: .isWhite(child.getStringValueCS())) {
108: // with xml:space=preserve, white space nodes may still be there
109: // ERR XT1040
110: compileError("Within xsl:perform-sort, significant text must not appear if there is a select attribute");
111: } else {
112: // ERR XT1040
113: ((StyleElement) child)
114: .compileError("Within xsl:perform-sort, child instructions are not allowed if there is a select attribute");
115: }
116: }
117: }
118: select = typeCheck("select", select);
119: }
120:
121: public Expression compile(Executable exec) throws XPathException {
122: SortKeyDefinition[] sortKeys = makeSortKeys();
123: if (select != null) {
124: SortExpression sortedSequence = new SortExpression(select,
125: sortKeys);
126: ExpressionTool.makeParentReferences(sortedSequence);
127: return sortedSequence;
128: } else {
129: Expression body = compileSequenceConstructor(exec,
130: iterateAxis(Axis.CHILD), true);
131: if (body == null) {
132: body = EmptySequence.getInstance();
133: }
134: try {
135: SortExpression sortedSequence = new SortExpression(body
136: .simplify(getStaticContext()), sortKeys);
137: ExpressionTool.makeParentReferences(sortedSequence);
138: return sortedSequence;
139: } catch (XPathException e) {
140: compileError(e);
141: return null;
142: }
143: }
144: }
145:
146: }
147:
148: //
149: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
150: // you may not use this file except in compliance with the License. You may obtain a copy of the
151: // License at http://www.mozilla.org/MPL/
152: //
153: // Software distributed under the License is distributed on an "AS IS" basis,
154: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
155: // See the License for the specific language governing rights and limitations under the License.
156: //
157: // The Original Code is: all this file.
158: //
159: // The Initial Developer of the Original Code is Michael H. Kay.
160: //
161: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
162: //
163: // Contributor(s): none.
164: //
|