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 */
017package org.apache.commons.jxpath.ri.model.beans;
018
019import org.apache.commons.jxpath.JXPathContext;
020import org.apache.commons.jxpath.ri.QName;
021import 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 22:02:00 +0200 (Fr, 02 Mai 2008) $
033 */
034public 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}