001    package railo.runtime.functions.struct;
002    
003    import java.util.Iterator;
004    import java.util.List;
005    import java.util.Map;
006    import java.util.Map.Entry;
007    
008    import railo.runtime.PageContext;
009    import railo.runtime.exp.PageException;
010    import railo.runtime.op.Caster;
011    import railo.runtime.op.Decision;
012    import railo.runtime.type.Collection;
013    import railo.runtime.type.Collection.Key;
014    import railo.runtime.type.KeyImpl;
015    import railo.runtime.type.Struct;
016    import railo.runtime.type.StructImpl;
017    
018    public class StructKeyTranslate {
019            public static double call(PageContext pc ,Struct sct) throws PageException {
020                    return call(pc, sct,false,false);
021        }
022            public static double call(PageContext pc ,Struct sct,boolean deepTranslation) throws PageException {
023                    return call(pc, sct,deepTranslation,false);
024        }
025            public static double call(PageContext pc ,Struct sct,boolean deepTranslation,boolean leaveOriginalKey) throws PageException {
026                    return translate(sct, deepTranslation,leaveOriginalKey);
027        }
028            
029            public static int translate(Collection coll,boolean deep,boolean leaveOrg) throws PageException {
030                    Iterator<Entry<Key, Object>> it = coll.entryIterator();
031                    Entry<Key, Object> e;
032                    boolean isStruct=coll instanceof Struct;
033                    String key;
034                    int index;
035                    int count=0;
036                    while(it.hasNext()){
037                            e = it.next();
038                            key=e.getKey().getString();
039                            if(deep)count+=translate(e.getValue(),leaveOrg);
040                            if(isStruct && (index=key.indexOf('.'))!=-1){
041                                    count++;
042                                    translate(index,e.getKey(),key,coll,leaveOrg);
043                            }
044                    }
045                    return count;
046        }
047    
048            private static int translate(Object value,boolean leaveOrg) throws PageException {
049                    if(value instanceof Collection)
050                            return translate((Collection)value, true,leaveOrg);
051                    if(value instanceof List)
052                            return translate((List)value, leaveOrg);
053                    if(value instanceof Map)
054                            return translate((Map)value, leaveOrg);
055                    if(Decision.isArray(value))
056                            return translate(Caster.toNativeArray(value), leaveOrg);
057                    return 0;
058            }
059    
060            private static int translate(List list,boolean leaveOrg) throws PageException {
061                    Iterator it = list.iterator();
062                    int count=0;
063                    while(it.hasNext()){
064                            count+=translate(it.next(),leaveOrg);
065                    }
066                    return count;
067            }
068    
069            private static int translate(Map map,boolean leaveOrg) throws PageException {
070                    Iterator it = map.entrySet().iterator();
071                    int count=0;
072                    while(it.hasNext()){
073                            count+=translate(((Map.Entry)it.next()).getValue(),leaveOrg);
074                    }
075                    return count;
076            }
077    
078            private static int translate(Object[] arr,boolean leaveOrg) throws PageException {
079                    int count=0;
080                    for(int i=0;i<arr.length;i++){
081                            count+=translate(arr[i],leaveOrg);
082                    }
083                    return count;
084            }
085    
086            private static void translate(int index, Key key, String strKey, Collection coll,boolean leaveOrg) throws PageException {
087                    String left;
088                    Object value=leaveOrg?coll.get(key):coll.remove(key);
089                    do{
090                            left=strKey.substring(0,index);
091                            strKey=strKey.substring(index+1);
092                            coll=touch(coll,KeyImpl.init(left));
093                            
094                    }
095                    while((index=strKey.indexOf('.'))!=-1);
096                    coll.set(KeyImpl.init(strKey), value);
097            }
098    
099            private static Collection touch(Collection coll, Key key) throws PageException {
100                    Object obj = coll.get(key,null);
101                    if(obj instanceof Collection) return (Collection) obj;
102                    if(Decision.isCastableToStruct(obj))
103                            return Caster.toStruct(obj);
104                    coll.set(key, coll=new StructImpl());
105                    return coll;
106                    
107            }
108    }