View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jxpath.ri.model.beans;
18  
19  import java.util.Locale;
20  
21  import org.apache.commons.jxpath.JXPathBeanInfo;
22  import org.apache.commons.jxpath.JXPathIntrospector;
23  import org.apache.commons.jxpath.ri.QName;
24  import org.apache.commons.jxpath.ri.model.NodePointer;
25  
26  /**
27   * A Pointer that points to a JavaBean or a collection. It is either
28   * the first element of a path or a pointer for a property value.
29   * Typically there is a {@link BeanPropertyPointer} between two BeanPointers
30   * in the chain.
31   *
32   * @author Dmitri Plotnikov
33   * @version $Revision: 670727 $ $Date: 2008-06-23 22:10:38 +0200 (Mo, 23 Jun 2008) $
34   */
35  public class BeanPointer extends PropertyOwnerPointer {
36      private QName name;
37      private Object bean;
38      private JXPathBeanInfo beanInfo;
39  
40      private static final long serialVersionUID = -8227317938284982440L;
41  
42      /**
43       * Create a new BeanPointer.
44       * @param name is the name given to the first node
45       * @param bean pointed
46       * @param beanInfo JXPathBeanInfo
47       * @param locale Locale
48       */
49      public BeanPointer(QName name, Object bean, JXPathBeanInfo beanInfo,
50              Locale locale) {
51          super(null, locale);
52          this.name = name;
53          this.bean = bean;
54          this.beanInfo = beanInfo;
55      }
56  
57      /**
58       * Create a new BeanPointer.
59       * @param parent pointer
60       * @param name is the name given to the first node
61       * @param bean pointed
62       * @param beanInfo JXPathBeanInfo
63       */
64      public BeanPointer(NodePointer parent, QName name, Object bean,
65              JXPathBeanInfo beanInfo) {
66          super(parent);
67          this.name = name;
68          this.bean = bean;
69          this.beanInfo = beanInfo;
70      }
71  
72      public PropertyPointer getPropertyPointer() {
73          return new BeanPropertyPointer(this, beanInfo);
74      }
75  
76      public QName getName() {
77          return name;
78      }
79  
80      public Object getBaseValue() {
81          return bean;
82      }
83  
84      /**
85       * {@inheritDoc}
86       * @return false
87       */
88      public boolean isCollection() {
89          return false;
90      }
91  
92      /**
93       * {@inheritDoc}
94       * @return 1
95       */
96      public int getLength() {
97          return 1;
98      }
99  
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 }