KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > Sort


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: Sort.java,v 1.23 2004/02/24 02:58:42 zongaro Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import java.text.Collator JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.NoSuchElementException JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import org.apache.bcel.classfile.Field;
29 import org.apache.bcel.classfile.Method;
30 import org.apache.bcel.generic.ALOAD;
31 import org.apache.bcel.generic.ANEWARRAY;
32 import org.apache.bcel.generic.CHECKCAST;
33 import org.apache.bcel.generic.ConstantPoolGen;
34 import org.apache.bcel.generic.GETFIELD;
35 import org.apache.bcel.generic.ICONST;
36 import org.apache.bcel.generic.ILOAD;
37 import org.apache.bcel.generic.INVOKEINTERFACE;
38 import org.apache.bcel.generic.INVOKESPECIAL;
39 import org.apache.bcel.generic.INVOKESTATIC;
40 import org.apache.bcel.generic.INVOKEVIRTUAL;
41 import org.apache.bcel.generic.InstructionHandle;
42 import org.apache.bcel.generic.InstructionList;
43 import org.apache.bcel.generic.NEW;
44 import org.apache.bcel.generic.NOP;
45 import org.apache.bcel.generic.PUSH;
46 import org.apache.bcel.generic.PUTFIELD;
47 import org.apache.bcel.generic.TABLESWITCH;
48 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
49 import org.apache.xalan.xsltc.compiler.util.CompareGenerator;
50 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
51 import org.apache.xalan.xsltc.compiler.util.IntType;
52 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
53 import org.apache.xalan.xsltc.compiler.util.NodeSortRecordFactGenerator;
54 import org.apache.xalan.xsltc.compiler.util.NodeSortRecordGenerator;
55 import org.apache.xalan.xsltc.compiler.util.StringType;
56 import org.apache.xalan.xsltc.compiler.util.Type;
57 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
58 import org.apache.xalan.xsltc.compiler.util.Util;
59 import org.apache.xalan.xsltc.dom.Axis;
60
61
62 /**
63  * @author Jacek Ambroziak
64  * @author Santiago Pericas-Geertsen
65  * @author Morten Jorgensen
66  */

67 final class Sort extends Instruction implements Closure {
68
69     private Expression _select;
70     private AttributeValue _order;
71     private AttributeValue _caseOrder;
72     private AttributeValue _dataType;
73     private String JavaDoc _lang; // bug! see 26869
74

75     private String JavaDoc _data = null;
76
77
78     private String JavaDoc _className = null;
79     private ArrayList JavaDoc _closureVars = null;
80     private boolean _needsSortRecordFactory = false;
81
82     // -- Begin Closure interface --------------------
83

84     /**
85      * Returns true if this closure is compiled in an inner class (i.e.
86      * if this is a real closure).
87      */

88     public boolean inInnerClass() {
89     return (_className != null);
90     }
91
92     /**
93      * Returns a reference to its parent closure or null if outermost.
94      */

95     public Closure getParentClosure() {
96     return null;
97     }
98
99     /**
100      * Returns the name of the auxiliary class or null if this predicate
101      * is compiled inside the Translet.
102      */

103     public String JavaDoc getInnerClassName() {
104     return _className;
105     }
106
107     /**
108      * Add new variable to the closure.
109      */

110     public void addVariable(VariableRefBase variableRef) {
111     if (_closureVars == null) {
112         _closureVars = new ArrayList JavaDoc();
113     }
114
115     // Only one reference per variable
116
if (!_closureVars.contains(variableRef)) {
117         _closureVars.add(variableRef);
118         _needsSortRecordFactory = true;
119     }
120     }
121
122     // -- End Closure interface ----------------------
123

124     private void setInnerClassName(String JavaDoc className) {
125     _className = className;
126     }
127
128     /**
129      * Parse the attributes of the xsl:sort element
130      */

131     public void parseContents(Parser parser) {
132
133     final SyntaxTreeNode parent = getParent();
134     if (!(parent instanceof ApplyTemplates) &&
135         !(parent instanceof ForEach)) {
136         reportError(this, parser, ErrorMsg.STRAY_SORT_ERR, null);
137         return;
138     }
139
140     // Parse the select expression (node string value if no expression)
141
_select = parser.parseExpression(this, "select", "string(.)");
142
143     // Get the sort order; default is 'ascending'
144
String JavaDoc val = getAttribute("order");
145     if (val.length() == 0) val = "ascending";
146     _order = AttributeValue.create(this, val, parser);
147
148     // Get the sort data type; default is text
149
val = getAttribute("data-type");
150     if (val.length() == 0) {
151         try {
152         final Type type = _select.typeCheck(parser.getSymbolTable());
153         if (type instanceof IntType)
154             val = "number";
155         else
156             val = "text";
157         }
158         catch (TypeCheckError e) {
159         val = "text";
160         }
161     }
162     _dataType = AttributeValue.create(this, val, parser);
163
164      _lang = getAttribute("lang"); // bug! see 26869
165
// val = getAttribute("lang");
166
// _lang = AttributeValue.create(this, val, parser);
167
// Get the case order; default is language dependant
168
val = getAttribute("case-order");
169     _caseOrder = AttributeValue.create(this, val, parser);
170     
171     }
172     
173     /**
174      * Run type checks on the attributes; expression must return a string
175      * which we will use as a sort key
176      */

177     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
178     final Type tselect = _select.typeCheck(stable);
179
180     // If the sort data-type is not set we use the natural data-type
181
// of the data we will sort
182
if (!(tselect instanceof StringType)) {
183         _select = new CastExpr(_select, Type.String);
184     }
185
186     _order.typeCheck(stable);
187     _caseOrder.typeCheck(stable);
188     _dataType.typeCheck(stable);
189     return Type.Void;
190     }
191
192     /**
193      * These two methods are needed in the static methods that compile the
194      * overloaded NodeSortRecord.compareType() and NodeSortRecord.sortOrder()
195      */

