View Javadoc

1   /*
2    * Created on 07.03.2005
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 //		return ! b;
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 //	private int startHashCode = 1;
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 { //if (!(o.equals(pvObject))) {
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         // Zugelassene Datentypen
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         // Konvertierung von primitiven Typen in zugelassene primitive Typen
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         // Behaelter
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             // um Reihenfolge zu merken, ist wichtig, 
228             // wenn Objekte aus der Map geholt werden
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                 // class before transformatio
240                 Class lvKeyClass = lvKey.getClass();
241                 // transformation from the key to simple object (e.g. from Long to Integer)
242                 lvKey = makeSimpleInternal(lvKey, pvPropName, pvGraph);
243                 // den Schluessel in eine Map verpacken, damit die Reihenfolge NICHT verloren geht
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         // Konvertierung von Objekten in eine Hashtable
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                		// test of cycles 
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                     // fuer das unmarshalling
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         // clazz ist vom Typ Object, pvObject aber NICHT,
346         // deshalb den typ von pvObject uebernehmen
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         // Zugelassene Datentypen
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         // Primitive Datentypen
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         // Konvertierung von primitiven Typen in zugelassene primitive Typen
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         	// wenn pvObject kein Array ist 
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         	// wenn pvObject kein Array ist 
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         // Behaelter
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                 // null value are ignored
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 		                    } // value != null
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 	    		// !!!!! Specialfall ?????
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 //        	??? throw new IllegalArgumentException("Illegal value: " + pvStringValue + " or type: " + pvClass); ???
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 		// 1. Versuch, Datum wie es bei der toString-Methode zurueck kommt, umzuwandeln
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 		// 2. Versuch, Datum wie es bei der toString-Methode zurueck kommt, umzuwandeln
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 		// 3. Verusch, Medium Datum umzuwandeln
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 	        	// PropName muss aus set oder get UND einen Namen bestehen
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         	} // if method != null
1084 		} // for
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 }