com.eucalyptus.util.CollectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.eucalyptus.util.CollectionUtils.java

Source

/*************************************************************************
 * Copyright 2009-2014 Eucalyptus Systems, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 *
 * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
 * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
 * additional information or have any questions.
 ************************************************************************/
package com.eucalyptus.util;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;

/**
 * Utility functions for collections
 */
public class CollectionUtils {

    /**
     * Apply the given function for each item in the iterable.
     *
     * <p>This method is an anti-pattern as the function is really an effect (it
     * can only be useful for its side effect)</p>
     *
     * @param iterable The iterable
     * @param function The function to apply
     * @param <T> The iterable type
     */
    public static <T> void each(final Iterable<T> iterable, final Function<? super T, ?> function) {
        Iterables.size(Iterables.transform(iterable, function)); // transform is lazy
    }

    /**
     * Apply the given predicate for each item in the iterable.
     *
     * <p>This method is an anti-pattern as the predicate is really an effect (it
     * can only be useful for its side effect)</p>
     *
     * @param iterable The iterable
     * @param predicate The predicate to apply
     * @param <T> The iterable type
     */
    public static <T> void each(final Iterable<T> iterable, final Predicate<? super T> predicate) {
        each(iterable, Functions.forPredicate(predicate));
    }

    /**
     * Create a fluent iterable for the given iterable.
     *
     * @param iterable The possibly null iterable
     * @param <T> The iterable type
     * @return the FluentIterable
     */
    @Nonnull
    public static <T> FluentIterable<T> fluent(@Nullable final Iterable<T> iterable) {
        return FluentIterable.from(iterable == null ? Collections.<T>emptyList() : iterable);
    }

    /**
     * Predicate for collections containing the given item.
     *
     * @param item The required item
     * @param <CIT> The item type
     * @param <CT> The collection type
     * @return A collection matching predicate
     */
    public static <CIT, CT extends Collection<? super CIT>> Predicate<CT> contains(final CIT item) {
        return new Predicate<CT>() {
            @Override
            public boolean apply(@Nullable final CT collection) {
                return collection != null && collection.contains(item);
            }
        };
    }

    /**
     * Convenience method for a predicate on a property value.
     *
     * @param propertyValue The property value to match
     * @param propertyFunction The function to extract the property
     * @param <T> The predicate type
     * @param <PT> The property type
     * @return A predicate that extracts a value to compare with the given value.
     */
    public static <T, PT> Predicate<T> propertyPredicate(final PT propertyValue,
            final Function<T, PT> propertyFunction) {
        return Predicates.compose(Predicates.equalTo(propertyValue), propertyFunction);
    }

    /**
     * Convenience method for a predicate on a property value.
     *
     * @param propertyValues The property values to match
     * @param propertyFunction The function to extract the property
     * @param <T> The predicate type
     * @param <PT> The property type
     * @return A predicate that extracts a value to compare with the given values.
     */
    public static <T, PT> Predicate<T> propertyPredicate(final Collection<PT> propertyValues,
            final Function<T, PT> propertyFunction) {
        return Predicates.compose(Predicates.in(propertyValues), propertyFunction);
    }

    /**
     * Convenience method for a predicate on a property value.
     *
     * @param propertyValue The property value to match
     * @param propertyFunction The function to extract the collection property
     * @param <T> The predicate type
     * @param <PCT> The property collection type
     * @param <PIT> The property collection item type
     * @return A predicate that extracts a value to compare with the given value.
     */
    public static <T, PIT, PCT extends Collection<? super PIT>> Predicate<T> propertyContainsPredicate(
            final PIT propertyValue, final Function<T, PCT> propertyFunction) {
        return Predicates.compose(contains(propertyValue), propertyFunction);
    }

    public static <T> Function<T, List<T>> listUnit() {
        return new Function<T, List<T>>() {
            @SuppressWarnings("unchecked")
            @Override
            public List<T> apply(final T t) {
                return t == null ? Lists.<T>newArrayList() : Lists.newArrayList(t);
            }
        };
    }

    public static <T> Function<List<List<T>>, List<T>> listJoin() {
        return new Function<List<List<T>>, List<T>>() {
            @SuppressWarnings("unchecked")
            @Override
            public List<T> apply(final List<List<T>> t) {
                return t == null ? Lists.<T>newArrayList() : Lists.newArrayList(Iterables.concat(t));
            }
        };
    }

    public static <T> Function<T, Optional<T>> optionalUnit() {
        return new Function<T, Optional<T>>() {
            @Override
            public Optional<T> apply(final T t) {
                return Optional.fromNullable(t);
            }
        };
    }

    public static <T> Function<Optional<T>, T> optionalOrNull() {
        return new Function<Optional<T>, T>() {
            @Nullable
            @Override
            public T apply(final Optional<T> optional) {
                return optional == null ? null : optional.orNull();
            }
        };
    }

    public static <T> Function<Optional<T>, T> optionalOr(final T value) {
        return new Function<Optional<T>, T>() {
            @Nullable
            @Override
            public T apply(final Optional<T> optional) {
                return optional == null ? null : optional.or(value);
            }
        };
    }

    /**
     * Unchecked cast function.
     *
     * @param target The type to cast to
     * @param <F> The source type
     * @param <T> The result type
     * @return A function that casts to the given type
     * @see Predicates#instanceOf(Class)
     * @see Iterables#filter(Iterable, Class)
     */
    public static <F, T> Function<F, T> cast(final Class<T> target) {
        //noinspection unchecked
        return (Function<F, T>) Functions.identity();
    }

