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.Collection;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.CopyOnWriteArraySet;
37 import java.util.function.BiConsumer;
38 import java.io.Serializable;
39 import it.tidalwave.util.Key;
40 import it.tidalwave.util.NotFoundException;
41 import it.tidalwave.util.TypeSafeMap;
42 import lombok.EqualsAndHashCode;
43
44 /***************************************************************************************************************************************************************
45 *
46 * An implementation of {@link TypeSafeMap}. This class is not part of the public API.
47 *
48 * @author Fabrizio Giudici
49 *
50 **************************************************************************************************************************************************************/
51 @Immutable @EqualsAndHashCode
52 public class TypeSafeHashMap implements TypeSafeMap, Serializable
53 {
54 private static final long serialVersionUID = 564564576856746L;
55
56 @Nonnull
57 private final Map<Key<?>, Object> map;
58
59 /***********************************************************************************************************************************************************
60 * Creates a new instance from the given contents.
61 *
62 * @param map the contents
63 **********************************************************************************************************************************************************/
64 public TypeSafeHashMap (@Nonnull final Map<? extends Key<?>, Object> map)
65 {
66 this(new HashMap<>(), false);
67 this.map.putAll(map);
68 }
69
70 /***********************************************************************************************************************************************************
71 *
72 **********************************************************************************************************************************************************/
73 /* package */ TypeSafeHashMap (@Nonnull final Map<Key<?>, Object> map, final boolean ignored)
74 {
75 this.map = map;
76 }
77
78 /***********************************************************************************************************************************************************
79 * {@inheritDoc}
80 **********************************************************************************************************************************************************/
81 @Override @Nonnull
82 public <T> T get (@Nonnull final Key<T> key)
83 throws NotFoundException
84 {
85 return NotFoundException.throwWhenNull(key.getType().cast(map.get(key)), "not found: %s", key);
86 }
87
88 /***********************************************************************************************************************************************************
89 * {@inheritDoc}
90 **********************************************************************************************************************************************************/
91 @Override
92 public boolean containsKey (@Nonnull final Key<?> key)
93 {
94 return map.containsKey(key);
95 }
96
97 /***********************************************************************************************************************************************************
98 * {@inheritDoc}
99 **********************************************************************************************************************************************************/
100 @Override @Nonnull
101 public <T> TypeSafeMap with (@Nonnull final Key<T> key, @Nonnull final T value)
102 {
103 final var map = asMap();
104 map.put(key, value);
105 return new TypeSafeHashMap(map, true);
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<Object> values()
122 {
123 return map.values();
124 }
125
126 /***********************************************************************************************************************************************************
127 * {@inheritDoc}
128 **********************************************************************************************************************************************************/
129 @Override @Nonnull
130 public Set<Map.Entry<Key<?>, Object>> entrySet()
131 {
132 return map.entrySet();
133 }
134
135 /***********************************************************************************************************************************************************
136 * {@inheritDoc}
137 **********************************************************************************************************************************************************/
138 @Override @Nonnegative
139 public int size()
140 {
141 return map.size();
142 }
143
144 /***********************************************************************************************************************************************************
145 * {@inheritDoc}
146 **********************************************************************************************************************************************************/
147 @Override @Nonnull
148 public Iterator<Map.Entry<Key<?>, Object>> iterator()
149 {
150 return map.entrySet().iterator();
151 }
152
153 /***********************************************************************************************************************************************************
154 * {@inheritDoc}
155 **********************************************************************************************************************************************************/
156 @Override @Nonnull
157 public Map<Key<?>, Object> 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 T> action)
167 {
168 map.forEach((BiConsumer<? super Key<?>, ? super Object>)action);
169 }
170
171 /***********************************************************************************************************************************************************
172 * {@inheritDoc}
173 **********************************************************************************************************************************************************/
174 @Override @Nonnull
175 public String toString()
176 {
177 return map.toString();
178 }
179 }