001    package railo.runtime.type.util;
002    
003    import java.util.AbstractList;
004    import java.util.Iterator;
005    import java.util.List;
006    
007    import railo.commons.lang.CFTypes;
008    import railo.runtime.PageContext;
009    import railo.runtime.converter.LazyConverter;
010    import railo.runtime.exp.ExpressionException;
011    import railo.runtime.exp.PageException;
012    import railo.runtime.exp.PageRuntimeException;
013    import railo.runtime.op.Caster;
014    import railo.runtime.type.Array;
015    import railo.runtime.type.Collection;
016    import railo.runtime.type.KeyImpl;
017    import railo.runtime.type.Objects;
018    import railo.runtime.type.Sizeable;
019    import railo.runtime.type.Struct;
020    import railo.runtime.type.dt.DateTime;
021    
022    public abstract class ArraySupport extends AbstractList implements Array,List,Sizeable,Objects {
023    
024            
025            public static final short TYPE_OBJECT = 0;
026            public static final short TYPE_BOOLEAN = 1;
027            public static final short TYPE_BYTE = 2;
028            public static final short TYPE_SHORT = 3;
029            public static final short TYPE_INT = 4;
030            public static final short TYPE_LONG = 5;
031            public static final short TYPE_FLOAT = 6;
032            public static final short TYPE_DOUBLE = 7;
033            public static final short TYPE_CHARACTER = 8;
034            public static final short TYPE_STRING = 9;
035            
036            @Override
037            public final void add(int index, Object element) {
038                    try {
039                            insert(index+1, element);
040                    } catch (PageException e) {
041                            throw new IndexOutOfBoundsException("can't insert value to List at position "+index+", " +
042                                            "valid values are from 0 to "+(size()-1)+", size is "+size());
043                    }
044            }
045    
046            @Override
047            public final boolean addAll(java.util.Collection c) {
048                    Iterator it = c.iterator();
049                    while(it.hasNext()) {
050                            add(it.next());
051                    }
052                    return true;
053            }
054            
055            @Override
056            public final boolean remove(Object o) {
057                    int index = indexOf(o);
058                    if(index==-1) return false;
059                    
060                    try {
061                            removeE(index+1);
062                    } catch (PageException e) {
063                            return false;
064                    }
065                    return true;
066            }
067    
068            @Override
069            public final boolean removeAll(java.util.Collection c) {
070                    Iterator it = c.iterator();
071                    boolean rtn=false;
072                    while(it.hasNext()) {
073                            if(remove(it.next()))rtn=true;
074                    }
075                    return rtn;
076            }
077    
078            @Override
079            public final boolean retainAll(java.util.Collection c) {
080                    boolean modified = false;
081                    Key[] keys = CollectionUtil.keys(this);
082                    Key k;
083                    for(int i=keys.length-1;i>=0;i--) {
084                            k = keys[i];
085                            if(!c.contains(get(k,null))) {
086                            removeEL(k);
087                            modified = true;
088                        }
089                    }
090                    return modified;
091            }
092    
093            @Override
094            public final Object[] toArray(Object[] a) {
095                    if(a==null) return toArray();
096                    
097                    
098                    Class trgClass=a.getClass().getComponentType();
099                    short type=TYPE_OBJECT;
100                    if(trgClass==Boolean.class) type=TYPE_BOOLEAN;
101                    else if(trgClass==Byte.class) type=TYPE_BYTE;
102                    else if(trgClass==Short.class) type=TYPE_SHORT;
103                    else if(trgClass==Integer.class) type=TYPE_INT;
104                    else if(trgClass==Long.class) type=TYPE_LONG;
105                    else if(trgClass==Float.class) type=TYPE_FLOAT;
106                    else if(trgClass==Double.class) type=TYPE_DOUBLE;
107                    else if(trgClass==Character.class) type=TYPE_CHARACTER;
108                    else if(trgClass==String.class) type=TYPE_STRING;
109                    
110                    
111                    Iterator it = iterator();
112                    int i=0;
113                    Object o;
114                    try {
115                            while(it.hasNext()) {
116                                    o=it.next();
117                                    switch(type){
118                                    case TYPE_BOOLEAN:
119                                            o=Caster.toBoolean(o);
120                                    break;
121                                    case TYPE_BYTE:
122                                            o=Caster.toByte(o);
123                                    break;
124                                    case TYPE_CHARACTER:
125                                            o=Caster.toCharacter(o);
126                                    break;
127                                    case TYPE_DOUBLE:
128                                            o=Caster.toDouble(o);
129                                    break;
130                                    case TYPE_FLOAT:
131                                            o=Caster.toFloat(o);
132                                    break;
133                                    case TYPE_INT:
134                                            o=Caster.toInteger(o);
135                                    break;
136                                    case TYPE_LONG:
137                                            o=Caster.toLong(o);
138                                    break;
139                                    case TYPE_SHORT:
140                                            o=Caster.toShort(o);
141                                    break;
142                                    case TYPE_STRING:
143                                            o=Caster.toString(o);
144                                    break;
145                                    }
146                                    a[i++]=o;
147                            }
148                    }
149                    catch(PageException pe){
150                            throw new PageRuntimeException(pe);
151                    }
152                    return a;
153            }
154    
155            @Override
156            public final Object get(int index) {
157                    if(index<0)  
158                            throw new IndexOutOfBoundsException("invalid index defintion ["+index+"], " +
159                                            "index should be a number between [0 - "+(size()-1)+"], size is "+size());
160                    if(index>=size())
161                            throw new IndexOutOfBoundsException("invalid index ["+index+"] defintion, " +
162                                            "index should be a number between [0 - "+(size()-1)+"], size is "+size());
163                    
164                    return get(index+1, null); 
165            }
166    
167            @Override
168            public final Object remove(int index) {
169                    if(index<0)  
170                            throw new IndexOutOfBoundsException("invalid index defintion ["+index+"], " +
171                                            "index should be a number between [0 - "+(size()-1)+"], size is "+size());
172                    if(index>=size())
173                            throw new IndexOutOfBoundsException("invalid index ["+index+"] defintion, " +
174                                            "index should be a number between [0 - "+(size()-1)+"], size is "+size());
175                    
176                    return removeEL(index+1); 
177            }
178    
179            @Override
180            public final Object set(int index, Object element) {
181                    Object o=get(index);
182                    setEL(index+1, element); 
183                    return o;
184            }
185            
186    
187        @Override
188        public boolean containsKey(String key) {
189            return get(KeyImpl.init(key),null)!=null;
190        }
191        
192        @Override
193        public boolean containsKey(Collection.Key key) {
194            return get(key,null)!=null;
195        }
196    
197        @Override
198        public boolean containsKey(int key) {
199            return get(key,null)!=null;
200        }
201    
202    
203            @Override
204            public String toString() {
205                    return LazyConverter.serialize(this);
206            }
207            
208            @Override
209            public synchronized Object clone() {
210                    return duplicate(true);
211            }
212    
213        @Override
214        public String castToString() throws PageException {
215            throw new ExpressionException("Can't cast Complex Object Type Array to String",
216              "Use Built-In-Function \"serialize(Array):String\" to create a String from Array");
217        }
218    
219        @Override
220        public String castToString(String defaultValue) {
221            return defaultValue;
222        }
223    
224    
225        @Override
226        public boolean castToBooleanValue() throws PageException {
227            throw new ExpressionException("Can't cast Complex Object Type Array to a boolean value");
228        }
229        
230        @Override
231        public Boolean castToBoolean(Boolean defaultValue) {
232            return defaultValue;
233        }
234        
235    
236    
237        @Override
238        public double castToDoubleValue() throws PageException {
239            throw new ExpressionException("Can't cast Complex Object Type Array to a number value");
240        }
241        
242        @Override
243        public double castToDoubleValue(double defaultValue) {
244            return defaultValue;
245        }
246        
247    
248    
249        @Override
250        public DateTime castToDateTime() throws PageException {
251            throw new ExpressionException("Can't cast Complex Object Type Array to a Date");
252        }
253        
254        @Override
255        public DateTime castToDateTime(DateTime defaultValue) {
256            return defaultValue;
257        }
258    
259            @Override
260            public int compareTo(boolean b) throws PageException {
261                    throw new ExpressionException("can't compare Complex Object Type Array with a boolean value");
262            }
263    
264            @Override
265            public int compareTo(DateTime dt) throws PageException {
266                    throw new ExpressionException("can't compare Complex Object Type Array with a DateTime Object");
267            }
268    
269            @Override
270            public int compareTo(double d) throws PageException {
271                    throw new ExpressionException("can't compare Complex Object Type Array with a numeric value");
272            }
273    
274            @Override
275            public int compareTo(String str) throws PageException {
276                    throw new ExpressionException("can't compare Complex Object Type Array with a String");
277            }
278    
279            @Override
280            public List toList() {
281                    return this;
282            }
283            
284            @Override
285            public Iterator<Object> valueIterator() {
286                    return iterator();
287            }
288    
289            @Override
290            public Object get(PageContext pc, Key key, Object defaultValue) {
291                    return get(key, defaultValue);
292            }
293    
294            @Override
295            public Object get(PageContext pc, Key key) throws PageException {
296                    return get(key);
297            }
298    
299            @Override
300            public Object set(PageContext pc, Key propertyName, Object value) throws PageException {
301                    return set(propertyName, value);
302            }
303    
304            @Override
305            public Object setEL(PageContext pc, Key propertyName, Object value) {
306                    return setEL(propertyName, value);
307            }
308    
309            @Override
310            public Object call(PageContext pc, Key methodName, Object[] args) throws PageException {
311                    return MemberUtil.call(pc, this, methodName, args, CFTypes.TYPE_ARRAY, "array");
312            }
313    
314            @Override
315            public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException {
316                    return MemberUtil.callWithNamedValues(pc,this,methodName,args, CFTypes.TYPE_ARRAY, "array");
317            }
318    
319            @Override
320            public java.util.Iterator<Object> getIterator() {
321            return valueIterator();
322        } 
323    
324            @Override
325            public synchronized void sort(String sortType, String sortOrder) throws PageException {
326                    if(getDimension()>1)
327                            throw new ExpressionException("only 1 dimensional arrays can be sorted");
328                    sort(ArrayUtil.toComparator(null, sortType, sortOrder,false));
329            }
330            
331            @Override
332            public boolean equals(Object obj){
333                    if(!(obj instanceof Collection)) return false;
334                    return CollectionUtil.equals(this,(Collection)obj);
335            }
336            
337            @Override
338            public int hashCode() {
339                    return CollectionUtil.hashCode(this);
340            }
341    }