package com.tek271.funj; import com.google.common.collect.Maps; import com.google.common.collect.ObjectArrays; import com.google.common.collect.Sets; import java.util.List; import java.util.Map; import java.util.Set; import static com.google.common.collect.Lists.newArrayList; import static com.tek271.funj.CollectionTools.isEmpty; import static com.tek271.funj.ReflectionTools.*; public class Mapper { /** * Extract a list of property values from a list of objects * @param iterable list of objects * @param propertyName name of property to extract * @param <OBJ> Generic type of the objects in the iterable * @param <PROP> Generic type of property * @return List of type PROP of the extracted property values */ public static <OBJ, PROP> List<PROP> pluck(Iterable<OBJ> iterable, String propertyName) { List<PROP> plucked = newArrayList(); if (isEmpty(iterable)) return plucked; checkPropertyExists(iterable, propertyName); for (OBJ obj: iterable) { plucked.add((PROP) getPropertyValue(obj, propertyName)); } return plucked; } /** * Extract a Set of property values from a list of objects * @param iterable list of objects * @param propertyName name of property to extract * @param <OBJ> Generic type of the objects in the iterable * @param <PROP> Generic type of property * @return Set of type PROP of the extracted property values */ public static <OBJ, PROP> Set<PROP> pluckToSet(Iterable<OBJ> iterable, String propertyName) { List<PROP> list = pluck(iterable, propertyName); return Sets.newHashSet(list); } public static <OBJ, K, V> Map<K, V> pluckKeyAndValue(Iterable<OBJ> iterable, String keyPropertyName, String valuePropertyName) { Map<K, V> map = Maps.newHashMap(); if (isEmpty(iterable)) { return map; } checkPropertiesExist(iterable, keyPropertyName, valuePropertyName); for (OBJ obj: iterable) { K k = getPropertyValue(obj, keyPropertyName); V v = getPropertyValue(obj, valuePropertyName); map.put(k, v); } return map; } /** * Map the objects in iterable into a list of objects by applying the callback on each object * in the iterable * @param iterable list of objects * @param staticCallbackFullName full name of a function, including package and class. The function * must have a single argument of type IN and return a value of type OUT * @param <IN> Generic type of objects to be mapped * @param <OUT> Generic type of the mapped values * @return List of mapped values. */ public static <IN, OUT> List<OUT> map(Iterable<IN> iterable, String staticCallbackFullName, Object... extraArgs) { FunctionDescriptor func = FunctionDescriptor.staticFunction(staticCallbackFullName); return map(iterable, func, extraArgs); } // TODO test this /** * Map the objects in iterable into a list of objects by applying the callback on each object * in the iterable * @param iterable list of objects * @param cls The class which contains the static callback * @param staticCallback name of a static callback function. The function must have a single * argument of type IN and return a value of type OUT * @param <IN> Generic type of objects to be mapped * @param <OUT> Generic type of the mapped values * @return List of mapped values. */ public static <IN, OUT> List<OUT> map(Iterable<IN> iterable, Class cls, String staticCallback, Object... extraArgs) { FunctionDescriptor func = FunctionDescriptor.staticFunction(cls, staticCallback); return map(iterable, func, extraArgs); } /** * Map the objects in iterable into a list of objects by applying the callback on each object * in the iterable * @param iterable list of objects * @param context The context (object) which contains the callback * @param callback name of a function which is a member of context. * The function must have at least single argument of type IN and return a value of type OUT. * The function may have other arguments which will use the extraArgs param. * @param extraArgs extra arguments to be passed to the callback function * @param <IN> Generic type of objects to be mapped * @param <OUT> Generic type of the mapped values * @return List of mapped values. */ public static <IN, OUT> List<OUT> map(Iterable<IN> iterable, Object context, String callback, Object... extraArgs) { FunctionDescriptor func = FunctionDescriptor.dynamicFunction(context, callback); return map(iterable, func, extraArgs); } public static <IN, OUT> List<OUT> map(Iterable<IN> iterable, FunctionDescriptor functionDescriptor, Object... extraArgs) { List<OUT> list = newArrayList(); for (IN i: iterable) { Object[] args = ObjectArrays.concat(i, extraArgs); OUT mapped = functionDescriptor.call(args); list.add(mapped); } return list; } }