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