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  
18  package org.apache.commons.jxpath.ri.model.beans;
19  
20  import java.util.Locale;
21  
22  import org.apache.commons.jxpath.JXPathBeanInfo;
23  import org.apache.commons.jxpath.JXPathIntrospector;
24  import org.apache.commons.jxpath.ri.QName;
25  import org.apache.commons.jxpath.ri.model.NodePointer;
26  
27  /**
28   * A Pointer that points to a JavaBean or a collection. It is either the first element of a path or a pointer for a property value. Typically there is a
29   * {@link BeanPropertyPointer} between two BeanPointers in the chain.
30   */
31  public class BeanPointer extends PropertyOwnerPointer {
32  
33      private static final long serialVersionUID = -8227317938284982440L;
34  
35      /**
36       * Qualified name.
37       */
38      private final QName qName;
39  
40      /**
41       * Bean.
42       */
43      private final Object bean;
44  
45      /**
46       * Bean info.
47       */
48      private final JXPathBeanInfo beanInfo;
49  
50      /**
51       * BeanPointer a new BeanPointer.
52       *
53       * @param parent   pointer
54       * @param qName     is the name given to the first node
55       * @param bean     pointed
56       * @param beanInfo JXPathBeanInfo
57       */
58      public BeanPointer(final NodePointer parent, final QName qName, final Object bean, final JXPathBeanInfo beanInfo) {
59          super(parent);
60          this.qName = qName;
61          this.bean = bean;
62          this.beanInfo = beanInfo;
63      }
64  
65      /**
66       * Constructs a new BeanPointer.
67       *
68       * @param qName     is the name given to the first node
69       * @param bean     pointed
70       * @param beanInfo JXPathBeanInfo
71       * @param locale   Locale
72       */
73      public BeanPointer(final QName qName, final Object bean, final JXPathBeanInfo beanInfo, final Locale locale) {
74          super(null, locale);
75          this.qName = qName;
76          this.bean = bean;
77          this.beanInfo = beanInfo;
78      }
79  
80      /**
81       * {@inheritDoc} If the pointer has a parent, then parent's path. If the bean is null, "null()". If the bean is a primitive value, the value itself.
82       * Otherwise - an empty string.
83       */
84      @Override
85      public String asPath() {
86          if (parent != null) {
87              return super.asPath();
88          }
89          if (bean == null) {
90              return "null()";
91          }
92          if (bean instanceof Number) {
93              String string = bean.toString();
94              if (string.endsWith(".0")) {
95                  string = string.substring(0, string.length() - 2);
96              }
97              return string;
98          }
99          if (bean instanceof Boolean) {
100             return ((Boolean) bean).booleanValue() ? "true()" : "false()";
101         }
102         if (bean instanceof String) {
103             return "'" + bean + "'";
104         }
105         return "/";
106     }
107 
108     @Override
109     public boolean equals(final Object object) {
110         if (object == this) {
111             return true;
112         }
113         if (!(object instanceof BeanPointer)) {
114             return false;
115         }
116         final BeanPointer other = (BeanPointer) object;
117         if (parent != other.parent && (parent == null || !parent.equals(other.parent))) {
118             return false;
119         }
120         if (qName == null && other.qName != null || qName != null && !qName.equals(other.qName)) {
121             return false;
122         }
123         final int iThis = index == WHOLE_COLLECTION ? 0 : index;
124         final int iOther = other.index == WHOLE_COLLECTION ? 0 : other.index;
125         if (iThis != iOther) {
126             return false;
127         }
128         if (bean instanceof Number || bean instanceof String || bean instanceof Boolean) {
129             return bean.equals(other.bean);
130         }
131         return bean == other.bean;
132     }
133 
134     @Override
135     public Object getBaseValue() {
136         return bean;
137     }
138 
139     /**
140      * {@inheritDoc}
141      *
142      * @return 1
143      */
144     @Override
145     public int getLength() {
146         return 1;
147     }
148 
149     @Override
150     public QName getName() {
151         return qName;
152     }
153 
154     @Override
155     public PropertyPointer getPropertyPointer() {
156         return new BeanPropertyPointer(this, beanInfo);
157     }
158 
159     @Override
160     public int hashCode() {
161         return qName == null ? 0 : qName.hashCode();
162     }
163 
164     /**
165      * {@inheritDoc}
166      *
167      * @return false
168      */
169     @Override
170     public boolean isCollection() {
171         return false;
172     }
173 
174     @Override
175     public boolean isLeaf() {
176         final Object value = getNode();
177         return value == null || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
178     }
179 }