Converter.java :  » Web-Services » crispy » net » sf » crispy » util » Java Open Source

Java Open Source » Web Services » crispy 
crispy » net » sf » crispy » util » Converter.java
/*
 * Created on 07.03.2005
 *
 */
package net.sf.crispy.util;

import java.beans.IntrospectionException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
import java.util.Map.Entry;

import net.sf.crispy.InvocationException;
import net.sf.crispy.impl.ServiceManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Convert complex object in a simple form and back to the object.
 * 
 * @author Linke
 *
 */
public class Converter {
  
  public final static String HASH_CODE_KEY = "~hashCode~";
  public final static int GET_METHOD = 1;
  public final static int SET_METHOD = 2;

  protected static final Log log = LogFactory.getLog (Converter.class);
  protected static final Map isSimpleDataType = new Hashtable();
  protected static final ClassPropertiesCache classPropertiesCacheGetter = new ClassPropertiesCache();
  protected static final ClassPropertiesCache classPropertiesCacheSetter = new ClassPropertiesCache();
  
  private String nullValue = null;
  private boolean withSimpleKeyMapper = false;
  
  public Converter() { }
  public Converter(String pvNullValue) { 
    setNullValue(pvNullValue);
  }
  public Converter(int pvStartHashCode) {
    uniqueIdMap = new Hashtable();
    startHashCode = pvStartHashCode;
  }
  
  public void setWithSimpleKeyMapper(boolean pvWithSimpleKeyMapper) { withSimpleKeyMapper = pvWithSimpleKeyMapper; }
  public boolean getWithSimpleKeyMapper() { return withSimpleKeyMapper; }
  
  public static boolean isValideEdge(Object pvObject) {
    if (pvObject == null) { return false; }
    if (isSimpleDataType.size() == 0) {
      isSimpleDataType.put(String.class, String.class);
      isSimpleDataType.put(Boolean.class, Boolean.class);
      isSimpleDataType.put(boolean.class, boolean.class);
      isSimpleDataType.put(Byte.class, Byte.class);
      isSimpleDataType.put(byte.class, byte.class);
      isSimpleDataType.put(Short.class, Short.class);
      isSimpleDataType.put(short.class, short.class);
      isSimpleDataType.put(Integer.class, Integer.class);
      isSimpleDataType.put(int.class, int.class);
      isSimpleDataType.put(Long.class, Long.class);
      isSimpleDataType.put(long.class, long.class);
      isSimpleDataType.put(Float.class, Float.class);
      isSimpleDataType.put(float.class, float.class);
      isSimpleDataType.put(Double.class, Double.class);
      isSimpleDataType.put(double.class, double.class);
      isSimpleDataType.put(Character.class, Character.class);
      isSimpleDataType.put(char.class, char.class);
      isSimpleDataType.put(BigDecimal.class, BigDecimal.class);
      isSimpleDataType.put(StringBuffer.class, StringBuffer.class);
      isSimpleDataType.put(BigInteger.class, BigInteger.class);
      isSimpleDataType.put(Class.class, Class.class);
      isSimpleDataType.put(java.sql.Date.class, java.sql.Date.class);
      isSimpleDataType.put(java.util.Date.class, java.util.Date.class);
      isSimpleDataType.put(Time.class, Time.class);
      isSimpleDataType.put(Timestamp.class, Timestamp.class);
    }
    boolean b = isSimpleDataType.containsKey(pvObject.getClass());
//    return ! b;
    if (b == true) { 
      return false; 
    }
    else {
      return true;
    }
  }

  private Map uniqueIdMap = null;
  private Map uniqueIdMap2 = null;
  private int hashCode = 0;
  private int startHashCode = -1000000000;
//  private int startHashCode = 1;

  public String getNullValue() { return nullValue; }
  public void setNullValue(String pvNullValue) { nullValue = pvNullValue; }
  
  public String findNextFreeId (int pvHashCode) {
    String lvHashCodeStr = Integer.toString(pvHashCode);
    if (uniqueIdMap.containsKey(lvHashCodeStr)) {
      int next = pvHashCode + 1;
      lvHashCodeStr = findNextFreeId (next);
    }
    return lvHashCodeStr;
  }
  
  private String getUniqueId(Object pvObject) {
    if (pvObject == null) {return null; }

    String lvHashCode = (String) uniqueIdMap2.get(pvObject); 
    if (lvHashCode != null){
      return lvHashCode;
    }
    
    lvHashCode = Integer.toString(pvObject.hashCode());
    Object o = uniqueIdMap.get(lvHashCode);
    if (o == null) { 
      uniqueIdMap.put(lvHashCode, pvObject); 
      uniqueIdMap2.put(pvObject, lvHashCode);
    }
    else { //if (!(o.equals(pvObject))) {
      lvHashCode = findNextFreeId(hashCode);
      uniqueIdMap.put(lvHashCode, pvObject);
      uniqueIdMap2.put(pvObject, lvHashCode);
    }
    return lvHashCode; 
  }

  
  /**
   * Convert complex object in a Hashtable and relations in Vector.
   * Cycles are finded and removed.
   * 
   * @param pvObject Complex or simple object.
   * @return Simple object structure.
   * @throws Exception
   */
  public Object makeSimple (Object pvObject) throws Exception {
    uniqueIdMap = new Hashtable();
    uniqueIdMap2 = new Hashtable();
    hashCode = startHashCode;
    Object lvReturn = null;
    try {
      lvReturn = makeSimpleInternal (pvObject, null, new Graph());
    } 
    finally {
      uniqueIdMap = null;
      uniqueIdMap2 = null;
      hashCode = startHashCode;
    }
    return lvReturn;
  }
    
