001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: AbsolutePathPattern.java 468650 2006-10-28 07:03:30Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler;
023    
024    import org.apache.bcel.generic.BranchHandle;
025    import org.apache.bcel.generic.ConstantPoolGen;
026    import org.apache.bcel.generic.GOTO_W;
027    import org.apache.bcel.generic.IF_ICMPEQ;
028    import org.apache.bcel.generic.ILOAD;
029    import org.apache.bcel.generic.INVOKEINTERFACE;
030    import org.apache.bcel.generic.ISTORE;
031    import org.apache.bcel.generic.InstructionHandle;
032    import org.apache.bcel.generic.InstructionList;
033    import org.apache.bcel.generic.LocalVariableGen;
034    import org.apache.bcel.generic.PUSH;
035    import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
036    import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
037    import org.apache.xalan.xsltc.compiler.util.Type;
038    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
039    import org.apache.xalan.xsltc.compiler.util.Util;
040    import org.apache.xml.dtm.DTM;
041    
042    /**
043     * @author Jacek Ambroziak
044     * @author Santiago Pericas-Geertsen
045     */
046    final class AbsolutePathPattern extends LocationPathPattern {
047        private final RelativePathPattern _left; // may be null
048    
049        public AbsolutePathPattern(RelativePathPattern left) {
050            _left = left;
051            if (left != null) {
052                left.setParent(this);
053            }
054        }
055    
056        public void setParser(Parser parser) {
057            super.setParser(parser);
058            if (_left != null)
059                _left.setParser(parser);
060        }
061        
062        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
063            return _left == null ? Type.Root : _left.typeCheck(stable);
064        }
065    
066        public boolean isWildcard() {
067            return false;
068        }
069            
070        public StepPattern getKernelPattern() {
071            return _left != null ? _left.getKernelPattern() : null;
072        }
073            
074        public void reduceKernelPattern() {
075            _left.reduceKernelPattern();
076        }
077            
078        public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
079            final ConstantPoolGen cpg = classGen.getConstantPool();
080            final InstructionList il = methodGen.getInstructionList();
081    
082            if (_left != null) {
083                if (_left instanceof StepPattern) {
084                    final LocalVariableGen local = 
085                        // absolute path pattern temporary
086                        methodGen.addLocalVariable2("apptmp", 
087                                                    Util.getJCRefType(NODE_SIG),
088                                                    null);
089                    il.append(DUP);
090                    local.setStart(il.append(new ISTORE(local.getIndex())));
091                    _left.translate(classGen, methodGen);
092                    il.append(methodGen.loadDOM());
093                    local.setEnd(il.append(new ILOAD(local.getIndex())));
094                    methodGen.removeLocalVariable(local);
095                }
096                else {
097                    _left.translate(classGen, methodGen);
098                }
099            }
100    
101            final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
102                                                            GET_PARENT,
103                                                            GET_PARENT_SIG);
104            final int getType = cpg.addInterfaceMethodref(DOM_INTF,
105                                                          "getExpandedTypeID",
106                                                          "(I)I");
107    
108            InstructionHandle begin = il.append(methodGen.loadDOM());
109            il.append(SWAP);
110            il.append(new INVOKEINTERFACE(getParent, 2));
111            if (_left instanceof AncestorPattern) { 
112                il.append(methodGen.loadDOM());
113                il.append(SWAP);
114            }
115            il.append(new INVOKEINTERFACE(getType, 2));
116            il.append(new PUSH(cpg, DTM.DOCUMENT_NODE));
117            
118            final BranchHandle skip = il.append(new IF_ICMPEQ(null));
119            _falseList.add(il.append(new GOTO_W(null)));
120            skip.setTarget(il.append(NOP));
121    
122            if (_left != null) {
123                _left.backPatchTrueList(begin);
124                
125                /*
126                 * If _left is an ancestor pattern, backpatch this pattern's false
127                 * list to the loop that searches for more ancestors.
128                 */
129                if (_left instanceof AncestorPattern) {
130                    final AncestorPattern ancestor = (AncestorPattern) _left;
131                    _falseList.backPatch(ancestor.getLoopHandle());         // clears list
132                }
133                _falseList.append(_left._falseList);
134            }
135        }
136            
137        public String toString() {
138            return "absolutePathPattern(" + (_left != null ? _left.toString() : ")");
139        }
140    }