    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    }