~vcs-imports/xena/trunk

« back to all changes in this revision

Viewing changes to ext/src/xalan-j_2_7_1/src/org/apache/xalan/xsltc/compiler/UnionPathExpr.java

  • Committer: matthewoliver
  • Date: 2009-12-10 03:18:07 UTC
  • Revision ID: vcs-imports@canonical.com-20091210031807-l086qguzdlljtkl9
Merged Xena Testing into Xena Stable for the Xena 5 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one
 
3
 * or more contributor license agreements. See the NOTICE file
 
4
 * distributed with this work for additional information
 
5
 * regarding copyright ownership. The ASF licenses this file
 
6
 * to you under the Apache License, Version 2.0 (the  "License");
 
7
 * you may not use this file except in compliance with the License.
 
8
 * You may obtain a copy of the License at
 
9
 *
 
10
 *     http://www.apache.org/licenses/LICENSE-2.0
 
11
 *
 
12
 * Unless required by applicable law or agreed to in writing, software
 
13
 * distributed under the License is distributed on an "AS IS" BASIS,
 
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
15
 * See the License for the specific language governing permissions and
 
16
 * limitations under the License.
 
17
 */
 
18
/*
 
19
 * $Id: UnionPathExpr.java,v 1.2 2009/12/10 03:18:18 matthewoliver Exp $
 
20
 */
 
21
 
 
22
package org.apache.xalan.xsltc.compiler;
 
23
 
 
24
import java.util.Vector;
 
25
 
 
26
import org.apache.bcel.generic.ConstantPoolGen;
 
27
import org.apache.bcel.generic.INVOKEINTERFACE;
 
28
import org.apache.bcel.generic.INVOKESPECIAL;
 
29
import org.apache.bcel.generic.INVOKEVIRTUAL;
 
30
import org.apache.bcel.generic.InstructionList;
 
31
import org.apache.bcel.generic.NEW;
 
32
import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
 
33
import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
 
34
import org.apache.xalan.xsltc.compiler.util.Type;
 
35
import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
 
36
import org.apache.xml.dtm.Axis;
 
37
import org.apache.xml.dtm.DTM;
 
38
 
 
39
/**
 
40
 * @author Jacek Ambroziak
 
41
 * @author Santiago Pericas-Geertsen
 
42
 */
 
43
final class UnionPathExpr extends Expression {
 
44
 
 
45
    private final Expression _pathExpr;
 
46
    private final Expression _rest;
 
47
    private boolean _reverse = false;
 
48
 
 
49
    // linearization for top level UnionPathExprs
 
50
    private Expression[] _components;
 
51
    
 
52
    public UnionPathExpr(Expression pathExpr, Expression rest) {
 
53
        _pathExpr = pathExpr;
 
54
        _rest     = rest;
 
55
    }
 
56
 
 
57
    public void setParser(Parser parser) {
 
58
        super.setParser(parser);
 
59
        // find all expressions in this Union
 
60
        final Vector components = new Vector();
 
61
        flatten(components);
 
62
        final int size = components.size();
 
63
        _components = (Expression[])components.toArray(new Expression[size]);
 
64
        for (int i = 0; i < size; i++) {
 
65
            _components[i].setParser(parser);
 
66
            _components[i].setParent(this);
 
67
            if (_components[i] instanceof Step) {
 
68
                final Step step = (Step)_components[i];
 
69
                final int axis = step.getAxis();
 
70
                final int type = step.getNodeType();
 
71
                // Put attribute iterators first
 
72
                if ((axis == Axis.ATTRIBUTE) || (type == DTM.ATTRIBUTE_NODE)) {
 
73
                    _components[i] = _components[0];
 
74
                    _components[0] = step;
 
75
                }
 
76
                // Check if the union contains a reverse iterator
 
77
        if (Axis.isReverse(axis)) _reverse = true;
 
78
            }
 
79
        }
 
80
        // No need to reverse anything if another expression lies on top of this
 
81
        if (getParent() instanceof Expression) _reverse = false;
 
82
    }
 
83
    
 
84
    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
 
85
        final int length = _components.length;
 
86
        for (int i = 0; i < length; i++) {
 
87
            if (_components[i].typeCheck(stable) != Type.NodeSet) {
 
88
                _components[i] = new CastExpr(_components[i], Type.NodeSet);
 
89
            }
 
90
        }
 
91
        return _type = Type.NodeSet;    
 
92
    }
 
93
 
 
94
    public String toString() {
 
95
        return "union(" + _pathExpr + ", " + _rest + ')';
 
96
    }
 
97
        
 
98
    private void flatten(Vector components) {
 
99
        components.addElement(_pathExpr);
 
100
        if (_rest != null) {
 
101
            if (_rest instanceof UnionPathExpr) {
 
102
                ((UnionPathExpr)_rest).flatten(components);
 
103
            }
 
104
            else {
 
105
                components.addElement(_rest);
 
106
            }
 
107
        }
 
108
    }
 
109
 
 
110
    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 
111
        final ConstantPoolGen cpg = classGen.getConstantPool();
 
112
        final InstructionList il = methodGen.getInstructionList();
 
113
 
 
114
        final int init = cpg.addMethodref(UNION_ITERATOR_CLASS,
 
115
                                          "<init>",
 
116
                                          "("+DOM_INTF_SIG+")V");
 
117
        final int iter = cpg.addMethodref(UNION_ITERATOR_CLASS,
 
118
                                          ADD_ITERATOR,
 
119
                                          ADD_ITERATOR_SIG);
 
120
 
 
121
        // Create the UnionIterator and leave it on the stack
 
122
        il.append(new NEW(cpg.addClass(UNION_ITERATOR_CLASS)));
 
123
        il.append(DUP);
 
124
        il.append(methodGen.loadDOM());
 
125
        il.append(new INVOKESPECIAL(init));
 
126
 
 
127
        // Add the various iterators to the UnionIterator
 
128
        final int length = _components.length;
 
129
        for (int i = 0; i < length; i++) {
 
130
            _components[i].translate(classGen, methodGen);
 
131
            il.append(new INVOKEVIRTUAL(iter));
 
132
        }
 
133
 
 
134
        // Order the iterator only if strictly needed
 
135
        if (_reverse) {
 
136
            final int order = cpg.addInterfaceMethodref(DOM_INTF,
 
137
                                                        ORDER_ITERATOR,
 
138
                                                        ORDER_ITERATOR_SIG);
 
139
            il.append(methodGen.loadDOM());
 
140
            il.append(SWAP);
 
141
            il.append(methodGen.loadContextNode());
 
142
            il.append(new INVOKEINTERFACE(order, 3));
 
143
 
 
144
        }
 
145
    }
 
146
}