001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.jxpath.ri.axes; 019 020import org.apache.commons.jxpath.ri.EvalContext; 021import org.apache.commons.jxpath.ri.compiler.NodeTest; 022import org.apache.commons.jxpath.ri.model.NodePointer; 023 024/** 025 * EvalContext that walks the "ancestor::" and "ancestor-or-self::" axes. 026 */ 027public class AncestorContext extends EvalContext { 028 029 private final NodeTest nodeTest; 030 private boolean setStarted; 031 private NodePointer currentNodePointer; 032 private final boolean includeSelf; 033 034 /** 035 * Constructs a new AncestorContext. 036 * 037 * @param parentContext represents the previous step on the path 038 * @param includeSelf differentiates between "ancestor::" and "ancestor-or-self::" axes 039 * @param nodeTest is the name of the element(s) we are looking for 040 */ 041 public AncestorContext(final EvalContext parentContext, final boolean includeSelf, final NodeTest nodeTest) { 042 super(parentContext); 043 this.includeSelf = includeSelf; 044 this.nodeTest = nodeTest; 045 } 046 047 @Override 048 public NodePointer getCurrentNodePointer() { 049 return currentNodePointer; 050 } 051 052 @Override 053 public int getDocumentOrder() { 054 return -1; 055 } 056 057 @Override 058 public boolean nextNode() { 059 if (!setStarted) { 060 setStarted = true; 061 currentNodePointer = parentContext.getCurrentNodePointer(); 062 if (includeSelf && currentNodePointer.testNode(nodeTest)) { 063 position++; 064 return true; 065 } 066 } 067 while (true) { 068 currentNodePointer = currentNodePointer.getImmediateParentPointer(); 069 if (currentNodePointer == null) { 070 return false; 071 } 072 if (currentNodePointer.testNode(nodeTest)) { 073 position++; 074 return true; 075 } 076 } 077 } 078 079 @Override 080 public void reset() { 081 super.reset(); 082 setStarted = false; 083 } 084 085 @Override 086 public boolean setPosition(final int position) { 087 if (position < getCurrentPosition()) { 088 reset(); 089 } 090 while (getCurrentPosition() < position) { 091 if (!nextNode()) { 092 return false; 093 } 094 } 095 return true; 096 } 097}