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