001    /**
002     * Implements the CFML Function structfindvalue
003     */
004    package railo.runtime.functions.struct;
005    
006    import java.util.Iterator;
007    import java.util.Map.Entry;
008    
009    import railo.runtime.PageContext;
010    import railo.runtime.exp.FunctionException;
011    import railo.runtime.exp.PageException;
012    import railo.runtime.ext.function.Function;
013    import railo.runtime.op.Caster;
014    import railo.runtime.type.Array;
015    import railo.runtime.type.ArrayImpl;
016    import railo.runtime.type.Collection;
017    import railo.runtime.type.Collection.Key;
018    import railo.runtime.type.Struct;
019    import railo.runtime.type.StructImpl;
020    import railo.runtime.type.util.KeyConstants;
021    
022    public final class StructFindValue implements Function {
023            public static Array call(PageContext pc , railo.runtime.type.Struct struct, String value) throws PageException {
024                    return call(pc,struct,value,"one");
025            }
026            public static Array call(PageContext pc , Struct struct, String value, String scope) throws PageException {
027                    // Scope
028                boolean all=false;
029                if(scope.equalsIgnoreCase("one")) all=false;
030                else if(scope.equalsIgnoreCase("all")) all=true;
031                else throw new FunctionException(pc,"structFindValue",3,"scope","invalid scope definition ["+scope+"], valid scopes are [one, all]");
032                
033                Array array=new ArrayImpl();
034                getValues(pc,array,struct,value,all,"");
035                return array;
036            }
037        /**
038         * @param coll
039         * @param value
040         * @param all
041         * @param buffer
042         * @return
043         * @throws PageException
044         */
045        private static boolean getValues(PageContext pc,Array array,Collection coll, String value, boolean all, String path) throws PageException {
046            //Key[] keys = coll.keys();
047            boolean abort=false;
048            Key key;
049            Iterator<Entry<Key, Object>> it = coll.entryIterator();
050            Entry<Key, Object> e;
051            loop:while(it.hasNext()) {
052                    e = it.next();
053                if(abort)break loop;
054                key=e.getKey();
055                Object o=e.getValue();
056                
057                // Collection (this function search first for sub)
058                if(o instanceof Collection) {
059                    abort=getValues(pc,array,((Collection)o), value, all, StructFindKey.createKey(coll, path, key));
060                    
061                }
062                // matching value
063                if(!abort && !StructFindKey.isArray(coll)){
064                String target=Caster.toString(o,null);
065                if((target!=null && target.equalsIgnoreCase(value)) /*|| (o instanceof Array && checkSub(array,((Array)o),value,all,path,abort))*/) {
066                    Struct sct=new StructImpl();
067                            sct.setEL(KeyConstants._key,key.getString());
068                                    sct.setEL(KeyConstants._path,StructFindKey.createKey(coll, path, key));
069                                    sct.setEL(KeyConstants._owner,coll);
070                    array.append(sct);
071                    if(!all)abort=true;
072                }
073            }
074            }
075            
076            return abort;
077        }
078    }