001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.op; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.Date; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.List; 027import java.util.ListIterator; 028import java.util.Map; 029 030import lucee.commons.lang.ClassException; 031import lucee.commons.lang.ClassUtil; 032import lucee.commons.lang.ExceptionUtil; 033import lucee.commons.lang.StringUtil; 034import lucee.commons.lang.types.RefBoolean; 035import lucee.commons.lang.types.RefBooleanImpl; 036import lucee.runtime.converter.JavaConverter; 037import lucee.runtime.exp.PageException; 038import lucee.runtime.type.Collection; 039import lucee.runtime.type.Duplicable; 040import lucee.runtime.type.UDF; 041 042 043/** 044 * 045 * 046 * To change the template for this generated type comment go to 047 * Window - Preferences - Java - Code Generation - Code and Comments 048 */ 049public final class Duplicator { 050 051 /** 052 * primitive value duplication (do nothing, value type must not be duplicated) 053 * @param _boolean boolean value to duplicate 054 * @return duplicated value 055 */ 056 public static boolean duplicate(boolean _boolean) { 057 return _boolean; 058 } 059 060 /** 061 * primitive value duplication (do nothing, value type must not be duplicated) 062 * @param _byte byte value to duplicate 063 * @return duplicated value 064 */ 065 public static byte duplicate(byte _byte) { 066 return _byte; 067 } 068 069 /** 070 * primitive value duplication (do nothing, value type must not be duplicated) 071 * @param _short byte value to duplicate 072 * @return duplicated value 073 */ 074 public static short duplicate(short _short) { 075 return _short; 076 } 077 078 /** 079 * primitive value duplication (do nothing, value type must not be duplicated) 080 * @param _int byte value to duplicate 081 * @return duplicated value 082 */ 083 public static int duplicate(int _int) { 084 return _int; 085 } 086 087 /** 088 * primitive value duplication (do nothing, value type must not be duplicated) 089 * @param _long byte value to duplicate 090 * @return duplicated value 091 */ 092 public static long duplicate(long _long) { 093 return _long; 094 } 095 096 /** 097 * primitive value duplication (do nothing, value type must not be duplicated) 098 * @param _double byte value to duplicate 099 * @return duplicated value 100 */ 101 public static double duplicate(double _double) { 102 return _double; 103 } 104 105 /** 106 * reference type value duplication 107 * @param object object to duplicate 108 * @return duplicated value 109 */ 110 111 public static Object duplicate(Object object, boolean deepCopy) { 112 if(object == null) return null; 113 if(object instanceof Number) return object; 114 if(object instanceof String) return object; 115 if(object instanceof Date) return ((Date)object).clone(); 116 if(object instanceof Boolean) return object; 117 118 RefBoolean before=new RefBooleanImpl(); 119 try{ 120 Object copy = ThreadLocalDuplication.get(object,before); 121 if(copy!=null){ 122 return copy; 123 } 124 125 126 //if(object instanceof CollectionPlus)return ((CollectionPlus)object).duplicate(deepCopy,ThreadLocalDuplication.getMap()); 127 if(object instanceof Collection)return ((Collection)object).duplicate(deepCopy); 128 if(object instanceof Duplicable)return ((Duplicable)object).duplicate(deepCopy); 129 if(object instanceof UDF) return ((UDF)object).duplicate(); 130 if(object instanceof List) return duplicateList((List)object,deepCopy); 131 if(object instanceof Map) return duplicateMap((Map)object,deepCopy); 132 if(object instanceof Serializable) { 133 try { 134 String ser = JavaConverter.serialize((Serializable)object); 135 return JavaConverter.deserialize(ser); 136 137 } catch (Throwable t) { 138 ExceptionUtil.rethrowIfNecessary(t); 139 } 140 } 141 } 142 finally { 143 if(!before.toBooleanValue())ThreadLocalDuplication.reset(); 144 } 145 146 return object; 147 } 148 149 public static List duplicateList(List list, boolean deepCopy) { 150 List newList; 151 try { 152 newList=(List) ClassUtil.loadInstance(list.getClass()); 153 } catch (ClassException e) { 154 newList=new ArrayList(); 155 } 156 return duplicateList(list, newList, deepCopy); 157 } 158 159 public static List duplicateList(List list,List newList, boolean deepCopy) { 160 ListIterator it = list.listIterator(); 161 while(it.hasNext()) { 162 if(deepCopy) 163 newList.add(Duplicator.duplicate(it.next(),deepCopy)); 164 else 165 newList.add(it.next()); 166 } 167 return newList; 168 } 169 170 /** 171 * duplicate a map 172 * @param map 173 * @param doKeysLower 174 * @return duplicated Map 175 * @throws PageException 176 */ 177 public static Map duplicateMap(Map map, boolean doKeysLower,boolean deepCopy) throws PageException{ 178 if(doKeysLower) { 179 Map newMap; 180 try { 181 newMap=(Map) ClassUtil.loadInstance(map.getClass()); 182 } catch (ClassException e) { 183 newMap=new HashMap(); 184 } 185 boolean inside=ThreadLocalDuplication.set(map,newMap); 186 try{ 187 Iterator it=map.keySet().iterator(); 188 while(it.hasNext()) { 189 Object key=it.next(); 190 if(deepCopy)newMap.put(StringUtil.toLowerCase(Caster.toString(key)),duplicate(map.get(key), deepCopy)); 191 else newMap.put(StringUtil.toLowerCase(Caster.toString(key)),map.get(key)); 192 } 193 } 194 finally { 195 if(!inside)ThreadLocalDuplication.reset(); 196 } 197 return newMap; 198 } 199 return duplicateMap(map,deepCopy); 200 } 201 202 public static Map duplicateMap(Map map,boolean deepCopy){ 203 Map other; 204 try { 205 other=(Map) ClassUtil.loadInstance(map.getClass()); 206 } catch (ClassException e) { 207 other=new HashMap(); 208 } 209 boolean inside=ThreadLocalDuplication.set(map,other); 210 try{ 211 duplicateMap(map,other, deepCopy); 212 } 213 finally { 214 if(!inside)ThreadLocalDuplication.reset(); 215 } 216 // 217 return other; 218 } 219 220 public static Map duplicateMap(Map map,Map newMap,boolean deepCopy){ 221 222 223 Iterator it=map.keySet().iterator(); 224 while(it.hasNext()) { 225 Object key=it.next(); 226 if(deepCopy)newMap.put(key,duplicate(map.get(key),deepCopy)); 227 else newMap.put(key,map.get(key)); 228 } 229 return newMap; 230 } 231} 232 233