    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}