001    package railo.runtime.type.util;
002    
003    import java.util.ArrayList;
004    import java.util.Arrays;
005    import java.util.HashSet;
006    import java.util.Iterator;
007    import java.util.Map;
008    import java.util.Map.Entry;
009    import java.util.Set;
010    
011    import railo.commons.lang.SizeOf;
012    import railo.commons.lang.StringUtil;
013    import railo.runtime.PageContext;
014    import railo.runtime.dump.DumpProperties;
015    import railo.runtime.dump.DumpTable;
016    import railo.runtime.dump.DumpUtil;
017    import railo.runtime.dump.SimpleDumpData;
018    import railo.runtime.exp.PageException;
019    import railo.runtime.op.Caster;
020    import railo.runtime.op.Duplicator;
021    import railo.runtime.type.Collection;
022    import railo.runtime.type.Collection.Key;
023    import railo.runtime.type.KeyImpl;
024    import railo.runtime.type.Struct;
025    import railo.runtime.type.StructImpl;
026    import railo.runtime.type.comparator.TextComparator;
027    
028    /**
029     * 
030     */
031    public final class StructUtil {
032    
033        /**
034         * copy data from source struct to target struct
035         * @param source 
036         * @param target 
037         * @param overwrite overwrite data if exist in target
038         */
039        public static void copy(Struct source, Struct target, boolean overwrite) {
040            Iterator<Entry<Key, Object>> it = source.entryIterator();
041            Entry<Key, Object> e;
042            while(it.hasNext()) {
043                    e = it.next();
044                if(overwrite || !target.containsKey(e.getKey())) 
045                    target.setEL(e.getKey(),e.getValue());
046            }
047        }
048    
049        public static railo.runtime.type.Collection.Key[] toCollectionKeys(String[] skeys) {
050            railo.runtime.type.Collection.Key[] keys = new railo.runtime.type.Collection.Key[skeys.length];
051                    for(int i=0;i<keys.length;i++) {
052                            keys[i]=KeyImpl.init(skeys[i]);
053                    }
054                return keys;
055        }
056        
057            /**
058             * @param sct
059             * @return
060             */
061            public static Struct duplicate(Struct sct,boolean deepCopy) {
062    
063                    Struct rtn=new StructImpl();
064                    //railo.runtime.type.Collection.Key[] keys=sct.keys();
065                    //railo.runtime.type.Collection.Key key;
066                    Iterator<Entry<Key, Object>> it = sct.entryIterator();
067            Entry<Key, Object> e;
068            while(it.hasNext()) {
069                    e=it.next();
070                            rtn.setEL(e.getKey(),Duplicator.duplicate(e.getValue(),deepCopy));
071                    }
072                    return rtn;
073            }
074    
075            public static void putAll(Struct struct, Map map) {
076                    Iterator it = map.entrySet().iterator();
077                    Map.Entry entry;
078                    while(it.hasNext()) {
079                            entry=(Entry) it.next();
080                            struct.setEL(KeyImpl.toKey(entry.getKey(),null), entry.getValue());
081                    }
082            }
083    
084            public static Set<Entry<String, Object>> entrySet(Struct sct) {
085                    Iterator<Entry<Key, Object>> it = sct.entryIterator();
086                    Entry<Key, Object> e;
087                    HashSet<Entry<String, Object>> set=new HashSet<Entry<String, Object>>();
088                    while(it.hasNext()){
089                            e= it.next();
090                            set.add(new StructMapEntry(sct,e.getKey(),e.getValue()));
091                    }
092                    return set;
093            }
094            
095            public static Set<String> keySet(Struct sct) {
096                    Iterator<Key> it = sct.keyIterator();
097                    Set<String> set=new HashSet<String>();
098                    while(it.hasNext()){
099                            set.add(it.next().getString());
100                    }
101                    return set;
102            }
103    
104            
105            public static DumpTable toDumpTable(Struct sct,String title,PageContext pageContext, int maxlevel, DumpProperties dp) {
106                    Key[] keys = order(CollectionUtil.keys(sct));
107                    DumpTable table = new DumpTable("struct","#9999ff","#ccccff","#000000");// "#9999ff","#ccccff","#000000"
108                    if(sct.size()>10 && dp.getMetainfo())table.setComment("Entries:"+sct.size());
109                if(!StringUtil.isEmpty(title))table.setTitle(title);
110                    maxlevel--;
111                    int maxkeys=dp.getMaxKeys();
112                    int index=0;
113                    for(int i=0;i<keys.length;i++) {
114                            if(DumpUtil.keyValid(dp,maxlevel,keys[i])){
115                                    if(maxkeys<=index++)break;
116                                    table.appendRow(1,
117                                                    new SimpleDumpData(keys[i].toString()),
118                                                    DumpUtil.toDumpData(sct.get(keys[i],null), 
119                                                    pageContext,maxlevel,dp));
120                            }
121                    }
122                    return table;
123            }
124            
125            
126    
127            private static Key[] order(Key[] keys) {
128                    TextComparator comp=new TextComparator(true,true);
129                    Arrays.sort(keys,comp);
130                    return keys;
131            }
132    
133            /**
134             * create a value return value out of a struct
135             * @param sct
136             * @return
137             */
138            public static java.util.Collection<?> values(Struct sct) {
139                    ArrayList<Object> arr = new ArrayList<Object>();
140                    //Key[] keys = sct.keys();
141                    Iterator<Object> it = sct.valueIterator();
142                    while(it.hasNext()) {
143                            arr.add(it.next());
144                    }
145                    return arr;
146            }
147    
148            public static Struct copyToStruct(Map map) throws PageException {
149            Struct sct = new StructImpl();
150            Iterator it=map.entrySet().iterator();
151            Map.Entry entry;
152            while(it.hasNext()) {
153                entry=(Entry) it.next();
154                sct.setEL(Caster.toString(entry.getKey()),entry.getValue());
155            }
156            return sct;
157            }
158    
159            /**
160             * return the size of given struct, size of values + keys
161             * @param sct
162             * @return
163             */
164            public static long sizeOf(Struct sct) {
165                    Iterator<Entry<Key, Object>> it = sct.entryIterator();
166                    Entry<Key, Object> e;
167                    long size = 0;
168                    while(it.hasNext()) {
169                            e = it.next();
170                            size+=SizeOf.size(e.getKey());
171                            size+=SizeOf.size(e.getValue());
172                    }
173                    return size;
174            }
175    
176            public static void setELIgnoreWhenNull(Struct sct, String key, Object value) {
177                    setELIgnoreWhenNull(sct, KeyImpl.init(key), value);
178            }
179            public static void setELIgnoreWhenNull(Struct sct, Collection.Key key, Object value) {
180                    if(value!=null)sct.setEL(key, value);
181            }
182    
183            /**
184             * remove every entry hat has this value
185             * @param map
186             * @param obj
187             */
188            public static void removeValue(Map map, Object value) {
189                    Iterator it = map.entrySet().iterator();
190                    Map.Entry entry;
191                    while(it.hasNext()){
192                            entry=(Entry) it.next();
193                            if(entry.getValue()==value)it.remove();
194                    }
195            }
196    
197            
198        public static Struct merge(Struct[] scts) { 
199                    Struct sct=new StructImpl();
200                    
201                    for(int i=scts.length-1;i>=0;i--){
202                            Iterator<Entry<Key, Object>> it = scts[i].entryIterator();
203                            Entry<Key, Object> e;
204                            while(it.hasNext()){
205                                    e = it.next();
206                                    sct.setEL(e.getKey(), e.getValue());
207                            }
208                    }
209                    return sct;
210            }
211    }