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 **/ 019package lucee.runtime.functions.closure; 020 021import java.util.Enumeration; 022import java.util.Iterator; 023import java.util.List; 024import java.util.ListIterator; 025import java.util.Map.Entry; 026 027import lucee.runtime.PageContext; 028import lucee.runtime.exp.CasterException; 029import lucee.runtime.exp.FunctionException; 030import lucee.runtime.exp.PageException; 031import lucee.runtime.functions.BIF; 032import lucee.runtime.op.Caster; 033import lucee.runtime.type.Array; 034import lucee.runtime.type.Collection.Key; 035import lucee.runtime.type.Iteratorable; 036import lucee.runtime.type.Query; 037import lucee.runtime.type.Struct; 038import lucee.runtime.type.UDF; 039import lucee.runtime.type.it.ForEachQueryIterator; 040import lucee.runtime.type.scope.ArgumentIntKey; 041import lucee.runtime.type.util.ListUtil; 042import lucee.runtime.type.util.StringListData; 043 044public class Reduce extends BIF { 045 046 private static final long serialVersionUID = -5940580562772523622L; 047 048 public static Object call(PageContext pc , Object obj, UDF udf) throws PageException { 049 return _call(pc, obj, udf,null); 050 } 051 052 public static Object call(PageContext pc , Object obj, UDF udf, Object initalValue) throws PageException { 053 return _call(pc, obj, udf,initalValue); 054 } 055 056 public static Object _call(PageContext pc , Object obj, UDF udf, Object initalValue) throws PageException { 057 058 059 Object value; 060 061 // Array 062 if(obj instanceof Array) { 063 value=invoke(pc, (Array)obj, udf,initalValue); 064 } 065 // Query 066 else if(obj instanceof Query) { 067 value=invoke(pc, (Query)obj, udf,initalValue); 068 } 069 // Struct 070 else if(obj instanceof Struct) { 071 value=invoke(pc, (Struct)obj, udf,initalValue); 072 } 073 // other Iteratorable 074 else if(obj instanceof Iteratorable) { 075 value=invoke(pc, (Iteratorable)obj, udf,initalValue); 076 } 077 // Map 078 else if(obj instanceof java.util.Map) { 079 value=invoke(pc, (java.util.Map)obj, udf,initalValue); 080 } 081 //List 082 else if(obj instanceof List) { 083 value=invoke(pc, (List)obj, udf,initalValue); 084 } 085 // Iterator 086 else if(obj instanceof Iterator) { 087 value=invoke(pc, (Iterator)obj, udf,initalValue); 088 } 089 // Enumeration 090 else if(obj instanceof Enumeration) { 091 value=invoke(pc, (Enumeration)obj, udf,initalValue); 092 } 093 else if(obj instanceof StringListData) { 094 value=invoke(pc, (StringListData)obj, udf,initalValue); 095 } 096 else 097 throw new FunctionException(pc, "Filter", 1, "data", "cannot iterate througth this type "+Caster.toTypeName(obj.getClass())); 098 099 100 return value; 101 } 102 103 private static Object invoke(PageContext pc, Array arr, UDF udf, Object initalValue) throws CasterException, PageException { 104 Iterator<Entry<Key, Object>> it = arr.entryIterator(); 105 Entry<Key, Object> e; 106 while(it.hasNext()){ 107 e = it.next(); 108 initalValue=udf.call(pc, new Object[]{initalValue,e.getValue(),Caster.toDoubleValue(e.getKey().getString()),arr}, true); 109 } 110 return initalValue; 111 } 112 113 private static Object invoke(PageContext pc, StringListData sld, UDF udf, Object initalValue) throws CasterException, PageException { 114 Array arr = ListUtil.listToArray(sld.list, sld.delimiter,sld.includeEmptyFieldsx,sld.multiCharacterDelimiter); 115 116 Iterator<Entry<Key, Object>> it = arr.entryIterator(); 117 Entry<Key, Object> e; 118 while(it.hasNext()){ 119 e = it.next(); 120 initalValue=udf.call(pc, new Object[]{initalValue,e.getValue(),Caster.toDoubleValue(e.getKey().getString()),sld.list,sld.delimiter}, true); 121 } 122 return initalValue; 123 } 124 125 private static Object invoke(PageContext pc, Query qry, UDF udf, Object initalValue) throws CasterException, PageException { 126 final int pid=pc.getId(); 127 ForEachQueryIterator it=new ForEachQueryIterator(qry, pid); 128 int rowNbr; 129 130 Object row; 131 while(it.hasNext()){ 132 row = it.next(); 133 rowNbr = qry.getCurrentrow(pid); 134 initalValue=udf.call(pc, new Object[]{initalValue,row,Caster.toDoubleValue(rowNbr),qry}, true); 135 } 136 return initalValue; 137 } 138 139 140 private static Object invoke(PageContext pc, List list, UDF udf, Object initalValue) throws CasterException, PageException { 141 ListIterator it = list.listIterator(); 142 Object v; 143 int index; 144 ArgumentIntKey k; 145 while(it.hasNext()){ 146 index = it.nextIndex(); 147 k = ArgumentIntKey.init(index); 148 v = it.next(); 149 initalValue=udf.call(pc, new Object[]{initalValue,v,Caster.toDoubleValue(k.getString()),list}, true); 150 } 151 return initalValue; 152 } 153 154 private static Object invoke(PageContext pc, Struct sct, UDF udf, Object initalValue) throws PageException { 155 Iterator<Entry<Key, Object>> it = sct.entryIterator(); 156 Entry<Key, Object> e; 157 while(it.hasNext()){ 158 e = it.next(); 159 initalValue=udf.call(pc, new Object[]{initalValue,e.getKey().getString(),e.getValue(),sct}, true); 160 } 161 return initalValue; 162 } 163 164 private static Object invoke(PageContext pc, java.util.Map map, UDF udf, Object initalValue) throws PageException { 165 Iterator<Entry> it = map.entrySet().iterator(); 166 Entry e; 167 while(it.hasNext()){ 168 e = it.next(); 169 initalValue=udf.call(pc, new Object[]{initalValue,e.getKey(),e.getValue(),map}, true); 170 } 171 return initalValue; 172 } 173 174 private static Object invoke(PageContext pc, Iteratorable i, UDF udf, Object initalValue) throws PageException { 175 Iterator<Entry<Key, Object>> it = i.entryIterator(); 176 177 Entry<Key, Object> e; 178 while(it.hasNext()){ 179 e = it.next(); 180 initalValue=udf.call(pc, new Object[]{initalValue,e.getKey().getString(),e.getValue()}, true); 181 } 182 return initalValue; 183 } 184 185 private static Object invoke(PageContext pc, Iterator it, UDF udf, Object initalValue) throws PageException { 186 187 Object v; 188 int count=0; 189 ArgumentIntKey k; 190 while(it.hasNext()){ 191 v = it.next(); 192 k = ArgumentIntKey.init(++count); 193 initalValue=udf.call(pc, new Object[]{initalValue,v}, true); 194 } 195 return initalValue; 196 } 197 198 private static Object invoke(PageContext pc, Enumeration e, UDF udf, Object initalValue) throws PageException { 199 200 Object v; 201 int count=0; 202 ArgumentIntKey k; 203 while(e.hasMoreElements()){ 204 v = e.nextElement(); 205 k = ArgumentIntKey.init(++count); 206 initalValue=udf.call(pc, new Object[]{initalValue,v}, true); 207 } 208 return initalValue; 209 } 210 211 @Override 212 public Object invoke(PageContext pc, Object[] args) throws PageException { 213 if(args.length==2) 214 return call(pc, (args[0]), Caster.toFunction(args[1])); 215 if(args.length==3) 216 return call(pc, (args[0]), Caster.toFunction(args[1]), args[2]); 217 218 throw new FunctionException(pc, "Reduce", 2, 3, args.length); 219 } 220 221}