    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 java.util.Locale;
    020
    021    import org.apache.commons.jxpath.JXPathBeanInfo;
    022    import org.apache.commons.jxpath.JXPathIntrospector;
    023    import org.apache.commons.jxpath.ri.QName;
    024    import org.apache.commons.jxpath.ri.model.NodePointer;
    025
    026    /**
    027     * A Pointer that points to a JavaBean or a collection. It is either
    028     * the first element of a path or a pointer for a property value.
    029     * Typically there is a {@link BeanPropertyPointer} between two BeanPointers
    030     * in the chain.
    031     *
    032     * @author Dmitri Plotnikov
    033     * @version $Revision: 670727 $ $Date: 2008-06-23 15:10:38 -0500 (Mon, 23 Jun 2008) $
    034     */
    035    public class BeanPointer extends PropertyOwnerPointer {
    036        private QName name;
    037        private Object bean;
    038        private JXPathBeanInfo beanInfo;
    039
    040        private static final long serialVersionUID = -8227317938284982440L;
    041
    042        /**
    043         * Create a new BeanPointer.
    044         * @param name is the name given to the first node
    045         * @param bean pointed
    046         * @param beanInfo JXPathBeanInfo
    047         * @param locale Locale
    048         */
    049        public BeanPointer(QName name, Object bean, JXPathBeanInfo beanInfo,
    050                Locale locale) {
    051            super(null, locale);
    052            this.name = name;
    053            this.bean = bean;
    054            this.beanInfo = beanInfo;
    055        }
    056
    057        /**
    058         * Create a new BeanPointer.
    059         * @param parent pointer
    060         * @param name is the name given to the first node
    061         * @param bean pointed
    062         * @param beanInfo JXPathBeanInfo
    063         */
    064        public BeanPointer(NodePointer parent, QName name, Object bean,
    065                JXPathBeanInfo beanInfo) {
    066            super(parent);
    067            this.name = name;
    068            this.bean = bean;
    069            this.beanInfo = beanInfo;
    070        }
    071
    072        public PropertyPointer getPropertyPointer() {
    073            return new BeanPropertyPointer(this, beanInfo);
    074        }
    075
    076        public QName getName() {
    077            return name;
    078        }
    079
    080        public Object getBaseValue() {
    081            return bean;
    082        }
    083
    084        /**
    085         * {@inheritDoc}
    086         * @return false
    087         */
    088        public boolean isCollection() {
    089            return false;
    090        }
    091
    092        /**
    093         * {@inheritDoc}
    094         * @return 1
    095         */
    096        public int getLength() {
    097            return 1;
    098        }
    099
    100        public boolean isLeaf() {
    101            Object value = getNode();
    102            return value == null
    103                || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
    104        }
    105
    106        public int hashCode() {
    107            return name == null ? 0 : name.hashCode();
    108        }
    109
    110        public boolean equals(Object object) {
    111            if (object == this) {
    112                return true;
    113            }
    114
    115            if (!(object instanceof BeanPointer)) {
    116                return false;
    117            }
    118
    119            BeanPointer other = (BeanPointer) object;
    120            if (parent != other.parent && (parent == null || !parent.equals(other.parent))) {
    121                return false;
    122            }
    123
    124            if ((name == null && other.name != null)
    125                    || (name != null && !name.equals(other.name))) {
    126                return false;
    127            }
    128
    129            int iThis = (index == WHOLE_COLLECTION ? 0 : index);
    130            int iOther = (other.index == WHOLE_COLLECTION ? 0 : other.index);
    131            if (iThis != iOther) {
    132                return false;
    133            }
    134
    135            if (bean instanceof Number
    136                    || bean instanceof String
    137                    || bean instanceof Boolean) {
    138                return bean.equals(other.bean);
    139            }
    140            return bean == other.bean;
    141        }
    142
    143        /**
    144         * {@inheritDoc}
    145         * If the pointer has a parent, then parent's path.
    146         * If the bean is null, "null()".
    147         * If the bean is a primitive value, the value itself.
    148         * Otherwise - an empty string.
    149         */
    150        public String asPath() {
    151            if (parent != null) {
    152                return super.asPath();
    153            }
    154            if (bean == null) {
    155                return "null()";
    156            }
    157            if (bean instanceof Number) {
    158                String string = bean.toString();
    159                if (string.endsWith(".0")) {
    160                    string = string.substring(0, string.length() - 2);
    161                }
    162                return string;
    163            }
    164            if (bean instanceof Boolean) {
    165                return ((Boolean) bean).booleanValue() ? "true()" : "false()";
    166            }
    167            if (bean instanceof String) {
    168                return "'" + bean + "'";
    169            }
    170            return "/";
    171        }
    172    }