1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. 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 package com.sun.org.apache.xpath.internal.axes; 22 23 import com.sun.org.apache.xml.internal.dtm.DTMIterator; 24 import com.sun.org.apache.xml.internal.utils.QName; 25 import com.sun.org.apache.xpath.internal.XPathContext; 26 import com.sun.org.apache.xpath.internal.objects.XObject; 27 import com.sun.org.apache.xpath.internal.patterns.NodeTest; 28 import java.util.List; 29 30 /** 31 * This class defines a simplified type of union iterator that only 32 * tests along the child axes. If the conditions are right, it is 33 * much faster than using a UnionPathIterator. 34 * 35 * @LastModified: Oct 2017 36 */ 37 public class UnionChildIterator extends ChildTestIterator 38 { 39 static final long serialVersionUID = 3500298482193003495L; 40 /** 41 * Even though these may hold full LocPathIterators, this array does 42 * not have to be cloned, since only the node test and predicate 43 * portion are used, and these only need static information. However, 44 * also note that index predicates can not be used! 45 */ 46 private PredicatedNodeTest[] m_nodeTests = null; 47 48 /** 49 * Constructor for UnionChildIterator 50 */ 51 public UnionChildIterator() 52 { 53 super(null); 54 } 55 56 /** 57 * Add a node test to the union list. 58 * 59 * @param test reference to a NodeTest, which will be added 60 * directly to the list of node tests (in other words, it will 61 * not be cloned). The parent of this test will be set to 62 * this object. 63 */ 64 public void addNodeTest(PredicatedNodeTest test) 65 { 66 67 // Increase array size by only 1 at a time. Fix this 68 // if it looks to be a problem. 69 if (null == m_nodeTests) 70 { 71 m_nodeTests = new PredicatedNodeTest[1]; 72 m_nodeTests[0] = test; 73 } 74 else 75 { 76 PredicatedNodeTest[] tests = m_nodeTests; 77 int len = m_nodeTests.length; 78 79 m_nodeTests = new PredicatedNodeTest[len + 1]; 80 81 System.arraycopy(tests, 0, m_nodeTests, 0, len); 82 83 m_nodeTests[len] = test; 84 } 85 test.exprSetParent(this); 86 } 87 88 /** 89 * This function is used to fixup variables from QNames to stack frame 90 * indexes at stylesheet build time. 91 * @param vars List of QNames that correspond to variables. This list 92 * should be searched backwards for the first qualified name that 93 * corresponds to the variable reference qname. The position of the 94 * QName in the vector from the start of the vector will be its position 95 * in the stack frame (but variables above the globalsTop value will need 96 * to be offset to the current stack frame). 97 */ 98 public void fixupVariables(List<QName> vars, int globalsSize) 99 { 100 super.fixupVariables(vars, globalsSize); 101 if (m_nodeTests != null) { 102 for (int i = 0; i < m_nodeTests.length; i++) { 103 m_nodeTests[i].fixupVariables(vars, globalsSize); 104 } 105 } 106 } 107 108 /** 109 * Test whether a specified node is visible in the logical view of a 110 * TreeWalker or NodeIterator. This function will be called by the 111 * implementation of TreeWalker and NodeIterator; it is not intended to 112 * be called directly from user code. 113 * @param n The node to check to see if it passes the filter or not. 114 * @return a constant to determine whether the node is accepted, 115 * rejected, or skipped, as defined above . 116 */ 117 public short acceptNode(int n) 118 { 119 XPathContext xctxt = getXPathContext(); 120 try 121 { 122 xctxt.pushCurrentNode(n); 123 for (int i = 0; i < m_nodeTests.length; i++) 124 { 125 PredicatedNodeTest pnt = m_nodeTests[i]; 126 XObject score = pnt.execute(xctxt, n); 127 if (score != NodeTest.SCORE_NONE) 128 { 129 // Note that we are assuming there are no positional predicates! 130 if (pnt.getPredicateCount() > 0) 131 { 132 if (pnt.executePredicates(n, xctxt)) 133 return DTMIterator.FILTER_ACCEPT; 134 } 135 else 136 return DTMIterator.FILTER_ACCEPT; 137 138 } 139 } 140 } 141 catch (javax.xml.transform.TransformerException se) 142 { 143 144 // TODO: Fix this. 145 throw new RuntimeException(se.getMessage()); 146 } 147 finally 148 { 149 xctxt.popCurrentNode(); 150 } 151 return DTMIterator.FILTER_SKIP; 152 } 153 154 }