    private Object makeSimpleInternal (Object pvObject, String pvPropName, Graph pvGraph) throws Exception {
      Method lvMethod = null;

      if (pvObject == null) { return nullValue; }

        Class clazz = pvObject.getClass();
          
        // Zugelassene Datentypen
        if (clazz.equals(String.class)) { return pvObject; }
        else if (clazz.equals(Date.class)) { return pvObject; }
        else if (clazz.equals(Integer.class)) { return pvObject; }
        else if (clazz.equals(Double.class)) { return pvObject; }
        else if (clazz.equals(Boolean.class)) { return pvObject; }

        else if ((clazz.isArray()) && (clazz.getComponentType().equals(byte.class))) { return pvObject; }
            
        // Konvertierung von primitiven Typen in zugelassene primitive Typen
        else if (clazz.equals(Long.class)) { return Integer.valueOf(pvObject.toString()); }
        else if (clazz.equals(Byte.class)) { return Integer.valueOf(pvObject.toString()); }
        else if (clazz.equals(Float.class)) { return new Double(pvObject.toString()); }
        else if (clazz.equals(Character.class)) { return pvObject.toString(); }
        else if (clazz.equals(Short.class)) { return Integer.valueOf(pvObject.toString()); }
        else if (clazz.equals(BigDecimal.class)) { return new Double(pvObject.toString()); }
        else if (clazz.equals(StringBuffer.class)) { return pvObject.toString(); }
        else if (clazz.equals(BigInteger.class)) { return Integer.valueOf(pvObject.toString()); }
        else if (clazz.equals(Class.class)) { return ((Class) pvObject).getName(); }
        else if (clazz.equals(java.sql.Date.class)) {  return new Date(((java.sql.Date) pvObject).getTime()); }
        else if (clazz.equals(Time.class)) { return (Date) pvObject; }
        else if (clazz.equals(Timestamp.class)) { return (Date) pvObject; }
  
        // Behaelter
        else if (pvObject instanceof Collection) {
          final Collection coll = (Collection) pvObject;
            Iterator it = coll.iterator();
            Vector v = new Vector(coll.size());
            while (it.hasNext()) {
                Object lvValue = it.next();
                String lvHashCode = getUniqueId(lvValue);
                if (pvGraph.getVertexCount(lvValue) == true) {
                  v.add(HASH_CODE_KEY + lvHashCode);
             } else {
                  Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
                  if (o != null) { v.add(o); }
             }
            }
            return v;
        }
          
        else if (pvObject instanceof Map) {
            Map map = (Map) pvObject;
            Hashtable lvHashtable = new Hashtable(map.size());
            // um Reihenfolge zu merken, ist wichtig, 
            // wenn Objekte aus der Map geholt werden
            int pos = 0;
            SimpleKeyMapper lvKeyMapper = new SimpleKeyMapper();
            Iterator it = map.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry lvMapEntry = (Entry) it.next();
                Object lvKey = lvMapEntry.getKey();
                pos = ++pos;
                if (isValideEdge(lvKey)) { throw new InvocationException("Complex Map-Key datatypes are not supported: " + lvKey.getClass().getName()); }
                Object lvValue = lvMapEntry.getValue();
                String lvHashCode = getUniqueId(lvValue);
                // class before transformatio
                Class lvKeyClass = lvKey.getClass();
                // transformation from the key to simple object (e.g. from Long to Integer)
                lvKey = makeSimpleInternal(lvKey, pvPropName, pvGraph);
                // den Schluessel in eine Map verpacken, damit die Reihenfolge NICHT verloren geht
                Object key = lvKeyMapper.toSimpleNewKey(lvKey, lvKeyClass, pos, withSimpleKeyMapper);
                if (pvGraph.getVertexCount(lvValue) == true) {
                  lvHashtable.put(key, HASH_CODE_KEY + lvHashCode); 
             } else {
                  Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
                  if (o != null) { lvHashtable.put(key, o); }
                }
            }
            return lvHashtable;
        }
        
        else if (clazz.isArray()) {
            int length = Array.getLength(pvObject);
            Vector v = new Vector(length);
            for (int i=0;i<length;i++) {
              Object lvValue = Array.get (pvObject, i);
              String lvHashCode = getUniqueId(lvValue);
                if (pvGraph.getVertexCount(lvValue) == true) {
                  v.add(HASH_CODE_KEY + lvHashCode); 
             } else { 
                Object o = makeSimpleInternal(lvValue, pvPropName, pvGraph);
                if (o != null) { v.add(o); }
                }
            }
            return v;
        }
        
