001 /** 002 * Implements the CFML Function structfindkey 003 */ 004 package railo.runtime.functions.struct; 005 006 import java.util.Iterator; 007 import java.util.List; 008 import java.util.Map; 009 import java.util.Map.Entry; 010 011 import railo.runtime.PageContext; 012 import railo.runtime.exp.FunctionException; 013 import railo.runtime.exp.PageException; 014 import railo.runtime.ext.function.Function; 015 import railo.runtime.type.Array; 016 import railo.runtime.type.ArrayImpl; 017 import railo.runtime.type.Collection; 018 import railo.runtime.type.Collection.Key; 019 import railo.runtime.type.Struct; 020 import railo.runtime.type.StructImpl; 021 import railo.runtime.type.scope.Argument; 022 import railo.runtime.type.util.KeyConstants; 023 import railo.runtime.type.wrap.ListAsArray; 024 import railo.runtime.type.wrap.MapAsStruct; 025 026 public final class StructFindKey implements Function { 027 028 public static Array call(PageContext pc , railo.runtime.type.Struct struct, String value) throws PageException { 029 return _call(pc,struct,value,false); 030 } 031 public static Array call(PageContext pc , Struct struct, String value, String scope) throws PageException { 032 // Scope 033 boolean all=false; 034 if(scope.equalsIgnoreCase("one")) all=false; 035 else if(scope.equalsIgnoreCase("all")) all=true; 036 else throw new FunctionException(pc,"structFindValue",3,"scope","invalid scope definition ["+scope+"], valid scopes are [one, all]"); 037 return _call(pc,struct,value,all); 038 } 039 private static Array _call(PageContext pc , Struct struct, String value, boolean all) throws PageException { 040 Array array=new ArrayImpl(); 041 getValues(array,struct,value,all,""); 042 return array; 043 } 044 /** 045 * @param coll 046 * @param value 047 * @param all 048 * @param buffer 049 * @return 050 * @throws PageException 051 */ 052 private static boolean getValues(Array array,Collection coll, String value, boolean all, String path) throws PageException { 053 //Collection.Key[] keys=coll.keys(); 054 Iterator<Entry<Key, Object>> it = coll.entryIterator(); 055 Entry<Key, Object> e; 056 boolean abort=false; 057 Collection.Key key; 058 059 while(it.hasNext()) { 060 e = it.next(); 061 if(abort)break; 062 key=e.getKey(); 063 Object o=e.getValue(); 064 065 // matching value (this function search first for base) 066 if(key.getString().equalsIgnoreCase(value)) { 067 Struct sct=new StructImpl(); 068 069 sct.setEL(KeyConstants._value,o); 070 sct.setEL(KeyConstants._path,createKey(coll,path,key)); 071 sct.setEL(KeyConstants._owner,coll); 072 array.append(sct); 073 if(!all)abort=true; 074 } 075 076 // Collection 077 if(!abort) { 078 if(o instanceof Collection) { 079 abort=getValues(array,((Collection)o), value, all, createKey(coll,path,key)); 080 } 081 else if(o instanceof List){ 082 abort=getValues(array,ListAsArray.toArray((List)o), value, all, createKey(coll,path,key)); 083 } 084 else if(o instanceof Map){ 085 abort=getValues(array,MapAsStruct.toStruct((Map)o), value, all, createKey(coll,path,key)); 086 } 087 } 088 } 089 090 return abort; 091 } 092 static String createKey(Collection coll,String path,Collection.Key key) { 093 StringBuffer p=new StringBuffer(path.toString()); 094 if(isArray(coll)){ 095 p.append('[').append(key.getString()).append(']'); 096 } 097 else{ 098 p.append('.').append(key.getString()); 099 } 100 return p.toString(); 101 } 102 static boolean isArray(Collection coll) { 103 return coll instanceof Array && !(coll instanceof Argument); 104 } 105 }