Skip to content

Commit 04221d6

Browse files
committed
Fixing Mappable copy method
1 parent 705c651 commit 04221d6

File tree

3 files changed

+71
-38
lines changed

3 files changed

+71
-38
lines changed

src/main/java/me/croabeast/file/HashMappable.java

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,51 @@
11
package me.croabeast.file;
22

3+
import lombok.Getter;
34
import org.jetbrains.annotations.NotNull;
45

56
import java.util.*;
7+
import java.util.function.Supplier;
68

79
/**
810
* A concrete implementation of {@link Mappable} backed by a {@link HashMap}.
911
* <p>
1012
* {@code HashMappable} associates integer keys with collections of elements of type {@code T}.
1113
* It extends {@code HashMap<Integer, C>} and implements the {@code Mappable} interface, providing
12-
* utility methods for ordering and copying the mapping. This implementation is intended as a base
13-
* class; certain methods (such as {@link #getStoredValues()}) must be overridden in subclasses or
14-
* specific instances to provide concrete functionality.
14+
* utility methods for ordering and copying the mapping. In addition, it stores a {@link Supplier} to
15+
* generate new instances of the collection type {@code C} when needed.
1516
* </p>
1617
*
1718
* @param <T> the type of elements stored in the collections.
1819
* @param <C> the type of collection that holds the elements.
1920
* @see Mappable
2021
*/
22+
@Getter
2123
public class HashMappable<T, C extends Collection<T>> extends HashMap<Integer, C> implements Mappable<T, C, HashMappable<T, C>> {
2224

2325
/**
24-
* Constructs an empty {@code HashMappable}.
26+
* A supplier for creating new instances of the collection type {@code C}.
2527
*/
26-
public HashMappable() {}
28+
private final Supplier<C> supplier;
29+
30+
/**
31+
* Constructs an empty {@code HashMappable} with the specified collection supplier.
32+
*
33+
* @param supplier a {@link Supplier} used to create new collections of type {@code C}; must not be {@code null}
34+
*/
35+
public HashMappable(Supplier<C> supplier) {
36+
super();
37+
this.supplier = Objects.requireNonNull(supplier);
38+
}
2739

2840
/**
2941
* Constructs a new {@code HashMappable} with the mappings copied from the provided map.
3042
*
31-
* @param map the map whose entries are to be placed in this mappable.
43+
* @param supplier a {@link Supplier} used to create new collections of type {@code C}; must not be {@code null}
44+
* @param map the map whose entries are to be placed in this mappable
3245
*/
33-
public HashMappable(Map<Integer, ? extends C> map) {
46+
public HashMappable(Supplier<C> supplier, Map<Integer, ? extends C> map) {
3447
super(map);
48+
this.supplier = Objects.requireNonNull(supplier);
3549
}
3650

3751
/**
@@ -42,49 +56,58 @@ public HashMappable(Map<Integer, ? extends C> map) {
4256
* containing the ordered entries.
4357
* </p>
4458
*
45-
* @param comparator the comparator used for ordering the keys.
46-
* @return a new {@code HashMappable} instance with entries ordered according to the comparator.
59+
* @param comparator the comparator used for ordering the keys; must not be {@code null}
60+
* @return a new {@code HashMappable} instance with entries ordered according to the comparator
4761
*/
4862
@NotNull
4963
public HashMappable<T, C> order(Comparator<Integer> comparator) {
5064
TreeMap<Integer, C> map = new TreeMap<>(comparator);
51-
map.putAll(this);
52-
return new HashMappable<>(map);
65+
forEach((k, v) -> {
66+
C collection = supplier.get();
67+
collection.addAll(v);
68+
map.put(k, collection);
69+
});
70+
return new HashMappable<>(supplier, map);
5371
}
5472

5573
/**
5674
* Creates a shallow copy of this {@code HashMappable}.
5775
* <p>
58-
* The returned copy contains the same keys and values as this instance.
76+
* The returned copy contains the same keys and values as this instance. Note that the collections
77+
* associated with each key are also copied using the supplier, but their elements are not deep-cloned.
5978
* </p>
6079
*
61-
* @return a new {@code HashMappable} instance with the same data.
80+
* @return a new {@code HashMappable} instance with the same data as this instance.
6281
*/
6382
@NotNull
6483
public HashMappable<T, C> copy() {
65-
return new HashMappable<>(this);
84+
HashMappable<T, C> mappable = new HashMappable<>(supplier);
85+
forEach((k, v) -> {
86+
C collection = supplier.get();
87+
collection.addAll(v);
88+
mappable.put(k, collection);
89+
});
90+
return mappable;
6691
}
6792

6893
/**
69-
* Retrieves all stored values combined into a single collection.
94+
* Retrieves all stored values across all keys combined into a single collection.
7095
* <p>
71-
* <b>Note:</b> This method is not implemented in {@code HashMappable} and throws an
72-
* {@link UnsupportedOperationException}. It must be overridden in a subclass or a concrete
73-
* instance to provide the desired behavior.
96+
* This method collects all elements from each collection in the mapping and returns a new collection
97+
* containing all these elements.
7498
* </p>
7599
*
76-
* @return a collection containing all values from the mapping.
77-
* @throws UnsupportedOperationException if this method is not overridden.
100+
* @return a collection containing all values from the mapping
78101
*/
79102
@NotNull
80103
public C getStoredValues() {
81-
throw new UnsupportedOperationException("getStoredValues");
104+
return getStoredValues(supplier);
82105
}
83106

84107
/**
85-
* Returns this instance.
108+
* Returns this instance as a {@code HashMappable}.
86109
*
87-
* @return this {@code HashMappable} instance.
110+
* @return this {@code HashMappable} instance
88111
*/
89112
@NotNull
90113
public HashMappable<T, C> instance() {

src/main/java/me/croabeast/file/MapUtils.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
* </p>
2020
* <ul>
2121
* <li>
22-
* <b>Section-based mappables:</b> for mapping {@link ConfigurationSection} instances,
22+
* <b>Section-based mappable:</b> for mapping {@link ConfigurationSection} instances,
2323
* represented by {@link AbstractSection} and its nested classes {@code SetImpl} and {@code ListImpl}.
2424
* </li>
2525
* <li>
26-
* <b>Unit-based mappables:</b> for mapping configurable units (instances of {@link ConfigurableUnit}),
26+
* <b>Unit-based mappable:</b> for mapping configurable units (instances of {@link ConfigurableUnit}),
2727
* represented by {@link AbstractUnit} and its nested classes {@code SetImpl} and {@code ListImpl}.
2828
* </li>
2929
* </ul>
@@ -43,15 +43,17 @@ static abstract class AbstractMappable<T, C extends Collection<T>, M extends Map
4343
/**
4444
* Creates an empty {@code AbstractMappable}.
4545
*/
46-
AbstractMappable() {}
46+
AbstractMappable() {
47+
super();
48+
}
4749

4850
/**
4951
* Creates a new {@code AbstractMappable} instance and populates it with the given map.
5052
*
5153
* @param map the initial map data; if {@code null} or empty, the mappable will be empty.
5254
*/
5355
AbstractMappable(Map<Integer, ? extends C> map) {
54-
if (map != null && !map.isEmpty()) putAll(map);
56+
super(map == null ? new HashMap<>() : map);
5557
}
5658
}
5759

@@ -138,7 +140,7 @@ public List toList() {
138140
@NotNull
139141
public Set order(Comparator<Integer> comparator) {
140142
TreeMap<Integer, java.util.Set<ConfigurationSection>> map = new TreeMap<>(comparator);
141-
map.putAll(this);
143+
forEach((k, v) -> map.put(k, new HashSet<>(v)));
142144
return new SetImpl(map);
143145
}
144146

@@ -149,7 +151,9 @@ public Set order(Comparator<Integer> comparator) {
149151
*/
150152
@NotNull
151153
public Set copy() {
152-
return new SetImpl(this);
154+
Set set = new SetImpl();
155+
forEach((k, v) -> set.put(k, new HashSet<>(v)));
156+
return set;
153157
}
154158

155159
/**
@@ -219,7 +223,7 @@ public Set toSet() {
219223
@NotNull
220224
public List order(Comparator<Integer> comparator) {
221225
TreeMap<Integer, java.util.List<ConfigurationSection>> map = new TreeMap<>(comparator);
222-
map.putAll(this);
226+
forEach((k, v) -> map.put(k, new ArrayList<>(v)));
223227
return new ListImpl(map);
224228
}
225229

@@ -230,7 +234,9 @@ public List order(Comparator<Integer> comparator) {
230234
*/
231235
@NotNull
232236
public List copy() {
233-
return new ListImpl(this);
237+
List list = new ListImpl();
238+
forEach((k, v) -> list.put(k, new ArrayList<>(v)));
239+
return list;
234240
}
235241

236242
/**
@@ -315,7 +321,7 @@ public List<U> toList() {
315321
@NotNull
316322
public Set<U> order(Comparator<Integer> comparator) {
317323
TreeMap<Integer, java.util.Set<U>> map = new TreeMap<>(comparator);
318-
map.putAll(this);
324+
forEach((k, v) -> map.put(k, new HashSet<>(v)));
319325
return new SetImpl<>(map);
320326
}
321327

@@ -326,7 +332,9 @@ public Set<U> order(Comparator<Integer> comparator) {
326332
*/
327333
@NotNull
328334
public Set<U> copy() {
329-
return new SetImpl<>(this);
335+
Set<U> set = new SetImpl<>();
336+
forEach((k, v) -> set.put(k, new HashSet<>(v)));
337+
return set;
330338
}
331339

332340
/**
@@ -382,7 +390,7 @@ public Set<U> toSet() {
382390
@NotNull
383391
public List<U> order(Comparator<Integer> comparator) {
384392
TreeMap<Integer, java.util.List<U>> map = new TreeMap<>(comparator);
385-
map.putAll(this);
393+
forEach((k, v) -> map.put(k, new ArrayList<>(v)));
386394
return new ListImpl<>(map);
387395
}
388396

@@ -393,7 +401,9 @@ public List<U> order(Comparator<Integer> comparator) {
393401
*/
394402
@NotNull
395403
public List<U> copy() {
396-
return new ListImpl<U>(this);
404+
List<U> list = new ListImpl<>();
405+
forEach((k, v) -> list.put(k, new ArrayList<>(v)));
406+
return list;
397407
}
398408

399409
/**

src/main/java/me/croabeast/file/Mappable.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ default B order(boolean ascendant) {
8383
* Retrieves all stored values merged into a single collection, using the provided supplier to create the collection.
8484
*
8585
* @param supplier The supplier used to create a new collection instance.
86-
* @param <X> The type of the resulting collection.
86+
* @param <V> The type of the resulting collection.
8787
* @return A collection containing all stored values across all keys.
8888
*/
8989
@NotNull
90-
default <X extends Collection<T>> X getStoredValues(Supplier<X> supplier) {
90+
default <V extends Collection<T>> V getStoredValues(Supplier<V> supplier) {
9191
Objects.requireNonNull(supplier);
92-
X collection = supplier.get();
92+
V collection = supplier.get();
9393
values().forEach(collection::addAll);
9494
return collection;
9595
}

0 commit comments

Comments
 (0)