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}