0
|
1 // MODIFIED FOR THE MSGPACK PROJECT
|
|
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, WITHOUT
|
|
13 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
14 // License for the specific language governing permissions and limitations under
|
|
15 // the License.
|
|
16 //
|
|
17
|
|
18 package org.msgpack.template.builder.beans;
|
|
19
|
|
20 import java.lang.reflect.Method;
|
|
21
|
|
22 import org.apache.harmony.beans.BeansUtils;
|
|
23 import org.apache.harmony.beans.internal.nls.Messages;
|
|
24
|
|
25 public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
|
26
|
|
27 private Class<?> indexedPropertyType;
|
|
28
|
|
29 private Method indexedGetter;
|
|
30
|
|
31 private Method indexedSetter;
|
|
32
|
|
33 /**
|
|
34 * Constructs a new instance of <code>IndexedPropertyDescriptor</code>.
|
|
35 *
|
|
36 * @param propertyName
|
|
37 * the specified indexed property's name.
|
|
38 * @param beanClass
|
|
39 * the bean class
|
|
40 * @param getterName
|
|
41 * the name of the array getter
|
|
42 * @param setterName
|
|
43 * the name of the array setter
|
|
44 * @param indexedGetterName
|
|
45 * the name of the indexed getter.
|
|
46 * @param indexedSetterName
|
|
47 * the name of the indexed setter.
|
|
48 * @throws IntrospectionException
|
|
49 */
|
|
50 public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
|
|
51 String getterName, String setterName, String indexedGetterName,
|
|
52 String indexedSetterName) throws IntrospectionException {
|
|
53 super(propertyName, beanClass, getterName, setterName);
|
|
54 setIndexedByName(beanClass, indexedGetterName, indexedSetterName);
|
|
55 }
|
|
56
|
|
57 private void setIndexedByName(Class<?> beanClass, String indexedGetterName,
|
|
58 String indexedSetterName) throws IntrospectionException {
|
|
59
|
|
60 String theIndexedGetterName = indexedGetterName;
|
|
61 if (theIndexedGetterName == null) {
|
|
62 if (indexedSetterName != null) {
|
|
63 setIndexedWriteMethod(beanClass, indexedSetterName);
|
|
64 }
|
|
65 } else {
|
|
66 if (theIndexedGetterName.length() == 0) {
|
|
67 theIndexedGetterName = "get" + name; //$NON-NLS-1$
|
|
68 }
|
|
69 setIndexedReadMethod(beanClass, theIndexedGetterName);
|
|
70 if (indexedSetterName != null) {
|
|
71 setIndexedWriteMethod(beanClass, indexedSetterName,
|
|
72 indexedPropertyType);
|
|
73 }
|
|
74 }
|
|
75
|
|
76 if (!isCompatible()) {
|
|
77 // custom.beans.57=Property type is incompatible with the indexed property type
|
|
78 throw new IntrospectionException(Messages.getString("custom.beans.57")); //$NON-NLS-1$
|
|
79 }
|
|
80 }
|
|
81
|
|
82 private boolean isCompatible() {
|
|
83 Class<?> propertyType = getPropertyType();
|
|
84
|
|
85 if (propertyType == null) {
|
|
86 return true;
|
|
87 }
|
|
88 Class<?> componentTypeOfProperty = propertyType.getComponentType();
|
|
89 if (componentTypeOfProperty == null) {
|
|
90 return false;
|
|
91 }
|
|
92 if (indexedPropertyType == null) {
|
|
93 return false;
|
|
94 }
|
|
95
|
|
96 return componentTypeOfProperty.getName().equals(
|
|
97 indexedPropertyType.getName());
|
|
98 }
|
|
99
|
|
100 /**
|
|
101 * Constructs a new instance of <code>IndexedPropertyDescriptor</code>.
|
|
102 *
|
|
103 * @param propertyName
|
|
104 * the specified indexed property's name.
|
|
105 * @param getter
|
|
106 * the array getter
|
|
107 * @param setter
|
|
108 * the array setter
|
|
109 * @param indexedGetter
|
|
110 * the indexed getter
|
|
111 * @param indexedSetter
|
|
112 * the indexed setter
|
|
113 * @throws IntrospectionException
|
|
114 */
|
|
115 public IndexedPropertyDescriptor(String propertyName, Method getter,
|
|
116 Method setter, Method indexedGetter, Method indexedSetter)
|
|
117 throws IntrospectionException {
|
|
118 super(propertyName, getter, setter);
|
|
119 if (indexedGetter != null) {
|
|
120 internalSetIndexedReadMethod(indexedGetter);
|
|
121 internalSetIndexedWriteMethod(indexedSetter, true);
|
|
122 } else {
|
|
123 internalSetIndexedWriteMethod(indexedSetter, true);
|
|
124 internalSetIndexedReadMethod(indexedGetter);
|
|
125 }
|
|
126
|
|
127 if (!isCompatible()) {
|
|
128 // custom.beans.57=Property type is incompatible with the indexed property type
|
|
129 throw new IntrospectionException(Messages.getString("custom.beans.57")); //$NON-NLS-1$
|
|
130 }
|
|
131 }
|
|
132
|
|
133 /**
|
|
134 * Constructs a new instance of <code>IndexedPropertyDescriptor</code>.
|
|
135 *
|
|
136 * @param propertyName
|
|
137 * the specified indexed property's name.
|
|
138 * @param beanClass
|
|
139 * the bean class.
|
|
140 * @throws IntrospectionException
|
|
141 */
|
|
142 public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
|
|
143 throws IntrospectionException {
|
|
144 super(propertyName, beanClass);
|
|
145 setIndexedByName(beanClass, "get" //$NON-NLS-1$
|
|
146 .concat(initialUpperCase(propertyName)), "set" //$NON-NLS-1$
|
|
147 .concat(initialUpperCase(propertyName)));
|
|
148 }
|
|
149
|
|
150 /**
|
|
151 * Sets the indexed getter as the specified method.
|
|
152 *
|
|
153 * @param indexedGetter
|
|
154 * the specified indexed getter.
|
|
155 * @throws IntrospectionException
|
|
156 */
|
|
157 public void setIndexedReadMethod(Method indexedGetter)
|
|
158 throws IntrospectionException {
|
|
159 this.internalSetIndexedReadMethod(indexedGetter);
|
|
160 }
|
|
161
|
|
162 /**
|
|
163 * Sets the indexed setter as the specified method.
|
|
164 *
|
|
165 * @param indexedSetter
|
|
166 * the specified indexed setter.
|
|
167 * @throws IntrospectionException
|
|
168 */
|
|
169 public void setIndexedWriteMethod(Method indexedSetter)
|
|
170 throws IntrospectionException {
|
|
171 this.internalSetIndexedWriteMethod(indexedSetter, false);
|
|
172 }
|
|
173
|
|
174 /**
|
|
175 * Obtains the indexed setter.
|
|
176 *
|
|
177 * @return the indexed setter.
|
|
178 */
|
|
179 public Method getIndexedWriteMethod() {
|
|
180 return indexedSetter;
|
|
181 }
|
|
182
|
|
183 /**
|
|
184 * Obtains the indexed getter.
|
|
185 *
|
|
186 * @return the indexed getter.
|
|
187 */
|
|
188 public Method getIndexedReadMethod() {
|
|
189 return indexedGetter;
|
|
190 }
|
|
191
|
|
192 /**
|
|
193 * Determines if this <code>IndexedPropertyDescriptor</code> is equal to
|
|
194 * the specified object. Two <code>IndexedPropertyDescriptor</code> s are
|
|
195 * equal if the reader, indexed reader, writer, indexed writer, property
|
|
196 * types, indexed property type, property editor and flags are equal.
|
|
197 *
|
|
198 * @param obj
|
|
199 * @return true if this indexed property descriptor is equal to the
|
|
200 * specified object.
|
|
201 */
|
|
202 @Override
|
|
203 public boolean equals(Object obj) {
|
|
204 if (!(obj instanceof IndexedPropertyDescriptor)) {
|
|
205 return false;
|
|
206 }
|
|
207
|
|
208 IndexedPropertyDescriptor other = (IndexedPropertyDescriptor) obj;
|
|
209
|
|
210 return (super.equals(other)
|
|
211 && (indexedPropertyType == null ? other.indexedPropertyType == null
|
|
212 : indexedPropertyType.equals(other.indexedPropertyType))
|
|
213 && (indexedGetter == null ? other.indexedGetter == null
|
|
214 : indexedGetter.equals(other.indexedGetter)) && (indexedSetter == null ? other.indexedSetter == null
|
|
215 : indexedSetter.equals(other.indexedSetter)));
|
|
216 }
|
|
217
|
|
218 /**
|
|
219 * HashCode of the IndexedPropertyDescriptor
|
|
220 */
|
|
221 @Override
|
|
222 public int hashCode() {
|
|
223 return super.hashCode() + BeansUtils.getHashCode(indexedPropertyType)
|
|
224 + BeansUtils.getHashCode(indexedGetter)
|
|
225 + BeansUtils.getHashCode(indexedSetter);
|
|
226 }
|
|
227
|
|
228 /**
|
|
229 * Obtains the Class object of the indexed property type.
|
|
230 *
|
|
231 * @return the Class object of the indexed property type.
|
|
232 */
|
|
233 public Class<?> getIndexedPropertyType() {
|
|
234 return indexedPropertyType;
|
|
235 }
|
|
236
|
|
237 private void setIndexedReadMethod(Class<?> beanClass, String indexedGetterName)
|
|
238 throws IntrospectionException {
|
|
239 Method getter;
|
|
240 try {
|
|
241 getter = beanClass.getMethod(indexedGetterName,
|
|
242 new Class[] { Integer.TYPE });
|
|
243 } catch (NoSuchMethodException exception) {
|
|
244 // custom.beans.58=No such indexed read method
|
|
245 throw new IntrospectionException(Messages.getString("custom.beans.58")); //$NON-NLS-1$
|
|
246 } catch (SecurityException exception) {
|
|
247 // custom.beans.59=Security violation accessing indexed read method
|
|
248 throw new IntrospectionException(Messages.getString("custom.beans.59")); //$NON-NLS-1$
|
|
249 }
|
|
250 internalSetIndexedReadMethod(getter);
|
|
251 }
|
|
252
|
|
253 private void internalSetIndexedReadMethod(Method indexGetter)
|
|
254 throws IntrospectionException {
|
|
255 // Clearing the indexed read method.
|
|
256 if (indexGetter == null) {
|
|
257 if (indexedSetter == null) {
|
|
258 if (getPropertyType() != null) {
|
|
259 // custom.beans.5A=Indexed method is not compatible with non indexed method
|
|
260 throw new IntrospectionException(Messages
|
|
261 .getString("custom.beans.5A")); //$NON-NLS-1$
|
|
262 }
|
|
263 indexedPropertyType = null;
|
|
264 }
|
|
265 this.indexedGetter = null;
|
|
266 return;
|
|
267 }
|
|
268 // Validate the indexed getter.
|
|
269 if ((indexGetter.getParameterTypes().length != 1)
|
|
270 || (indexGetter.getParameterTypes()[0] != Integer.TYPE)) {
|
|
271 // custom.beans.5B=Indexed read method must take a single int argument
|
|
272 throw new IntrospectionException(Messages.getString("custom.beans.5B")); //$NON-NLS-1$
|
|
273 }
|
|
274 Class<?> indexedReadType = indexGetter.getReturnType();
|
|
275 if (indexedReadType == Void.TYPE) {
|
|
276 // custom.beans.5B=Indexed read method must take a single int argument
|
|
277 throw new IntrospectionException(Messages.getString("custom.beans.5B")); //$NON-NLS-1$
|
|
278 } else if (indexedSetter != null
|
|
279 && indexGetter.getReturnType() != indexedSetter
|
|
280 .getParameterTypes()[1]) {
|
|
281 // custom.beans.5A=Indexed read method is not compatible with indexed write method
|
|
282 throw new IntrospectionException(Messages.getString("custom.beans.5A")); //$NON-NLS-1$
|
|
283 }
|
|
284
|
|
285 // Set the indexed property type if not already set, confirm validity if
|
|
286 // it is.
|
|
287 if (this.indexedGetter == null) {
|
|
288 indexedPropertyType = indexedReadType;
|
|
289 } else {
|
|
290 if (indexedPropertyType != indexedReadType) {
|
|
291 // custom.beans.5A=Indexed read method is not compatible with indexed write method
|
|
292 throw new IntrospectionException(Messages.getString("custom.beans.5A")); //$NON-NLS-1$
|
|
293 }
|
|
294 }
|
|
295
|
|
296 // Set the indexed getter
|
|
297 this.indexedGetter = indexGetter;
|
|
298 }
|
|
299
|
|
300 private void setIndexedWriteMethod(Class<?> beanClass, String indexedSetterName)
|
|
301 throws IntrospectionException {
|
|
302 Method setter = null;
|
|
303 try {
|
|
304 setter = beanClass.getMethod(indexedSetterName, new Class[] {
|
|
305 Integer.TYPE, getPropertyType().getComponentType() });
|
|
306 } catch (SecurityException e) {
|
|
307 // custom.beans.5C=Security violation accessing indexed write method
|
|
308 throw new IntrospectionException(Messages.getString("custom.beans.5C")); //$NON-NLS-1$
|
|
309 } catch (NoSuchMethodException e) {
|
|
310 // custom.beans.5D=No such indexed write method
|
|
311 throw new IntrospectionException(Messages.getString("custom.beans.5D")); //$NON-NLS-1$
|
|
312 }
|
|
313 internalSetIndexedWriteMethod(setter, true);
|
|
314 }
|
|
315
|
|
316 private void setIndexedWriteMethod(Class<?> beanClass,
|
|
317 String indexedSetterName, Class<?> argType)
|
|
318 throws IntrospectionException {
|
|
319 try {
|
|
320 Method setter = beanClass.getMethod(indexedSetterName, new Class[] {
|
|
321 Integer.TYPE, argType });
|
|
322 internalSetIndexedWriteMethod(setter, true);
|
|
323 } catch (NoSuchMethodException exception) {
|
|
324 // custom.beans.5D=No such indexed write method
|
|
325 throw new IntrospectionException(Messages.getString("custom.beans.5D")); //$NON-NLS-1$
|
|
326 } catch (SecurityException exception) {
|
|
327 // custom.beans.5C=Security violation accessing indexed write method
|
|
328 throw new IntrospectionException(Messages.getString("custom.beans.5C")); //$NON-NLS-1$
|
|
329 }
|
|
330 }
|
|
331
|
|
332 private void internalSetIndexedWriteMethod(Method indexSetter,
|
|
333 boolean initialize) throws IntrospectionException {
|
|
334 // Clearing the indexed write method.
|
|
335 if (indexSetter == null) {
|
|
336 if (indexedGetter == null) {
|
|
337 if (getPropertyType() != null) {
|
|
338 // custom.beans.5E=Indexed method is not compatible with non indexed method
|
|
339 throw new IntrospectionException(Messages
|
|
340 .getString("custom.beans.5E")); //$NON-NLS-1$
|
|
341 }
|
|
342 indexedPropertyType = null;
|
|
343 }
|
|
344 this.indexedSetter = null;
|
|
345 return;
|
|
346 }
|
|
347
|
|
348 // Validate the indexed write method.
|
|
349 Class<?>[] indexedSetterArgs = indexSetter.getParameterTypes();
|
|
350 if (indexedSetterArgs.length != 2) {
|
|
351 // custom.beans.5F=Indexed write method must take two arguments
|
|
352 throw new IntrospectionException(Messages.getString("custom.beans.5F")); //$NON-NLS-1$
|
|
353 }
|
|
354 if (indexedSetterArgs[0] != Integer.TYPE) {
|
|
355 // custom.beans.60=Indexed write method must take an int as its first argument
|
|
356 throw new IntrospectionException(Messages.getString("custom.beans.60")); //$NON-NLS-1$
|
|
357 }
|
|
358
|
|
359 // Set the indexed property type if not already set, confirm validity if
|
|
360 // it is.
|
|
361 Class<?> indexedWriteType = indexedSetterArgs[1];
|
|
362 if (initialize && indexedGetter == null) {
|
|
363 indexedPropertyType = indexedWriteType;
|
|
364 } else {
|
|
365 if (indexedPropertyType != indexedWriteType) {
|
|
366 // custom.beans.61=Indexed write method is not compatible with indexed read method
|
|
367 throw new IntrospectionException(Messages.getString("custom.beans.61")); //$NON-NLS-1$
|
|
368 }
|
|
369 }
|
|
370
|
|
371 // Set the indexed write method.
|
|
372 this.indexedSetter = indexSetter;
|
|
373 }
|
|
374
|
|
375 private static String initialUpperCase(String string) {
|
|
376 if (Character.isUpperCase(string.charAt(0))) {
|
|
377 return string;
|
|
378 }
|
|
379
|
|
380 String initial = string.substring(0, 1).toUpperCase();
|
|
381 return initial.concat(string.substring(1));
|
|
382 }
|
|
383 }
|