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

org.opencastproject.util.data.Collections Maven / Gradle / Ivy

There is a newer version: 16.6
Show newest version
/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community 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://opensource.org/licenses/ecl2.txt
 *
 * 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.opencastproject.util.data;

import static org.opencastproject.util.data.Option.some;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * This class provides functions to ease and secure the handling of collections by supporting a type safe -- at least to
 * the extent Java's type system allows -- immutable and more functional style.
 *
 * Note that all functions do not mutate input collections unless otherwise stated.
 *
 * @deprecated By now, all of this is natively available in Java.
 */
@Deprecated
public final class Collections {
  private Collections() {
  }

  // TODO check all clients of this method since it potentially breaks!
  @SuppressWarnings("unchecked")
  private static  Collection buildFrom(Collection as) {
    try {
      return as.getClass().newInstance();
    } catch (Exception e) {
      throw new IllegalArgumentException("Type " + as.getClass() + " needs a parameterless constructor");
    }
  }

  /**
   * Apply a function f to all elements of collection as to produce a new collection
   * bs.
   *
   * An (empty) instance of the target collection has to be provided explicitly.
   *
   * @param as
   *          the source collection
   * @param bs
   *          the (empty) target collection
   * @param f
   *          the function to apply to each element of as
   * @deprecated use {@link Monadics}
   */
  @Deprecated
  public static > M map(Collection as, M bs, Function f) {
    for (A x : as) {
      bs.add(f.apply(x));
    }
    return bs;
  }

  /**
   * Apply a function f to all elements of collection as to produce a new collection
   * bs.
   *
   * The type of collection as needs a parameterless constructor.
   *
   * Please note that since java does not support higher-order polymorphism -- which is needed to capture the type of
   * the collection -- some casting on the client side may still be necessary.
   *
   * @throws RuntimeException
   *           if the target collection cannot be created
   * @deprecated use {@link Monadics}
   */
  @Deprecated
  public static  Collection map(Collection as, Function f) {
    Collection b = buildFrom(as);
    for (A x : as) {
      b.add(f.apply(x));
    }
    return b;
  }

  /**
   * Return a new collection containing only the elements that satisfy predicate p.
   *
   * The type of collection as needs a parameterless constructor.
   *
   * @deprecated use {@link Monadics}
   */
  @Deprecated
  public static > M filter(M as, Predicate p) {
    @SuppressWarnings("unchecked")
    final M filtered = (M) buildFrom(as);
    for (A a : as) {
      if (p.apply(a))
        filtered.add(a);
    }
    return filtered;
  }

  /** Return the head of list as or none. */
  public static  Option head(List as) {
    if (!as.isEmpty()) {
      return some(as.get(0));
    } else {
      return Option.none();
    }
  }

  /** Make a string from a collection separating each element by sep. */
  public static String mkString(Collection as, String sep) {
    final StringBuilder b = new StringBuilder();
    for (Object a : as)
      b.append(a).append(sep);
    return b.substring(0, Math.max(b.length() - sep.length(), 0));
  }

  /** Append source collection as to target. */
  public static , S extends Iterable> T appendTo(T target, S as) {
    for (A a : as)
      target.add(a);
    return target;
  }

  /** Append source collections as to target. */
  @SafeVarargs
  public static , S extends Iterable> T appendToM(T target, S... as) {
    for (S s : as) {
      for (A a : s)
        target.add(a);
    }
    return target;
  }

  /** Append source collections as to target. */
  @SafeVarargs
  public static , X extends A> T appendToA(T target, X... as) {
    java.util.Collections.addAll(target, as);
    return target;
  }

  /** Concatenates two iterables into a new list. */
  public static > List concat(M as, M bs) {
    List x = new ArrayList<>();
    for (A a : as)
      x.add(a);
    for (A b : bs)
      x.add(b);
    return x;
  }

  /**
   * Merge two maps where b takes precedence.
   *
   * @return a new immutable map
   */
  public static  Map merge(Map a, Map b) {
    final Map x = new HashMap<>();
    x.putAll(a);
    x.putAll(b);
    return java.util.Collections.unmodifiableMap(x);
  }

  /** Drain all elements of as into a list. */
  public static  List toList(Iterator as) {
    final List t = new ArrayList<>();
    while (as.hasNext()) {
      t.add(as.next());
    }
    return t;
  }

  /** Drain all elements of as into a list. */
  public static  List toList(Collection as) {
    return new ArrayList<>(as);
  }

