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.Function; 021import org.apache.commons.jxpath.JXPathContext; 022import org.apache.commons.jxpath.NodeSet; 023import org.apache.commons.jxpath.ri.EvalContext; 024import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl; 025import org.apache.commons.jxpath.ri.QName; 026import org.apache.commons.jxpath.ri.model.NodePointer; 027 028/** 029 * EvalContext that is used to hold the root node for the path traversal. 030 */ 031public class RootContext extends EvalContext { 032 033 /** 034 * Unknown value marker. 035 */ 036 public static final Object UNKNOWN_VALUE = new Object(); 037 038 private static final int MAX_REGISTER = 4; 039 private final JXPathContextReferenceImpl jxpathContext; 040 private final NodePointer pointer; 041 private Object[] registers; 042 private int availableRegister; 043 044 /** 045 * Constructs a new RootContext. 046 * 047 * @param jxpathContext context 048 * @param pointer pointer 049 */ 050 public RootContext(final JXPathContextReferenceImpl jxpathContext, final NodePointer pointer) { 051 super(null); 052 this.jxpathContext = jxpathContext; 053 this.pointer = pointer; 054 if (pointer != null) { 055 pointer.setNamespaceResolver(jxpathContext.getNamespaceResolver()); 056 } 057 } 058 059 /** 060 * Gets absolute root context 061 * 062 * @return EvalContext 063 */ 064 public EvalContext getAbsoluteRootContext() { 065 return jxpathContext.getAbsoluteRootContext(); 066 } 067 068 /** 069 * Gets a context that points to the specified object. 070 * 071 * @param constant object 072 * @return EvalContext 073 */ 074 public EvalContext getConstantContext(final Object constant) { 075 if (constant instanceof NodeSet) { 076 return new NodeSetContext(new RootContext(jxpathContext, null), (NodeSet) constant); 077 } 078 NodePointer pointer; 079 if (constant instanceof NodePointer) { 080 pointer = (NodePointer) constant; 081 } else { 082 pointer = NodePointer.newNodePointer(new QName(null, ""), constant, null); 083 } 084 return new InitialContext(new RootContext(jxpathContext, pointer)); 085 } 086 087 @Override 088 public NodePointer getCurrentNodePointer() { 089 return pointer; 090 } 091 092 @Override 093 public int getCurrentPosition() { 094 throw new UnsupportedOperationException(); 095 } 096 097 /** 098 * Gets the specified function from the context. 099 * 100 * @param functionName QName 101 * @param parameters Object[] 102 * @return Function 103 */ 104 public Function getFunction(final QName functionName, final Object[] parameters) { 105 return jxpathContext.getFunction(functionName, parameters); 106 } 107 108 @Override 109 public JXPathContext getJXPathContext() { 110 return jxpathContext; 111 } 112 113 /** 114 * Gets a registered value. 115 * 116 * @param id int 117 * @return Object 118 */ 119 public Object getRegisteredValue(final int id) { 120 if (registers == null || id >= MAX_REGISTER || id == -1) { 121 return UNKNOWN_VALUE; 122 } 123 return registers[id]; 124 } 125 126 @Override 127 public RootContext getRootContext() { 128 return this; 129 } 130 131 @Override 132 public Object getValue() { 133 return pointer; 134 } 135 136 /** 137 * Gets variable context. 138 * 139 * @param variableName variable name 140 * @return EvalContext 141 */ 142 public EvalContext getVariableContext(final QName variableName) { 143 return new InitialContext(new RootContext(jxpathContext, jxpathContext.getVariablePointer(variableName))); 144 } 145 146 @Override 147 public boolean nextNode() { 148 throw new UnsupportedOperationException(); 149 } 150 151 @Override 152 public boolean nextSet() { 153 throw new UnsupportedOperationException(); 154 } 155 156 @Override 157 public boolean setPosition(final int position) { 158 throw new UnsupportedOperationException(); 159 } 160 161 /** 162 * Sets the next registered value. 163 * 164 * @param value Object 165 * @return the id that can reclaim value. 166 */ 167 public int setRegisteredValue(final Object value) { 168 if (registers == null) { 169 registers = new Object[MAX_REGISTER]; 170 for (int i = 0; i < MAX_REGISTER; i++) { 171 registers[i] = UNKNOWN_VALUE; 172 } 173 } 174 if (availableRegister >= MAX_REGISTER) { 175 return -1; 176 } 177 registers[availableRegister] = value; 178 availableRegister++; 179 return availableRegister - 1; 180 } 181 182 @Override 183 public String toString() { 184 return super.toString() + ":" + pointer.asPath(); 185 } 186}