View Javadoc
1   /*
2    * Copyright 2004-2026 the original author or authors.
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    *    https://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 com.ibatis.common.beans;
17  
18  import java.util.List;
19  import java.util.Map;
20  import java.util.StringTokenizer;
21  
22  /**
23   * StaticBeanProbe provides methods that allow simple, reflective access to JavaBeans style properties. Methods are
24   * provided for all simple types as well as object types.
25   * <p>
26   * Examples:
27   * <p>
28   * StaticBeanProbe.setObject(object, propertyName, value);
29   * <P>
30   * Object value = StaticBeanProbe.getObject(object, propertyName);
31   */
32  public class GenericProbe extends BaseProbe {
33  
34    /** The Constant BEAN_PROBE. */
35    private static final BaseProbe BEAN_PROBE = new ComplexBeanProbe();
36  
37    /** The Constant DOM_PROBE. */
38    private static final BaseProbe DOM_PROBE = new DomProbe();
39  
40    /**
41     * Instantiates a new generic probe.
42     */
43    protected GenericProbe() {
44    }
45  
46    /**
47     * Gets an object from a Map or bean
48     *
49     * @param object
50     *          - the object to probe
51     * @param name
52     *          - the name of the property (or map entry)
53     *
54     * @return The value of the property (or map entry)
55     *
56     * @see com.ibatis.common.beans.BaseProbe#getObject(java.lang.Object, java.lang.String)
57     */
58    @Override
59    public Object getObject(Object object, String name) {
60  
61      if (object instanceof org.w3c.dom.Document) {
62        return DOM_PROBE.getObject(object, name);
63      }
64      if (object instanceof List || object instanceof Object[] || object instanceof char[] || object instanceof boolean[]
65          || object instanceof byte[] || object instanceof double[] || object instanceof float[]
66          || object instanceof int[] || object instanceof long[] || object instanceof short[]) {
67        return BEAN_PROBE.getIndexedProperty(object, name);
68      }
69      return BEAN_PROBE.getObject(object, name);
70    }
71  
72    /**
73     * Sets an object in a Map or bean
74     *
75     * @param object
76     *          - the object to probe
77     * @param name
78     *          - the name of the property (or map entry)
79     * @param value
80     *          - the new value of the property (or map entry)
81     *
82     * @see com.ibatis.common.beans.BaseProbe#setObject(java.lang.Object, java.lang.String, java.lang.Object)
83     */
84    @Override
85    public void setObject(Object object, String name, Object value) {
86      if (object instanceof org.w3c.dom.Document) {
87        DOM_PROBE.setObject(object, name, value);
88      } else {
89        BEAN_PROBE.setObject(object, name, value);
90      }
91    }
92  
93    /**
94     * Gets an array of the readable properties in a Map or JavaBean
95     *
96     * @param object
97     *          - the object to get properties for
98     *
99     * @return The array of properties (or map entries)
100    *
101    * @see com.ibatis.common.beans.BaseProbe#getReadablePropertyNames(java.lang.Object)
102    */
103   @Override
104   public String[] getReadablePropertyNames(Object object) {
105     if (object instanceof org.w3c.dom.Document) {
106       return DOM_PROBE.getReadablePropertyNames(object);
107     }
108     return BEAN_PROBE.getReadablePropertyNames(object);
109   }
110 
111   /**
112    * Gets an array of the writeable properties in a Map or JavaBean
113    *
114    * @param object
115    *          - the object to get properties for
116    *
117    * @return The array of properties (or map entries)
118    *
119    * @see com.ibatis.common.beans.BaseProbe#getWriteablePropertyNames(java.lang.Object)
120    */
121   @Override
122   public String[] getWriteablePropertyNames(Object object) {
123     if (object instanceof org.w3c.dom.Document) {
124       return DOM_PROBE.getWriteablePropertyNames(object);
125     }
126     return BEAN_PROBE.getWriteablePropertyNames(object);
127   }
128 
129   /**
130    * Returns the class that the setter expects to receive as a parameter when setting a property value.
131    *
132    * @param object
133    *          - The class to check
134    * @param name
135    *          - the name of the property
136    *
137    * @return The type of the property
138    *
139    * @see com.ibatis.common.beans.Probe#getPropertyTypeForSetter(java.lang.Object, java.lang.String)
140    */
141   @Override
142   public Class getPropertyTypeForSetter(Object object, String name) {
143     if (object instanceof Class) {
144       return getClassPropertyTypeForSetter((Class) object, name);
145     }
146     if (object instanceof org.w3c.dom.Document) {
147       return DOM_PROBE.getPropertyTypeForSetter(object, name);
148     }
149     return BEAN_PROBE.getPropertyTypeForSetter(object, name);
150   }
151 
152   /**
153    * Returns the class that the getter will return when reading a property value.
154    *
155    * @param object
156    *          The bean to check
157    * @param name
158    *          The name of the property
159    *
160    * @return The type of the property
161    *
162    * @see com.ibatis.common.beans.Probe#getPropertyTypeForGetter(java.lang.Object, java.lang.String)
163    */
164   @Override
165   public Class getPropertyTypeForGetter(Object object, String name) {
166     if (object instanceof Class) {
167       return getClassPropertyTypeForGetter((Class) object, name);
168     }
169     if (object instanceof org.w3c.dom.Document) {
170       return DOM_PROBE.getPropertyTypeForGetter(object, name);
171     }
172     if (name.indexOf('[') > -1) {
173       return BEAN_PROBE.getIndexedType(object, name);
174     }
175     return BEAN_PROBE.getPropertyTypeForGetter(object, name);
176   }
177 
178   /**
179    * Checks to see if an object has a writable property by a given name
180    *
181    * @param object
182    *          The bean to check
183    * @param propertyName
184    *          The property to check for
185    *
186    * @return True if the property exists and is writable
187    *
188    * @see com.ibatis.common.beans.Probe#hasWritableProperty(java.lang.Object, java.lang.String)
189    */
190   @Override
191   public boolean hasWritableProperty(Object object, String propertyName) {
192     if (object instanceof org.w3c.dom.Document) {
193       return DOM_PROBE.hasWritableProperty(object, propertyName);
194     }
195     return BEAN_PROBE.hasWritableProperty(object, propertyName);
196   }
197 
198   /**
199    * Checks to see if a bean has a readable property by a given name
200    *
201    * @param object
202    *          The bean to check
203    * @param propertyName
204    *          The property to check for
205    *
206    * @return True if the property exists and is readable
207    *
208    * @see com.ibatis.common.beans.Probe#hasReadableProperty(java.lang.Object, java.lang.String)
209    */
210   @Override
211   public boolean hasReadableProperty(Object object, String propertyName) {
212     if (object instanceof org.w3c.dom.Document) {
213       return DOM_PROBE.hasReadableProperty(object, propertyName);
214     }
215     return BEAN_PROBE.hasReadableProperty(object, propertyName);
216   }
217 
218   @Override
219   protected void setProperty(Object object, String property, Object value) {
220     if (object instanceof org.w3c.dom.Document) {
221       DOM_PROBE.setProperty(object, property, value);
222     } else {
223       BEAN_PROBE.setProperty(object, property, value);
224     }
225   }
226 
227   @Override
228   protected Object getProperty(Object object, String property) {
229     if (object instanceof org.w3c.dom.Document) {
230       return DOM_PROBE.getProperty(object, property);
231     }
232     return BEAN_PROBE.getProperty(object, property);
233   }
234 
235   /**
236    * Gets the class property type for getter.
237    *
238    * @param type
239    *          the type
240    * @param name
241    *          the name
242    *
243    * @return the class property type for getter
244    */
245   private Class getClassPropertyTypeForGetter(Class type, String name) {
246 
247     if (name.indexOf('.') > -1) {
248       StringTokenizer parser = new StringTokenizer(name, ".");
249       while (parser.hasMoreTokens()) {
250         name = parser.nextToken();
251         if (Map.class.isAssignableFrom(type)) {
252           type = Object.class;
253           break;
254         }
255         type = ClassInfo.getInstance(type).getGetterType(name);
256       }
257     } else {
258       type = ClassInfo.getInstance(type).getGetterType(name);
259     }
260 
261     return type;
262   }
263 
264   /**
265    * Returns the class that the setter expects to receive as a parameter when setting a property value.
266    *
267    * @param type
268    *          The class to check
269    * @param name
270    *          The name of the property
271    *
272    * @return The type of the property
273    */
274   private Class getClassPropertyTypeForSetter(Class type, String name) {
275 
276     if (name.indexOf('.') > -1) {
277       StringTokenizer parser = new StringTokenizer(name, ".");
278       while (parser.hasMoreTokens()) {
279         name = parser.nextToken();
280         if (Map.class.isAssignableFrom(type)) {
281           type = Object.class;
282           break;
283         }
284         type = ClassInfo.getInstance(type).getSetterType(name);
285       }
286     } else {
287       type = ClassInfo.getInstance(type).getSetterType(name);
288     }
289 
290     return type;
291   }
292 
293 }