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.dynamic;
019
020import java.util.Locale;
021
022import org.apache.commons.jxpath.DynamicPropertyHandler;
023import org.apache.commons.jxpath.JXPathIntrospector;
024import org.apache.commons.jxpath.ri.QName;
025import org.apache.commons.jxpath.ri.model.NodeIterator;
026import org.apache.commons.jxpath.ri.model.NodePointer;
027import org.apache.commons.jxpath.ri.model.beans.PropertyIterator;
028import org.apache.commons.jxpath.ri.model.beans.PropertyOwnerPointer;
029import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
030
031/**
032 * A Pointer that points to an object with Dynamic Properties. It is used for the first element of a path; following elements will by of type
033 * {@link PropertyPointer}.
034 */
035public class DynamicPointer extends PropertyOwnerPointer {
036
037    private static final long serialVersionUID = -1842347025295904256L;
038
039    /**
040     * Qualified name.
041     */
042    private final QName qName;
043
044    /**
045     * Java bean.
046     */
047    private final Object bean;
048
049    /**
050     * Dynamic property handler.
051     */
052    private final DynamicPropertyHandler handler;
053
054    /**
055     * Constructs a new DynamicPointer.
056     *
057     * @param parent  parent pointer
058     * @param qName    property name
059     * @param bean    owning bean
060     * @param handler DynamicPropertyHandler
061     */
062    public DynamicPointer(final NodePointer parent, final QName qName, final Object bean, final DynamicPropertyHandler handler) {
063        super(parent);
064        this.qName = qName;
065        this.bean = bean;
066        this.handler = handler;
067    }
068
069    /**
070     * Constructs a new DynamicPointer.
071     *
072     * @param qName    property name
073     * @param bean    owning bean
074     * @param handler DynamicPropertyHandler
075     * @param locale  Locale
076     */
077    public DynamicPointer(final QName qName, final Object bean, final DynamicPropertyHandler handler, final Locale locale) {
078        super(null, locale);
079        this.qName = qName;
080        this.bean = bean;
081        this.handler = handler;
082    }
083
084    @Override
085    public String asPath() {
086        return parent == null ? "/" : super.asPath();
087    }
088
089    @Override
090    public NodeIterator attributeIterator(final QName qName) {
091        return new DynamicAttributeIterator(this, qName);
092    }
093
094    @Override
095    public NodeIterator createNodeIterator(final String property, final boolean reverse, final NodePointer startWith) {
096        return new PropertyIterator(this, property, reverse, startWith);
097    }
098
099    @Override
100    public boolean equals(final Object object) {
101        if (object == this) {
102            return true;
103        }
104        if (!(object instanceof DynamicPointer)) {
105            return false;
106        }
107        final DynamicPointer other = (DynamicPointer) object;
108        if (bean != other.bean) {
109            return false;
110        }
111        return qName == other.qName || qName != null && qName.equals(other.qName);
112    }
113
114    /**
115     * Returns the DP object iself.
116     *
117     * @return Object
118     */
119    @Override
120    public Object getBaseValue() {
121        return bean;
122    }
123
124    /**
125     * Returns 1.
126     *
127     * @return int
128     */
129    @Override
130    public int getLength() {
131        return 1;
132    }
133
134    @Override
135    public QName getName() {
136        return qName;
137    }
138
139    @Override
140    public PropertyPointer getPropertyPointer() {
141        return new DynamicPropertyPointer(this, handler);
142    }
143
144    @Override
145    public int hashCode() {
146        return System.identityHashCode(bean) + (qName == null ? 0 : qName.hashCode());
147    }
148
149    @Override
150    public boolean isCollection() {
151        return false;
152    }
153
154    @Override
155    public boolean isDynamicPropertyDeclarationSupported() {
156        return true;
157    }
158
159    @Override
160    public boolean isLeaf() {
161        final Object value = getNode();
162        return value == null || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
163    }
164}