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
018package org.apache.commons.jxpath.ri.model.beans;
019
020import java.util.Locale;
021
022import org.apache.commons.jxpath.JXPathContext;
023import org.apache.commons.jxpath.ri.QName;
024import org.apache.commons.jxpath.ri.model.NodePointer;
025
026/**
027 * Pointer whose value is {@code null}.
028 */
029public class NullPointer extends PropertyOwnerPointer {
030
031    private static final long serialVersionUID = 2193425983220679887L;
032
033    /**
034     * The name of this node
035     */
036    private final QName qName;
037
038    /**
039     * Optional ID, may be null.
040     */
041    private final String id;
042
043    /**
044     * Constructs a new NullPointer.
045     *
046     * @param locale Locale.
047     * @param id     ID.
048     */
049    public NullPointer(final Locale locale, final String id) {
050        super(null, locale);
051        this.id = id;
052        this.qName = null;
053    }
054
055    /**
056     * Used for the root node.
057     *
058     * @param parent parent pointer
059     * @param qName  node name
060     */
061    public NullPointer(final NodePointer parent, final QName qName) {
062        super(parent);
063        this.qName = qName;
064        this.id = null;
065    }
066
067    /**
068     * Constructs a new NullPointer.
069     *
070     * @param qName  node name
071     * @param locale Locale
072     */
073    public NullPointer(final QName qName, final Locale locale) {
074        super(null, locale);
075        this.qName = qName;
076        this.id = null;
077    }
078
079    @Override
080    public String asPath() {
081        if (id != null) {
082            return "id(" + id + ")";
083        }
084        return parent == null ? "null()" : super.asPath();
085    }
086
087    @Override
088    public NodePointer createChild(final JXPathContext context, final QName qName, final int index) {
089        return createPath(context).createChild(context, qName, index);
090    }
091
092    @Override
093    public NodePointer createChild(final JXPathContext context, final QName qName, final int index, final Object value) {
094        return createPath(context).createChild(context, qName, index, value);
095    }
096
097    @Override
098    public NodePointer createPath(final JXPathContext context) {
099        if (parent != null) {
100            return parent.createPath(context).getValuePointer();
101        }
102        throw new UnsupportedOperationException("Cannot create the root object: " + asPath());
103    }
104
105    @Override
106    public NodePointer createPath(final JXPathContext context, final Object value) {
107        if (parent != null) {
108            return parent.createPath(context, value).getValuePointer();
109        }
110        throw new UnsupportedOperationException("Cannot create the root object: " + asPath());
111    }
112
113    @Override
114    public boolean equals(final Object object) {
115        if (object == this) {
116            return true;
117        }
118        if (!(object instanceof NullPointer)) {
119            return false;
120        }
121        final NullPointer other = (NullPointer) object;
122        return qName == other.qName || qName != null && qName.equals(other.qName);
123    }
124
125    @Override
126    public Object getBaseValue() {
127        return null;
128    }
129
130    @Override
131    public int getLength() {
132        return 0;
133    }
134
135    @Override
136    public QName getName() {
137        return qName;
138    }
139
140    @Override
141    public PropertyPointer getPropertyPointer() {
142        return new NullPropertyPointer(this);
143    }
144
145    @Override
146    public int hashCode() {
147        return qName == null ? 0 : qName.hashCode();
148    }
149
150    @Override
151    public boolean isActual() {
152        return false;
153    }
154
155    @Override
156    public boolean isCollection() {
157        return false;
158    }
159
160    @Override
161    public boolean isLeaf() {
162        return true;
163    }
164}