/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2009-2010 Sun Microsystems, Inc. */ package com.forgerock.opendj.util; import java.util.AbstractCollection; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.forgerock.opendj.ldap.Function; /** * Additional {@code Collection} based utility methods. */ public final class Collections2 { private static class TransformedCollection> extends AbstractCollection implements Collection { protected final C collection; protected final Function funcMtoN; protected final Function funcNtoM; protected final P p; protected TransformedCollection(final C collection, final Function funcMtoN, final Function funcNtoM, final P p) { this.collection = collection; this.funcMtoN = funcMtoN; this.funcNtoM = funcNtoM; this.p = p; } /** * {@inheritDoc} */ @Override public boolean add(final N e) { return collection.add(funcNtoM.apply(e, p)); } /** * {@inheritDoc} */ @Override public void clear() { collection.clear(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public boolean contains(final Object o) { final N tmp = (N) o; return collection.contains(funcNtoM.apply(tmp, p)); } /** * {@inheritDoc} */ @Override public boolean isEmpty() { return collection.isEmpty(); } /** * {@inheritDoc} */ @Override public Iterator iterator() { return Iterators.transformedIterator(collection.iterator(), funcMtoN, p); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public boolean remove(final Object o) { final N tmp = (N) o; return collection.remove(funcNtoM.apply(tmp, p)); } /** * {@inheritDoc} */ @Override public int size() { return collection.size(); } } private static final class TransformedList extends TransformedCollection> implements List { private TransformedList(final List list, final Function funcMtoN, final Function funcNtoM, final P p) { super(list, funcMtoN, funcNtoM, p); } /** * {@inheritDoc} */ @Override public void add(final int index, final N element) { collection.add(index, funcNtoM.apply(element, p)); } /** * {@inheritDoc} */ @Override public boolean addAll(final int index, final Collection c) { // We cannot transform c here due to type-safety. boolean result = false; for (final N e : c) { result |= add(e); } return result; } /** * {@inheritDoc} */ @Override public N get(final int index) { return funcMtoN.apply(collection.get(index), p); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public int indexOf(final Object o) { final N tmp = (N) o; return collection.indexOf(funcNtoM.apply(tmp, p)); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") public int lastIndexOf(final Object o) { final N tmp = (N) o; return collection.lastIndexOf(funcNtoM.apply(tmp, p)); } /** * {@inheritDoc} */ @Override public ListIterator listIterator() { return listIterator(0); } /** * {@inheritDoc} */ @Override public ListIterator listIterator(final int index) { final ListIterator iterator = collection.listIterator(index); return new ListIterator() { @Override public void add(final N e) { iterator.add(funcNtoM.apply(e, p)); } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public boolean hasPrevious() { return iterator.hasPrevious(); } @Override public N next() { return funcMtoN.apply(iterator.next(), p); } @Override public int nextIndex() { return iterator.nextIndex(); } @Override public N previous() { return funcMtoN.apply(iterator.previous(), p); } @Override public int previousIndex() { return iterator.previousIndex(); } @Override public void remove() { iterator.remove(); } @Override public void set(final N e) { iterator.set(funcNtoM.apply(e, p)); } }; } /** * {@inheritDoc} */ @Override public N remove(final int index) { return funcMtoN.apply(collection.remove(index), p); } /** * {@inheritDoc} */ @Override public N set(final int index, final N element) { final M result = collection.set(index, funcNtoM.apply(element, p)); return funcMtoN.apply(result, p); } /** * {@inheritDoc} */ @Override public List subList(final int fromIndex, final int toIndex) { final List subList = collection.subList(fromIndex, toIndex); return new TransformedList(subList, funcMtoN, funcNtoM, p); } } /** * Returns a view of {@code collection} whose values have been mapped to * elements of type {@code N} using {@code funcMtoN}. The returned * collection supports all operations. * * @param * The type of elements contained in {@code collection}. * @param * The type of elements contained in the returned collection. * @param

* The type of the additional parameter to the function's * {@code apply} method. Use {@link java.lang.Void} for functions * that do not need an additional parameter. * @param collection * The collection to be transformed. * @param funcMtoN * A function which maps values of type {@code M} to values of * type {@code N}. This function will be used when retrieving * values from {@code collection}. * @param funcNtoM * A function which maps values of type {@code N} to values of * type {@code M}. This function will be used when performing * queries and adding values to {@code collection} . * @param p * A predicate specified parameter. * @return A view of {@code collection} whose values have been mapped to * elements of type {@code N} using {@code funcMtoN}. */ public static Collection transformedCollection(final Collection collection, final Function funcMtoN, final Function funcNtoM, final P p) { return new TransformedCollection>(collection, funcMtoN, funcNtoM, p); } /** * Returns a view of {@code collection} whose values have been mapped to * elements of type {@code N} using {@code funcMtoN}. The returned * collection supports all operations. * * @param * The type of elements contained in {@code collection}. * @param * The type of elements contained in the returned collection. * @param collection * The collection to be transformed. * @param funcMtoN * A function which maps values of type {@code M} to values of * type {@code N}. This function will be used when retrieving * values from {@code collection}. * @param funcNtoM * A function which maps values of type {@code N} to values of * type {@code M}. This function will be used when performing * queries and adding values to {@code collection} . * @return A view of {@code collection} whose values have been mapped to * elements of type {@code N} using {@code funcMtoN}. */ public static Collection transformedCollection(final Collection collection, final Function funcMtoN, final Function funcNtoM) { return new TransformedCollection>(collection, funcMtoN, funcNtoM, null); } /** * Returns a view of {@code list} whose values have been mapped to elements * of type {@code N} using {@code funcMtoN}. The returned list supports all * operations. * * @param * The type of elements contained in {@code list}. * @param * The type of elements contained in the returned list. * @param

* The type of the additional parameter to the function's * {@code apply} method. Use {@link java.lang.Void} for functions * that do not need an additional parameter. * @param list * The list to be transformed. * @param funcMtoN * A function which maps values of type {@code M} to values of * type {@code N}. This function will be used when retrieving * values from {@code list}. * @param funcNtoM * A function which maps values of type {@code N} to values of * type {@code M}. This function will be used when performing * queries and adding values to {@code list} . * @param p * A predicate specified parameter. * @return A view of {@code list} whose values have been mapped to elements * of type {@code N} using {@code funcMtoN}. */ public static List transformedList(final List list, final Function funcMtoN, final Function funcNtoM, final P p) { return new TransformedList(list, funcMtoN, funcNtoM, p); } /** * Returns a view of {@code list} whose values have been mapped to elements * of type {@code N} using {@code funcMtoN}. The returned list supports all * operations. * * @param * The type of elements contained in {@code list}. * @param * The type of elements contained in the returned list. * @param list * The list to be transformed. * @param funcMtoN * A function which maps values of type {@code M} to values of * type {@code N}. This function will be used when retrieving * values from {@code list}. * @param funcNtoM * A function which maps values of type {@code N} to values of * type {@code M}. This function will be used when performing * queries and adding values to {@code list} . * @return A view of {@code list} whose values have been mapped to elements * of type {@code N} using {@code funcMtoN}. */ public static List transformedList(final List list, final Function funcMtoN, final Function funcNtoM) { return new TransformedList(list, funcMtoN, funcNtoM, null); } // Prevent instantiation private Collections2() { // Do nothing. } }