  /**
   * Return the list as is or nil, if as is null.
   * 
   * @deprecated use {@link #nullToNil(java.util.List)}
   */
  @Deprecated
  public static  List mkList(List as) {
    return as != null ? as : Collections. nil();
  }

  /** Return the list as is or nil, if as is null. */
  public static  List nullToNil(List as) {
    return as != null ? as : Collections. nil();
  }

  /** Create a list from an array. */
  @SafeVarargs
  public static  List list(A... as) {
    final List t = new ArrayList<>();
    java.util.Collections.addAll(t, as);
    return t;
  }

  /** Create a list from an array. */
  @SafeVarargs
  public static  List nonNullList(A... as) {
    final List t = new ArrayList<>();
    for (A a : as) {
      if (null != a) {
        t.add(a);
      }
    }
    return t;
  }

  /** The empty list. */
  @SuppressWarnings("unchecked")
  public static  List nil() {
    return java.util.Collections.EMPTY_LIST;
  }

  /** The empty list. */
  @SuppressWarnings("unchecked")
  public static  List nil(Class type) {
    return java.util.Collections.EMPTY_LIST;
  }

  /** Construct a new list by prepending an element to a given list. */
  public static  List cons(A a, List as) {
    final List target = new ArrayList<>(as.size() + 1);
    target.add(a);
    target.addAll(as);
    return target;
  }

  /** Create a set from an array. */
  @SafeVarargs
  public static  Set set(A... as) {
    final Set t = new HashSet<>(as.length);
    java.util.Collections.addAll(t, as);
    return t;
  }

  /** Create a set from a list. */
  public static  Set toSet(List as) {
    Set r = new HashSet<>(as.size());
    for (A a : as)
      r.add(a);
    return r;
  }

  /** Create a map from a list of tuples (K, V). */
  @SafeVarargs
  public static  Map map(Tuple... ts) {
    final Map map = new HashMap<>(ts.length);
    for (Tuple t : ts) {
      map.put(t.getA(), t.getB());
    }
    return map;
  }

  /** Create a dictionary from a list of tuples (K, V). */
  @SafeVarargs
  public static  Dictionary dict(Tuple... ts) {
    final Dictionary dict = new Hashtable<>(ts.length);
    for (Tuple t : ts) {
      dict.put(t.getA(), t.getB());
    }
    return dict;
  }

  /** Create an array from a collection. */
  @SuppressWarnings("unchecked")
  public static  A[] toArray(Class elemType, Collection a) {
    return a.toArray((A[]) Array.newInstance(elemType, a.size()));
  }

  /** Convert a collection of {@link Double}s into an array of primitive type. */
  public static double[] toDoubleArray(Collection as) {
    final double[] target = new double[as.size()];
    int i = 0;
    for (Double a : as) {
      target[i] = a;
      i++;
    }
    return target;
  }

  /** Create an iterator form an array. */
  @SafeVarargs
  public static  Iterator iterator(final A... as) {
    return new Iterator() {
      private int i = 0;

      @Override
      public boolean hasNext() {
        return as.length > i;
      }

      @Override
      public A next() {
        if (i < as.length) {
          return as[i++];
        } else {
          throw new NoSuchElementException();
        }
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }

  /** Create an iterator that repeats a for the said times. */
  public static  Iterator repeat(final X a, final int times) {
    return new Iterator() {
      private int count = times;

      @Override
      public boolean hasNext() {
        return count > 0;
      }

      @Override
      public A next() {
        count--;
        return a;
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }

  /** Join two iterators. */
  public static  Iterator join(final Iterator a, final Iterator b) {
    return new Iterator() {
      @Override
      public boolean hasNext() {
        return a.hasNext() || b.hasNext();
      }

      @Override
      public A next() {
        return a.hasNext() ? a.next() : b.next();
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }

  /**
   * Make an Iterator usable in a for comprehension like this:
   *
   * 
   *   Iterator<A> as = ...
   *   for (A a : forc(as)) {
   *     ...
   *   }
   * 
*/ public static
Iterable forc(final Iterator as) { return new Iterable() { @Override public Iterator iterator() { return as; } }; } /** Concat (aka flatten) a collection of collections by concatenating them all. [[a]] -> [a] */ public static >> List concat(M as) { final List target = new ArrayList<>(as.size()); for (Collection a : as) { target.addAll(a); } return target; } }