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