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.container;
19  
20  import java.util.Locale;
21  
22  import org.apache.commons.jxpath.Container;
23  import org.apache.commons.jxpath.ri.QName;
24  import org.apache.commons.jxpath.ri.compiler.NodeTest;
25  import org.apache.commons.jxpath.ri.model.NodeIterator;
26  import org.apache.commons.jxpath.ri.model.NodePointer;
27  import org.apache.commons.jxpath.util.ValueUtils;
28  
29  /**
30   * Transparent pointer to a Container. The {@link #getValue()} method returns the contents of the container, rather than the container itself.
31   */
32  public class ContainerPointer extends NodePointer {
33  
34      private static final long serialVersionUID = 6140752946621686118L;
35  
36      /**
37       * A Container.
38       */
39      private final Container container;
40  
41      /**
42       * Supports {@link #getImmediateValuePointer()}.
43       */
44      private NodePointer valuePointer;
45  
46      /**
47       * Constructs a new ContainerPointer.
48       *
49       * @param container Container object
50       * @param locale    Locale
51       */
52      public ContainerPointer(final Container container, final Locale locale) {
53          super(null, locale);
54          this.container = container;
55      }
56  
57      /**
58       * Constructs a new ContainerPointer.
59       *
60       * @param parent    parent pointer
61       * @param container Container object
62       */
63      public ContainerPointer(final NodePointer parent, final Container container) {
64          super(parent);
65          this.container = container;
66      }
67  
68      @Override
69      public String asPath() {
70          return parent == null ? "/" : parent.asPath();
71      }
72  
73      @Override
74      public NodeIterator attributeIterator(final QName qName) {
75          return getValuePointer().attributeIterator(qName);
76      }
77  
78      @Override
79      public NodeIterator childIterator(final NodeTest test, final boolean reverse, final NodePointer startWith) {
80          return getValuePointer().childIterator(test, reverse, startWith);
81      }
82  
83      @Override
84      public int compareChildNodePointers(final NodePointer pointer1, final NodePointer pointer2) {
85          return pointer1.getIndex() - pointer2.getIndex();
86      }
87  
88      @Override
89      public boolean equals(final Object object) {
90          if (object == this) {
91              return true;
92          }
93          if (!(object instanceof ContainerPointer)) {
94              return false;
95          }
96          final ContainerPointer other = (ContainerPointer) object;
97          return container == other.container && index == other.index;
98      }
99  
100     @Override
101     public Object getBaseValue() {
102         return container;
103     }
104 
105     @Override
106     public Object getImmediateNode() {
107         final Object value = getBaseValue();
108         if (index != WHOLE_COLLECTION) {
109             return index >= 0 && index < getLength() ? ValueUtils.getValue(value, index) : null;
110         }
111         return ValueUtils.getValue(value);
112     }
113 
114     @Override
115     public NodePointer getImmediateValuePointer() {
116         if (valuePointer == null) {
117             final Object value = getImmediateNode();
118             valuePointer = newChildNodePointer(this, getName(), value);
119         }
120         return valuePointer;
121     }
122 
123     @Override
124     public int getLength() {
125         final Object value = getBaseValue();
126         return value == null ? 1 : ValueUtils.getLength(value);
127     }
128 
129     @Override
130     public QName getName() {
131         return null;
132     }
133 
134     @Override
135     public String getNamespaceURI(final String prefix) {
136         return getValuePointer().getNamespaceURI(prefix);
137     }
138 
139     @Override
140     public int hashCode() {
141         return System.identityHashCode(container) + index;
142     }
143 
144     @Override
145     public boolean isCollection() {
146         final Object value = getBaseValue();
147         return value != null && ValueUtils.isCollection(value);
148     }
149 
150     /**
151      * This type of node is auxiliary.
152      *
153      * @return {@code true}.
154      */
155     @Override
156     public boolean isContainer() {
157         return true;
158     }
159 
160     @Override
161     public boolean isLeaf() {
162         return getValuePointer().isLeaf();
163     }
164 
165     @Override
166     public NodeIterator namespaceIterator() {
167         return getValuePointer().namespaceIterator();
168     }
169 
170     @Override
171     public NodePointer namespacePointer(final String namespace) {
172         return getValuePointer().namespacePointer(namespace);
173     }
174 
175     @Override
176     public void setValue(final Object value) {
177         // TODO: what if this is a collection?
178         container.setValue(value);
179     }
180 
181     @Override
182     public boolean testNode(final NodeTest nodeTest) {
183         return getValuePointer().testNode(nodeTest);
184     }
185 }