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.type.util; 020 021import java.util.Iterator; 022import java.util.Map; 023import java.util.Set; 024 025import lucee.commons.lang.CFTypes; 026import lucee.commons.lang.ExceptionUtil; 027import lucee.runtime.PageContext; 028import lucee.runtime.config.Config; 029import lucee.runtime.converter.LazyConverter; 030import lucee.runtime.dump.DumpData; 031import lucee.runtime.dump.DumpProperties; 032import lucee.runtime.engine.ThreadLocalPageContext; 033import lucee.runtime.exp.ExpressionException; 034import lucee.runtime.exp.PageException; 035import lucee.runtime.type.Collection; 036import lucee.runtime.type.KeyImpl; 037import lucee.runtime.type.Sizeable; 038import lucee.runtime.type.Struct; 039import lucee.runtime.type.UDFPlus; 040import lucee.runtime.type.dt.DateTime; 041import lucee.runtime.type.it.KeyAsStringIterator; 042 043public abstract class StructSupport implements Map,Struct,Sizeable { 044 045 private static final long serialVersionUID = 7433668961838400995L; 046 047 /** 048 * throw exception for invalid key 049 * @param key Invalid key 050 * @return returns an invalid key Exception 051 */ 052 public static ExpressionException invalidKey(Config config,Struct sct,Key key) { 053 Iterator<Key> it = sct.keyIterator(); 054 Key k; 055 056 while(it.hasNext()){ 057 k = it.next(); 058 if( k.equals( key ) ) 059 return new ExpressionException( "the value from key [" + key.getString() + "] is NULL, which is the same as not existing in CFML" ); 060 } 061 config=ThreadLocalPageContext.getConfig(config); 062 if(config!=null && config.debug()) 063 return new ExpressionException(ExceptionUtil.similarKeyMessage(sct, key.getString(), "key", "keys",true)); 064 065 066 return new ExpressionException( "key [" + key.getString() + "] doesn't exist" ); 067 } 068 069 @Override 070 public long sizeOf() { 071 return StructUtil.sizeOf(this); 072 } 073 074 @Override 075 public Set entrySet() { 076 return StructUtil.entrySet(this); 077 } 078 079 @Override 080 public final Object get(Object key) { 081 return get(KeyImpl.toKey(key,null), null); 082 } 083 084 @Override 085 public final boolean isEmpty() { 086 return size()==0; 087 } 088 089 @Override 090 public Set keySet() { 091 return StructUtil.keySet(this); 092 } 093 094 @Override 095 public Object put(Object key, Object value) { 096 return setEL(KeyImpl.toKey(key,null), value); 097 } 098 099 @Override 100 public final void putAll(Map t) { 101 StructUtil.putAll(this, t); 102 } 103 104 @Override 105 public final Object remove(Object key) { 106 return removeEL(KeyImpl.toKey(key,null)); 107 } 108 109 @Override 110 public final Object clone(){ 111 return duplicate(true); 112 } 113 114 @Override 115 public final boolean containsKey(Object key) { 116 return containsKey(KeyImpl.toKey(key,null)); 117 } 118 119 @Override 120 public final boolean containsKey(String key) { 121 return containsKey(KeyImpl.init(key)); 122 } 123 124 @Override 125 public final Object get(String key, Object defaultValue) { 126 return get(KeyImpl.init(key), defaultValue); 127 } 128 129 @Override 130 public final Object get(String key) throws PageException { 131 return get(KeyImpl.init(key)); 132 } 133 134 @Override 135 public final Object set(String key, Object value) throws PageException { 136 return set(KeyImpl.init(key), value); 137 } 138 139 @Override 140 public final Object setEL(String key, Object value) { 141 return setEL(KeyImpl.init(key), value); 142 } 143 144 @Override 145 public DumpData toDumpData(PageContext pageContext, int maxlevel,DumpProperties properties) { 146 return StructUtil.toDumpTable(this,"Struct",pageContext,maxlevel,properties); 147 } 148 149 @Override 150 public boolean castToBooleanValue() throws PageException { 151 throw new ExpressionException("can't cast Complex Object Type Struct to a boolean value"); 152 } 153 154 @Override 155 public Boolean castToBoolean(Boolean defaultValue) { 156 return defaultValue; 157 } 158 159 @Override 160 public double castToDoubleValue() throws PageException { 161 throw new ExpressionException("can't cast Complex Object Type Struct to a number value"); 162 } 163 164 @Override 165 public double castToDoubleValue(double defaultValue) { 166 return defaultValue; 167 } 168 169 @Override 170 public DateTime castToDateTime() throws PageException { 171 throw new ExpressionException("can't cast Complex Object Type Struct to a Date"); 172 } 173 174 @Override 175 public DateTime castToDateTime(DateTime defaultValue) { 176 return defaultValue; 177 } 178 179 @Override 180 public String castToString() throws PageException { 181 throw new ExpressionException("Can't cast Complex Object Type Struct to String", 182 "Use Built-In-Function \"serialize(Struct):String\" to create a String from Struct"); 183 } 184 185 @Override 186 public String castToString(String defaultValue) { 187 return defaultValue; 188 } 189 190 @Override 191 public int compareTo(boolean b) throws PageException { 192 throw new ExpressionException("can't compare Complex Object Type Struct with a boolean value"); 193 } 194 195 @Override 196 public int compareTo(DateTime dt) throws PageException { 197 throw new ExpressionException("can't compare Complex Object Type Struct with a DateTime Object"); 198 } 199 200 @Override 201 public int compareTo(double d) throws PageException { 202 throw new ExpressionException("can't compare Complex Object Type Struct with a numeric value"); 203 } 204 205 @Override 206 public int compareTo(String str) throws PageException { 207 throw new ExpressionException("can't compare Complex Object Type Struct with a String"); 208 } 209 210 @Override 211 public String toString() { 212 return LazyConverter.serialize(this); 213 } 214 215 @Override 216 public java.util.Collection values() { 217 return StructUtil.values(this); 218 } 219 220 @Override 221 public boolean containsValue(Object value) { 222 return values().contains(value); 223 } 224 225 @Override 226 public Iterator<String> keysAsStringIterator() { 227 return new KeyAsStringIterator(keyIterator()); 228 } 229 230 @Override 231 public Object get(PageContext pc, Key key, Object defaultValue) { 232 return get(key, defaultValue); 233 } 234 235 @Override 236 public Object get(PageContext pc, Key key) throws PageException { 237 return get(key); 238 } 239 240 @Override 241 public Object set(PageContext pc, Key propertyName, Object value) throws PageException { 242 return set(propertyName, value); 243 } 244 245 @Override 246 public Object setEL(PageContext pc, Key propertyName, Object value) { 247 return setEL(propertyName, value); 248 } 249 250 @Override 251 public Object call(PageContext pc, Key methodName, Object[] args) throws PageException { 252 Object obj = get(methodName,null); 253 if(obj instanceof UDFPlus) { 254 return ((UDFPlus)obj).call(pc,methodName,args,false); 255 } 256 return MemberUtil.call(pc, this, methodName, args, CFTypes.TYPE_STRUCT, "struct"); 257 } 258 259 @Override 260 public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException { 261 Object obj = get(methodName,null); 262 if(obj instanceof UDFPlus) { 263 return ((UDFPlus)obj).callWithNamedValues(pc,methodName,args,false); 264 } 265 return MemberUtil.callWithNamedValues(pc,this,methodName,args, CFTypes.TYPE_STRUCT, "struct"); 266 } 267 268 public java.util.Iterator<String> getIterator() { 269 return keysAsStringIterator(); 270 } 271 272 @Override 273 public boolean equals(Object obj){ 274 if(!(obj instanceof Collection)) return false; 275 return CollectionUtil.equals(this,(Collection)obj); 276 } 277 278 /*@Override 279 public int hashCode() { 280 return CollectionUtil.hashCode(this); 281 }*/ 282}