TypeSafeHashMultiMap.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  23.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.util.impl;

  28. import javax.annotation.Nonnegative;
  29. import javax.annotation.Nonnull;
  30. import javax.annotation.concurrent.Immutable;
  31. import java.util.ArrayList;
  32. import java.util.Collection;
  33. import java.util.HashMap;
  34. import java.util.Iterator;
  35. import java.util.Map;
  36. import java.util.Set;
  37. import java.util.concurrent.CopyOnWriteArrayList;
  38. import java.util.concurrent.CopyOnWriteArraySet;
  39. import java.util.function.BiConsumer;
  40. import java.io.Serializable;
  41. import it.tidalwave.util.Key;
  42. import it.tidalwave.util.TypeSafeMultiMap;
  43. import lombok.EqualsAndHashCode;

  44. /***********************************************************************************************************************
  45.  *
  46.  * @author  Fabrizio Giudici
  47.  *
  48.  **********************************************************************************************************************/
  49. @Immutable @EqualsAndHashCode
  50. public class TypeSafeHashMultiMap implements TypeSafeMultiMap, Serializable
  51.   {
  52.     private static final long serialVersionUID = 759233572056L;

  53.     @Nonnull
  54.     private final Map<Key<?>, Collection<?>> map;

  55.     /*******************************************************************************************************************
  56.      *
  57.      * Creates a new instance from the given contents.
  58.      *
  59.      * @param   map   the contents
  60.      *
  61.      ******************************************************************************************************************/
  62.     public TypeSafeHashMultiMap (@Nonnull final Map<? extends Key<?>, ? extends Collection<?>> map)
  63.       {
  64.         this(new HashMap<>(), true);
  65.         this.map.putAll(map);
  66.       }

  67.     /*******************************************************************************************************************
  68.      *
  69.      *
  70.      ******************************************************************************************************************/
  71.     /* package */ TypeSafeHashMultiMap (@Nonnull final Map<Key<?>, Collection<?>> map, final boolean dummy)
  72.       {
  73.         this.map = map;
  74.       }

  75.     /*******************************************************************************************************************
  76.      *
  77.      * {@inheritDoc}
  78.      *
  79.      ******************************************************************************************************************/
  80.     @Override @Nonnull @SuppressWarnings("unchecked")
  81.     public <T> Collection<T> get (@Nonnull final Key<T> key)
  82.       {
  83.         return containsKey(key) ? new CopyOnWriteArrayList<>((Collection<T>)map.get(key))
  84.                                 : new ArrayList<>();
  85.       }

  86.     /*******************************************************************************************************************
  87.      *
  88.      * {@inheritDoc}
  89.      *
  90.      ******************************************************************************************************************/
  91.     @Override
  92.     public boolean containsKey (@Nonnull final Key<?> key)
  93.       {
  94.         return map.containsKey(key);
  95.       }

  96.     /*******************************************************************************************************************
  97.      *
  98.      * {@inheritDoc}
  99.      *
  100.      ******************************************************************************************************************/
  101.     @Override @Nonnull
  102.     public <T> TypeSafeHashMultiMap with (@Nonnull final Key<T> key, @Nonnull final T value)
  103.       {
  104.         final var map = asMap();
  105.         final var values = get(key);
  106.         values.add(value);
  107.         map.put(key, values);
  108.         return new TypeSafeHashMultiMap(map);
  109.       }

  110.     /*******************************************************************************************************************
  111.      *
  112.      * {@inheritDoc}
  113.      *
  114.      ******************************************************************************************************************/
  115.     @Override @Nonnull
  116.     public Set<Key<?>> keySet()
  117.       {
  118.         return new CopyOnWriteArraySet<>(map.keySet());
  119.       }

  120.     /*******************************************************************************************************************
  121.      *
  122.      * {@inheritDoc}
  123.      *
  124.      ******************************************************************************************************************/
  125.     @Override @Nonnull
  126.     public Collection<Collection<?>> values()
  127.       {
  128.         return map.values();
  129.       }

  130.     /*******************************************************************************************************************
  131.      *
  132.      * {@inheritDoc}
  133.      *
  134.      ******************************************************************************************************************/
  135.     @Override @Nonnull
  136.     public Set<Map.Entry<Key<?>, Collection<?>>> entrySet()
  137.       {
  138.         return map.entrySet();
  139.       }

  140.     /*******************************************************************************************************************
  141.      *
  142.      * {@inheritDoc}
  143.      *
  144.      ******************************************************************************************************************/
  145.     @Override @Nonnull
  146.     public Iterator<Map.Entry<Key<?>, Collection<?>>> iterator()
  147.       {
  148.         return map.entrySet().iterator();
  149.       }

  150.     /*******************************************************************************************************************
  151.      *
  152.      * {@inheritDoc}
  153.      *
  154.      ******************************************************************************************************************/
  155.     @Override @Nonnegative
  156.     public int size()
  157.       {
  158.         return map.size();
  159.       }

  160.     /*******************************************************************************************************************
  161.      *
  162.      * {@inheritDoc}
  163.      *
  164.      ******************************************************************************************************************/
  165.     @Override @Nonnull
  166.     public Map<Key<?>, Collection<?>> asMap()
  167.       {
  168.         return new HashMap<>(map);
  169.       }

  170.     /*******************************************************************************************************************
  171.      *
  172.      * {@inheritDoc}
  173.      *
  174.      ******************************************************************************************************************/
  175.     @Override
  176.     public void forEach (@Nonnull final BiConsumer<? super Key<?>, ? super Collection<?>> action)
  177.       {
  178.         map.forEach(action);
  179.       }

  180.     /*******************************************************************************************************************
  181.      *
  182.      * {@inheritDoc}
  183.      *
  184.      ******************************************************************************************************************/
  185.     @Override @Nonnull
  186.     public String toString()
  187.       {
  188.         return map.toString();
  189.       }
  190.   }