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 }