    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jxpath.ri.model.beans;
    17
    18  import java.util.Locale;
    19
    20  import org.apache.commons.jxpath.JXPathBeanInfo;
    21  import org.apache.commons.jxpath.JXPathIntrospector;
    22  import org.apache.commons.jxpath.ri.QName;
    23  import org.apache.commons.jxpath.ri.model.NodePointer;
    24
    25  /***
    26   * A Pointer that points to a JavaBean or a collection. It is either
    27   * the first element of a path or a pointer for a property value.
    28   * Typically there is a BeanPropertyPointer between two BeanPointers
    29   * in the chain.
    30   *
    31   * @author Dmitri Plotnikov
    32   * @version $Revision: 1.13 $ $Date: 2004/02/29 14:17:41 $
    33   */
    34  public class BeanPointer extends PropertyOwnerPointer {
    35      private QName name;
    36      private Object bean;
    37      private JXPathBeanInfo beanInfo;
    38
    39      public BeanPointer(
    40              QName name,
    41              Object bean,
    42              JXPathBeanInfo beanInfo,
    43              Locale locale)
    44      {
    45          super(null, locale);
    46          this.name = name;
    47          this.bean = bean;
    48          this.beanInfo = beanInfo;
    49      }
    50
    51      /***
    52       * @param name is the name given to the first node
    53       */
    54      public BeanPointer(
    55              NodePointer parent,
    56              QName name,
    57              Object bean,
    58              JXPathBeanInfo beanInfo)
    59      {
    60          super(parent);
    61          this.name = name;
    62          this.bean = bean;
    63          this.beanInfo = beanInfo;
    64      }
    65
    66      public PropertyPointer getPropertyPointer() {
    67          return new BeanPropertyPointer(this, beanInfo);
    68      }
    69
    70      public QName getName() {
    71          return name;
    72      }
    73
    74      /***
    75       * Returns the bean itself
    76       */
    77      public Object getBaseValue() {
    78          return bean;
    79      }
    80
    81      /***
    82       * Returns false
    83       */
    84      public boolean isCollection() {
    85          return false;
    86      }
    87
    88      /***
    89       * Returns 1.
    90       */
    91      public int getLength() {
    92          return 1;
    93      }
    94
    95      public boolean isLeaf() {
    96          Object value = getNode();
    97          return value == null
    98              || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
    99      }
    100
    101     public int hashCode() {
    102         return name == null ? 0 : name.hashCode();
    103     }
    104
    105     public boolean equals(Object object) {
    106         if (object == this) {
    107             return true;
    108         }
    109
    110         if (!(object instanceof BeanPointer)) {
    111             return false;
    112         }
    113
    114         BeanPointer other = (BeanPointer) object;
    115         if (parent != other.parent) {
    116             if (parent == null || !parent.equals(other.parent)) {
    117                 return false;
    118             }
    119         }
    120
    121         if ((name == null && other.name != null)
    122             || (name != null && !name.equals(other.name))) {
    123             return false;
    124         }
    125
    126         int iThis = (index == WHOLE_COLLECTION ? 0 : index);
    127         int iOther = (other.index == WHOLE_COLLECTION ? 0 : other.index);
    128         if (iThis != iOther) {
    129             return false;
    130         }
    131
    132         if (bean instanceof Number
    133             || bean instanceof String
    134             || bean instanceof Boolean) {
    135             return bean.equals(other.bean);
    136         }
    137         return bean == other.bean;
    138     }
    139
    140     /***
    141      * If the pointer has a parent, then parent's path.
    142      * If the bean is null, "null()".
    143      * If the bean is a primitive value, the value itself.
    144      * Otherwise - an empty string.
    145      */
    146     public String asPath() {
    147         if (parent != null) {
    148             return super.asPath();
    149         }
    150         else if (bean == null) {
    151             return "null()";
    152         }
    153         else if (bean instanceof Number) {
    154             String string = bean.toString();
    155             if (string.endsWith(".0")) {
    156                 string = string.substring(0, string.length() - 2);
    157             }
    158             return string;
    159         }
    160         else if (bean instanceof Boolean) {
    161             return ((Boolean) bean).booleanValue() ? "true()" : "false()";
    162         }
    163         else if (bean instanceof String) {
    164             return "'" + bean + "'";
    165         }
    166         return "/";
    167     }
    168 }