com.yammer.collections.transforming.TransformingCollection.java Source code

Java tutorial

Introduction

Here is the source code for com.yammer.collections.transforming.TransformingCollection.java

Source

/**
 * Copyright (c) Microsoft Corporation
 * All rights reserved.
 *
 * Licensed 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
 *
 * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
 * OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
 *
 * See the Apache Version 2.0 License for specific language governing permissions and limitations under
 * the License.
 */
package com.yammer.collections.transforming;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterators;

import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.yammer.collections.transforming.TransformationUtil.safeTransform;

/**
 * This implementation will break if the following is not satisfied:
 * <p/>
 * - for every element F f, fromFunction(toFunction(f)) = f
 * - for every element T f, toFunction(FromFunction(t)) = t
 * <p/>
 * i.e., fromFunction is a bijection and the toFunction is its reverse
 * <p/>
 * Does not support null values, i.e., contains(null) returns false, add(null) throws a NullPointerException
 */
public class TransformingCollection<F, T> extends AbstractCollection<F> {
    private final Collection<T> backingCollection;
    private final Function<F, T> toFunction;
    private final Function<T, F> fromFunction;

    /* package */ TransformingCollection(Collection<T> backingCollection, Function<F, T> toFunction,
            Function<T, F> fromFunction) {
        this.backingCollection = checkNotNull(backingCollection);
        this.toFunction = checkNotNull(toFunction);
        this.fromFunction = checkNotNull(fromFunction);
    }

    public static <F, T> Collection<F> create(Collection<T> backingCollection, Function<F, T> toFunction,
            Function<T, F> fromFunction) {
        return new TransformingCollection<>(backingCollection, toFunction, fromFunction);
    }

    @Override
    public int size() {
        return backingCollection.size();
    }

    @Override
    public boolean isEmpty() {
        return backingCollection.isEmpty();
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean contains(Object o) {
        try {
            return o != null && backingCollection.contains(safeTransform((F) o, toFunction));
        } catch (ClassCastException ignored) {
            return false;
        }
    }

    @SuppressWarnings("NullableProblems")
    @Override
    public Iterator<F> iterator() {
        return Iterators.transform(backingCollection.iterator(), fromFunction);
    }

    @Override
    public boolean add(F f) {
        return backingCollection.add(safeTransform(checkNotNull(f), toFunction));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean remove(Object o) {
        try {
            return o != null && backingCollection.remove(safeTransform((F) o, toFunction));
        } catch (ClassCastException ignored) {
            return false;
        }
    }

    @Override
    public void clear() {
        backingCollection.clear();
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsAll(Collection<?> c) {
        return backingCollection
                .containsAll(Collections2.transform(checkNotNull(c), (Function<Object, Object>) toFunction));
    }

    @Override
    public boolean addAll(Collection<? extends F> c) {
        return backingCollection.addAll(Collections2.transform(checkNotNull(c), toFunction));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean removeAll(Collection<?> c) {
        return backingCollection
                .removeAll(Collections2.transform(checkNotNull(c), (Function<Object, Object>) toFunction));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean retainAll(Collection<?> c) {
        return backingCollection
                .retainAll(Collections2.transform(checkNotNull(c), (Function<Object, Object>) toFunction));
    }

    @Override
    public int hashCode() {
        int hashCode = 43;
        for (F f : this) {
            hashCode = hashCode * 17 + (f == null ? 0 : f.hashCode());
        }
        return hashCode;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o == this) {
            return true;
        }
        if (!(o instanceof Collection)) {
            return false;
        }
        Collection s = (Collection) o;

        Iterator<?> i = s.iterator();
        for (F f : this) {
            if (!i.hasNext() || !f.equals(i.next())) {
                return false;
            }
        }

        return !i.hasNext();
    }

}