AbstractSetValuedMap.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.collections4.multimap;

  18. import java.util.Collections;
  19. import java.util.Map;
  20. import java.util.Set;

  21. import org.apache.commons.collections4.SetUtils;
  22. import org.apache.commons.collections4.SetValuedMap;

  23. /**
  24.  * Abstract implementation of the {@link SetValuedMap} interface to simplify the
  25.  * creation of subclass implementations.
  26.  * <p>
  27.  * Subclasses specify a Map implementation to use as the internal storage and
  28.  * the Set implementation to use as values.
  29.  * </p>
  30.  *
  31.  * @param <K> the type of the keys in this map
  32.  * @param <V> the type of the values in this map
  33.  * @since 4.1
  34.  */
  35. public abstract class AbstractSetValuedMap<K, V> extends AbstractMultiValuedMap<K, V>
  36.     implements SetValuedMap<K, V> {

  37.     /**
  38.      * Wrapped set to handle add and remove on the collection returned by
  39.      * {@code get(Object)}.
  40.      */
  41.     private final class WrappedSet extends WrappedCollection implements Set<V> {

  42.         WrappedSet(final K key) {
  43.             super(key);
  44.         }

  45.         @Override
  46.         public boolean equals(final Object other) {
  47.             final Set<V> set = (Set<V>) getMapping();
  48.             if (set == null) {
  49.                 return Collections.emptySet().equals(other);
  50.             }
  51.             if (!(other instanceof Set)) {
  52.                 return false;
  53.             }
  54.             final Set<?> otherSet = (Set<?>) other;
  55.             return SetUtils.isEqualSet(set, otherSet);
  56.         }

  57.         @Override
  58.         public int hashCode() {
  59.             final Set<V> set = (Set<V>) getMapping();
  60.             return SetUtils.hashCodeForSet(set);
  61.         }

  62.     }

  63.     /**
  64.      * Constructor needed for subclass serialization.
  65.      */
  66.     protected AbstractSetValuedMap() {
  67.     }

  68.     /**
  69.      * A constructor that wraps, not copies
  70.      *
  71.      * @param map  the map to wrap, must not be null
  72.      * @throws NullPointerException if the map is null
  73.      */
  74.     protected AbstractSetValuedMap(final Map<K, ? extends Set<V>> map) {
  75.         super(map);
  76.     }

  77.     /**
  78.      * Creates a new value collection using the provided factory.
  79.      * @return a new set
  80.      */
  81.     @Override
  82.     protected abstract Set<V> createCollection();

  83.     /**
  84.      * Gets the set of values associated with the specified key. This would
  85.      * return an empty set in case the mapping is not present
  86.      *
  87.      * @param key  the key to retrieve
  88.      * @return the {@code Set} of values, will return an empty
  89.      *   {@code Set} for no mapping
  90.      */
  91.     @Override
  92.     public Set<V> get(final K key) {
  93.         return wrappedCollection(key);
  94.     }

  95.     @Override
  96.     @SuppressWarnings("unchecked")
  97.     protected Map<K, Set<V>> getMap() {
  98.         return (Map<K, Set<V>>) super.getMap();
  99.     }

  100.     /**
  101.      * Removes all values associated with the specified key.
  102.      * <p>
  103.      * A subsequent {@code get(Object)} would return an empty set.
  104.      * </p>
  105.      *
  106.      * @param key the key to remove values from
  107.      * @return the {@code Set} of values removed, will return an empty,
  108.      *   unmodifiable set for no mapping found.
  109.      */
  110.     @Override
  111.     public Set<V> remove(final Object key) {
  112.         return SetUtils.emptyIfNull(getMap().remove(key));
  113.     }

  114.     @Override
  115.     Set<V> wrappedCollection(final K key) {
  116.         return new WrappedSet(key);
  117.     }
  118. }