001 package railo.runtime.type; 002 003 import java.util.HashMap; 004 import java.util.Iterator; 005 import java.util.LinkedHashMap; 006 import java.util.Map; 007 008 import railo.commons.collections.HashTable; 009 import railo.runtime.PageContext; 010 import railo.runtime.dump.DumpData; 011 import railo.runtime.dump.DumpProperties; 012 import railo.runtime.exp.ExpressionException; 013 import railo.runtime.exp.PageException; 014 import railo.runtime.op.Duplicator; 015 import railo.runtime.op.ThreadLocalDuplication; 016 import railo.runtime.type.dt.DateTime; 017 import railo.runtime.type.util.StructUtil; 018 019 /** 020 * CFML data type struct 021 */ 022 public final class StructImplString extends StructImpl implements Struct { 023 024 public static final int TYPE_WEAKED=0; 025 public static final int TYPE_LINKED=1; 026 public static final int TYPE_SYNC=2; 027 public static final int TYPE_REGULAR=3; 028 029 private Map<Collection.Key,Object> map; 030 //private static int scount=0; 031 //private static int kcount=0; 032 033 /** 034 * default constructor 035 */ 036 public StructImplString() { 037 map=new HashMap<Collection.Key, Object>(); 038 } 039 040 /** 041 * This implementation spares its clients from the unspecified, 042 * generally chaotic ordering provided by normally Struct , 043 * without incurring the increased cost associated with TreeMap. 044 * It can be used to produce a copy of a map that has the same order as the original 045 * @param doubleLinked 046 */ 047 public StructImplString(int type) { 048 if(type==TYPE_LINKED) map=new LinkedHashMap<Collection.Key, Object>(); 049 else if(type==TYPE_WEAKED) map=new java.util.WeakHashMap<Collection.Key, Object>(); 050 else if(type==TYPE_SYNC) map=new HashTable(); 051 else map=new HashMap<Collection.Key, Object>(); 052 } 053 054 /** 055 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object) 056 */ 057 public Object get(Collection.Key key, Object defaultValue) { 058 Object rtn=map.get(key.getLowerString()); 059 if(rtn!=null) return rtn; 060 return defaultValue; 061 } 062 063 /** 064 * 065 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key) 066 */ 067 public Object get(Collection.Key key) throws PageException { 068 Object rtn=map.get(key.getLowerString()); 069 if(rtn!=null) return rtn; 070 throw invalidKey(key.getString()); 071 } 072 073 /** 074 * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object) 075 */ 076 public Object set(Collection.Key key, Object value) throws PageException { 077 map.put(key,value); 078 return value; 079 } 080 081 /** 082 * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object) 083 */ 084 public Object setEL(Collection.Key key, Object value) { 085 map.put(key,value); 086 return value; 087 } 088 089 /** 090 * @see railo.runtime.type.Collection#size() 091 */ 092 public int size() { 093 return map.size(); 094 } 095 096 public Collection.Key[] keys() { 097 Iterator<Key> it = map.keySet().iterator(); 098 Collection.Key[] keys = new Collection.Key[size()]; 099 int count=0; 100 while(it.hasNext()) { 101 keys[count++]=it.next(); 102 } 103 return keys; 104 } 105 106 /** 107 * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key) 108 */ 109 public Object remove(Collection.Key key) throws PageException { 110 Object obj= map.remove(key.getLowerString()); 111 if(obj==null) throw new ExpressionException("can't remove key ["+key+"] from struct, key doesn't exist"); 112 return obj; 113 } 114 115 /** 116 * 117 * @see railo.runtime.type.Collection#removeEL(railo.runtime.type.Collection.Key) 118 */ 119 public Object removeEL(Collection.Key key) { 120 return map.remove(key.getLowerString()); 121 } 122 123 /** 124 * @see railo.runtime.type.Collection#clear() 125 */ 126 public void clear() { 127 map.clear(); 128 } 129 130 /** 131 * 132 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 133 */ 134 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 135 return StructUtil.toDumpTable(this, "struct", pageContext, maxlevel, dp); 136 /*Iterator it=map.keySet().iterator(); 137 138 DumpTable table = new DumpTable("struct","#9999ff","#ccccff","#000000"); 139 table.setTitle("Struct"); 140 maxlevel--; 141 while(it.hasNext()) { 142 Object key=it.next(); 143 if(DumpUtil.keyValid(dp, maxlevel,key.toString())) 144 table.appendRow(1,new SimpleDumpData(key.toString()),DumpUtil.toDumpData(map.get(key), pageContext,maxlevel,dp)); 145 } 146 return table;*/ 147 } 148 149 /** 150 * throw exception for invalid key 151 * @param key Invalid key 152 * @return returns an invalid key Exception 153 */ 154 protected ExpressionException invalidKey(String key) { 155 return new ExpressionException("key ["+key+"] doesn't exist in struct"); 156 } 157 158 /** 159 * @see railo.runtime.type.Collection#duplicate(boolean) 160 */ 161 public Collection duplicate(boolean deepCopy) { 162 Struct sct=new StructImplString(); 163 copy(this,sct,deepCopy); 164 return sct; 165 } 166 167 public static void copy(Struct src,Struct trg,boolean deepCopy) { 168 Iterator<Entry<Key, Object>> it = src.entryIterator(); 169 Entry<Key, Object> e; 170 ThreadLocalDuplication.set(src, trg); 171 try { 172 while(it.hasNext()) { 173 e = it.next(); 174 if(!deepCopy) trg.setEL(e.getKey(),e.getValue()); 175 else trg.setEL(e.getKey(),Duplicator.duplicate(e.getValue(),deepCopy)); 176 } 177 } 178 finally { 179 // ThreadLocalDuplication.remove(src); removed "remove" to catch sisters and brothers 180 } 181 } 182 183 /** 184 * @see railo.runtime.type.Collection#keyIterator() 185 */ 186 public Iterator<Collection.Key> keyIterator() { 187 return map.keySet().iterator(); 188 } 189 190 /** 191 * @see railo.runtime.type.Iteratorable#iterator() 192 */ 193 public Iterator valueIterator() { 194 return map.values().iterator(); 195 } 196 197 /** 198 * @see railo.runtime.type.Collection#_contains(java.lang.String) 199 */ 200 public boolean containsKey(Collection.Key key) { 201 return map.containsKey(key.getLowerString()); 202 } 203 204 /** 205 * @see railo.runtime.op.Castable#castToString() 206 */ 207 public String castToString() throws ExpressionException { 208 throw new ExpressionException("Can't cast Complex Object Type Struct to String", 209 "Use Built-In-Function \"serialize(Struct):String\" to create a String from Struct"); 210 } 211 212 /** 213 * @see railo.runtime.type.util.StructSupport#castToString(java.lang.String) 214 */ 215 public String castToString(String defaultValue) { 216 return defaultValue; 217 } 218 219 /** 220 * @see railo.runtime.op.Castable#castToBooleanValue() 221 */ 222 public boolean castToBooleanValue() throws ExpressionException { 223 throw new ExpressionException("can't cast Complex Object Type Struct to a boolean value"); 224 } 225 226 /** 227 * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean) 228 */ 229 public Boolean castToBoolean(Boolean defaultValue) { 230 return defaultValue; 231 } 232 233 234 /** 235 * @see railo.runtime.op.Castable#castToDoubleValue() 236 */ 237 public double castToDoubleValue() throws ExpressionException { 238 throw new ExpressionException("can't cast Complex Object Type Struct to a number value"); 239 } 240 241 /** 242 * @see railo.runtime.op.Castable#castToDoubleValue(double) 243 */ 244 public double castToDoubleValue(double defaultValue) { 245 return defaultValue; 246 } 247 248 249 /** 250 * @see railo.runtime.op.Castable#castToDateTime() 251 */ 252 public DateTime castToDateTime() throws ExpressionException { 253 throw new ExpressionException("can't cast Complex Object Type Struct to a Date"); 254 } 255 256 /** 257 * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime) 258 */ 259 public DateTime castToDateTime(DateTime defaultValue) { 260 return defaultValue; 261 } 262 263 /** 264 * @see railo.runtime.op.Castable#compare(boolean) 265 */ 266 public int compareTo(boolean b) throws ExpressionException { 267 throw new ExpressionException("can't compare Complex Object Type Struct with a boolean value"); 268 } 269 270 /** 271 * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime) 272 */ 273 public int compareTo(DateTime dt) throws PageException { 274 throw new ExpressionException("can't compare Complex Object Type Struct with a DateTime Object"); 275 } 276 277 /** 278 * @see railo.runtime.op.Castable#compareTo(double) 279 */ 280 public int compareTo(double d) throws PageException { 281 throw new ExpressionException("can't compare Complex Object Type Struct with a numeric value"); 282 } 283 284 /** 285 * @see railo.runtime.op.Castable#compareTo(java.lang.String) 286 */ 287 public int compareTo(String str) throws PageException { 288 throw new ExpressionException("can't compare Complex Object Type Struct with a String"); 289 } 290 291 public boolean containsValue(Object value) { 292 return map.containsValue(value); 293 } 294 295 296 public java.util.Collection values() { 297 return map.values(); 298 } 299 300 }