KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > style > XSLForEachGroup


1 package net.sf.saxon.style;
2 import net.sf.saxon.expr.*;
3 import net.sf.saxon.instruct.Executable;
4 import net.sf.saxon.instruct.ForEachGroup;
5 import net.sf.saxon.om.AttributeCollection;
6 import net.sf.saxon.om.Axis;
7 import net.sf.saxon.pattern.Pattern;
8 import net.sf.saxon.pattern.PatternSponsor;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.value.EmptySequence;
11 import net.sf.saxon.value.SequenceType;
12
13 import java.util.Comparator JavaDoc;
14
15 /**
16 * Handler for xsl:for-each-group elements in stylesheet. This is a new instruction
17 * defined in XSLT 2.0
18 */

19
20 public final class XSLForEachGroup extends StyleElement {
21
22     private Expression select = null;
23     private Expression groupBy = null;
24     private Expression groupAdjacent = null;
25     private Pattern starting = null;
26     private Pattern ending = null;
27     private String JavaDoc collationName;
28
29     /**
30     * Determine whether this node is an instruction.
31     * @return true - it is an instruction
32     */

33
34     public boolean isInstruction() {
35         return true;
36     }
37
38     /**
39      * Specify that xsl:sort is a permitted child
40      */

41
42     protected boolean isPermittedChild(StyleElement child) {
43         return (child instanceof XSLSort);
44     }
45
46     /**
47     * Determine whether this type of element is allowed to contain a template-body
48     * @return true: yes, it may contain a template-body
49     */

50
51     public boolean mayContainSequenceConstructor() {
52         return true;
53     }
54
55     public void prepareAttributes() throws XPathException {
56
57         AttributeCollection atts = getAttributeList();
58
59         String JavaDoc selectAtt = null;
60         String JavaDoc groupByAtt = null;
61         String JavaDoc groupAdjacentAtt = null;
62         String JavaDoc startingAtt = null;
63         String JavaDoc endingAtt = null;
64
65         for (int a=0; a<atts.getLength(); a++) {
66             int nc = atts.getNameCode(a);
67             String JavaDoc f = getNamePool().getClarkName(nc);
68             if (f==StandardNames.SELECT) {
69                 selectAtt = atts.getValue(a);
70             } else if (f==StandardNames.GROUP_BY) {
71                 groupByAtt = atts.getValue(a);
72             } else if (f==StandardNames.GROUP_ADJACENT) {
73                 groupAdjacentAtt = atts.getValue(a);
74             } else if (f==StandardNames.GROUP_STARTING_WITH) {
75                 startingAtt = atts.getValue(a);
76             } else if (f==StandardNames.GROUP_ENDING_WITH) {
77                 endingAtt = atts.getValue(a);
78             } else if (f==StandardNames.COLLATION) {
79                 collationName = atts.getValue(a).trim();
80             } else {
81                 checkUnknownAttribute(nc);
82             }
83         }
84
85         if (selectAtt==null) {
86             reportAbsence("select");
87             select = EmptySequence.getInstance(); // for error recovery
88
} else {
89             select = makeExpression(selectAtt);
90         }
91
92         int c = (groupByAtt==null ? 0 : 1) +
93                 (groupAdjacentAtt==null ? 0 : 1) +
94                 (startingAtt==null ? 0 : 1) +
95                 (endingAtt==null ? 0 : 1);;
96         if (c!=1) {
97             compileError("Exactly one of the attributes group-by, group-adjacent, group-starting-with, " +
98                     "and group-ending-with must be specified", "XTSE1080");
99         }
100
101         if (groupByAtt != null) {
102             groupBy = makeExpression(groupByAtt);
103         }
104
105         if (groupAdjacentAtt != null) {
106             groupAdjacent = makeExpression(groupAdjacentAtt);
107         }
108
109         if (startingAtt != null) {
110             starting = makePattern(startingAtt);
111         }
112
113         if (endingAtt != null) {
114             ending = makePattern(endingAtt);
115         }
116
117         if (collationName!=null && groupBy==null && groupAdjacent==null) {
118             compileError("A collation may be specified only if group-by or group-adjacent is specified", "XTSE1090");
119         }
120     }
121
122     public void validate() throws XPathException {
123         checkWithinTemplate();
124         checkSortComesFirst(false);
125         select = typeCheck("select", select);
126
127         ExpressionLocation locator = new ExpressionLocation(this);
128         if (groupBy != null) {
129             groupBy = typeCheck("group-by", groupBy);
130             try {
131                 RoleLocator role =
132                     new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/group-by", 0, null);
133                 role.setSourceLocator(locator);
134                 groupBy = TypeChecker.staticTypeCheck(groupBy,
135                         SequenceType.ATOMIC_SEQUENCE,
136                         false, role, getStaticContext());
137             } catch (XPathException err) {
138                 compileError(err);
139             }
140         } else if (groupAdjacent != null) {
141             groupAdjacent = typeCheck("group-adjacent", groupAdjacent);
142             try {
143                 RoleLocator role =
144                     new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/group-adjacent", 0, null);
145                 role.setSourceLocator(locator);
146                 role.setErrorCode("XTTE1100");
147                 groupAdjacent = TypeChecker.staticTypeCheck(groupAdjacent,
148                         SequenceType.SINGLE_ATOMIC,
149                         false, role, getStaticContext());
150             } catch (XPathException err) {
151                 compileError(err);
152             }
153         }
154
155         starting = typeCheck("starting", starting);
156         ending = typeCheck("ending", ending);
157
158         if (starting != null || ending != null) {
159             try {
160                 RoleLocator role =
161                     new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/select", 0, null);
162                 role.setSourceLocator(locator);
163                 role.setErrorCode("XTTE1120");
164                 select = TypeChecker.staticTypeCheck(select,
165                                             SequenceType.NODE_SEQUENCE,
166                                             false, role, getStaticContext());
167             } catch (XPathException err) {
168                 String JavaDoc prefix = (starting != null ?
169                         "With group-starting-with attribute: " :
170                         "With group-ending-with attribute: ");
171                 compileError(prefix + err.getMessage(), err.getErrorCodeLocalPart());
172             }
173         }
174     }
175
176     public Expression compile(Executable exec) throws XPathException {
177
178         Comparator JavaDoc collator = null;
179         if (collationName != null) {
180             collator = getPrincipalStylesheet().findCollation(collationName);
181             if (collator==null) {
182                 compileError("The collation name '" + collationName + "' has not been defined", "XTDE1110");
183             }
184         }
185
186         byte algorithm = 0;
187         Expression key = null;
188         if (groupBy != null) {
189             algorithm = ForEachGroup.GROUP_BY;
190             key = groupBy;
191         } else if (groupAdjacent != null) {
192             algorithm = ForEachGroup.GROUP_ADJACENT;
193             key = groupAdjacent;
194         } else if (starting != null) {
195             algorithm = ForEachGroup.GROUP_STARTING;
196             key = new PatternSponsor(starting);
197         } else if (ending != null) {
198             algorithm = ForEachGroup.GROUP_ENDING;
199             key = new PatternSponsor(ending);
200         }
201
202 // Block action = new Block();
203
// compileChildren(exec, action, true);
204
Expression action = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true);
205         if (action == null) {
206             // body of for-each is empty: it's a no-op.
207
return EmptySequence.getInstance();
208         }
209         try {
210             ForEachGroup inst = new ForEachGroup(
211                                         select,
212                                         action.simplify(getStaticContext()),
213                                         algorithm,
214                                         key,
215                                         collator,
216                                         makeSortKeys() );
217             ExpressionTool.makeParentReferences(inst);
218             return inst;
219         } catch (XPathException e) {
220             compileError(e);
221             return null;
222         }
223
224     }
225
226 }
227
228 //
229
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
230
// you may not use this file except in compliance with the License. You may obtain a copy of the
231
// License at http://www.mozilla.org/MPL/
232
//
233
// Software distributed under the License is distributed on an "AS IS" basis,
234
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
235
// See the License for the specific language governing rights and limitations under the License.
236
//
237
// The Original Code is: all this file.
238
//
239
// The Initial Developer of the Original Code is Michael H. Kay.
240
//
241
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
242
//
243
// Contributor(s): none.
244
//
245
Popular Tags