196     public void translateSortType(ClassGenerator classGen,
197                   MethodGenerator methodGen) {
198     _dataType.translate(classGen, methodGen);
199     }
200     
201     public void translateSortOrder(ClassGenerator classGen,
202                    MethodGenerator methodGen) {
203     _order.translate(classGen, methodGen);
204     }
205     
206      public void translateCaseOrder(ClassGenerator classGen,
207                    MethodGenerator methodGen) {
208     _caseOrder.translate(classGen, methodGen);
209     }
210     
211     public void translateLang(ClassGenerator classGen,
212                    MethodGenerator methodGen) {
213     final ConstantPoolGen cpg = classGen.getConstantPool();
214     final InstructionList il = methodGen.getInstructionList();
215     il.append(new PUSH(cpg, _lang)); // bug! see 26869
216
}
217     
218     /**
219      * This method compiles code for the select expression for this
220      * xsl:sort element. The method is called from the static code-generating
221      * methods in this class.
222      */

223     public void translateSelect(ClassGenerator classGen,
224                 MethodGenerator methodGen) {
225     _select.translate(classGen,methodGen);
226     }
227
228     /**
229      * This method should not produce any code
230      */

231     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
232     // empty
233
}
234
235     /**
236      * Compiles code that instantiates a SortingIterator object.
237      * This object's constructor needs referencdes to the current iterator
238      * and a node sort record producing objects as its parameters.
239      */

240     public static void translateSortIterator(ClassGenerator classGen,
241                       MethodGenerator methodGen,
242                       Expression nodeSet,
243                       Vector JavaDoc sortObjects)
244     {
245     final ConstantPoolGen cpg = classGen.getConstantPool();
246     final InstructionList il = methodGen.getInstructionList();
247
248     // SortingIterator.SortingIterator(NodeIterator,NodeSortRecordFactory);
249
final int init = cpg.addMethodref(SORT_ITERATOR, "<init>",
250                       "("
251                       + NODE_ITERATOR_SIG
252                       + NODE_SORT_FACTORY_SIG
253                       + ")V");
254
255     il.append(new NEW(cpg.addClass(SORT_ITERATOR)));
256     il.append(DUP);
257
258     // Get the current node iterator
259
if (nodeSet == null) { // apply-templates default
260
final int children = cpg.addInterfaceMethodref(DOM_INTF,
261                                "getAxisIterator",
262                                "(I)"+
263                                NODE_ITERATOR_SIG);
264         il.append(methodGen.loadDOM());
265         il.append(new PUSH(cpg, Axis.CHILD));
266         il.append(new INVOKEINTERFACE(children, 2));
267     }
268     else {
269         nodeSet.translate(classGen, methodGen);
270     }
271     
272     // Compile the code for the NodeSortRecord producing class and pass
273
// that as the last argument to the SortingIterator constructor.
274
compileSortRecordFactory(sortObjects, classGen, methodGen);
275     il.append(new INVOKESPECIAL(init));
276     }
277
278
279     /**
280      * Compiles code that instantiates a NodeSortRecordFactory object which
281      * will produce NodeSortRecord objects of a specific type.
282      */