    /**
     * Reduce a collection using an initial value and a reduction function.
     * 
     * @param iterable The iterable to be reduced
     * @param initialValue The initial value
     * @param reducer The reduction function
     * @param <T> The result type
     * @param <I> The iterable type
     * @return The final value
     */
    public static <T, I> T reduce(final Iterable<? extends I> iterable, final T initialValue,
            final Function<T, Function<I, T>> reducer) {
        T value = initialValue;
        for (I item : iterable) {
            value = reducer.apply(value).apply(item);
        }
        return value;
    }

    public static <I, K, V> Map<K, V> putAll(final Iterable<? extends I> iterable, final Map<K, V> targetMap,
            final Function<? super I, K> keyFunction, final Function<? super I, V> valueFunction) {
        if (iterable != null)
            for (final I item : iterable) {
                targetMap.put(keyFunction.apply(item), valueFunction.apply(item));
            }
        return targetMap;
    }

    public static <I, K, V> Multimap<K, V> putAll(final Iterable<? extends I> iterable,
            final Multimap<K, V> targetMap, final Function<? super I, K> keyFunction,
            final Function<? super I, V> valueFunction) {
        if (iterable != null)
            for (final I item : iterable) {
                targetMap.put(keyFunction.apply(item), valueFunction.apply(item));
            }
        return targetMap;
    }

    /**
     * Transform the given map, ignoring mapped entries with null keys or values.
     *
     * <p>WARNING! if the transform produces duplicate keys entries will be
     * overwritten.</p>
     *
     * @param map The map to transform
     * @param targetMap The result map
     * @param keyFunction The key transform
     * @param valueFunction The value transform
     * @param <K1> The source key type
     * @param <V1> The source value type
     * @param <K2> The target key type
     * @param <V2> The target value type
     * @return The supplied target map
     */
    public static <K1, V1, K2, V2> Map<K2, V2> transform(final Map<K1, V1> map, final Map<K2, V2> targetMap,
            final Function<? super K1, K2> keyFunction, final Function<? super V1, V2> valueFunction) {
        if (map != null)
            for (final Map.Entry<K1, V1> entry : map.entrySet()) {
                final K2 targetKey = keyFunction.apply(entry.getKey());
                final V2 targetValue = valueFunction.apply(entry.getValue());
                if (targetKey != null && targetValue != null) {
                    targetMap.put(targetKey, targetValue);
                }
            }
        return targetMap;
    }

    /**
     * Min function suitable for use with reduce.
     *
     * @return The min function.
     */
    public static Function<Integer, Function<Integer, Integer>> min() {
        return new Function<Integer, Function<Integer, Integer>>() {
            @Override
            public Function<Integer, Integer> apply(final Integer integer1) {
                return new Function<Integer, Integer>() {
                    @Override
                    public Integer apply(final Integer integer2) {
                        return Math.min(integer1, integer2);
                    }
                };
            }
        };
    }

    /**
     * Count function suitable for use with reduce.
     * 
     * @param evaluator Predicate matching items to be counted.
     * @param <I> The evaluated type
     * @return The count function.
     */
    public static <I> Function<Integer, Function<I, Integer>> count(final Predicate<I> evaluator) {
        return sum(new Function<I, Integer>() {
            @Override
            public Integer apply(@Nullable final I item) {
                return evaluator.apply(item) ? 1 : 0;
            }
        });
    }

    /**
     * Sum function suitable for use with reduce.
     *
     * @param evaluator Function to obtain an int from an I
     * @param <I> The evaluated type
     * @return The sum function.
     */
    public static <I> Function<Integer, Function<I, Integer>> sum(final Function<I, Integer> evaluator) {
        return new Function<Integer, Function<I, Integer>>() {
            @Override
            public Function<I, Integer> apply(final Integer sum) {
                return new Function<I, Integer>() {
                    @Override
                    public Integer apply(final I item) {
                        return sum + evaluator.apply(item);
                    }
                };
            }
        };
    }

    /**
     * Flip parameter order for curried function.
     *
     * @param curried The function to flip
     * @param <F1> The first parameter type
     * @param <F2> The second parameter type
     * @param <T> The result type
     * @return The flipped function
     */
    public static <F1, F2, T> Function<F2, Function<F1, T>> flipCurried(
            final Function<F1, Function<F2, T>> curried) {
        return new Function<F2, Function<F1, T>>() {
            @Override
            public Function<F1, T> apply(@Nullable final F2 f2) {
                return new Function<F1, T>() {
                    @Override
                    public T apply(@Nullable final F1 f1) {
                        //noinspection ConstantConditions
                        return curried.apply(f1).apply(f2);
                    }
                };
            }
        };
    }

    /**
     * Comparator function suitable for use with reduce.
     *
     * <p>Use with reduce to obtain a min or max value.</p>
     * 
     * @param comparator The comparator to use
     * @param <T> The compared type
     * @return The comparator function.
     * @see com.google.common.collect.Ordering
     */
    public static <T> Function<T, Function<T, T>> comparator(final Comparator<T> comparator) {
        return new Function<T, Function<T, T>>() {
            @Override
            public Function<T, T> apply(final T t1) {
                return new Function<T, T>() {
                    @Override
                    public T apply(final T t2) {
                        return comparator.compare(t1, t2) < 0 ? t1 : t2;
                    }
                };
            }
        };
    }
}