        // Konvertierung von Objekten in eine Hashtable
        else {
            Hashtable map = new Hashtable();
            String lvHashCode = getUniqueId(pvObject);
            map.put(HASH_CODE_KEY, lvHashCode);
          pvGraph.addVertex(pvObject); 
          Map lvGetterMap = getAllGetterMethodWithCache(clazz);
          Iterator it = lvGetterMap.entrySet().iterator();
          while (it.hasNext()) {
            Map.Entry lvMapEntry = (Entry) it.next();
            String propName = (String) lvMapEntry.getKey(); 
                if (propName.equals("class") == false) {
                   Object lvValue = null;
                   try {
                       lvMethod = (Method)lvMapEntry.getValue();
                     lvValue = lvMethod.invoke(pvObject, null);
                   } catch (Exception e) {
                     if (log.isDebugEnabled()) { log.debug("Problem by invoke method (in makeSimple): " + lvMethod, e); }
                     if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
                   }


                   // test of cycles 
                  if (lvValue != null)  {
                    Edge lvEdge = new Edge(pvObject, lvValue);
                    if (pvGraph.containsKey(lvEdge) == false) {
                      if (isValideEdge(lvValue) == true) { 
                        pvGraph.put(lvEdge, "");
                      } 
                      Edge lvKnownEdgeToThisNode = pvGraph.isFromContains(lvValue); 
                      if (lvKnownEdgeToThisNode != null) {
                        lvEdge.setMethodName(lvMethod.getName());
                        map.put(propName, HASH_CODE_KEY + getUniqueId(lvValue));
                      } 
                      else {
                        Object o = makeSimpleInternal(lvValue, propName, pvGraph);
                          map.put(propName, o);
                         }
                       } 
                    
                    else {
                      map.put(propName, HASH_CODE_KEY + getUniqueId(lvValue));
                    }
                  }
                   
                } else {
                    // fuer das unmarshalling
                     map.put("class", clazz.getName()); 
                }
            }
            return  map;
        }
    }
    
    public Object makeComplex (Object pvObject) throws Exception {
      return makeComplex(pvObject, null); 
    }
    
    public Object makeComplex (Object pvObject, Class clazz) throws Exception {
      return makeComplex(pvObject, clazz, null); 
    }
    
    public Object makeComplex (Object pvObject, Class clazz, Class clazzInArray) throws Exception {
      return makeComplexInternal(pvObject, clazz, clazzInArray, new Hashtable()); 
    }
    
    private Object makeComplexInternal (final Object pvObject, final Class pvClazz, final Class clazzInArray, final Map pvHashCodeMap) throws Exception {
      Method lvMethod = null;
      Class clazz = pvClazz;

      if (pvObject == null || pvObject.equals(nullValue)) { return null; }
  
        if (pvClazz == null) { clazz = pvObject.getClass(); }

        // clazz ist vom Typ Object, pvObject aber NICHT,
        // deshalb den typ von pvObject uebernehmen
        if ((clazz.equals(Object.class)) && (!(pvObject.getClass().equals(Object.class)))) {
          if (log.isDebugEnabled()) { 
            log.debug("Class: "+ clazz.getName() + " is different from Object: " + pvObject.getClass().getName()); 
          }
          clazz = pvObject.getClass();
        }

        // Zugelassene Datentypen
        if (clazz.equals(String.class)) { return pvObject; }
        else if (clazz.equals(Integer.class)) { return pvObject; }
        else if (clazz.equals(Double.class)) { return pvObject; }
        else if (clazz.equals(Boolean.class)) { return pvObject; }
        else if (clazz.equals(Date.class)) { return pvObject; }
        else if ((clazz.isArray()) && (clazz.getComponentType().equals(byte.class))) { return pvObject; }
          
        // Primitive Datentypen
        else if (clazz.equals(boolean.class)) { return pvObject; }
        else if (clazz.equals(short.class)) { return new Short(pvObject.toString()); }
        else if (clazz.equals(byte.class)) { return new Byte(pvObject.toString()); }
        else if (clazz.equals(int.class)) { return pvObject; }
        else if (clazz.equals(long.class)) { return new Long(pvObject.toString()); }
        else if (clazz.equals(double.class)) { return new Double(pvObject.toString()); }
        else if (clazz.equals(float.class)) { return new Float(pvObject.toString()); }
        else if (clazz.equals(char.class)) { return new Character(pvObject.toString().charAt(0)); }
          
        // Konvertierung von primitiven Typen in zugelassene primitive Typen
        else if (clazz.equals(Byte.class)) { return new Byte(pvObject.toString()); }
        else if (clazz.equals(Float.class)) { return new Float(pvObject.toString()); }
        else if (clazz.equals(Character.class)) { return new Character(pvObject.toString().charAt(0)); }
        else if (clazz.equals(Long.class)) { return new Long(pvObject.toString()); }
        else if (clazz.equals(Short.class)) { return new Short(pvObject.toString()); }
        else if (clazz.equals(BigDecimal.class)) { return new BigDecimal (((Double) pvObject).doubleValue()); }
        else if (clazz.equals(StringBuffer.class)) { return new StringBuffer(pvObject.toString()); }
        else if (clazz.equals(BigInteger.class)) { return new BigInteger(pvObject.toString()); }
        else if (clazz.equals(Class.class)) { return Class.forName(pvObject.toString()); }
        else if (clazz.equals(java.sql.Date.class)) { return new java.sql.Date(((Date) pvObject).getTime()); }
        else if (clazz.equals(Time.class)) {
          if (pvObject instanceof Time) {
            return (Time) pvObject;  
          }
          else if (pvObject instanceof Timestamp) {
            Timestamp ts = (Timestamp) pvObject;
            return new Time(ts.getTime());
          }
          else if (pvObject instanceof Date) {
            return new Time(((Date) pvObject).getTime());
          }
          else if (pvObject instanceof Long) {
            Long l = (Long) pvObject;
            return new Time(l.longValue());
          } 
          else {
            throw new InvocationException("Exception by Converter.makeComplex. The datatype: " + pvObject.getClass().getName()
                  + " is not compatible to java.sql.Time");              
          }
            
        }
        else if (clazz.equals(Timestamp.class)) {
          if (pvObject instanceof Timestamp) {
            return (Timestamp) pvObject;  
          }
          else if (pvObject instanceof Time) {
            Time t = (Time) pvObject;
            return new Timestamp(t.getTime());
          }
          else if (pvObject instanceof Date) {
            return new Timestamp(((Date) pvObject).getTime());
          }
          else if (pvObject instanceof Long) {
            Long l = (Long) pvObject;
            return new Timestamp(l.longValue());
          }             
          else {
            throw new InvocationException("Exception by Converter.makeComplex. The datatype: " + pvObject.getClass().getName()
                  + " is not compatible to java.sql.Timestamp");
          }
            
        }
          
        else if (clazz.isArray()) {
          // wenn pvObject kein Array ist 
          if ((!pvObject.getClass().isArray()) &&  (pvObject instanceof Collection)) {
              Collection coll = (Collection) pvObject;
              Class lvType = (clazzInArray == null ? getArrayType(pvObject) : clazzInArray);
              Object[] lvTempArray = (Object[]) Array.newInstance(lvType, coll.size());
              Iterator it = coll.iterator();
              int i = 0;
              while (it.hasNext()) {
                Object objInList = it.next();
                      String lvHashCode = objInList.toString();
                        if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
                          lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
                          Object value = pvHashCodeMap.get(lvHashCode);
                          if (value == null) {
                            throw new InvocationException("Internal Converter-Exception. " +
                                "For the HashCode: " + lvHashCode + " can not find a object in the Array: " + coll);
                          } else {
                      lvTempArray[i] = value;
                          }
                        } else {
                  if (clazzInArray == null) { 
                    lvTempArray[i] = objInList; 
                    }
                    else { 
                      lvTempArray[i] = makeComplexInternal(objInList, clazzInArray, null, pvHashCodeMap); 
                    }
                        }
                i++;
              }
              return lvTempArray;
          }

          // wenn pvObject kein Array ist 
          if ((!pvObject.getClass().isArray()) &&  (pvObject instanceof Map)) {
            return makeComplexInternal(pvObject, null, null, pvHashCodeMap);
          } else {
            int length = Array.getLength(pvObject);
            Class lvType = (clazzInArray == null ? getArrayType(pvObject) : clazzInArray);
            Object[] o = (Object[]) Array.newInstance(lvType, length);
            for (int i=0;i<length;i++) {
              Object _o = Array.get (pvObject, i);
              o[i] = makeComplexInternal(_o, lvType, null, pvHashCodeMap); 
            }
            return o;
          }
        }

        // Behaelter
        else if (pvObject instanceof Collection) {
          Collection coll = (Collection) pvObject;
            Iterator it = coll.iterator();
            Collection lvNewColl = new Vector(coll.size());
            while (it.hasNext()) {
                Object o = it.next();
                // null value are ignored
                if (o != null) {
                  String lvHashCode = o.toString();
                    if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
                      lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
                      Object value = pvHashCodeMap.get(lvHashCode);
                      if (value == null) {
                        throw new InvocationException("Internal Converter-Exception. " +
                            "For the HashCode: " + lvHashCode + " can not find a object in the Collection: " + coll);
                      } else {
                        lvNewColl.add(value);
                      }
                    } else {
                    Object value = makeComplexInternal(o, o.getClass(), null, pvHashCodeMap);
                    lvNewColl.add(value); 
                    }
                }
            }
            return lvNewColl;
        }
          
        else if (pvObject instanceof Map) {
            Map map = (Map) pvObject;
            String aClazzStr = (String) map.get("class");
            if (aClazzStr == null) {
              
              SimpleKeyMapper lvSimpleKeyMapper = new SimpleKeyMapper();
              map = lvSimpleKeyMapper.orderMapByKey(map, withSimpleKeyMapper);
                
              Iterator it = map.entrySet().iterator();
              Hashtable lvHashtable = new Hashtable(map.size());
              while (it.hasNext()) {
                Map.Entry lvMapEntry = (Entry) it.next();
                Object lvKey = lvMapEntry.getKey();
                Object key = lvSimpleKeyMapper.toComplexNewKey(lvKey, withSimpleKeyMapper);
                Object lvValue = lvMapEntry.getValue();
                    String lvHashCode = extractHashCode(lvValue); 
                    if (lvHashCode != null) {
                    lvValue = pvHashCodeMap.get(lvHashCode);
                    if (lvValue == null) {
                      throw new InvocationException("Internal Converter-Exception. " +
                          "For the HashCode: " + lvHashCode + " can not find a object in a map: " + map);
                    } else {
                      lvHashtable.put(key, lvValue);
                    }
                  } else {
                    lvValue = makeComplexInternal(lvValue, lvValue.getClass(), null, pvHashCodeMap);
                    lvHashtable.put(key, lvValue); 
                  }
              }
              return lvHashtable;

            } else {
                Class aClazz = null;
                try {
                  aClazz = Class.forName(aClazzStr);
                } catch (Exception e) {
                  throw new InvocationException("Can't load class: " + aClazzStr);
                }
                Object ret = null;
                try {
                  ret = aClazz.newInstance();
                } catch (Exception e) {
                  throw new InvocationException("Can't create object from class: " + aClazzStr + " (No constructor without parameter!)");
                }

                String lvMapHashCode = (String) map.get(HASH_CODE_KEY);
                if (lvMapHashCode != null) { pvHashCodeMap.put(lvMapHashCode, ret);  }
                
                try {
                Map lvSetterMap = getAllSetterMethodWithCache(aClazz);
                Iterator it = lvSetterMap.entrySet().iterator();
                  while (it.hasNext()) {
                    Map.Entry lvMapEntry = (Entry) it.next();
                      String propName = (String) lvMapEntry.getKey(); 
                          Object value = map.get(propName);
                          if (value != null) {
                              String lvHashCode = extractHashCode(value);
                              lvMethod = (Method) lvMapEntry.getValue();
                          Class lvParamType = lvMethod.getParameterTypes()[0];                                
                              
                              if (lvHashCode != null) {
                                value = pvHashCodeMap.get(lvHashCode);
                              } else {
                                value = makeComplexInternal(value, lvParamType, lvParamType.getComponentType(), pvHashCodeMap);  
                              }
                               try {
                               value = makeAssignable(lvParamType, value);
                               lvMethod.invoke(ret, new Object [] {value});
                               } catch (Exception e) { 
                                 if (log.isDebugEnabled()) { log.debug("Problem by invoke method (in makeComplex): " + lvMethod, e); }
                                 if (ServiceManager.DEBUG_MODE_ON) {
                                   e.printStackTrace(); 
                                 }
                               }
                        } // value != null
                    }
                } catch (Exception e) {
                if (log.isWarnEnabled()) { log.warn("Error in Converter.makeComplex by Method: " + lvMethod, e); }
                if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
                }
                  
                return ret;
              }
          }
          else {
            if (log.isInfoEnabled()) {
              log.info("Invalide Type in makeComplex for Class: " + clazz + " with value: " + pvObject 
                      + " (Class from Object: " + pvObject.getClass().getName() + ")");
            }
              return null;
          }
    }
    
    
    public static Object makeAssignable(Class pvSourceClass, Object pvValue) {
      if (pvSourceClass.equals(Object.class)) {
        return pvValue;
      }
      else if (pvSourceClass.isAssignableFrom(Set.class) && pvValue instanceof Collection) {
        return new HashSet((Collection) pvValue);
      }
      else if (pvSourceClass.isAssignableFrom(Properties.class) && pvValue instanceof Map) {
        Map lvMap = (Map) pvValue;
        Properties lvProperties = new Properties();
        Iterator it = lvMap.entrySet().iterator();
        while (it.hasNext()) {
          Map.Entry lvMapEntry = (Entry) it.next();
          lvProperties.put(lvMapEntry.getKey(), lvMapEntry.getValue());
        }
        return lvProperties;
      }
      return pvValue;
    }
    
    /**
     * Analysed the objects in an Array/Collection. If all Object from the same class type,
     * then is the return value this class. If are several class types in the Array,
     * then ist the return class from type Object.
     * @param pvListObj
     * @return Class, that are in the Array or Collection
     */
    public static Class getArrayType (Object pvListObj) {
      Class lvType = Object.class;
      if (pvListObj == null) { return lvType; }
      if (pvListObj.getClass().isArray()) {
        Object o[] = (Object[]) pvListObj;
        if (o.length > 0) {
          Class lvClass = o[0].getClass(); 
          
          // !!!!! Specialfall ?????
          if(Map.class.isAssignableFrom(lvClass)) {
            return Object.class;
          }
          
          for (int i = 0; i < o.length; i++) {
          if (!lvClass.equals(o[i].getClass())) {
            return lvType;
          }
        }
          return lvClass;
        } else {
          return o.getClass().getComponentType();
        }
      }
      else if (pvListObj instanceof Collection) {
        Collection coll = (Collection) pvListObj;
        if (coll.size() > 0) {
          Class lvClass = coll.iterator().next().getClass();
          Iterator it = coll.iterator();
          while (it.hasNext()) {
          if (!lvClass.equals(it.next().getClass())) {
            return lvType;
          }
          }
          return lvClass;
        } else {
          return lvType;
        }
      }
      return lvType;
    }
    
    
    public static Object convertClassString2Object (String pvClassName) throws Exception {
      
      if (pvClassName == null) { return null; }
      
      else if (pvClassName.equals(int.class.getName())) { return Integer.valueOf("0"); }
        else if (pvClassName.equals(short.class.getName())) { return Short.valueOf("0"); }
        else if (pvClassName.equals(byte.class.getName()))  { return Byte.valueOf("0"); }
        else if (pvClassName.equals(long.class.getName()))  { return Long.valueOf("0"); }

        
        else if (pvClassName.equals(double.class.getName())) { return Double.valueOf("0"); }
        else if (pvClassName.equals(float.class.getName())) { return Float.valueOf("0"); }

        else if (pvClassName.equals(char.class.getName())) { return new Character(' '); }
        else if (pvClassName.equals(Character.class.getName())) { return new Character(' '); }
        
        else if (pvClassName.equals(boolean.class.getName())) { return Boolean.TRUE; }
        else if (pvClassName.equals(Boolean.class.getName())) { return Boolean.TRUE; }
        
        else if ((pvClassName.startsWith("[L")) && (pvClassName.endsWith(";"))) {
          try {
            String lvClassName = pvClassName.substring(2, (pvClassName.length() - 1));
            lvClassName = lvClassName.replaceAll("/", "\\.");
            Class clazz = Class.forName(lvClassName);
            Object lvArray = Array.newInstance(clazz, 0);
            return lvArray; 
          } catch (Exception e) {
            if (log.isDebugEnabled()) { log.debug("convertClassString2Object: " + pvClassName, e); }
            if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
            return null;
          }
        }
      
        else {
             Object lvReturn = createObjectWithParamConstructor(null, null, pvClassName);
             if (lvReturn == null) {
               lvReturn = createObjectWithParamConstructor(new Long(0), long.class, pvClassName);
             }
             if (lvReturn == null) {
               lvReturn = createObjectWithParamConstructor("0", String.class, pvClassName);
             }
             return lvReturn;             
        }
      
    }
    
    public static Object createObjectWithParamConstructor (Object pvParam, Class pvParamType, String pvClassName) {
      try {
        Class clazz = Class.forName(pvClassName);
        if (pvParam == null) {
          return clazz.newInstance();
        } else {
            Constructor lvConstructor = clazz.getConstructor(new Class[] {pvParamType});
            return lvConstructor.newInstance(new Object [] {pvParam});          
        }
      } catch (Exception e) {
        if (log.isDebugEnabled()) { log.debug("convertString2ClassString: " + pvClassName, e); }
        if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
      }
      return null;
    }
    
    /**  
     * For example String to Integer or String to Date, ...
     * 
     * @param pvStringValue Value in String class.
     * @param pvClassName Class name to convert the String value.
     * @return The converted String value. 
     */
    public static Object convertString2Value (String pvStringValue, String pvClassName) throws Exception {
      Class clazz = null;
      
      if (pvClassName.equals(int.class.getName())) { clazz = int.class; }
        else if (pvClassName.equals(short.class.getName())) { clazz = short.class; }
        else if (pvClassName.equals(byte.class.getName()))  { clazz = byte.class; }
        else if (pvClassName.equals(long.class.getName()))  { clazz = long.class; }
        
        
        else if (pvClassName.equals(double.class.getName())) { clazz = double.class; }
        else if (pvClassName.equals(float.class.getName())) { clazz = float.class; }

        else if (pvClassName.equals(char.class.getName())) { clazz = char.class; }
        
        else if (pvClassName.equals(boolean.class.getName())) { clazz = boolean.class; }
        
        else {
          try {
            clazz = Class.forName(pvClassName);  
      } catch (Exception e) {
        if (ServiceManager.DEBUG_MODE_ON) {
          e.printStackTrace();
        }
      }
           
        }
      
      return convertString2Value (pvStringValue, clazz);
    }
    
    public static Object convertString2Value (Object pvValue, Class pvClass) {
      if (pvValue instanceof String) {
        return convertString2Value((String) pvValue, pvClass);
      } else {
        return pvValue;
      }
    }
    /**
     * For example String to Integer or String to Date, ...
     * 
     * @param pvStringValue Value in String class.
     * @param pvClass Type to convert the String value.
     * @return The converted String value.
     */
    public static Object convertString2Value (String pvStringValue, Class pvClass) {
        if ((pvClass == null) || (pvStringValue == null)) { return null; }
        
        if ((pvClass.equals(Integer.class)) || (pvClass.equals(int.class))) { return Integer.valueOf(pvStringValue); }
        else if ((pvClass.equals(Short.class)) || (pvClass.equals(short.class))) { return Short.valueOf(pvStringValue); }
        else if ((pvClass.equals(Byte.class))  || (pvClass.equals(byte.class)))  { return Byte.valueOf(pvStringValue); }
        else if ((pvClass.equals(Long.class))  || (pvClass.equals(long.class)))  { return Long.valueOf(pvStringValue); }
        
        
        else if ((pvClass.equals(Double.class)) || (pvClass.equals(double.class))) { return Double.valueOf(pvStringValue); }
        else if ((pvClass.equals(Float.class))  || (pvClass.equals(float.class))) { return Float.valueOf(pvStringValue); }
        else if (pvClass.equals(BigDecimal.class)) { return new BigDecimal (pvStringValue); }
        
        
        else if ((pvClass.equals(Boolean.class)) || (pvClass.equals(boolean.class))) { return Boolean.valueOf(pvStringValue); }
        
        
        else if ((pvClass.equals(Character.class)) || (pvClass.equals(char.class))) { return new Character(pvStringValue.charAt(0)); }
        else if (pvClass.equals(String.class)) { return pvStringValue; }
        
        else if ((pvClass.equals(Date.class)) || (pvClass.equals(java.sql.Date.class))){ return Converter.string2Date(pvStringValue); }
        
        else {
//          ??? throw new IllegalArgumentException("Illegal value: " + pvStringValue + " or type: " + pvClass); ???
          log.warn("Illegal value in Converter.convertString2Value: " + pvStringValue + " for class: " + pvClass);
          try { 
            return pvClass.newInstance(); 
          } catch (Exception e) { 
            if (log.isDebugEnabled()) { 
              log.debug("Error by convertString2Value by new Instance for class: " + pvClass, e);
              if (ServiceManager.DEBUG_MODE_ON) { e.printStackTrace(); }
            }
            return null;
          }
        }      
    }
    
    /**
     * Convert String-Parameter (contains in the Vector) in Method-ParameterTypes.
     * For example: Vector ["5", "8"] convert to new Integer [] { new Integer(5), new Integer (8) }
     * 
     * @param pvMethod Method with ParameterTypes.
     * @param pvParams Vector with Strings.
     * 
     * @return Array with ParameterTypes and ParameterValues. 
     */
    public static Object[] convertStringParams2MethodParams (Method pvMethod, Vector pvParams) {
      if ((pvMethod == null) || (pvParams == null)) {
        throw new IllegalArgumentException("The method parameter: " + pvMethod + " or params array: " + pvParams +
              " must not null!");
      }

      Class lvParamTypes[] = pvMethod.getParameterTypes();
    if (pvParams.size() != lvParamTypes.length) {
      throw new IllegalArgumentException("The parameter size: " + pvParams.size() 
            + " is not equal to method parameter: " + lvParamTypes.length);
    } 
    Object lvNewParams[] = new Object[pvParams.size()];
    for (int i = 0; i < lvNewParams.length; i++) {
      lvNewParams[i] = Converter.convertString2Value(pvParams.get(i), lvParamTypes[i]);
    }
    return lvNewParams;
    }

    
  /**
   * Convert a Date-String to a Date. The Converter <b>neglected the Millisecond</b>.
   * Example: Thu Aug 11 19:30:57 CEST 2005
   * 
   * @param pvDateString The Date-String (unequal null).
   * @return Valid <code>java.util.Date</code>.
   */
  public static Date string2Date (String pvDateString) {
    if (pvDateString == null) { throw new IllegalArgumentException ("The Date-String was null by string2Date."); }
    
    Date date = null;
    
    // 1. Versuch, Datum wie es bei der toString-Methode zurueck kommt, umzuwandeln
    DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CEST' yyyy", Locale.ENGLISH);
    try { 
      date = df.parse(pvDateString); 
      return date;
    } catch (ParseException e) {
      log.debug("Error by string2Date: " + pvDateString , e);
    }
    
    // 2. Versuch, Datum wie es bei der toString-Methode zurueck kommt, umzuwandeln
    df = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CET' yyyy", Locale.ENGLISH);
    try { 
      date = df.parse(pvDateString); 
      return date;
    } catch (ParseException e) {
      log.debug("Error by string2Date: " + pvDateString , e); 
    }
    
    // 3. Verusch, Medium Datum umzuwandeln
    df = DateFormat.getDateInstance(DateFormat.MEDIUM);
    try { 
      date = df.parse(pvDateString);
      return date;
    } catch (ParseException e) { 
      log.debug("Error by string2Date: " + pvDateString , e); 
    }
    
    throw new IllegalStateException ("The String: \"" + pvDateString + "\" is not valid date."); 
  }

  /**
   * Extract from package + class name, the class name.
   * Example (<code>pvToLowerCase = false)</code>): Input: <code>net.sf.crispy.ServiceManager</code> -> Output: <code>ServiceManger</code>.
   * Example (<code>pvToLowerCase = true)</code>): Input: <code>net.sf.crispy.ServiceManager</code> -> Output: <code>servicemanger</code>.
   * 
   * @param pvClassWitchPackage
   * @param pvToLowerCase
   * @return The class without package.
   */
  public static String getClassWithoutPackage(String pvClassWitchPackage, boolean pvToLowerCase) {
    if (pvClassWitchPackage == null) { return null; }
    int lvIndex = pvClassWitchPackage.lastIndexOf('.') + 1;
    String lvClassName = pvClassWitchPackage.substring(lvIndex);
    if (pvToLowerCase == true) { lvClassName = lvClassName.toLowerCase(); }
    return lvClassName;
  }
  
  /**
   * If pvObject.toString - method start with <code>Converter.HASH_CODE_KEY</code>, then extract
   * the hash code.
   * Example: make from <code>~hashCode~24306761</code> to <code>24306761</code>.
   * 
   * @param pvObject
   * @return The hash code.
   */
  public static String extractHashCode (Object pvObject) {
    if (pvObject == null) { return null; }
        String lvHashCode = pvObject.toString(); 
        if (lvHashCode.startsWith(HASH_CODE_KEY) == true) {
          lvHashCode = lvHashCode.substring(HASH_CODE_KEY.length());
          return lvHashCode;
        } else { 
          return null;
        }

  }
  
  /**
   * Remove all getter-method where no setter-method exist.
   */
  public static Map getAllNotEqualsGetterAndSetterAndRemoveThisProperties(Map pvGetterMap, Map pvSetterMap) {
    Iterator it = new ArrayList(pvGetterMap.keySet()).iterator();
    while (it.hasNext()) {
      Object lvGetterProp = it.next();
      if (!(pvSetterMap.containsKey(lvGetterProp)) && !(lvGetterProp.equals("class"))) {
        if (log.isDebugEnabled()) {
          log.debug("For Getter: " + lvGetterProp + " --> no Setter!");
        }
        pvGetterMap.remove(lvGetterProp);
      }
    }
    return pvGetterMap;
  }
  
  /**
   * Find all getter-method from a Class and remove all getter-method where no setter-method exist.
   * @param pvClass Class to anaylse.
   * @return Map from getter-method (key=property name, value=method).
   * @throws IntrospectionException
   */
  public static Map getAllGetterMethodWithCache(Class pvClass) throws IntrospectionException {
    Map lvGetterMap = classPropertiesCacheGetter.getClassPropertiesMapByClass(pvClass);
    if (lvGetterMap == null) {
      try {
        lvGetterMap = Converter.getAllGetterMethod(pvClass);
        Map lvSetterMap = getAllSetterMethodWithCache(pvClass);
        lvGetterMap = getAllNotEqualsGetterAndSetterAndRemoveThisProperties (lvGetterMap, lvSetterMap);
        classPropertiesCacheGetter.addClassPropertiesMap(pvClass, lvGetterMap);
      } catch (IntrospectionException e) {
        if (ServiceManager.DEBUG_MODE_ON) {
          e.printStackTrace();
        }
      }
    }
    return lvGetterMap;
  }

  /**
   * Find all setter-method from a Class.
   * @param pvClass Class to analyse.
   * @return Map all setter-Method (key=property name, value=method).
   * @throws IntrospectionException
   */
  public static Map getAllSetterMethodWithCache(Class pvClass) throws IntrospectionException {
    Map lvMap = classPropertiesCacheSetter.getClassPropertiesMapByClass(pvClass);
    if (lvMap == null) {
      try {
        lvMap = Converter.getAllSetterMethod(pvClass);
        classPropertiesCacheSetter.addClassPropertiesMap(pvClass, lvMap);
      } catch (IntrospectionException e) {
        if (ServiceManager.DEBUG_MODE_ON) {
          e.printStackTrace();
        }
      }
    }
    return lvMap;
  }
  /**
   * Find all getter-method from a Class.
   * @param pvClass Class to analyse.
   * @return Map all getter-Method (key=property name, value=method).
   * @throws IntrospectionException
   */
  public static Map getAllGetterMethod(Class pvClass) throws IntrospectionException {
    return getAllGetterAndSetterMethod(pvClass, GET_METHOD);
  }
  
  /**
   * Find all setter-method from a Class.
   * @param pvClass Class to analyse.
   * @return Map all setter-Method (key=property name, value=method).
   * @throws IntrospectionException
   */
  public static Map getAllSetterMethod(Class pvClass) throws IntrospectionException {
    return getAllGetterAndSetterMethod(pvClass, SET_METHOD);
  }

  
  /**
   * Get all set/get methods from a Class. With methods from all super classes.
   * @param pvClass Analyse Class.
   * @return All finded methods.
   */
  public static Method[] getAllMethodsByClass (Class pvClass) {
    Collection lvColl = getAllMethodsByClassIntern(pvClass, new Hashtable());
    return (Method[]) getAllMethodsByClassIntern(pvClass, new Hashtable()).toArray(new Method [lvColl.size()]);
  }

  /**
   * Recursive search alle method from the Class in the Class Hierarchy to Object.class.
   * @param pvClass Search class.
   * @param pvMethodsMap Method map (key=property name, value=method).
   * @return All finded methods.
   */
  private static Collection getAllMethodsByClassIntern (Class pvClass, Map pvMethodsMap) {
    putAllMethodsIntern( pvClass.getMethods(), pvMethodsMap) ;    
    putAllMethodsIntern( pvClass.getDeclaredMethods(), pvMethodsMap);
    
    if (!(pvClass.getSuperclass().equals(Object.class))) {
      getAllMethodsByClassIntern(pvClass.getSuperclass(), pvMethodsMap);
    }
    
    return pvMethodsMap.values();
  }
  
  private static void putAllMethodsIntern (Method pvAllMethods[], Map pvMethodsMap) {
    for (int i = 0; i < pvAllMethods.length; i++) {
      String lvMethodName = pvAllMethods[i].getName();
      if (lvMethodName.startsWith("set") || lvMethodName.startsWith("get")) {
        pvMethodsMap.put(pvAllMethods[i], pvAllMethods[i]);
      }
    }    
  }

  /**
   * 
   * @param pvClass Find all get or set method from a Class.
   * @param pvMethodType get or set
   * @return Method map (key=property name, value=method).
   * @throws IntrospectionException
   */
  public static Map getAllGetterAndSetterMethod(Class pvClass, int pvMethodType) throws IntrospectionException {
    Method lvAllAmethods[] = getAllMethodsByClass(pvClass);
    Map lvGetterOrSetter = new TreeMap();
        for (int i = 0; i < lvAllAmethods.length; i++) {
          Method lvMethod = null;
          String lvPropName = lvAllAmethods[i].getName();
          switch (pvMethodType) {
        case GET_METHOD:
          if (lvPropName.startsWith("get")) {
            lvMethod = lvAllAmethods[i];            
          }
          break;
        case SET_METHOD:
          if (lvPropName.startsWith("set")) {
            lvMethod = lvAllAmethods[i];
          }
          break;
        default:
          break;
      }
          if (lvMethod != null) {
            
            AccessController.doPrivileged(new MethodAccessiblePrivilegedAction(lvMethod));
            
            lvPropName = lvPropName.substring(3);
            // PropName muss aus set oder get UND einen Namen bestehen
            if (lvPropName.length() > 0) {
              lvPropName = lvPropName.substring(0, 1).toLowerCase()+ lvPropName.substring(1);
              if (lvPropName.equals("class")) {
                lvGetterOrSetter.put(lvPropName, pvClass.getName());
              } else {
                lvGetterOrSetter.put(lvPropName, lvMethod);
              }
            } else {
              throw new InvocationException("Invalid Property-Name: '" + lvAllAmethods[i].getName() 
                  + "' (Valid Property-Name is: set[name] themed get[name], eg. setYear and getYear).");
            }
          } // if method != null
    } // for
        return lvGetterOrSetter;
  }
     
  public static Object createDefaultValueForPrimitiveClass(Class pvClass) {
    Object lvReturn = null;
        if (pvClass.equals(boolean.class)) { lvReturn = Boolean.FALSE; }
        else if (pvClass.equals(short.class)) { lvReturn = Short.valueOf("0"); }
        else if (pvClass.equals(byte.class)) { lvReturn = Byte.valueOf("0"); }
        else if (pvClass.equals(int.class)) { lvReturn = Integer.valueOf("0"); }
        else if (pvClass.equals(long.class)) { lvReturn = Long.valueOf("0"); }
        else if (pvClass.equals(double.class)) { lvReturn = Double.valueOf("0"); }
        else if (pvClass.equals(float.class)) { lvReturn = Float.valueOf("0"); }
        else if (pvClass.equals(char.class)) { lvReturn = new Character(' '); }
        
        return lvReturn;
  }
  
  private class SimpleKeyMapper implements Comparator {
    
    public static final String DELIMITER = "~_-_~";
    
    private String pos = null;
    private Object key = null;
    
    public SimpleKeyMapper() {}    
    public SimpleKeyMapper(String pvPos, Object pvKey) {
      pos = pvPos;
      key = pvKey;
    }
    
    public int getPos () {
      Integer integer = Integer.valueOf(pos);
      return integer.intValue();
    }
    
    public Object getKey() {
      return key;
    }
    
    public Object toSimpleNewKey(final Object pvOldKey, final Class pvOldKeyClass, int pvPos, boolean pvWithSimpleKeyMapper) {
            if (pvWithSimpleKeyMapper) {
              String lvNewKey = null;
              int l = pvOldKey.toString().split(DELIMITER).length;
              if (l == 3 || l == 2) {
                lvNewKey = pvOldKey.toString();
              } else {
                if (pvOldKeyClass.equals(String.class)) {
                  lvNewKey = pvPos + DELIMITER + pvOldKey;
                } else {
                  lvNewKey = pvPos + DELIMITER + pvOldKey + DELIMITER + pvOldKeyClass.getName();
                }
              }
              return lvNewKey;
            } else {
              return pvOldKey;
            }
    }

    public Object toComplexNewKey(Object pvOriginalKey, boolean pvWithSimpleKeyMapper) {
      if (pvWithSimpleKeyMapper == false) {
        return pvOriginalKey;
      } else {
        Object lvKey = ((SimpleKeyMapper) pvOriginalKey).getKey();        
        return lvKey;        
      }
    }

    
    public Map orderMapByKey (final Map pvMap, boolean pvWithSimpleKeyMapper) throws Exception {
      if (pvWithSimpleKeyMapper == false) {
        return pvMap;
      } else {
        Iterator it = pvMap.keySet().iterator();
        TreeMap lvTreeMap = new TreeMap(new SimpleKeyMapper());
        while (it.hasNext()) {
          Object o = it.next();
          if ( ! (o instanceof String) ) {
            throw new IllegalArgumentException("Expected String and object is: " + o + " -> class: " + o.getClass().getName());
          }
          String lvKeyStr = (String) o;
          String lvKeyArray[] = lvKeyStr.split(DELIMITER);
          if (lvKeyArray.length < 2) {
            throw new IllegalArgumentException("If the property Converter.withSimpleKeyMappe is true, than must the key contains" +
                " the delimiter: " + DELIMITER + " - " + lvKeyStr + " (" + lvKeyArray.length + ")");
          }
          
          Object lvValue = pvMap.get(lvKeyStr);

          String lvPos = lvKeyArray[0];
          String lvKeyValue = lvKeyArray[1];
          Object lvKey = null;
          if (lvKeyArray.length == 3) {
            String lvKeyClass = lvKeyArray[2];
            lvKey = Converter.convertString2Value(lvKeyValue, lvKeyClass);
          } else {
            lvKey = lvKeyValue;
          }
                    
          
          SimpleKeyMapper skm = new SimpleKeyMapper(lvPos, lvKey);
          lvTreeMap.put(skm, lvValue);
        }
        return lvTreeMap;
      }
    }

    public int compare(Object pvO1, Object pvO2) {
      SimpleKeyMapper skm1 = (SimpleKeyMapper) pvO1;
      SimpleKeyMapper skm2 = (SimpleKeyMapper) pvO2;
      if (skm1.getPos() > skm2.getPos()) {
        return 1;
      }
      else {
        return -1;
      }
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.