283     public static void compileSortRecordFactory(Vector JavaDoc sortObjects,
284     ClassGenerator classGen, MethodGenerator methodGen)
285     {
286     String JavaDoc sortRecordClass =
287         compileSortRecord(sortObjects, classGen, methodGen);
288
289     boolean needsSortRecordFactory = false;
290     final int nsorts = sortObjects.size();
291     for (int i = 0; i < nsorts; i++) {
292         final Sort sort = (Sort) sortObjects.elementAt(i);
293         needsSortRecordFactory |= sort._needsSortRecordFactory;
294     }
295
296     String JavaDoc sortRecordFactoryClass = NODE_SORT_FACTORY;
297     if (needsSortRecordFactory) {
298         sortRecordFactoryClass =
299         compileSortRecordFactory(sortObjects, classGen, methodGen,
300             sortRecordClass);
301     }
302
303     final ConstantPoolGen cpg = classGen.getConstantPool();
304     final InstructionList il = methodGen.getInstructionList();
305     
306     il.append(new NEW(cpg.addClass(sortRecordFactoryClass)));
307     il.append(DUP);
308     il.append(methodGen.loadDOM());
309     il.append(new PUSH(cpg, sortRecordClass));
310     il.append(classGen.loadTranslet());
311
312     // Compile code that initializes the static _sortOrder
313
il.append(new PUSH(cpg, nsorts));
314     il.append(new ANEWARRAY(cpg.addClass(STRING)));
315     for (int level = 0; level < nsorts; level++) {
316         final Sort sort = (Sort)sortObjects.elementAt(level);
317         il.append(DUP);
318         il.append(new PUSH(cpg, level));
319         sort.translateSortOrder(classGen, methodGen);
320         il.append(AASTORE);
321     }
322
323     il.append(new PUSH(cpg, nsorts));
324     il.append(new ANEWARRAY(cpg.addClass(STRING)));
325     for (int level = 0; level < nsorts; level++) {
326         final Sort sort = (Sort)sortObjects.elementAt(level);
327         il.append(DUP);
328         il.append(new PUSH(cpg, level));
329         sort.translateSortType(classGen, methodGen);
330         il.append(AASTORE);
331     }
332   
333   il.append(new PUSH(cpg, nsorts));
334   il.append(new ANEWARRAY(cpg.addClass(STRING)));
335   for (int level = 0; level < nsorts; level++) {
336         final Sort sort = (Sort)sortObjects.elementAt(level);
337         il.append(DUP);
338         il.append(new PUSH(cpg, level));
339         sort.translateLang(classGen, methodGen);
340         il.append(AASTORE);
341    }
342  
343    il.append(new PUSH(cpg, nsorts));
344    il.append(new ANEWARRAY(cpg.addClass(STRING)));
345    for (int level = 0; level < nsorts; level++) {
346         final Sort sort = (Sort)sortObjects.elementAt(level);
347         il.append(DUP);
348         il.append(new PUSH(cpg, level));
349         sort.translateCaseOrder(classGen, methodGen);
350         il.append(AASTORE);
351   }
352
353     il.append(new INVOKESPECIAL(
354         cpg.addMethodref(sortRecordFactoryClass, "<init>",
355         "(" + DOM_INTF_SIG
356             + STRING_SIG
357             + TRANSLET_INTF_SIG
358             + "[" + STRING_SIG
359         + "[" + STRING_SIG
360         + "[" + STRING_SIG
361             + "[" + STRING_SIG + ")V")));
362
363     // Initialize closure variables in sortRecordFactory
364
final ArrayList JavaDoc dups = new ArrayList JavaDoc();
365
366     for (int j = 0; j < nsorts; j++) {
367         final Sort sort = (Sort) sortObjects.get(j);
368         final int length = (sort._closureVars == null) ? 0 :
369         sort._closureVars.size();
370
371         for (int i = 0; i < length; i++) {
372         VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i);
373
374         // Discard duplicate variable references
375
if (dups.contains(varRef)) continue;
376
377         final VariableBase var = varRef.getVariable();
378
379         // Store variable in new closure
380
il.append(DUP);
381         il.append(var.loadInstruction());
382         il.append(new PUTFIELD(
383             cpg.addFieldref(sortRecordFactoryClass, var.getEscapedName(),
384                 var.getType().toSignature())));
385         dups.add(varRef);
386         }
387     }
388     }
389
390     public static String JavaDoc compileSortRecordFactory(Vector JavaDoc sortObjects,
391     ClassGenerator classGen, MethodGenerator methodGen,
392     String JavaDoc sortRecordClass)
393     {
394     final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC();
395     final String JavaDoc className = xsltc.getHelperClassName();
396
397     final NodeSortRecordFactGenerator sortRecordFactory =
398         new NodeSortRecordFactGenerator(className,
399                     NODE_SORT_FACTORY,
400                     className + ".java",
401                     ACC_PUBLIC | ACC_SUPER | ACC_FINAL,
402                     new String JavaDoc[] {},
403                     classGen.getStylesheet());
404
405     ConstantPoolGen cpg = sortRecordFactory.getConstantPool();
406
407     // Add a new instance variable for each var in closure
408
final int nsorts = sortObjects.size();
409     final ArrayList JavaDoc dups = new ArrayList JavaDoc();
410
411     for (int j = 0; j < nsorts; j++) {
412         final Sort sort = (Sort) sortObjects.get(j);
413         final int length = (sort._closureVars == null) ? 0 :
414         sort._closureVars.size();
415
416         for (int i = 0; i < length; i++) {
417         final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i);
418
419         // Discard duplicate variable references
420
if (dups.contains(varRef)) continue;
421
422         final VariableBase var = varRef.getVariable();
423         sortRecordFactory.addField(new Field(ACC_PUBLIC,
424                        cpg.addUtf8(var.getEscapedName()),
425                        cpg.addUtf8(var.getType().toSignature()),
426                        null, cpg.getConstantPool()));
427         dups.add(varRef);
428         }
429     }
430
431     // Define a constructor for this class
432
final org.apache.bcel.generic.Type[] argTypes =
433         new org.apache.bcel.generic.Type[7];
434     argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
435     argTypes[1] = Util.getJCRefType(STRING_SIG);
436     argTypes[2] = Util.getJCRefType(TRANSLET_INTF_SIG);
437     argTypes[3] = Util.getJCRefType("[" + STRING_SIG);
438     argTypes[4] = Util.getJCRefType("[" + STRING_SIG);
439   argTypes[5] = Util.getJCRefType("[" + STRING_SIG);
440   argTypes[6] = Util.getJCRefType("[" + STRING_SIG);
441
442     final String JavaDoc[] argNames = new String JavaDoc[7];
443     argNames[0] = DOCUMENT_PNAME;
444     argNames[1] = "className";
445     argNames[2] = TRANSLET_PNAME;
446     argNames[3] = "order";
447     argNames[4] = "type";
448   argNames[5] = "lang";
449   argNames[6] = "case_order";
450   
451
452     InstructionList il = new InstructionList();
453     final MethodGenerator constructor =
454         new MethodGenerator(ACC_PUBLIC,
455                 org.apache.bcel.generic.Type.VOID,
456                 argTypes, argNames, "<init>",
457                 className, il, cpg);
458
459     // Push all parameters onto the stack and called super.<init>()
460
il.append(ALOAD_0);
461     il.append(ALOAD_1);
462     il.append(ALOAD_2);
463     il.append(new ALOAD(3));
464     il.append(new ALOAD(4));
465     il.append(new ALOAD(5));
466   il.append(new ALOAD(6));
467   il.append(new ALOAD(7));
468     il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_FACTORY,
469         "<init>",
470         "(" + DOM_INTF_SIG
471         + STRING_SIG
472         + TRANSLET_INTF_SIG
473         + "[" + STRING_SIG
474     + "[" + STRING_SIG
475     + "[" + STRING_SIG
476         + "[" + STRING_SIG + ")V")));
477     il.append(RETURN);
478
479     // Override the definition of makeNodeSortRecord()
480
il = new InstructionList();
481     final MethodGenerator makeNodeSortRecord =
482         new MethodGenerator(ACC_PUBLIC,
483         Util.getJCRefType(NODE_SORT_RECORD_SIG),
484         new org.apache.bcel.generic.Type[] {
485             org.apache.bcel.generic.Type.INT,
486             org.apache.bcel.generic.Type.INT },
487         new String JavaDoc[] { "node", "last" }, "makeNodeSortRecord",
488         className, il, cpg);
489
490     il.append(ALOAD_0);
491     il.append(ILOAD_1);
492     il.append(ILOAD_2);
493     il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_FACTORY,
494         "makeNodeSortRecord", "(II)" + NODE_SORT_RECORD_SIG)));
495     il.append(DUP);
496     il.append(new CHECKCAST(cpg.addClass(sortRecordClass)));
497
498     // Initialize closure in record class
499
final int ndups = dups.size();
500     for (int i = 0; i < ndups; i++) {
501         final VariableRefBase varRef = (VariableRefBase) dups.get(i);
502         final VariableBase var = varRef.getVariable();
503         final Type varType = var.getType();
504         
505         il.append(DUP);
506
507         // Get field from factory class
508
il.append(ALOAD_0);
509         il.append(new GETFIELD(
510         cpg.addFieldref(className,
511             var.getEscapedName(), varType.toSignature())));
512
513         // Put field in record class
514
il.append(new PUTFIELD(
515         cpg.addFieldref(sortRecordClass,
516             var.getEscapedName(), varType.toSignature())));
517     }
518     il.append(POP);
519     il.append(ARETURN);
520
521     constructor.setMaxLocals();
522     constructor.setMaxStack();
523     sortRecordFactory.addMethod(constructor.getMethod());
524     makeNodeSortRecord.setMaxLocals();
525     makeNodeSortRecord.setMaxStack();
526     sortRecordFactory.addMethod(makeNodeSortRecord.getMethod());
527     xsltc.dumpClass(sortRecordFactory.getJavaClass());
528
529     return className;
530     }
531
532     /**
533      * Create a new auxillary class extending NodeSortRecord.
534      */

