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 package org.apache.commons.jxpath.ri.model.container;
018
019 import java.util.Locale;
020
021 import org.apache.commons.jxpath.Container;
022 import org.apache.commons.jxpath.ri.QName;
023 import org.apache.commons.jxpath.ri.compiler.NodeTest;
024 import org.apache.commons.jxpath.ri.model.NodeIterator;
025 import org.apache.commons.jxpath.ri.model.NodePointer;
026 import org.apache.commons.jxpath.util.ValueUtils;
027
028 /**
029 * Transparent pointer to a Container. The {@link #getValue()} method
030 * returns the contents of the container, rather than the container
031 * itself.
032 *
033 * @author Dmitri Plotnikov
034 * @version $Revision: 652884 $ $Date: 2008-05-02 15:02:00 -0500 (Fri, 02 May 2008) $
035 */
036 public class ContainerPointer extends NodePointer {
037 private Container container;
038 private NodePointer valuePointer;
039
040 private static final long serialVersionUID = 6140752946621686118L;
041
042 /**
043 * Create a new ContainerPointer.
044 * @param container Container object
045 * @param locale Locale
046 */
047 public ContainerPointer(Container container, Locale locale) {
048 super(null, locale);
049 this.container = container;
050 }
051
052 /**
053 * Create a new ContainerPointer.
054 * @param parent parent pointer
055 * @param container Container object
056 */
057 public ContainerPointer(NodePointer parent, Container container) {
058 super(parent);
059 this.container = container;
060 }
061
062 /**
063 * This type of node is auxiliary.
064 * @return <code>true</code>.
065 */
066 public boolean isContainer() {
067 return true;
068 }
069
070 public QName getName() {
071 return null;
072 }
073
074 public Object getBaseValue() {
075 return container;
076 }
077
078 public boolean isCollection() {
079 Object value = getBaseValue();
080 return value != null && ValueUtils.isCollection(value);
081 }
082
083 public int getLength() {
084 Object value = getBaseValue();
085 return value == null ? 1 : ValueUtils.getLength(value);
086 }
087
088 public boolean isLeaf() {
089 return getValuePointer().isLeaf();
090 }
091
092 public Object getImmediateNode() {
093 Object value = getBaseValue();
094 if (index != WHOLE_COLLECTION) {
095 return index >= 0 && index < getLength() ? ValueUtils.getValue(value, index) : null;
096 }
097 return ValueUtils.getValue(value);
098 }
099
100 public void setValue(Object value) {
101 // TODO: what if this is a collection?
102 container.setValue(value);
103 }
104
105 public NodePointer getImmediateValuePointer() {
106 if (valuePointer == null) {
107 Object value = getImmediateNode();
108 valuePointer = NodePointer.newChildNodePointer(this, getName(), value);
109 }
110 return valuePointer;
111 }
112
113 public int hashCode() {
114 return System.identityHashCode(container) + index;
115 }
116
117 public boolean equals(Object object) {
118 if (object == this) {
119 return true;
120 }
121
122 if (!(object instanceof ContainerPointer)) {
123 return false;
124 }
125
126 ContainerPointer other = (ContainerPointer) object;
127 return container == other.container && index == other.index;
128 }
129
130 public NodeIterator childIterator(
131 NodeTest test,
132 boolean reverse,
133 NodePointer startWith) {
134 return getValuePointer().childIterator(test, reverse, startWith);
135 }
136
137 public NodeIterator attributeIterator(QName name) {
138 return getValuePointer().attributeIterator(name);
139 }
140
141 public NodeIterator namespaceIterator() {
142 return getValuePointer().namespaceIterator();
143 }
144
145 public NodePointer namespacePointer(String namespace) {
146 return getValuePointer().namespacePointer(namespace);
147 }
148
149 public boolean testNode(NodeTest nodeTest) {
150 return getValuePointer().testNode(nodeTest);
151 }
152
153 public int compareChildNodePointers(
154 NodePointer pointer1,
155 NodePointer pointer2) {
156 return pointer1.getIndex() - pointer2.getIndex();
157 }
158
159 public String getNamespaceURI(String prefix) {
160 return getValuePointer().getNamespaceURI(prefix);
161 }
162
163 public String asPath() {
164 return parent == null ? "/" : parent.asPath();
165 }
166 }