All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.brooklyn.util.collections.CollectionFunctionals Maven / Gradle / Ivy

Go to download

Utility classes and methods developed for Brooklyn but not dependendent on Brooklyn or much else

There is a newer version: 1.1.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.brooklyn.util.collections;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

/** things which it seems should be in guava, but i can't find 
 * @author alex */
public class CollectionFunctionals {

    private static final class EqualsSetPredicate implements Predicate> {
        private final Iterable target;

        private EqualsSetPredicate(Iterable target) {
            this.target = target;
        }

        @Override
        public boolean apply(@Nullable Iterable input) {
            if (input==null) return false;
            return Sets.newHashSet(target).equals(Sets.newHashSet(input));
        }
    }

    private static final class KeysOfMapFunction implements Function, Set> {
        @Override
        public Set apply(Map input) {
            if (input==null) return null;
            return input.keySet();
        }

        @Override public String toString() { return "keys"; }
    }

    private static final class SizeSupplier implements Supplier {
        private final Iterable collection;

        private SizeSupplier(Iterable collection) {
            this.collection = collection;
        }

        @Override
        public Integer get() {
            return Iterables.size(collection);
        }

        @Override public String toString() { return "sizeSupplier("+collection+")"; }
    }

    public static final class SizeFunction implements Function, Integer> {
        private final Integer valueIfInputNull;

        private SizeFunction(Integer valueIfInputNull) {
            this.valueIfInputNull = valueIfInputNull;
        }

        @Override
        public Integer apply(Iterable input) {
            if (input==null) return valueIfInputNull;
            return Iterables.size(input);
        }

        @Override public String toString() { return "sizeFunction"; }
    }

    public static Supplier sizeSupplier(final Iterable collection) {
        return new SizeSupplier(collection);
    }
    
    public static Function, Integer> sizeFunction() { return sizeFunction(null); }
    
    public static Function, Integer> sizeFunction(final Integer valueIfInputNull) {
        return new SizeFunction(valueIfInputNull);
    }

    public static final class FirstElementFunction implements Function, T> {
        public FirstElementFunction() {
        }

        @Override
        public T apply(Iterable input) {
            if (input==null || Iterables.isEmpty(input)) return null;
            return Iterables.get(input, 0);
        }

        @Override public String toString() { return "firstElementFunction"; }
    }

    public static  Function, T> firstElement() {
        return new FirstElementFunction();
    }
    
    public static  Function,Set> keys() {
        return new KeysOfMapFunction();
    }

    public static  Function, Integer> mapSize() {
        return mapSize(null);
    }
    
    public static  Function, Integer> mapSize(Integer valueIfNull) {
        return Functions.compose(CollectionFunctionals.sizeFunction(valueIfNull), CollectionFunctionals.keys());
    }

    /** default guava Equals predicate will reflect order of target, and will fail when matching against a list;
     * this treats them both as sets */
    public static Predicate> equalsSetOf(Object... target) {
        return equalsSet(Arrays.asList(target));
    }
    public static Predicate> equalsSet(final Iterable target) {
        return new EqualsSetPredicate(target);
    }

    public static Predicate> sizeEquals(int targetSize) {
        return Predicates.compose(Predicates.equalTo(targetSize), CollectionFunctionals.sizeFunction());
    }

    public static Predicate> empty() {
        return sizeEquals(0);
    }

    public static Predicate> emptyOrNull() {
        return Predicates.or(Predicates.isNull(), sizeEquals(0));
    }

    public static Predicate> notEmpty() {
        return Predicates.not(emptyOrNull());
    }

    public static  Predicate> mapSizeEquals(int targetSize) {
        return Predicates.compose(Predicates.equalTo(targetSize), CollectionFunctionals.mapSize());
    }

    public static  Predicate> mapEmptyOrNull() {
        return Predicates.>or(Predicates.isNull(), CollectionFunctionals.mapSizeEquals(0));
    }

    public static  Predicate> mapNotEmpty() {
        return Predicates.not(CollectionFunctionals.mapEmptyOrNull());
    }

    public static > Function> limit(final int max) {
        return new LimitFunction(max);
    }

    private static final class LimitFunction> implements Function> {
        private final int max;
        private LimitFunction(int max) {
            this.max = max;
        }
        @Override
        public List apply(I input) {
            if (input==null) return null;
            MutableList result = MutableList.of();
            for (T i: input) {
                result.add(i);
                if (result.size()>=max)
                    return result;
            }
            return result;
        }
    }

    // ---------
    public static > Predicate contains(I item) {
        return new CollectionContains(item);
    }
    
    private static final class CollectionContains> implements Predicate {
        private final I item;
        private CollectionContains(I item) {
            this.item = item;
        }
        @Override
        public boolean apply(T input) {
            if (input==null) return false;
            return input.contains(item);
        }
        @Override
        public String toString() {
            return "contains("+item+")";
        }
    }

    // ---------
    
    /** 
     * Returns a predicate for a collection which is true if 
     * all elements in the collection given to the predicate
     * which satisfies the predicate given here.
     * 

* This will return true for the empty set. * To require additionally that there is at least one * use {@link #quorum(QuorumCheck, Predicate)} with * {@link QuorumChecks#allAndAtLeastOne()}. */ public static > Predicate all(Predicate attributeSatisfies) { return quorum(QuorumChecks.all(), attributeSatisfies); } /** Returns a predicate for a collection which is true if * there is at least one element in the collection given to the predicate * which satisfies the predicate given here. */ public static > Predicate any(Predicate attributeSatisfies) { // implementation could be more efficient -- ie succeed fast return quorum(QuorumChecks.atLeastOne(), attributeSatisfies); } /** Returns a predicate for a collection which is true if * the number of elements in the collection satisfying the predicate given here * passes the {@link QuorumCheck} given here. */ public static > Predicate quorum(QuorumCheck quorumCheck, Predicate attributeSatisfies) { return new QuorumSatisfies(quorumCheck, attributeSatisfies); } private static final class QuorumSatisfies> implements Predicate { private final Predicate itemCheck; private final QuorumCheck quorumCheck; private QuorumSatisfies(QuorumCheck quorumCheck, Predicate itemCheck) { this.itemCheck = Preconditions.checkNotNull(itemCheck, "itemCheck"); this.quorumCheck = Preconditions.checkNotNull(quorumCheck, "quorumCheck"); } @Override public boolean apply(T input) { if (input==null) return false; int sizeHealthy = 0, totalSize = 0; for (I item: input) { totalSize++; if (itemCheck.apply(item)) sizeHealthy++; } return quorumCheck.isQuorate(sizeHealthy, totalSize); } @Override public String toString() { return quorumCheck.toString()+"("+itemCheck+")"; } } }