535     private static String JavaDoc compileSortRecord(Vector JavaDoc sortObjects,
536                         ClassGenerator classGen,
537                         MethodGenerator methodGen) {
538     final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC();
539     final String JavaDoc className = xsltc.getHelperClassName();
540
541     // This generates a new class for handling this specific sort
542
final NodeSortRecordGenerator sortRecord =
543         new NodeSortRecordGenerator(className,
544                     NODE_SORT_RECORD,
545                     "sort$0.java",
546                     ACC_PUBLIC | ACC_SUPER | ACC_FINAL,
547                     new String JavaDoc[] {},
548                     classGen.getStylesheet());
549     
550     final ConstantPoolGen cpg = sortRecord.getConstantPool();
551
552     // Add a new instance variable for each var in closure
553
final int nsorts = sortObjects.size();
554     final ArrayList JavaDoc dups = new ArrayList JavaDoc();
555
556     for (int j = 0; j < nsorts; j++) {
557         final Sort sort = (Sort) sortObjects.get(j);
558
559         // Set the name of the inner class in this sort object
560
sort.setInnerClassName(className);
561
562         final int length = (sort._closureVars == null) ? 0 :
563         sort._closureVars.size();
564         for (int i = 0; i < length; i++) {
565         final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i);
566
567         // Discard duplicate variable references
568
if (dups.contains(varRef)) continue;
569
570         final VariableBase var = varRef.getVariable();
571         sortRecord.addField(new Field(ACC_PUBLIC,
572                     cpg.addUtf8(var.getEscapedName()),
573                     cpg.addUtf8(var.getType().toSignature()),
574                     null, cpg.getConstantPool()));
575         dups.add(varRef);
576         }
577     }
578
579     Method init = compileInit(sortObjects, sortRecord,
580                      cpg, className);
581     Method extract = compileExtract(sortObjects, sortRecord,
582                     cpg, className);
583     sortRecord.addMethod(init);
584     sortRecord.addMethod(extract);
585
586     xsltc.dumpClass(sortRecord.getJavaClass());
587     return className;
588     }
589
590     /**
591      * Create a constructor for the new class. Updates the reference to the
592      * collator in the super calls only when the stylesheet specifies a new
593      * language in xsl:sort.
594      */

