package railo.runtime.op; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import railo.commons.lang.ClassException; import railo.commons.lang.ClassUtil; import railo.commons.lang.StringUtil; import railo.commons.lang.types.RefBoolean; import railo.commons.lang.types.RefBooleanImpl; import railo.runtime.converter.JavaConverter; import railo.runtime.exp.PageException; import railo.runtime.type.Collection; import railo.runtime.type.Duplicable; import railo.runtime.type.UDF; /** * * * To change the template for this generated type comment go to * Window - Preferences - Java - Code Generation - Code and Comments */ public final class Duplicator { /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _boolean boolean value to duplicate * @return duplicated value */ public static boolean duplicate(boolean _boolean) { return _boolean; } /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _byte byte value to duplicate * @return duplicated value */ public static byte duplicate(byte _byte) { return _byte; } /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _short byte value to duplicate * @return duplicated value */ public static short duplicate(short _short) { return _short; } /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _int byte value to duplicate * @return duplicated value */ public static int duplicate(int _int) { return _int; } /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _long byte value to duplicate * @return duplicated value */ public static long duplicate(long _long) { return _long; } /** * primitive value duplication (do nothing, value type must not be duplicated) * @param _double byte value to duplicate * @return duplicated value */ public static double duplicate(double _double) { return _double; } /** * reference type value duplication * @param object object to duplicate * @return duplicated value */ public static Object duplicate(Object object, boolean deepCopy) { if(object == null) return null; if(object instanceof Number) return object; if(object instanceof String) return object; if(object instanceof Date) return ((Date)object).clone(); if(object instanceof Boolean) return object; RefBoolean before=new RefBooleanImpl(); try{ Object copy = ThreadLocalDuplication.get(object,before); if(copy!=null){ return copy; } //if(object instanceof CollectionPlus)return ((CollectionPlus)object).duplicate(deepCopy,ThreadLocalDuplication.getMap()); if(object instanceof Collection)return ((Collection)object).duplicate(deepCopy); if(object instanceof Duplicable)return ((Duplicable)object).duplicate(deepCopy); if(object instanceof UDF) return ((UDF)object).duplicate(); if(object instanceof List) return duplicateList((List)object,deepCopy); if(object instanceof Map) return duplicateMap((Map)object,deepCopy); if(object instanceof Serializable) { try { String ser = JavaConverter.serialize((Serializable)object); return JavaConverter.deserialize(ser); } catch (Throwable t) {} } } finally { if(!before.toBooleanValue())ThreadLocalDuplication.reset(); } return object; } public static List duplicateList(List list, boolean deepCopy) { List newList; try { newList=(List) ClassUtil.loadInstance(list.getClass()); } catch (ClassException e) { newList=new ArrayList(); } return duplicateList(list, newList, deepCopy); } public static List duplicateList(List list,List newList, boolean deepCopy) { ListIterator it = list.listIterator(); while(it.hasNext()) { if(deepCopy) newList.add(Duplicator.duplicate(it.next(),deepCopy)); else newList.add(it.next()); } return newList; } /** * duplicate a map * @param map * @param doKeysLower * @return duplicated Map * @throws PageException */ public static Map duplicateMap(Map map, boolean doKeysLower,boolean deepCopy) throws PageException{ if(doKeysLower) { Map newMap; try { newMap=(Map) ClassUtil.loadInstance(map.getClass()); } catch (ClassException e) { newMap=new HashMap(); } ThreadLocalDuplication.set(map,newMap); Iterator it=map.keySet().iterator(); while(it.hasNext()) { Object key=it.next(); if(deepCopy)newMap.put(StringUtil.toLowerCase(Caster.toString(key)),duplicate(map.get(key), deepCopy)); else newMap.put(StringUtil.toLowerCase(Caster.toString(key)),map.get(key)); } //ThreadLocalDuplication.remove(map); removed "remove" to catch sisters and brothers return newMap; } return duplicateMap(map,deepCopy); } public static Map duplicateMap(Map map,boolean deepCopy){ Map other; try { other=(Map) ClassUtil.loadInstance(map.getClass()); } catch (ClassException e) { other=new HashMap(); } ThreadLocalDuplication.set(map,other); duplicateMap(map,other, deepCopy); //ThreadLocalDuplication.remove(map); removed "remove" to catch sisters and brothers return other; } public static Map duplicateMap(Map map,Map newMap,boolean deepCopy){ Iterator it=map.keySet().iterator(); while(it.hasNext()) { Object key=it.next(); if(deepCopy)newMap.put(key,duplicate(map.get(key),deepCopy)); else newMap.put(key,map.get(key)); } return newMap; } }