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.model.beans; 019 020import org.apache.commons.jxpath.JXPathContext; 021import org.apache.commons.jxpath.ri.QName; 022import org.apache.commons.jxpath.ri.model.NodePointer; 023 024/** 025 * Used when there is a need to construct a Pointer for a collection element that does not exist. For example, if the path is "foo[3]", but the collection "foo" 026 * only has one element or is empty or is null, the NullElementPointer can be used to capture this situation without putting a regular NodePointer into an 027 * invalid state. Just create a NullElementPointer with index 2 (= 3 - 1) and a "foo" pointer as the parent. 028 */ 029public class NullElementPointer extends CollectionPointer { 030 031 private static final long serialVersionUID = 8714236818791036721L; 032 033 /** 034 * Constructs a new NullElementPointer. 035 * 036 * @param parent parent pointer 037 * @param index int 038 */ 039 public NullElementPointer(final NodePointer parent, final int index) { 040 super(parent, (Object) null); 041 this.index = index; 042 } 043 044 @Override 045 public String asPath() { 046 final StringBuilder buffer = new StringBuilder(); 047 final NodePointer parent = getImmediateParentPointer(); 048 if (parent != null) { 049 buffer.append(parent.asPath()); 050 } 051 if (index != WHOLE_COLLECTION) { 052 // Address the list[1][2] case 053 if (parent != null && parent.getIndex() != WHOLE_COLLECTION) { 054 buffer.append("/."); 055 } else if (parent != null && parent.getImmediateParentPointer() != null && parent.getImmediateParentPointer().getIndex() != WHOLE_COLLECTION) { 056 buffer.append("/."); 057 } 058 buffer.append("[").append(index + 1).append(']'); 059 } 060 return buffer.toString(); 061 } 062 063 @Override 064 public NodePointer createPath(final JXPathContext context) { 065 return parent.createChild(context, null, index); 066 } 067 068 @Override 069 public NodePointer createPath(final JXPathContext context, final Object value) { 070 return parent.createChild(context, null, index, value); 071 } 072 073 @Override 074 public boolean equals(final Object object) { 075 if (object == this) { 076 return true; 077 } 078 if (!(object instanceof NullElementPointer)) { 079 return false; 080 } 081 final NullElementPointer other = (NullElementPointer) object; 082 return getImmediateParentPointer() == other.getImmediateParentPointer() && index == other.index; 083 } 084 085 @Override 086 public Object getBaseValue() { 087 return null; 088 } 089 090 @Override 091 public Object getImmediateNode() { 092 return null; 093 } 094 095 @Override 096 public int getLength() { 097 return 0; 098 } 099 100 @Override 101 public QName getName() { 102 return null; 103 } 104 105 /** 106 * Gets the property pointer for this. 107 * 108 * @return PropertyPointer 109 */ 110 public PropertyPointer getPropertyPointer() { 111 return new NullPropertyPointer(this); 112 } 113 114 @Override 115 public NodePointer getValuePointer() { 116 return new NullPointer(this, getName()); 117 } 118 119 @Override 120 public int hashCode() { 121 return getImmediateParentPointer().hashCode() + index; 122 } 123 124 @Override 125 public boolean isActual() { 126 return false; 127 } 128 129 @Override 130 public boolean isCollection() { 131 return false; 132 } 133 134 @Override 135 public boolean isContainer() { 136 return true; 137 } 138 139 @Override 140 public boolean isLeaf() { 141 return true; 142 } 143 144 @Override 145 public void setValue(final Object value) { 146 throw new UnsupportedOperationException("Collection element does not exist: " + this); 147 } 148}