595     private static Method compileInit(Vector JavaDoc sortObjects,
596                        NodeSortRecordGenerator sortRecord,
597                        ConstantPoolGen cpg,
598                        String JavaDoc className)
599     {
600     final InstructionList il = new InstructionList();
601     final MethodGenerator init =
602         new MethodGenerator(ACC_PUBLIC,
603                 org.apache.bcel.generic.Type.VOID,
604                 null, null, "<init>", className,
605                 il, cpg);
606
607     // Call the constructor in the NodeSortRecord superclass
608
il.append(ALOAD_0);
609     il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_RECORD,
610                              "<init>", "()V")));
611
612     
613
614     il.append(RETURN);
615
616     init.stripAttributes(true);
617     init.setMaxLocals();
618     init.setMaxStack();
619
620     return init.getMethod();
621     }
622
623
624     /**
625      * Compiles a method that overloads NodeSortRecord.extractValueFromDOM()
626      */

627     private static Method compileExtract(Vector JavaDoc sortObjects,
628                      NodeSortRecordGenerator sortRecord,
629                      ConstantPoolGen cpg,
630                      String JavaDoc className) {
631     final InstructionList il = new InstructionList();
632     
633     // String NodeSortRecord.extractValueFromDOM(dom,node,level);
634
final CompareGenerator extractMethod =
635         new CompareGenerator(ACC_PUBLIC | ACC_FINAL,
636                  org.apache.bcel.generic.Type.STRING,
637                  new org.apache.bcel.generic.Type[] {
638                              Util.getJCRefType(DOM_INTF_SIG),
639                      org.apache.bcel.generic.Type.INT,
640                      org.apache.bcel.generic.Type.INT,
641                      Util.getJCRefType(TRANSLET_SIG),
642                      org.apache.bcel.generic.Type.INT
643                  },
644                  new String JavaDoc[] { "dom",
645                         "current",
646                         "level",
647                         "translet",
648                         "last"
649                  },
650                  "extractValueFromDOM", className, il, cpg);
651
652     // Values needed for the switch statement
653
final int levels = sortObjects.size();
654     final int match[] = new int[levels];
655     final InstructionHandle target[] = new InstructionHandle[levels];
656     InstructionHandle tblswitch = null;
657
658     // Compile switch statement only if the key has multiple levels
659
if (levels > 1) {
660         // Put the parameter to the swtich statement on the stack
661
il.append(new ILOAD(extractMethod.getLocalIndex("level")));
662         // Append the switch statement here later on
663
tblswitch = il.append(new NOP());
664     }
665
666     // Append all the cases for the switch statment
667
for (int level = 0; level < levels; level++) {
668         match[level] = level;
669         final Sort sort = (Sort)sortObjects.elementAt(level);
670         target[level] = il.append(NOP);
671         sort.translateSelect(sortRecord, extractMethod);
672         il.append(ARETURN);
673     }
674     
675     // Compile def. target for switch statement if key has multiple levels
676
if (levels > 1) {
677         // Append the default target - it will _NEVER_ be reached
678
InstructionHandle defaultTarget =
679         il.append(new PUSH(cpg, EMPTYSTRING));
680         il.insert(tblswitch,new TABLESWITCH(match, target, defaultTarget));
681         il.append(ARETURN);
682     }
683
684     extractMethod.stripAttributes(true);
685     extractMethod.setMaxLocals();
686     extractMethod.setMaxStack();
687     extractMethod.removeNOPs();
688
689     return extractMethod.getMethod();
690     }
691 }
692
Popular Tags