· 8 years ago · Jun 17, 2018, 08:42 AM
1/*
2 * File : IndexedMap.java
3 * Last Modified: 20180614-18:37:19-0400
4 *
5 * Copyright (c) 2018 srs_bsns (forfrdm [at] gmail.com)
6 *
7 * The MIT License (MIT)
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28package srscode.storage.map;
29
30import java.io.Serializable;
31import java.util.Map;
32import java.util.Objects;
33import java.util.function.Function;
34import javax.annotation.Nonnull;
35import javax.annotation.Nullable;
36
37
38public interface IndexedMap<K, V, I extends Comparable<I>> extends Map<K, V>, Serializable
39{
40 boolean isStrict();
41
42 boolean isMutable();
43
44 boolean areEntriesMutable();
45
46 Function<K, I> getIndexer();
47
48 I getIndex(@Nonnull K key);
49
50 @Nullable
51 V putAt(@Nonnull K key, @Nonnull V value, @Nullable I index);
52
53 @Nullable
54 K getKeyAt(I index);
55
56 @Nullable
57 V getValueAt(I index);
58
59 @Nullable
60 V remove(I index);
61
62 interface LimitedIndexedMap<K, V, I extends Comparable<I>> extends IndexedMap<K, V, I>
63 {
64 int getCapacity();
65
66 default boolean checkBounds(int index)
67 {
68 if (index < 0 || index >= getCapacity())
69 {
70 if (isStrict()) { throw new IndexOutOfBoundsException("Index is out of bounds for map entry: " + index); }
71 return true;
72 }
73 return false;
74 }
75
76 interface ByteLIMap <K, V> extends LimitedIndexedMap<K, V, Byte> {}
77 interface ShortLIMap <K, V> extends LimitedIndexedMap<K, V, Short> {}
78 interface IntegerLIMap<K, V> extends LimitedIndexedMap<K, V, Integer> {}
79 interface LongLIMap <K, V> extends LimitedIndexedMap<K, V, Long> {}
80 }
81
82 interface IndexMapEntry<K, V, I extends Comparable<I>> extends Entry<K, V>, Comparable<IndexMapEntry<K, V, I>>, Serializable
83 {
84 I getIndex();
85
86 // default comparison of only the index
87 @Override
88 default int compareTo(@Nonnull final IndexMapEntry<K, V, I> other)
89 {
90 return getIndex().compareTo(other.getIndex());
91 }
92
93 abstract class IndexEntryBase<K, V, I extends Comparable<I>> implements IndexMapEntry<K, V, I>
94 {
95 private static final long serialVersionUID = -5154097056428766455L;
96
97 private final K key;
98 private V value;
99 private final I index;
100
101 IndexEntryBase(@Nonnull final K key, @Nonnull final V value, @Nonnull final I index)
102 {
103 this.key = key;
104 this.value = value;
105 this.index = index;
106 }
107
108 @Override
109 public K getKey() { return key; }
110
111 @Override
112 public V getValue() { return value; }
113
114 @Override
115 public I getIndex() { return index; }
116
117 V putValue(@Nonnull final V newValue)
118 {
119 V oldValue = getValue();
120 value = newValue;
121 return oldValue;
122 }
123
124 @Override
125 public boolean equals(final Object o)
126 {
127 if (this == o) { return true; }
128 if (!(o instanceof IndexMapEntry.IndexEntryBase)) { return false; }
129 IndexEntryBase<?, ?, ?> other = (IndexEntryBase<?, ?, ?>) o;
130 return Objects.equals(getKey(), other.getKey())
131 && Objects.equals(getValue(), other.getValue())
132 && Objects.equals(getIndex(), other.getIndex());
133 }
134
135 @Override
136 public int hashCode()
137 {
138 return getIndex().hashCode() ^ getKey().hashCode() ^ getValue().hashCode();
139 }
140
141 @Override
142 public String toString() {
143 return getClass().getSimpleName() + "[" + getIndex() + "[" + getKey() + "=" + getValue() + "]]";
144 }
145
146
147 public static class SimpleMutableIndexEntry<K, V, I extends Comparable<I>> extends IndexEntryBase<K, V, I>
148 {
149 private static final long serialVersionUID = -2225795238508933466L;
150
151 public SimpleMutableIndexEntry(@Nonnull final K key, @Nonnull final V value, @Nonnull final I index)
152 {
153 super(key, value, index);
154 }
155
156 public SimpleMutableIndexEntry(@Nonnull final K key, @Nonnull final V value, @Nonnull final Function<K, I> indexer)
157 {
158 super(key, value, indexer.apply(key));
159 }
160
161 @Override
162 public V setValue(@Nonnull final V newValue)
163 {
164 return putValue(newValue);
165 }
166 }
167
168 public static class SimpleImmutableIndexEntry<K, V, I extends Comparable<I>> extends IndexEntryBase<K, V, I>
169 {
170 private static final long serialVersionUID = 2533506876382702762L;
171
172 public SimpleImmutableIndexEntry(@Nonnull final K key, @Nonnull final V value, @Nonnull final I index)
173 {
174 super(key, value, index);
175 }
176
177 public SimpleImmutableIndexEntry(@Nonnull final K key, @Nonnull final V value, @Nonnull final Function<K, I> indexer)
178 {
179 super(key, value, indexer.apply(key));
180 }
181
182 @Override
183 public V setValue(@Nonnull final V newValue)
184 {
185 throw new UnsupportedOperationException("Immutable data");
186 }
187 }
188 }
189 }
190}