/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco 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 Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.util;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Various common helper methods for Collections. This class is probably only appropriate for use with relatively
* small collections as it has not been optimised for dealing with large collections.
*
* @author Neil Mc Erlean
* @since 2.4.a
*/
// This class should all be moved to core Alfresco whenever possible and reused from there.
public final class RMCollectionUtils
{
private RMCollectionUtils() { /* Intentionally empty. */}
/**
* Gets the list of duplicate elements contained within the specified list, if any.
* @param l the list in which to find duplicates.
* @param <T> the element type of the list.
* @return a list of duplicate elements. If there are no duplicates, returns an empty list.
*/
public static <T> List<T> getDuplicateElements(List<T> l)
{
final Set<T> uniqueElems = new HashSet<>();
final List<T> duplicateElems = new ArrayList<>();
for (T elem: l)
{
if (uniqueElems.contains(elem))
{
if (!duplicateElems.contains(elem)) duplicateElems.add(elem);
}
else
{
uniqueElems.add(elem);
}
}
return duplicateElems;
}
/** Returns the head (element at index 0) of the provided List.
*
* @param l the list whose head is sought.
* @param <T> the type of the List.
* @return the head element or {@code null} for the empty list.
* @throws NullPointerException if l is {@code null}
*/
public static <T> T head(List<T> l)
{
return l.isEmpty() ? null : l.get(0);
}
/**
* Returns the tail of the provided List i.e. the sublist which contains
* all elements of the given list except the {@link #head(List) head}.
*
* @param l the list whose tail is sought.
* @param <T> the type of the List.
* @return the tail sublist, which will be an empty list if the provided list had only a single element.
* @throws NullPointerException if l is {@code null}
* @throws UnsupportedOperationException if the provided list was empty.
*/
public static <T> List<T> tail(List<T> l)
{
if (l.isEmpty())
{
throw new UnsupportedOperationException("Cannot get tail of empty list.");
}
else
{
return l.subList(1, l.size());
}
}
/**
* Returns a Serializable List containing all of the provided elements.
*
* @param elements the elements to put in a list.
* @param <T> the element type.
* @return a Serializable List containing all the provided elements.
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static <T extends Serializable, LIST extends Serializable & List<T>>
LIST asSerializableList(T... elements)
{
final LIST l = (LIST)new ArrayList<T>(elements.length);
for (T element : elements)
{
l.add(element);
}
return l;
}
/**
* Returns a Set containing all of the provided elements. Duplicate elements will be removed as per the
* {@code Set} contract.
*
* @param elements the elements to put in a Set.
* @param <T> the element type.
* @return a Set containing all the provided elements (without duplicates).
*/
@SafeVarargs
public static <T> HashSet<T> asSet(T... elements)
{
final HashSet<T> set = new HashSet<>(elements.length);
for (T element : elements)
{
set.add(element);
}
return set;
}
/**
* Returns a Set containing all of the elements in the provided collection.
* Duplicate elements will be removed as per the
* {@code Set} contract.
*
* @param c the elements to put in a Set.
* @param <T> the element type.
* @return a Set containing all the provided elements (without duplicates).
*/
public static <T> HashSet<T> asSet(Collection<T> c)
{
return new HashSet<>(c);
}
/**
* This enum represents a change in an entry between 2 collections.
*/
public enum Difference
{
ADDED, REMOVED, CHANGED, UNCHANGED
}
/**
* Determines the change in a Map entry between two Maps.
* Note that both maps must have the same types of key-value pair.
*
* @param from the first collection.
* @param to the second collection.
* @param key the key identifying the entry.
* @param <K> the type of the key.
* @param <V> the type of the value.
* @return the {@link Difference}.
*
* @throws IllegalArgumentException if {@code key} is {@code null}.
*/
public static <K, V> Difference diffKey(Map<K, V> from, Map<K, V> to, K key)
{
if (key == null) { throw new IllegalArgumentException("Key cannot be null."); }
if (from.containsKey(key))
{
if (to.containsKey(key))
{
if (nullSafeEquals(from.get(key), to.get(key))) { return Difference.UNCHANGED; }
else { return Difference.CHANGED; }
}
else { return Difference.REMOVED; }
}
else
{
if (to.containsKey(key)) { return Difference.ADDED; }
else { return Difference.UNCHANGED; }
}
}
}