001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/** 020 * Implements the CFML Function structfindvalue 021 */ 022package lucee.runtime.functions.struct; 023 024import java.util.Iterator; 025import java.util.Map.Entry; 026 027import lucee.runtime.PageContext; 028import lucee.runtime.exp.FunctionException; 029import lucee.runtime.exp.PageException; 030import lucee.runtime.functions.BIF; 031import lucee.runtime.op.Caster; 032import lucee.runtime.type.Array; 033import lucee.runtime.type.ArrayImpl; 034import lucee.runtime.type.Collection; 035import lucee.runtime.type.Collection.Key; 036import lucee.runtime.type.Struct; 037import lucee.runtime.type.StructImpl; 038import lucee.runtime.type.util.KeyConstants; 039 040public final class StructFindValue extends BIF { 041 042 private static final long serialVersionUID = 1499023912262918840L; 043 044 public static Array call(PageContext pc , lucee.runtime.type.Struct struct, String value) throws PageException { 045 return call(pc,struct,value,"one"); 046 } 047 public static Array call(PageContext pc , Struct struct, String value, String scope) throws PageException { 048 // Scope 049 boolean all=false; 050 if(scope.equalsIgnoreCase("one")) all=false; 051 else if(scope.equalsIgnoreCase("all")) all=true; 052 else throw new FunctionException(pc,"structFindValue",3,"scope","invalid scope definition ["+scope+"], valid scopes are [one, all]"); 053 054 Array array=new ArrayImpl(); 055 getValues(pc,array,struct,value,all,""); 056 return array; 057 } 058 /** 059 * @param coll 060 * @param value 061 * @param all 062 * @param buffer 063 * @return 064 * @throws PageException 065 */ 066 private static boolean getValues(PageContext pc,Array array,Collection coll, String value, boolean all, String path) throws PageException { 067 //Key[] keys = coll.keys(); 068 boolean abort=false; 069 Key key; 070 Iterator<Entry<Key, Object>> it = coll.entryIterator(); 071 Entry<Key, Object> e; 072 loop:while(it.hasNext()) { 073 e = it.next(); 074 if(abort)break loop; 075 key=e.getKey(); 076 Object o=e.getValue(); 077 078 // Collection (this function search first for sub) 079 if(o instanceof Collection) { 080 abort=getValues(pc,array,((Collection)o), value, all, StructFindKey.createKey(coll, path, key)); 081 082 } 083 // matching value 084 if(!abort && !StructFindKey.isArray(coll)){ 085 String target=Caster.toString(o,null); 086 if((target!=null && target.equalsIgnoreCase(value)) /*|| (o instanceof Array && checkSub(array,((Array)o),value,all,path,abort))*/) { 087 Struct sct=new StructImpl(); 088 sct.setEL(KeyConstants._key,key.getString()); 089 sct.setEL(KeyConstants._path,StructFindKey.createKey(coll, path, key)); 090 sct.setEL(KeyConstants._owner,coll); 091 array.append(sct); 092 if(!all)abort=true; 093 } 094 } 095 } 096 097 return abort; 098 } 099 100 @Override 101 public Object invoke(PageContext pc, Object[] args) throws PageException { 102 if(args.length==3) return call(pc,Caster.toStruct(args[0]),Caster.toString(args[1]),Caster.toString(args[2])); 103 return call(pc,Caster.toStruct(args[0]),Caster.toString(args[1])); 104 } 105}