1
2
3
4
5 package net.sf.crispy.util;
6
7 import java.beans.IntrospectionException;
8 import java.lang.reflect.Array;
9 import java.lang.reflect.Constructor;
10 import java.lang.reflect.Method;
11 import java.math.BigDecimal;
12 import java.math.BigInteger;
13 import java.security.AccessController;
14 import java.sql.Time;
15 import java.sql.Timestamp;
16 import java.text.DateFormat;
17 import java.text.ParseException;
18 import java.text.SimpleDateFormat;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Comparator;
22 import java.util.Date;
23 import java.util.HashSet;
24 import java.util.Hashtable;
25 import java.util.Iterator;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Properties;
29 import java.util.Set;
30 import java.util.TreeMap;
31 import java.util.Vector;
32 import java.util.Map.Entry;
33
34 import net.sf.crispy.InvocationException;
35 import net.sf.crispy.impl.ServiceManager;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 /**
41 * Convert complex object in a simple form and back to the object.
42 *
43 * @author Linke
44 *
45 */
46 public class Converter {
47
48 public final static String HASH_CODE_KEY = "~hashCode~";
49 public final static int GET_METHOD = 1;
50 public final static int SET_METHOD = 2;
51
52 protected static final Log log = LogFactory.getLog (Converter.class);
53 protected static final Map isSimpleDataType = new Hashtable();
54 protected static final ClassPropertiesCache classPropertiesCacheGetter = new ClassPropertiesCache();
55 protected static final ClassPropertiesCache classPropertiesCacheSetter = new ClassPropertiesCache();
56
57 private String nullValue = null;
58 private boolean withSimpleKeyMapper = false;
59
60 public Converter() { }
61 public Converter(String pvNullValue) {
62 setNullValue(pvNullValue);
63 }
64 public Converter(int pvStartHashCode) {
65 uniqueIdMap = new Hashtable();
66 startHashCode = pvStartHashCode;
67 }
68
69 public void setWithSimpleKeyMapper(boolean pvWithSimpleKeyMapper) { withSimpleKeyMapper = pvWithSimpleKeyMapper; }
70 public boolean getWithSimpleKeyMapper() { return withSimpleKeyMapper; }
71
72 public static boolean isValideEdge(Object pvObject) {
73 if (pvObject == null) { return false; }
74 if (isSimpleDataType.size() == 0) {
75 isSimpleDataType.put(String.class, String.class);
76 isSimpleDataType.put(Boolean.class, Boolean.class);
77 isSimpleDataType.put(boolean.class, boolean.class);
78 isSimpleDataType.put(Byte.class, Byte.class);
79 isSimpleDataType.put(byte.class, byte.class);
80 isSimpleDataType.put(Short.class, Short.class);
81 isSimpleDataType.put(short.class, short.class);
82 isSimpleDataType.put(Integer.class, Integer.class);
83 isSimpleDataType.put(int.class, int.class);
84 isSimpleDataType.put(Long.class, Long.class);
85 isSimpleDataType.put(long.class, long.class);
86 isSimpleDataType.put(Float.class, Float.class);
87 isSimpleDataType.put(float.class, float.class);
88 isSimpleDataType.put(Double.class, Double.class);
89 isSimpleDataType.put(double.class, double.class);
90 isSimpleDataType.put(Character.class, Character.class);
91 isSimpleDataType.put(char.class, char.class);
92 isSimpleDataType.put(BigDecimal.class, BigDecimal.class);
93 isSimpleDataType.put(StringBuffer.class, StringBuffer.class);
94 isSimpleDataType.put(BigInteger.class, BigInteger.class);
95 isSimpleDataType.put(Class.class, Class.class);
96 isSimpleDataType.put(java.sql.Date.class, java.sql.Date.class);
97 isSimpleDataType.put(java.util.Date.class, java.util.Date.class);
98 isSimpleDataType.put(Time.class, Time.class);
99 isSimpleDataType.put(Timestamp.class, Timestamp.class);
100 }
101 boolean b = isSimpleDataType.containsKey(pvObject.getClass());
102
103 if (b == true) {
104 return false;
105 }
106 else {
107 return true;
108 }
109 }
110
111 private Map uniqueIdMap = null;
112 private Map uniqueIdMap2 = null;
113 private int hashCode = 0;
114 private int startHashCode = -1000000000;
115
116
117 public String getNullValue() { return nullValue; }
118 public void setNullValue(String pvNullValue) { nullValue = pvNullValue; }
119
120 public String findNextFreeId (int pvHashCode) {
121 String lvHashCodeStr = Integer.toString(pvHashCode);
122 if (uniqueIdMap.containsKey(lvHashCodeStr)) {
123 int next = pvHashCode + 1;
124 lvHashCodeStr = findNextFreeId (next);
125 }
126 return lvHashCodeStr;
127 }
128
129 private String getUniqueId(Object pvObject) {
130 if (pvObject == null) {return null; }
131
132 String lvHashCode = (String) uniqueIdMap2.get(pvObject);
133 if (lvHashCode != null){
134 return lvHashCode;
135 }
136
137 lvHashCode = Integer.toString(pvObject.hashCode());
138 Object o = uniqueIdMap.get(lvHashCode);
139 if (o == null) {
140 uniqueIdMap.put(lvHashCode, pvObject);
141 uniqueIdMap2.put(pvObject, lvHashCode);
142 }
143 else {
144 lvHashCode = findNextFreeId(hashCode);
145 uniqueIdMap.put(lvHashCode, pvObject);
146 uniqueIdMap2.put(pvObject, lvHashCode);
147 }
148 return lvHashCode;
149 }
150
151
152 /**
153 * Convert complex object in a Hashtable and relations in Vector.
154 * Cycles are finded and removed.
155 *
156 * @param pvObject Complex or simple object.
157 * @return Simple object structure.
158 * @throws Exception
159 */
160 public Object makeSimple (Object pvObject) throws Exception {
161 uniqueIdMap = new Hashtable();
162 uniqueIdMap2 = new Hashtable();
163 hashCode = startHashCode;
164 Object lvReturn = null;
165 try {
166 lvReturn = makeSimpleInternal (pvObject, null, new Graph());
167 }
168 finally {
169 uniqueIdMap = null;
170 uniqueIdMap2 = null;
171 hashCode = startHashCode;
172 }
173 return lvReturn;
174 }
175
176 private Object makeSimpleInternal (Object pvObject, String pvPropName, Graph pvGraph) throws Exception {
177 Method lvMethod = null;
178
179 if (pvObject == null) { return nullValue; }
180
181 Class clazz = pvObject.getClass();
182
183
184 if (clazz.equals(String.class)) { return pvObject; }
185 else if (clazz.equals(Date.class)) { return pvObject; }
186 else if (clazz.equals(Integer.class)) { return pvObject; }
187 else if (clazz.equals(Double.class)) { return pvObject; }
188 else if (clazz.equals(Boolean.class)) { return pvObject; }
189
190 else if ((clazz.isArray()) && (clazz.getComponentType().equals(byte.class))) { return pvObject; }
191
192
193 else if (clazz.equals(Long.class)) { return Integer.valueOf(pvObject.toString()); }
194 else if (clazz.equals(Byte.class)) { return Integer.valueOf(pvObject.toString()); }
195 else if (clazz.equals(Float.class)) { return new Double(pvObject.toString()); }
196 else if (clazz.equals(Character.class)) { return pvObject.toString(); }
197 else if (clazz.equals(Short.class)) { return Integer.valueOf(pvObject.toString()); }
198 else if (clazz.equals(BigDecimal.class)) { return new Double(pvObject.toString()); }
199 else if (clazz.equals(StringBuffer.class)) { return pvObject.toString(); }
200 else if (clazz.equals(BigInteger.class)) { return Integer.valueOf(pvObject.toString()); }
201 else if (clazz.equals(Class.class)) { return ((Class) pvObject).getName(); }
202 else if (clazz.equals(java.sql.Date.class)) { return new Date(((java.sql.Date) pvObject).getTime()); }
203 else if (clazz.equals(Time.class)) { return (Date) pvObject; }
204 else if (clazz.equals(Timestamp.class)) { return (Date) pvObject; }
205
206
207 else if (pvObject instanceof Collection) {
208 final Collection coll = (Collection) pvObject;
209 Iterator it = coll.iterator();
210 Vector v = new Vector(coll.size());
211 while (it.hasNext()) {
212 Object lvValue = it.next();
213 String lvHashCode = getUniqueId(lvValue);
214 if (pvGraph.getVertexCount(lvValue) == true) {
215 v.add(HASH_CODE_KEY + lvHashCode);
216 } else {
217 Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
218 if (o != null) { v.add(o); }
219 }
220 }
221 return v;
222 }
223
224 else if (pvObject instanceof Map) {
225 Map map = (Map) pvObject;
226 Hashtable lvHashtable = new Hashtable(map.size());
227
228
229 int pos = 0;
230 SimpleKeyMapper lvKeyMapper = new SimpleKeyMapper();
231 Iterator it = map.entrySet().iterator();
232 while (it.hasNext()) {
233 Map.Entry lvMapEntry = (Entry) it.next();
234 Object lvKey = lvMapEntry.getKey();
235 pos = ++pos;
236 if (isValideEdge(lvKey)) { throw new InvocationException("Complex Map-Key datatypes are not supported: " + lvKey.getClass().getName()); }
237 Object lvValue = lvMapEntry.getValue();
238 String lvHashCode = getUniqueId(lvValue);
239
240 Class lvKeyClass = lvKey.getClass();
241
242 lvKey = makeSimpleInternal(lvKey, pvPropName, pvGraph);
243
244 Object key = lvKeyMapper.toSimpleNewKey(lvKey, lvKeyClass, pos, withSimpleKeyMapper);
245 if (pvGraph.getVertexCount(lvValue) == true) {
246 lvHashtable.put(key, HASH_CODE_KEY + lvHashCode);
247 } else {
248 Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
249 if (o != null) { lvHashtable.put(key, o); }
250 }
251 }
252 return lvHashtable;
253 }
254
255 else if (clazz.isArray()) {
256 int length = Array.getLength(pvObject);
257 Vector v = new Vector(length);
258 for (int i=0;i<length;i++) {
259 Object lvValue = Array.get (pvObject, i);
260 String lvHashCode = getUniqueId(lvValue);
261 if (pvGraph.getVertexCount(lvValue) == true) {
262 v.add(HASH_CODE_KEY + lvHashCode);
263 } else {
264 Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
265 if (o != null) { v.add(o); }
266 }
267 }
268 return v;
269 }
270
271
272 else {
273 Hashtable map = new Hashtable();
274 String lvHashCode = getUniqueId(pvObject);
275 map.put(HASH_CODE_KEY, lvHashCode);
276 pvGraph.addVertex(pvObject);
277 Map lvGetterMap = getAllGetterMethodWithCache(clazz);
278 Iterator it = lvGetterMap.entrySet().iterator();
279 while (it.hasNext()) {
280 Map.Entry lvMapEntry = (Entry) it.next();
281 String propName = (String) lvMapEntry.getKey();
282 if (propName.equals("class") == false) {
283 Object lvValue = null;
284 try {
285 lvMethod = (Method)lvMapEntry.getValue();
286 lvValue = lvMethod.invoke(pvObject, null);
287 } catch (Exception e) {
288 if (log.isDebugEnabled()) { log.debug("Problem by invoke method (in makeSimple): " + lvMethod, e); }
289 if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
290 }
291
292
293
294 if (lvValue != null) {
295 Edge lvEdge = new Edge(pvObject, lvValue);
296 if (pvGraph.containsKey(lvEdge) == false) {
297 if (isValideEdge(lvValue) == true) {
298 pvGraph.put(lvEdge, "");
299 }
300 Edge lvKnownEdgeToThisNode = pvGraph.isFromContains(lvValue);
301 if (lvKnownEdgeToThisNode != null) {
302 lvEdge.setMethodName(lvMethod.getName());
303 map.put(propName, HASH_CODE_KEY + getUniqueId(lvValue));
304 }
305 else {
306 Object o = makeSimpleInternal(lvValue, propName, pvGraph);
307 map.put(propName, o);
308 }
309 }
310
311 else {
312 map.put(propName, HASH_CODE_KEY + getUniqueId(lvValue));
313 }
314 }
315
316 } else {
317
318 map.put("class", clazz.getName());
319 }
320 }
321 return map;
322 }
323 }
324
325 public Object makeComplex (Object pvObject) throws Exception {
326 return makeComplex(pvObject, null);
327 }
328
329 public Object makeComplex (Object pvObject, Class clazz) throws Exception {
330 return makeComplex(pvObject, clazz, null);
331 }
332
333 public Object makeComplex (Object pvObject, Class clazz, Class clazzInArray) throws Exception {
334 return makeComplexInternal(pvObject, clazz, clazzInArray, new Hashtable());
335 }
336
337 private Object makeComplexInternal (final Object pvObject, final Class pvClazz, final Class clazzInArray, final Map pvHashCodeMap) throws Exception {
338 Method lvMethod = null;
339 Class clazz = pvClazz;
340
341 if (pvObject == null || pvObject.equals(nullValue)) { return null; }
342
343 if (pvClazz == null) { clazz = pvObject.getClass(); }
344
345
346
347 if ((clazz.equals(Object.class)) && (!(pvObject.getClass().equals(Object.class)))) {
348 if (log.isDebugEnabled()) {
349 log.debug("Class: "+ clazz.getName() + " is different from Object: " + pvObject.getClass().getName());
350 }
351 clazz = pvObject.getClass();
352 }
353
354
355 if (clazz.equals(String.class)) { return pvObject; }
356 else if (clazz.equals(Integer.class)) { return pvObject; }
357 else if (clazz.equals(Double.class)) { return pvObject; }
358 else if (clazz.equals(Boolean.class)) { return pvObject; }
359 else if (clazz.equals(Date.class)) { return pvObject; }
360 else if ((clazz.isArray()) && (clazz.getComponentType().equals(byte.class))) { return pvObject; }
361
362
363 else if (clazz.equals(boolean.class)) { return pvObject; }
364 else if (clazz.equals(short.class)) { return new Short(pvObject.toString()); }
365 else if (clazz.equals(byte.class)) { return new Byte(pvObject.toString()); }
366 else if (clazz.equals(int.class)) { return pvObject; }
367 else if (clazz.equals(long.class)) { return new Long(pvObject.toString()); }
368 else if (clazz.equals(double.class)) { return new Double(pvObject.toString()); }
369 else if (clazz.equals(float.class)) { return new Float(pvObject.toString()); }
370 else if (clazz.equals(char.class)) { return new Character(pvObject.toString().charAt(0)); }
371
372
373 else if (clazz.equals(Byte.class)) { return new Byte(pvObject.toString()); }
374 else if (clazz.equals(Float.class)) { return new Float(pvObject.toString()); }
375 else if (clazz.equals(Character.class)) { return new Character(pvObject.toString().charAt(0)); }
376 else if (clazz.equals(Long.class)) { return new Long(pvObject.toString()); }
377 else if (clazz.equals(Short.class)) { return new Short(pvObject.toString()); }
378 else if (clazz.equals(BigDecimal.class)) { return new BigDecimal (((Double) pvObject).doubleValue()); }
379 else if (clazz.equals(StringBuffer.class)) { return new StringBuffer(pvObject.toString()); }
380 else if (clazz.equals(BigInteger.class)) { return new BigInteger(pvObject.toString()); }
381 else if (clazz.equals(Class.class)) { return Class.forName(pvObject.toString()); }
382 else if (clazz.equals(java.sql.Date.class)) { return new java.sql.Date(((Date) pvObject).getTime()); }
383 else if (clazz.equals(Time.class)) {
384 if (pvObject instanceof Time) {
385 return (Time) pvObject;
386 }
387 else if (pvObject instanceof Timestamp) {
388 Timestamp ts = (Timestamp) pvObject;
389 return new Time(ts.getTime());
390 }
391 else if (pvObject instanceof Date) {
392 return new Time(((Date) pvObject).getTime());
393 }
394 else if (pvObject instanceof Long) {
395 Long l = (Long) pvObject;
396 return new Time(l.longValue());
397 }
398 else {
399 throw new InvocationException("Exception by Converter.makeComplex. The datatype: " + pvObject.getClass().getName()
400 + " is not compatible to java.sql.Time");
401 }
402
403 }
404 else if (clazz.equals(Timestamp.class)) {
405 if (pvObject instanceof Timestamp) {
406 return (Timestamp) pvObject;
407 }
408 else if (pvObject instanceof Time) {
409 Time t = (Time) pvObject;
410 return new Timestamp(t.getTime());
411 }
412 else if (pvObject instanceof Date) {
413 return new Timestamp(((Date) pvObject).getTime());
414 }
415 else if (pvObject instanceof Long) {
416 Long l = (Long) pvObject;
417 return new Timestamp(l.longValue());
418 }
419 else {
420 throw new InvocationException("Exception by Converter.makeComplex. The datatype: " + pvObject.getClass().getName()
421 + " is not compatible to java.sql.Timestamp");
422 }
423
424 }
425
426 else if (clazz.isArray()) {
427
428 if ((!pvObject.getClass().isArray()) && (pvObject instanceof Collection)) {
429 Collection coll = (Collection) pvObject;
430 Class lvType = (clazzInArray == null ? getArrayType(pvObject) : clazzInArray);
431 Object[] lvTempArray = (Object[]) Array.newInstance(lvType, coll.size());
432 Iterator it = coll.iterator();
433 int i = 0;
434 while (it.hasNext()) {
435 Object objInList = it.next();
436 String lvHashCode = objInList.toString();
437 if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
438 lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
439 Object value = pvHashCodeMap.get(lvHashCode);
440 if (value == null) {
441 throw new InvocationException("Internal Converter-Exception. " +
442 "For the HashCode: " + lvHashCode + " can not find a object in the Array: " + coll);
443 } else {
444 lvTempArray[i] = value;
445 }
446 } else {
447 if (clazzInArray == null) {
448 lvTempArray[i] = objInList;
449 }
450 else {
451 lvTempArray[i] = makeComplexInternal(objInList, clazzInArray, null, pvHashCodeMap);
452 }
453 }
454 i++;
455 }
456 return lvTempArray;
457 }
458
459
460 if ((!pvObject.getClass().isArray()) && (pvObject instanceof Map)) {
461 return makeComplexInternal(pvObject, null, null, pvHashCodeMap);
462 } else {
463 int length = Array.getLength(pvObject);
464 Class lvType = (clazzInArray == null ? getArrayType(pvObject) : clazzInArray);
465 Object[] o = (Object[]) Array.newInstance(lvType, length);
466 for (int i=0;i<length;i++) {
467 Object _o = Array.get (pvObject, i);
468 o[i] = makeComplexInternal(_o, lvType, null, pvHashCodeMap);
469 }
470 return o;
471 }
472 }
473
474
475 else if (pvObject instanceof Collection) {
476 Collection coll = (Collection) pvObject;
477 Iterator it = coll.iterator();
478 Collection lvNewColl = new Vector(coll.size());
479 while (it.hasNext()) {
480 Object o = it.next();
481
482 if (o != null) {
483 String lvHashCode = o.toString();
484 if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
485 lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
486 Object value = pvHashCodeMap.get(lvHashCode);
487 if (value == null) {
488 throw new InvocationException("Internal Converter-Exception. " +
489 "For the HashCode: " + lvHashCode + " can not find a object in the Collection: " + coll);
490 } else {
491 lvNewColl.add(value);
492 }
493 } else {
494 Object value = makeComplexInternal(o, o.getClass(), null, pvHashCodeMap);
495 lvNewColl.add(value);
496 }
497 }
498 }
499 return lvNewColl;
500 }
501
502 else if (pvObject instanceof Map) {
503 Map map = (Map) pvObject;
504 String aClazzStr = (String) map.get("class");
505 if (aClazzStr == null) {
506
507 SimpleKeyMapper lvSimpleKeyMapper = new SimpleKeyMapper();
508 map = lvSimpleKeyMapper.orderMapByKey(map, withSimpleKeyMapper);
509
510 Iterator it = map.entrySet().iterator();
511 Hashtable lvHashtable = new Hashtable(map.size());
512 while (it.hasNext()) {
513 Map.Entry lvMapEntry = (Entry) it.next();
514 Object lvKey = lvMapEntry.getKey();
515 Object key = lvSimpleKeyMapper.toComplexNewKey(lvKey, withSimpleKeyMapper);
516 Object lvValue = lvMapEntry.getValue();
517 String lvHashCode = extractHashCode(lvValue);
518 if (lvHashCode != null) {
519 lvValue = pvHashCodeMap.get(lvHashCode);
520 if (lvValue == null) {
521 throw new InvocationException("Internal Converter-Exception. " +
522 "For the HashCode: " + lvHashCode + " can not find a object in a map: " + map);
523 } else {
524 lvHashtable.put(key, lvValue);
525 }
526 } else {
527 lvValue = makeComplexInternal(lvValue, lvValue.getClass(), null, pvHashCodeMap);
528 lvHashtable.put(key, lvValue);
529 }
530 }
531 return lvHashtable;
532
533 } else {
534 Class aClazz = null;
535 try {
536 aClazz = Class.forName(aClazzStr);
537 } catch (Exception e) {
538 throw new InvocationException("Can't load class: " + aClazzStr);
539 }
540 Object ret = null;
541 try {
542 ret = aClazz.newInstance();
543 } catch (Exception e) {
544 throw new InvocationException("Can't create object from class: " + aClazzStr + " (No constructor without parameter!)");
545 }
546
547 String lvMapHashCode = (String) map.get(HASH_CODE_KEY);
548 if (lvMapHashCode != null) { pvHashCodeMap.put(lvMapHashCode, ret); }
549
550 try {
551 Map lvSetterMap = getAllSetterMethodWithCache(aClazz);
552 Iterator it = lvSetterMap.entrySet().iterator();
553 while (it.hasNext()) {
554 Map.Entry lvMapEntry = (Entry) it.next();
555 String propName = (String) lvMapEntry.getKey();
556 Object value = map.get(propName);
557 if (value != null) {
558 String lvHashCode = extractHashCode(value);
559 lvMethod = (Method) lvMapEntry.getValue();
560 Class lvParamType = lvMethod.getParameterTypes()[0];
561
562 if (lvHashCode != null) {
563 value = pvHashCodeMap.get(lvHashCode);
564 } else {
565 value = makeComplexInternal(value, lvParamType, lvParamType.getComponentType(), pvHashCodeMap);
566 }
567 try {
568 value = makeAssignable(lvParamType, value);
569 lvMethod.invoke(ret, new Object [] {value});
570 } catch (Exception e) {
571 if (log.isDebugEnabled()) { log.debug("Problem by invoke method (in makeComplex): " + lvMethod, e); }
572 if (ServiceManager.DEBUG_MODE_ON) {
573 e.printStackTrace();
574 }
575 }
576 }
577 }
578 } catch (Exception e) {
579 if (log.isWarnEnabled()) { log.warn("Error in Converter.makeComplex by Method: " + lvMethod, e); }
580 if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
581 }
582
583 return ret;
584 }
585 }
586 else {
587 if (log.isInfoEnabled()) {
588 log.info("Invalide Type in makeComplex for Class: " + clazz + " with value: " + pvObject
589 + " (Class from Object: " + pvObject.getClass().getName() + ")");
590 }
591 return null;
592 }
593 }
594
595
596 public static Object makeAssignable(Class pvSourceClass, Object pvValue) {
597 if (pvSourceClass.equals(Object.class)) {
598 return pvValue;
599 }
600 else if (pvSourceClass.isAssignableFrom(Set.class) && pvValue instanceof Collection) {
601 return new HashSet((Collection) pvValue);
602 }
603 else if (pvSourceClass.isAssignableFrom(Properties.class) && pvValue instanceof Map) {
604 Map lvMap = (Map) pvValue;
605 Properties lvProperties = new Properties();
606 Iterator it = lvMap.entrySet().iterator();
607 while (it.hasNext()) {
608 Map.Entry lvMapEntry = (Entry) it.next();
609 lvProperties.put(lvMapEntry.getKey(), lvMapEntry.getValue());
610 }
611 return lvProperties;
612 }
613 return pvValue;
614 }
615
616 /**
617 * Analysed the objects in an Array/Collection. If all Object from the same class type,
618 * then is the return value this class. If are several class types in the Array,
619 * then ist the return class from type Object.
620 * @param pvListObj
621 * @return Class, that are in the Array or Collection
622 */
623 public static Class getArrayType (Object pvListObj) {
624 Class lvType = Object.class;
625 if (pvListObj == null) { return lvType; }
626 if (pvListObj.getClass().isArray()) {
627 Object o[] = (Object[]) pvListObj;
628 if (o.length > 0) {
629 Class lvClass = o[0].getClass();
630
631
632 if(Map.class.isAssignableFrom(lvClass)) {
633 return Object.class;
634 }
635
636 for (int i = 0; i < o.length; i++) {
637 if (!lvClass.equals(o[i].getClass())) {
638 return lvType;
639 }
640 }
641 return lvClass;
642 } else {
643 return o.getClass().getComponentType();
644 }
645 }
646 else if (pvListObj instanceof Collection) {
647 Collection coll = (Collection) pvListObj;
648 if (coll.size() > 0) {
649 Class lvClass = coll.iterator().next().getClass();
650 Iterator it = coll.iterator();
651 while (it.hasNext()) {
652 if (!lvClass.equals(it.next().getClass())) {
653 return lvType;
654 }
655 }
656 return lvClass;
657 } else {
658 return lvType;
659 }
660 }
661 return lvType;
662 }
663
664
665 public static Object convertClassString2Object (String pvClassName) throws Exception {
666
667 if (pvClassName == null) { return null; }
668
669 else if (pvClassName.equals(int.class.getName())) { return Integer.valueOf("0"); }
670 else if (pvClassName.equals(short.class.getName())) { return Short.valueOf("0"); }
671 else if (pvClassName.equals(byte.class.getName())) { return Byte.valueOf("0"); }
672 else if (pvClassName.equals(long.class.getName())) { return Long.valueOf("0"); }
673
674
675 else if (pvClassName.equals(double.class.getName())) { return Double.valueOf("0"); }
676 else if (pvClassName.equals(float.class.getName())) { return Float.valueOf("0"); }
677
678 else if (pvClassName.equals(char.class.getName())) { return new Character(' '); }
679 else if (pvClassName.equals(Character.class.getName())) { return new Character(' '); }
680
681 else if (pvClassName.equals(boolean.class.getName())) { return Boolean.TRUE; }
682 else if (pvClassName.equals(Boolean.class.getName())) { return Boolean.TRUE; }
683
684 else if ((pvClassName.startsWith("[L")) && (pvClassName.endsWith(";"))) {
685 try {
686 String lvClassName = pvClassName.substring(2, (pvClassName.length() - 1));
687 lvClassName = lvClassName.replaceAll("/", "\\.");
688 Class clazz = Class.forName(lvClassName);
689 Object lvArray = Array.newInstance(clazz, 0);
690 return lvArray;
691 } catch (Exception e) {
692 if (log.isDebugEnabled()) { log.debug("convertClassString2Object: " + pvClassName, e); }
693 if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
694 return null;
695 }
696 }
697
698 else {
699 Object lvReturn = createObjectWithParamConstructor(null, null, pvClassName);
700 if (lvReturn == null) {
701 lvReturn = createObjectWithParamConstructor(new Long(0), long.class, pvClassName);
702 }
703 if (lvReturn == null) {
704 lvReturn = createObjectWithParamConstructor("0", String.class, pvClassName);
705 }
706 return lvReturn;
707 }
708
709 }
710
711 public static Object createObjectWithParamConstructor (Object pvParam, Class pvParamType, String pvClassName) {
712 try {
713 Class clazz = Class.forName(pvClassName);
714 if (pvParam == null) {
715 return clazz.newInstance();
716 } else {
717 Constructor lvConstructor = clazz.getConstructor(new Class[] {pvParamType});
718 return lvConstructor.newInstance(new Object [] {pvParam});
719 }
720 } catch (Exception e) {
721 if (log.isDebugEnabled()) { log.debug("convertString2ClassString: " + pvClassName, e); }
722 if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
723 }
724 return null;
725 }
726
727 /**
728 * For example String to Integer or String to Date, ...
729 *
730 * @param pvStringValue Value in String class.
731 * @param pvClassName Class name to convert the String value.
732 * @return The converted String value.
733 */
734 public static Object convertString2Value (String pvStringValue, String pvClassName) throws Exception {
735 Class clazz = null;
736
737 if (pvClassName.equals(int.class.getName())) { clazz = int.class; }
738 else if (pvClassName.equals(short.class.getName())) { clazz = short.class; }
739 else if (pvClassName.equals(byte.class.getName())) { clazz = byte.class; }
740 else if (pvClassName.equals(long.class.getName())) { clazz = long.class; }
741
742
743 else if (pvClassName.equals(double.class.getName())) { clazz = double.class; }
744 else if (pvClassName.equals(float.class.getName())) { clazz = float.class; }
745
746 else if (pvClassName.equals(char.class.getName())) { clazz = char.class; }
747
748 else if (pvClassName.equals(boolean.class.getName())) { clazz = boolean.class; }
749
750 else {
751 try {
752 clazz = Class.forName(pvClassName);
753 } catch (Exception e) {
754 if (ServiceManager.DEBUG_MODE_ON) {
755 e.printStackTrace();
756 }
757 }
758
759 }
760
761 return convertString2Value (pvStringValue, clazz);
762 }
763
764 public static Object convertString2Value (Object pvValue, Class pvClass) {
765 if (pvValue instanceof String) {
766 return convertString2Value((String) pvValue, pvClass);
767 } else {
768 return pvValue;
769 }
770 }
771 /**
772 * For example String to Integer or String to Date, ...
773 *
774 * @param pvStringValue Value in String class.
775 * @param pvClass Type to convert the String value.
776 * @return The converted String value.
777 */
778 public static Object convertString2Value (String pvStringValue, Class pvClass) {
779 if ((pvClass == null) || (pvStringValue == null)) { return null; }
780
781 if ((pvClass.equals(Integer.class)) || (pvClass.equals(int.class))) { return Integer.valueOf(pvStringValue); }
782 else if ((pvClass.equals(Short.class)) || (pvClass.equals(short.class))) { return Short.valueOf(pvStringValue); }
783 else if ((pvClass.equals(Byte.class)) || (pvClass.equals(byte.class))) { return Byte.valueOf(pvStringValue); }
784 else if ((pvClass.equals(Long.class)) || (pvClass.equals(long.class))) { return Long.valueOf(pvStringValue); }
785
786
787 else if ((pvClass.equals(Double.class)) || (pvClass.equals(double.class))) { return Double.valueOf(pvStringValue); }
788 else if ((pvClass.equals(Float.class)) || (pvClass.equals(float.class))) { return Float.valueOf(pvStringValue); }
789 else if (pvClass.equals(BigDecimal.class)) { return new BigDecimal (pvStringValue); }
790
791
792 else if ((pvClass.equals(Boolean.class)) || (pvClass.equals(boolean.class))) { return Boolean.valueOf(pvStringValue); }
793
794
795 else if ((pvClass.equals(Character.class)) || (pvClass.equals(char.class))) { return new Character(pvStringValue.charAt(0)); }
796 else if (pvClass.equals(String.class)) { return pvStringValue; }
797
798 else if ((pvClass.equals(Date.class)) || (pvClass.equals(java.sql.Date.class))){ return Converter.string2Date(pvStringValue); }
799
800 else {
801
802 log.warn("Illegal value in Converter.convertString2Value: " + pvStringValue + " for class: " + pvClass);
803 try {
804 return pvClass.newInstance();
805 } catch (Exception e) {
806 if (log.isDebugEnabled()) {
807 log.debug("Error by convertString2Value by new Instance for class: " + pvClass, e);
808 if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
809 }
810 return null;
811 }
812 }
813 }
814
815 /**
816 * Convert String-Parameter (contains in the Vector) in Method-ParameterTypes.
817 * For example: Vector ["5", "8"] convert to new Integer [] { new Integer(5), new Integer (8) }
818 *
819 * @param pvMethod Method with ParameterTypes.
820 * @param pvParams Vector with Strings.
821 *
822 * @return Array with ParameterTypes and ParameterValues.
823 */
824 public static Object[] convertStringParams2MethodParams (Method pvMethod, Vector pvParams) {
825 if ((pvMethod == null) || (pvParams == null)) {
826 throw new IllegalArgumentException("The method parameter: " + pvMethod + " or params array: " + pvParams +
827 " must not null!");
828 }
829
830 Class lvParamTypes[] = pvMethod.getParameterTypes();
831 if (pvParams.size() != lvParamTypes.length) {
832 throw new IllegalArgumentException("The parameter size: " + pvParams.size()
833 + " is not equal to method parameter: " + lvParamTypes.length);
834 }
835 Object lvNewParams[] = new Object[pvParams.size()];
836 for (int i = 0; i < lvNewParams.length; i++) {
837 lvNewParams[i] = Converter.convertString2Value(pvParams.get(i), lvParamTypes[i]);
838 }
839 return lvNewParams;
840 }
841
842
843 /**
844 * Convert a Date-String to a Date. The Converter <b>neglected the Millisecond</b>.
845 * Example: Thu Aug 11 19:30:57 CEST 2005
846 *
847 * @param pvDateString The Date-String (unequal null).
848 * @return Valid <code>java.util.Date</code>.
849 */
850 public static Date string2Date (String pvDateString) {
851 if (pvDateString == null) { throw new IllegalArgumentException ("The Date-String was null by string2Date."); }
852
853 Date date = null;
854
855
856 DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CEST' yyyy", Locale.ENGLISH);
857 try {
858 date = df.parse(pvDateString);
859 return date;
860 } catch (ParseException e) {
861 log.debug("Error by string2Date: " + pvDateString , e);
862 }
863
864
865 df = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CET' yyyy", Locale.ENGLISH);
866 try {
867 date = df.parse(pvDateString);
868 return date;
869 } catch (ParseException e) {
870 log.debug("Error by string2Date: " + pvDateString , e);
871 }
872
873
874 df = DateFormat.getDateInstance(DateFormat.MEDIUM);
875 try {
876 date = df.parse(pvDateString);
877 return date;
878 } catch (ParseException e) {
879 log.debug("Error by string2Date: " + pvDateString , e);
880 }
881
882 throw new IllegalStateException ("The String: \"" + pvDateString + "\" is not valid date.");
883 }
884
885 /**
886 * Extract from package + class name, the class name.
887 * Example (<code>pvToLowerCase = false)</code>): Input: <code>net.sf.crispy.ServiceManager</code> -> Output: <code>ServiceManger</code>.
888 * Example (<code>pvToLowerCase = true)</code>): Input: <code>net.sf.crispy.ServiceManager</code> -> Output: <code>servicemanger</code>.
889 *
890 * @param pvClassWitchPackage
891 * @param pvToLowerCase
892 * @return The class without package.
893 */
894 public static String getClassWithoutPackage(String pvClassWitchPackage, boolean pvToLowerCase) {
895 if (pvClassWitchPackage == null) { return null; }
896 int lvIndex = pvClassWitchPackage.lastIndexOf('.') + 1;
897 String lvClassName = pvClassWitchPackage.substring(lvIndex);
898 if (pvToLowerCase == true) { lvClassName = lvClassName.toLowerCase(); }
899 return lvClassName;
900 }
901
902 /**
903 * If pvObject.toString - method start with <code>Converter.HASH_CODE_KEY</code>, then extract
904 * the hash code.
905 * Example: make from <code>~hashCode~24306761</code> to <code>24306761</code>.
906 *
907 * @param pvObject
908 * @return The hash code.
909 */
910 public static String extractHashCode (Object pvObject) {
911 if (pvObject == null) { return null; }
912 String lvHashCode = pvObject.toString();
913 if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
914 lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
915 return lvHashCode;
916 } else {
917 return null;
918 }
919
920 }
921
922 /**
923 * Remove all getter-method where no setter-method exist.
924 */
925 public static Map getAllNotEqualsGetterAndSetterAndRemoveThisProperties(Map pvGetterMap, Map pvSetterMap) {
926 Iterator it = new ArrayList(pvGetterMap.keySet()).iterator();
927 while (it.hasNext()) {
928 Object lvGetterProp = it.next();
929 if (!(pvSetterMap.containsKey(lvGetterProp)) && !(lvGetterProp.equals("class"))) {
930 if (log.isDebugEnabled()) {
931 log.debug("For Getter: " + lvGetterProp + " --> no Setter!");
932 }
933 pvGetterMap.remove(lvGetterProp);
934 }
935 }
936 return pvGetterMap;
937 }
938
939 /**
940 * Find all getter-method from a Class and remove all getter-method where no setter-method exist.
941 * @param pvClass Class to anaylse.
942 * @return Map from getter-method (key=property name, value=method).
943 * @throws IntrospectionException
944 */
945 public static Map getAllGetterMethodWithCache(Class pvClass) throws IntrospectionException {
946 Map lvGetterMap = classPropertiesCacheGetter.getClassPropertiesMapByClass(pvClass);
947 if (lvGetterMap == null) {
948 try {
949 lvGetterMap = Converter.getAllGetterMethod(pvClass);
950 Map lvSetterMap = getAllSetterMethodWithCache(pvClass);
951 lvGetterMap = getAllNotEqualsGetterAndSetterAndRemoveThisProperties (lvGetterMap, lvSetterMap);
952 classPropertiesCacheGetter.addClassPropertiesMap(pvClass, lvGetterMap);
953 } catch (IntrospectionException e) {
954 if (ServiceManager.DEBUG_MODE_ON) {
955 e.printStackTrace();
956 }
957 }
958 }
959 return lvGetterMap;
960 }
961
962 /**
963 * Find all setter-method from a Class.
964 * @param pvClass Class to analyse.
965 * @return Map all setter-Method (key=property name, value=method).
966 * @throws IntrospectionException
967 */
968 public static Map getAllSetterMethodWithCache(Class pvClass) throws IntrospectionException {
969 Map lvMap = classPropertiesCacheSetter.getClassPropertiesMapByClass(pvClass);
970 if (lvMap == null) {
971 try {
972 lvMap = Converter.getAllSetterMethod(pvClass);
973 classPropertiesCacheSetter.addClassPropertiesMap(pvClass, lvMap);
974 } catch (IntrospectionException e) {
975 if (ServiceManager.DEBUG_MODE_ON) {
976 e.printStackTrace();
977 }
978 }
979 }
980 return lvMap;
981 }
982 /**
983 * Find all getter-method from a Class.
984 * @param pvClass Class to analyse.
985 * @return Map all getter-Method (key=property name, value=method).
986 * @throws IntrospectionException
987 */
988 public static Map getAllGetterMethod(Class pvClass) throws IntrospectionException {
989 return getAllGetterAndSetterMethod(pvClass, GET_METHOD);
990 }
991
992 /**
993 * Find all setter-method from a Class.
994 * @param pvClass Class to analyse.
995 * @return Map all setter-Method (key=property name, value=method).
996 * @throws IntrospectionException
997 */
998 public static Map getAllSetterMethod(Class pvClass) throws IntrospectionException {
999 return getAllGetterAndSetterMethod(pvClass, SET_METHOD);
1000 }
1001
1002
1003 /**
1004 * Get all set/get methods from a Class. With methods from all super classes.
1005 * @param pvClass Analyse Class.
1006 * @return All finded methods.
1007 */
1008 public static Method[] getAllMethodsByClass (Class pvClass) {
1009 Collection lvColl = getAllMethodsByClassIntern(pvClass, new Hashtable());
1010 return (Method[]) getAllMethodsByClassIntern(pvClass, new Hashtable()).toArray(new Method [lvColl.size()]);
1011 }
1012
1013 /**
1014 * Recursive search alle method from the Class in the Class Hierarchy to Object.class.
1015 * @param pvClass Search class.
1016 * @param pvMethodsMap Method map (key=property name, value=method).
1017 * @return All finded methods.
1018 */
1019 private static Collection getAllMethodsByClassIntern (Class pvClass, Map pvMethodsMap) {
1020 putAllMethodsIntern( pvClass.getMethods(), pvMethodsMap) ;
1021 putAllMethodsIntern( pvClass.getDeclaredMethods(), pvMethodsMap);
1022
1023 if (!(pvClass.getSuperclass().equals(Object.class))) {
1024 getAllMethodsByClassIntern(pvClass.getSuperclass(), pvMethodsMap);
1025 }
1026
1027 return pvMethodsMap.values();
1028 }
1029
1030 private static void putAllMethodsIntern (Method pvAllMethods[], Map pvMethodsMap) {
1031 for (int i = 0; i < pvAllMethods.length; i++) {
1032 String lvMethodName = pvAllMethods[i].getName();
1033 if (lvMethodName.startsWith("set") || lvMethodName.startsWith("get")) {
1034 pvMethodsMap.put(pvAllMethods[i], pvAllMethods[i]);
1035 }
1036 }
1037 }
1038
1039 /**
1040 *
1041 * @param pvClass Find all get or set method from a Class.
1042 * @param pvMethodType get or set
1043 * @return Method map (key=property name, value=method).
1044 * @throws IntrospectionException
1045 */
1046 public static Map getAllGetterAndSetterMethod(Class pvClass, int pvMethodType) throws IntrospectionException {
1047 Method lvAllAmethods[] = getAllMethodsByClass(pvClass);
1048 Map lvGetterOrSetter = new TreeMap();
1049 for (int i = 0; i < lvAllAmethods.length; i++) {
1050 Method lvMethod = null;
1051 String lvPropName = lvAllAmethods[i].getName();
1052 switch (pvMethodType) {
1053 case GET_METHOD:
1054 if (lvPropName.startsWith("get")) {
1055 lvMethod = lvAllAmethods[i];
1056 }
1057 break;
1058 case SET_METHOD:
1059 if (lvPropName.startsWith("set")) {
1060 lvMethod = lvAllAmethods[i];
1061 }
1062 break;
1063 default:
1064 break;
1065 }
1066 if (lvMethod != null) {
1067
1068 AccessController.doPrivileged(new MethodAccessiblePrivilegedAction(lvMethod));
1069
1070 lvPropName = lvPropName.substring(3);
1071
1072 if (lvPropName.length() > 0) {
1073 lvPropName = lvPropName.substring(0, 1).toLowerCase()+ lvPropName.substring(1);
1074 if (lvPropName.equals("class")) {
1075 lvGetterOrSetter.put(lvPropName, pvClass.getName());
1076 } else {
1077 lvGetterOrSetter.put(lvPropName, lvMethod);
1078 }
1079 } else {
1080 throw new InvocationException("Invalid Property-Name: '" + lvAllAmethods[i].getName()
1081 + "' (Valid Property-Name is: set[name] themed get[name], eg. setYear and getYear).");
1082 }
1083 }
1084 }
1085 return lvGetterOrSetter;
1086 }
1087
1088 public static Object createDefaultValueForPrimitiveClass(Class pvClass) {
1089 Object lvReturn = null;
1090 if (pvClass.equals(boolean.class)) { lvReturn = Boolean.FALSE; }
1091 else if (pvClass.equals(short.class)) { lvReturn = Short.valueOf("0"); }
1092 else if (pvClass.equals(byte.class)) { lvReturn = Byte.valueOf("0"); }
1093 else if (pvClass.equals(int.class)) { lvReturn = Integer.valueOf("0"); }
1094 else if (pvClass.equals(long.class)) { lvReturn = Long.valueOf("0"); }
1095 else if (pvClass.equals(double.class)) { lvReturn = Double.valueOf("0"); }
1096 else if (pvClass.equals(float.class)) { lvReturn = Float.valueOf("0"); }
1097 else if (pvClass.equals(char.class)) { lvReturn = new Character(' '); }
1098
1099 return lvReturn;
1100 }
1101
1102 private class SimpleKeyMapper implements Comparator {
1103
1104 public static final String DELIMITER = "~_-_~";
1105
1106 private String pos = null;
1107 private Object key = null;
1108
1109 public SimpleKeyMapper() {}
1110 public SimpleKeyMapper(String pvPos, Object pvKey) {
1111 pos = pvPos;
1112 key = pvKey;
1113 }
1114
1115 public int getPos () {
1116 Integer integer = Integer.valueOf(pos);
1117 return integer.intValue();
1118 }
1119
1120 public Object getKey() {
1121 return key;
1122 }
1123
1124 public Object toSimpleNewKey(final Object pvOldKey, final Class pvOldKeyClass, int pvPos, boolean pvWithSimpleKeyMapper) {
1125 if (pvWithSimpleKeyMapper) {
1126 String lvNewKey = null;
1127 int l = pvOldKey.toString().split(DELIMITER).length;
1128 if (l == 3 || l == 2) {
1129 lvNewKey = pvOldKey.toString();
1130 } else {
1131 if (pvOldKeyClass.equals(String.class)) {
1132 lvNewKey = pvPos + DELIMITER + pvOldKey;
1133 } else {
1134 lvNewKey = pvPos + DELIMITER + pvOldKey + DELIMITER + pvOldKeyClass.getName();
1135 }
1136 }
1137 return lvNewKey;
1138 } else {
1139 return pvOldKey;
1140 }
1141 }
1142
1143 public Object toComplexNewKey(Object pvOriginalKey, boolean pvWithSimpleKeyMapper) {
1144 if (pvWithSimpleKeyMapper == false) {
1145 return pvOriginalKey;
1146 } else {
1147 Object lvKey = ((SimpleKeyMapper) pvOriginalKey).getKey();
1148 return lvKey;
1149 }
1150 }
1151
1152
1153 public Map orderMapByKey (final Map pvMap, boolean pvWithSimpleKeyMapper) throws Exception {
1154 if (pvWithSimpleKeyMapper == false) {
1155 return pvMap;
1156 } else {
1157 Iterator it = pvMap.keySet().iterator();
1158 TreeMap lvTreeMap = new TreeMap(new SimpleKeyMapper());
1159 while (it.hasNext()) {
1160 Object o = it.next();
1161 if ( ! (o instanceof String) ) {
1162 throw new IllegalArgumentException("Expected String and object is: " + o + " -> class: " + o.getClass().getName());
1163 }
1164 String lvKeyStr = (String) o;
1165 String lvKeyArray[] = lvKeyStr.split(DELIMITER);
1166 if (lvKeyArray.length < 2) {
1167 throw new IllegalArgumentException("If the property Converter.withSimpleKeyMappe is true, than must the key contains" +
1168 " the delimiter: " + DELIMITER + " - " + lvKeyStr + " (" + lvKeyArray.length + ")");
1169 }
1170
1171 Object lvValue = pvMap.get(lvKeyStr);
1172
1173 String lvPos = lvKeyArray[0];
1174 String lvKeyValue = lvKeyArray[1];
1175 Object lvKey = null;
1176 if (lvKeyArray.length == 3) {
1177 String lvKeyClass = lvKeyArray[2];
1178 lvKey = Converter.convertString2Value(lvKeyValue, lvKeyClass);
1179 } else {
1180 lvKey = lvKeyValue;
1181 }
1182
1183
1184 SimpleKeyMapper skm = new SimpleKeyMapper(lvPos, lvKey);
1185 lvTreeMap.put(skm, lvValue);
1186 }
1187 return lvTreeMap;
1188 }
1189 }
1190
1191 public int compare(Object pvO1, Object pvO2) {
1192 SimpleKeyMapper skm1 = (SimpleKeyMapper) pvO1;
1193 SimpleKeyMapper skm2 = (SimpleKeyMapper) pvO2;
1194 if (skm1.getPos() > skm2.getPos()) {
1195 return 1;
1196 }
1197 else {
1198 return -1;
1199 }
1200 }
1201 }
1202 }