View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: ProcessingInstructionPattern.java,v 1.2.4.1 2005/09/12 11:04:08 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.compiler;
25  
26  import com.sun.org.apache.bcel.internal.generic.BranchHandle;
27  import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
28  import com.sun.org.apache.bcel.internal.generic.GOTO;
29  import com.sun.org.apache.bcel.internal.generic.IFEQ;
30  import com.sun.org.apache.bcel.internal.generic.IF_ICMPEQ;
31  import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
32  import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
33  import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
34  import com.sun.org.apache.bcel.internal.generic.InstructionList;
35  import com.sun.org.apache.bcel.internal.generic.PUSH;
36  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
37  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
38  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
39  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
40  import com.sun.org.apache.xml.internal.dtm.Axis;
41  import com.sun.org.apache.xml.internal.dtm.DTM;
42  
43  /**
44   * @author Morten Jorgensen
45   */
46  final class ProcessingInstructionPattern extends StepPattern {
47  
48      private String _name = null;
49      private boolean _typeChecked = false;
50  
51      /**
52       * Handles calls with no parameter (current node is implicit parameter).
53       */
54      public ProcessingInstructionPattern(String name) {
55          super(Axis.CHILD, DTM.PROCESSING_INSTRUCTION_NODE, null);
56          _name = name;
57          //if (_name.equals("*")) _typeChecked = true; no wildcard allowed!
58      }
59  
60      /**
61       *
62       */
63       public double getDefaultPriority() {
64          return (_name != null) ? 0.0 : -0.5;
65       }
66      public String toString() {
67          if (_predicates == null)
68              return "processing-instruction("+_name+")";
69          else
70              return "processing-instruction("+_name+")"+_predicates;
71      }
72  
73      public void reduceKernelPattern() {
74          _typeChecked = true;
75      }
76  
77      public boolean isWildcard() {
78          return false;
79      }
80  
81      public Type typeCheck(SymbolTable stable) throws TypeCheckError {
82          if (hasPredicates()) {
83              // Type check all the predicates (e -> position() = e)
84              final int n = _predicates.size();
85              for (int i = 0; i < n; i++) {
86                  final Predicate pred = (Predicate)_predicates.elementAt(i);
87                  pred.typeCheck(stable);
88              }
89          }
90          return Type.NodeSet;
91      }
92  
93      public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
94          final ConstantPoolGen cpg = classGen.getConstantPool();
95          final InstructionList il = methodGen.getInstructionList();
96  
97          // context node is on the stack
98          int gname = cpg.addInterfaceMethodref(DOM_INTF,
99                                                "getNodeName",
100                                               "(I)Ljava/lang/String;");
101         int cmp = cpg.addMethodref(STRING_CLASS,
102                                    "equals", "(Ljava/lang/Object;)Z");
103 
104         // Push current node on the stack
105         il.append(methodGen.loadCurrentNode());
106         il.append(SWAP);
107 
108         // Overwrite current node with matching node
109         il.append(methodGen.storeCurrentNode());
110 
111         // If pattern not reduced then check kernel
112         if (!_typeChecked) {
113             il.append(methodGen.loadCurrentNode());
114             final int getType = cpg.addInterfaceMethodref(DOM_INTF,
115                                                           "getExpandedTypeID",
116                                                           "(I)I");
117             il.append(methodGen.loadDOM());
118             il.append(methodGen.loadCurrentNode());
119             il.append(new INVOKEINTERFACE(getType, 2));
120             il.append(new PUSH(cpg, DTM.PROCESSING_INSTRUCTION_NODE));
121             _falseList.add(il.append(new IF_ICMPEQ(null)));
122         }
123 
124         // Load the requested processing instruction name
125         il.append(new PUSH(cpg, _name));
126         // Load the current processing instruction's name
127         il.append(methodGen.loadDOM());
128         il.append(methodGen.loadCurrentNode());
129         il.append(new INVOKEINTERFACE(gname, 2));
130         // Compare the two strings
131         il.append(new INVOKEVIRTUAL(cmp));
132         _falseList.add(il.append(new IFEQ(null)));
133 
134         // Compile the expressions within the predicates
135         if (hasPredicates()) {
136             final int n = _predicates.size();
137             for (int i = 0; i < n; i++) {
138                 Predicate pred = (Predicate)_predicates.elementAt(i);
139                 Expression exp = pred.getExpr();
140                 exp.translateDesynthesized(classGen, methodGen);
141                 _trueList.append(exp._trueList);
142                 _falseList.append(exp._falseList);
143             }
144         }
145 
146         // Backpatch true list and restore current iterator/node
147         InstructionHandle restore;
148         restore = il.append(methodGen.storeCurrentNode());
149         backPatchTrueList(restore);
150         BranchHandle skipFalse = il.append(new GOTO(null));
151 
152         // Backpatch false list and restore current iterator/node
153         restore = il.append(methodGen.storeCurrentNode());
154         backPatchFalseList(restore);
155         _falseList.add(il.append(new GOTO(null)));
156 
157         // True list falls through
158         skipFalse.setTarget(il.append(NOP));
159     }
160 }