View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jxpath.ri.model.beans;
19  
20  import org.apache.commons.jxpath.JXPathContext;
21  import org.apache.commons.jxpath.ri.QName;
22  import org.apache.commons.jxpath.ri.model.NodePointer;
23  
24  /**
25   * 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"
26   * 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
27   * invalid state. Just create a NullElementPointer with index 2 (= 3 - 1) and a "foo" pointer as the parent.
28   */
29  public class NullElementPointer extends CollectionPointer {
30  
31      private static final long serialVersionUID = 8714236818791036721L;
32  
33      /**
34       * Constructs a new NullElementPointer.
35       *
36       * @param parent parent pointer
37       * @param index  int
38       */
39      public NullElementPointer(final NodePointer parent, final int index) {
40          super(parent, (Object) null);
41          this.index = index;
42      }
43  
44      @Override
45      public String asPath() {
46          final StringBuilder buffer = new StringBuilder();
47          final NodePointer parent = getImmediateParentPointer();
48          if (parent != null) {
49              buffer.append(parent.asPath());
50          }
51          if (index != WHOLE_COLLECTION) {
52              // Address the list[1][2] case
53              if (parent != null && parent.getIndex() != WHOLE_COLLECTION) {
54                  buffer.append("/.");
55              } else if (parent != null && parent.getImmediateParentPointer() != null && parent.getImmediateParentPointer().getIndex() != WHOLE_COLLECTION) {
56                  buffer.append("/.");
57              }
58              buffer.append("[").append(index + 1).append(']');
59          }
60          return buffer.toString();
61      }
62  
63      @Override
64      public NodePointer createPath(final JXPathContext context) {
65          return parent.createChild(context, null, index);
66      }
67  
68      @Override
69      public NodePointer createPath(final JXPathContext context, final Object value) {
70          return parent.createChild(context, null, index, value);
71      }
72  
73      @Override
74      public boolean equals(final Object object) {
75          if (object == this) {
76              return true;
77          }
78          if (!(object instanceof NullElementPointer)) {
79              return false;
80          }
81          final NullElementPointer other = (NullElementPointer) object;
82          return getImmediateParentPointer() == other.getImmediateParentPointer() && index == other.index;
83      }
84  
85      @Override
86      public Object getBaseValue() {
87          return null;
88      }
89  
90      @Override
91      public Object getImmediateNode() {
92          return null;
93      }
94  
95      @Override
96      public int getLength() {
97          return 0;
98      }
99  
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 }