Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2006-2015 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* 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
*
* 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 com.phloc.commons.collections;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.phloc.commons.annotations.ReturnsMutableCopy;
import com.phloc.commons.collections.multimap.AbstractMultiHashMapSetBased;
import com.phloc.commons.id.IHasID;
import com.phloc.commons.name.IHasName;
/**
* This is a helper class for accessing containers with explicit locking
*
* @author Boris Gregorcic
*/
public final class LockedContainerHelper
{
private LockedContainerHelper ()
{
// private
}
/**
* Looks for the map entry with the passed key and return the corresponding
* object
*
* @param aKey
* The key of the object (e.g. ID or name)
* @param aObjectsByKey
* A map containing all available objects mapped to their key
* @param aLock
* The monitor to use
* @return The Object or null if not found
*/
@Nullable
public static T getByKey (final K aKey,
@Nonnull final Map aObjectsByKey,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return aObjectsByKey.get (aKey);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Performs a lookup using
* {@link #getByKey(Object, Map, ReentrantReadWriteLock)} returning the result
* casted according to the requested type
*
* @param aKey
* The key of the object (e.g. ID or name)
* @param aObjectsByKey
* A map containing all available objects mapped to their key
* @param aLock
* The monitor to use
* @return The Object or null if not found
*/
@SuppressWarnings ("unchecked")
public static R getByKeyCasted (final K aKey,
@Nonnull final Map aObjectsByKey,
@Nonnull final ReentrantReadWriteLock aLock)
{
return (R) getByKey (aKey, aObjectsByKey, aLock);
}
/**
* Returns a copy of the passed container performed in a read locked context
*
* @param aObjects
* The container to copy
* @param aLock
* The lock to use
* @return An copy of the container
*/
@ReturnsMutableCopy
public static Collection getCollection (@Nonnull final Collection aObjects,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newSet (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the passed container as a list performed in a read locked
* context
*
* @param aObjects
* The container to copy
* @param aLock
* The lock to use
* @return A list copy of the container
*/
@ReturnsMutableCopy
public static List getList (@Nonnull final Collection aObjects,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newList (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the passed map in a read locked context
*
* @param aObjects
* The map to copy
* @param aLock
* The lock to use
* @return A map copy
*/
@ReturnsMutableCopy
public static Map getMap (@Nonnull final Map aObjects,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newMap (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns the element with the specified index from the passed list in a read
* locked context
*
* @param aObjects
* The list to access
* @param nIndex
* @param aLock
* The lock to use
* @return The element with the specified index or null
*/
public static T get (@Nonnull final List aObjects,
final int nIndex,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
try
{
return aObjects.get (nIndex);
}
catch (final IndexOutOfBoundsException aEx)
{
return null;
}
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the values in the passed map performed in a read locked
* context
*
* @param aObjects
* The map containing the values to retrieve
* @param aLock
* The lock to use
* @return A copy of the map values
*/
@ReturnsMutableCopy
public static Set getValues (@Nonnull final Map aObjects,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newSet (aObjects.values ());
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the keys in the passed map performed in a read locked
* context
*
* @param aObjects
* The map containing the values to retrieve
* @param aLock
* The lock to use
* @return The keys in the passed map
*/
@ReturnsMutableCopy
public static Collection getKeys (@Nonnull final Map aObjects,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
if (aObjects instanceof LinkedHashMap)
{
return ContainerHelper.newList (aObjects.keySet ());
}
return ContainerHelper.newSet (aObjects.keySet ());
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the entry in the passed multi-map corresponding to the
* passed key, performing the access in a read locked context
*
* @param aMap
* The container to copy
* @param aKey
* The map entry key
* @param aLock
* The lock to use
* @return A copy of the entry
*/
@ReturnsMutableCopy
@Nonnull
public static Set getMultiMapEntry (@Nonnull final AbstractMultiHashMapSetBased aMap,
@Nonnull final K aKey,
@Nonnull final ReentrantReadWriteLock aLock)
{
if (aMap == null)
{
throw new NullPointerException ("aMap"); //$NON-NLS-1$
}
aLock.readLock ().lock ();
try
{
return ContainerHelper.newSet (aMap.get (aKey));
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the passed container performed in a read locked context
*
* @param aObjects
* The container to copy
* @param aLock
* The lock to use
* @return An copy of the container
*/
@ReturnsMutableCopy
public static Set getSet (@Nonnull final Set aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newSet (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a copy of the passed ordered container performed in a read locked
* context
*
* @param aObjects
* The container to copy
* @param aLock
* The lock to use
* @return An copy of the container
*/
@ReturnsMutableCopy
public static Set getOrderedSet (@Nonnull final Set aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.newOrderedSet (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Returns a mutable copy of the passed stack performed in a read locked
* context
*
* @param aObjects
* the stack to copy
* @param aLock
* the lock to use
* @return A mutable copied representation of the passed stack
*/
@Nonnull
@ReturnsMutableCopy
public static Stack getStack (@Nonnull final Stack aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
final Stack aCopyStack = new Stack ();
aLock.readLock ().lock ();
try
{
aCopyStack.addAll (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
return aCopyStack;
}
/**
* Performs a simple remove operation of the passed collection using the
* passed object, locking the operation using the passed lock
*
* @param aObjects
* @param aObject
* @param aLock
* @return the boolean result value of the remove operation
*/
public static boolean remove (@Nonnull final Collection aObjects,
@Nonnull final T aObject,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aObject != null)
{
return aObjects.remove (aObject);
}
return false;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Checks if the passed item is contained in the passed collection in a thread
* safe manner
*
* @param aCollection
* @param aItem
* @param aLock
* @return
*/
public static boolean contains (@Nonnull final Collection aCollection,
@Nonnull final T aItem,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aItem != null)
{
return aCollection.contains (aItem);
}
return false;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Checks if all the passed items is contained in the passed collection in a
* thread safe manner
*
* @param aCollection
* @param aItems
* @param aLock
* @return
*/
public static boolean containsAll (@Nullable final Collection aCollection,
@Nonnull final Collection aItems,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aCollection != null)
{
return aCollection.containsAll (aItems);
}
return false;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple clear operation on the passed collection, locking the
* operation using the passed lock
*
* @param aObjects
* @param aLock
*/
public static void clear (@Nonnull final Collection aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
aObjects.clear ();
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple add operation of the passed collection using the passed
* object, locking the operation using the passed lock
*
* @param aObjects
* @param aObject
* @param aLock
* @return the boolean result value of the add operation
*/
public static boolean add (@Nonnull final Collection aObjects,
@Nonnull final T aObject,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aObject != null)
{
return aObjects.add (aObject);
}
return false;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple addAll operation of the passed collection using the
* passed objects, locking the operation using the passed lock
*
* @param aObjects
* @param aObjectsToAdd
* @param aLock
* @return the boolean result value of the add operation
*/
public static boolean addAll (@Nonnull final Collection aObjects,
@Nullable final Collection aObjectsToAdd,
@Nonnull final ReentrantReadWriteLock aLock)
{
if (aObjects != null && aObjectsToAdd != null)
{
aLock.writeLock ().lock ();
try
{
return aObjects.addAll (aObjectsToAdd);
}
finally
{
aLock.writeLock ().unlock ();
}
}
return false;
}
/**
* Performs a simple removeAll operation of the passed collection using the
* passed objects, locking the operation using the passed lock
*
* @param aObjects
* @param aObjectsToRemove
* @param aLock
* @return the boolean result value of the remove operation
*/
public static boolean removeAll (@Nonnull final Collection aObjects,
@Nullable final Collection aObjectsToRemove,
@Nonnull final ReentrantReadWriteLock aLock)
{
if (aObjects != null && aObjectsToRemove != null)
{
aLock.writeLock ().lock ();
try
{
return aObjects.removeAll (aObjectsToRemove);
}
finally
{
aLock.writeLock ().unlock ();
}
}
return false;
}
/**
* Performs a simple put action on a map, locking the operation using the
* passed lock
*
* @param aMap
* @param aKey
* @param aValue
* @param aLock
* @return the usual return value of the underlying map
*/
public static V put (@Nonnull final Map aMap,
@Nonnull final K aKey,
@Nonnull final V aValue,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aMap != null)
{
return aMap.put (aKey, aValue);
}
return null;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Tries to put all entries in the seconds map into the first map
*
* @param aMap
* The main map that should be modified
* @param aEntries
* A map containing the entries that should be put to the first map,
* may be null
* @param aLock
*/
public static void putAll (@Nonnull final Map aMap,
@Nullable final Map aEntries,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aMap != null && aEntries != null)
{
aMap.putAll (aEntries);
}
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple remove action on a map, locking the operation using the
* passed lock
*
* @param aMap
* @param aKey
* @param aLock
* @return the usual return value of the underlying map
*/
public static V remove (@Nonnull final Map aMap,
@Nonnull final K aKey,
@Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
if (aMap != null)
{
return aMap.remove (aKey);
}
return null;
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple clear operation on the passed map, locking the operation
* using the passed lock
*
* @param aObjects
* @param aLock
*/
public static void clear (@Nonnull final Map aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.writeLock ().lock ();
try
{
aObjects.clear ();
}
finally
{
aLock.writeLock ().unlock ();
}
}
/**
* Performs a simple check on the passed collection to see if it is empty,
* locking the operation using the passed lock
*
* @param aObjects
* @param aLock
* @return the boolean result value of the add operation
*/
public static boolean isEmpty (@Nonnull final Collection aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.isEmpty (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Performs a simple check on the passed map to see if it is empty, locking
* the operation using the passed lock
*
* @param aObjects
* @param aLock
* @return the boolean result value of the add operation
*/
public static boolean isEmpty (@Nonnull final Map aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.isEmpty (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* returns the size of the passed map, locking the operation using the passed
* lock
*
* @param aObjects
* @param aLock
* @return the size of the passed map
*/
public static int getSize (@Nonnull final Map aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.getSize (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* returns the size of the passed collection, locking the operation using the
* passed lock
*
* @param aObjects
* @param aLock
* @return the size of the passed map
*/
public static int getSize (@Nonnull final Collection aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.getSize (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* returns the first element of the passed collection, locking the operation
* using the passed lock
*
* @param aObjects
* @param aLock
* @return the first element of the passed collection, or null if
* empty
*/
public static T getFirst (@Nonnull final Collection aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.getFirstElement (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* returns the value of the first entry in the passed map, locking the
* operation using the passed lock
*
* @param aObjects
* @param aLock
* @return the first value of the passed map, or null if empty
*/
public static T getFirstValue (@Nonnull final Map , T> aObjects, @Nonnull final ReentrantReadWriteLock aLock)
{
aLock.readLock ().lock ();
try
{
return ContainerHelper.getFirstValue (aObjects);
}
finally
{
aLock.readLock ().unlock ();
}
}
/**
* Iterates all passed objects and collect their IDs
*
* @param aElements
* Objects for which to collect the IDs, must not be null
* @param aLock
* The lock to use
* @return All IDs (no duplicates)
*/
@Nonnull
public static final Set getIDs (@Nonnull final Collection extends IHasID > aSourceCollection,
@Nullable final ReentrantReadWriteLock aLock)
{
final Set aNames = ContainerHelper.newSet ();
extractIDs (aSourceCollection, aNames, aLock);
return aNames;
}
/**
* Iterates all passed objects and collect their IDs
*
* @param aElements
* Objects for which to collect the IDs, must not be null
* @param aLock
* The lock to use
* @return All IDs in stable order (may contain duplicates)
*/
@Nonnull
public static final List getIDs (@Nonnull final List extends IHasID > aSourceList,
@Nullable final ReentrantReadWriteLock aLock)
{
final List aNames = ContainerHelper.newList ();
extractIDs (aSourceList, aNames, aLock);
return aNames;
}
/**
* Iterates all passed objects and collect their names
*
* @param aElements
* Objects for which to collect the names, must not be
* null
* @param aLock
* The lock to use
* @return All names (no duplicates)
*/
@Nonnull
public static final Set getNames (@Nonnull final Collection extends IHasName> aSourceCollection,
@Nullable final ReentrantReadWriteLock aLock)
{
final Set aNames = ContainerHelper.newSet ();
extractNames (aSourceCollection, aNames, aLock);
return aNames;
}
/**
* Iterates all passed objects and collect their names
*
* @param aElements
* Objects for which to collect the names, must not be
* null
* @param aLock
* The lock to use
* @return All names in stable order (may contain duplicates)
*/
@Nonnull
public static final List getNames (@Nonnull final List extends IHasName> aSourceList,
@Nullable final ReentrantReadWriteLock aLock)
{
final List aNames = ContainerHelper.newList ();
extractNames (aSourceList, aNames, aLock);
return aNames;
}
private static final void extractNames (@Nonnull final Collection extends IHasName> aSource,
@Nonnull final Collection aTarget,
@Nullable final ReentrantReadWriteLock aLock)
{
if (aSource == null)
{
throw new NullPointerException ("aSource"); //$NON-NLS-1$
}
if (aLock != null)
{
aLock.readLock ().lock ();
}
try
{
for (final IHasName aElement : aSource)
{
aTarget.add (aElement.getName ());
}
}
finally
{
if (aLock != null)
{
aLock.readLock ().unlock ();
}
}
}
private static final void extractIDs (@Nonnull final Collection extends IHasID > aSource,
@Nonnull final Collection aTarget,
@Nullable final ReentrantReadWriteLock aLock)
{
if (aSource == null)
{
throw new NullPointerException ("aSource"); //$NON-NLS-1$
}
if (aLock != null)
{
aLock.readLock ().lock ();
}
try
{
for (final IHasID aElement : aSource)
{
aTarget.add (aElement.getID ());
}
}
finally
{
if (aLock != null)
{
aLock.readLock ().unlock ();
}
}
}
}