View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * TheseFoolishThings: Miscellaneous utilities
5    * http://tidalwave.it/projects/thesefoolishthings
6    *
7    * Copyright (C) 2009 - 2025 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 the License.
12   * 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 an "AS IS" BASIS, WITHOUT WARRANTIES OR
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22   * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.util.impl;
27  
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   *
47   * @author  Fabrizio Giudici
48   *
49   **************************************************************************************************************************************************************/
50  @Immutable @EqualsAndHashCode
51  public class TypeSafeHashMultiMap implements TypeSafeMultiMap, Serializable
52    {
53      private static final long serialVersionUID = 759233572056L;
54  
55      @Nonnull
56      private final Map<Key<?>, Collection<?>> map;
57  
58      /***********************************************************************************************************************************************************
59       * Creates a new instance from the given contents.
60       *
61       * @param   map   the contents
62       **********************************************************************************************************************************************************/
63      public TypeSafeHashMultiMap (@Nonnull final Map<? extends Key<?>, ? extends Collection<?>> map)
64        {
65          this(new HashMap<>(), true);
66          this.map.putAll(map);
67        }
68  
69      /***********************************************************************************************************************************************************
70       **********************************************************************************************************************************************************/
71      /* package */ TypeSafeHashMultiMap (@Nonnull final Map<Key<?>, Collection<?>> map, final boolean ignored)
72        {
73          this.map = map;
74        }
75  
76      /***********************************************************************************************************************************************************
77       * {@inheritDoc}
78       **********************************************************************************************************************************************************/
79      @Override @Nonnull @SuppressWarnings("unchecked")
80      public <T> Collection<T> get (@Nonnull final Key<T> key)
81        {
82          return containsKey(key) ? new CopyOnWriteArrayList<>((Collection<T>)map.get(key))
83                                  : new ArrayList<>();
84        }
85  
86      /***********************************************************************************************************************************************************
87       * {@inheritDoc}
88       **********************************************************************************************************************************************************/
89      @Override
90      public boolean containsKey (@Nonnull final Key<?> key)
91        {
92          return map.containsKey(key);
93        }
94  
95      /***********************************************************************************************************************************************************
96       * {@inheritDoc}
97       **********************************************************************************************************************************************************/
98      @Override @Nonnull
99      public <T> TypeSafeHashMultiMap with (@Nonnull final Key<T> key, @Nonnull final T value)
100       {
101         final var map = asMap();
102         final var values = get(key);
103         values.add(value);
104         map.put(key, values);
105         return new TypeSafeHashMultiMap(map);
106       }
107 
108     /***********************************************************************************************************************************************************
109      * {@inheritDoc}
110      **********************************************************************************************************************************************************/
111     @Override @Nonnull
112     public Set<Key<?>> keySet()
113       {
114         return new CopyOnWriteArraySet<>(map.keySet());
115       }
116 
117     /***********************************************************************************************************************************************************
118      * {@inheritDoc}
119      **********************************************************************************************************************************************************/
120     @Override @Nonnull
121     public Collection<Collection<?>> values()
122       {
123         return map.values();
124       }
125 
126     /***********************************************************************************************************************************************************
127      * {@inheritDoc}
128      **********************************************************************************************************************************************************/
129     @Override @Nonnull
130     public Set<Map.Entry<Key<?>, Collection<?>>> entrySet()
131       {
132         return map.entrySet();
133       }
134 
135     /***********************************************************************************************************************************************************
136      * {@inheritDoc}
137      **********************************************************************************************************************************************************/
138     @Override @Nonnull
139     public Iterator<Map.Entry<Key<?>, Collection<?>>> iterator()
140       {
141         return map.entrySet().iterator();
142       }
143 
144     /***********************************************************************************************************************************************************
145      * {@inheritDoc}
146      **********************************************************************************************************************************************************/
147     @Override @Nonnegative
148     public int size()
149       {
150         return map.size();
151       }
152 
153     /***********************************************************************************************************************************************************
154      * {@inheritDoc}
155      **********************************************************************************************************************************************************/
156     @Override @Nonnull
157     public Map<Key<?>, Collection<?>> asMap()
158       {
159         return new HashMap<>(map);
160       }
161 
162     /***********************************************************************************************************************************************************
163      * {@inheritDoc}
164      **********************************************************************************************************************************************************/
165     @Override @SuppressWarnings("unchecked")
166     public <T> void forEach (@Nonnull final BiConsumer<? super Key<T>, ? super Collection<T>> action)
167       {
168         map.forEach((BiConsumer<? super Key<?>, ? super Collection<?>>)action);
169       }
170 
171     /***********************************************************************************************************************************************************
172      * {@inheritDoc}
173      **********************************************************************************************************************************************************/
174     @Override @Nonnull
175     public String toString()
176       {
177         return map.toString();
178       }
179   }