Skip to content

Commit 862dab1

Browse files
author
Gerald Unterrainer
committed
Merge branch 'develop'
2 parents 403abf0 + 795fa25 commit 862dab1

File tree

7 files changed

+352
-4
lines changed

7 files changed

+352
-4
lines changed

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
<modelVersion>4.0.0</modelVersion>
1212
<artifactId>jre-utils</artifactId>
13-
<version>0.1.12</version>
13+
<version>0.2.0</version>
1414
<name>JreUtils</name>
1515
<packaging>jar</packaging>
1616

@@ -27,6 +27,11 @@
2727
<artifactId>cli-utils</artifactId>
2828
<version>0.2.10</version>
2929
</dependency>
30+
<dependency>
31+
<groupId>org.apache.commons</groupId>
32+
<artifactId>commons-collections4</artifactId>
33+
<version>4.4</version>
34+
</dependency>
3035
</dependencies>
3136

3237
<build>

src/main/java/info/unterrainer/commons/jreutils/Exceptions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class Exceptions {
99

1010
/**
1111
* Swallows any given Exception (checked or unchecked alike) silently.
12-
*
12+
*
1313
* @param runnable the {@link Runnable} that could throw the exception to
1414
* swallow
1515
* @param throwables a List of Exception-types
@@ -25,7 +25,7 @@ public static void swallow(final Runnable runnable, final Class<?>... throwables
2525

2626
/**
2727
* Swallows any given Exception (checked or unchecked alike) silently.
28-
*
28+
*
2929
* @param <T> the return-value of the {@link Supplier}
3030
* @param supplier the {@link Supplier} that could throw the exception to
3131
* swallow
@@ -39,7 +39,7 @@ public static <T> T swallowReturning(final Supplier<T> supplier, final Class<?>.
3939
} catch (Exception throwable) {
4040
boolean swallow = false;
4141
for (Class<?> omit : throwables)
42-
if (omit.getClass().isAssignableFrom(throwable.getClass())) {
42+
if (omit.isAssignableFrom(throwable.getClass())) {
4343
swallow = true;
4444
break;
4545
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package info.unterrainer.commons.jreutils.collections;
2+
3+
import java.util.Collection;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
import java.util.Map.Entry;
7+
import java.util.Set;
8+
9+
import lombok.NoArgsConstructor;
10+
11+
@NoArgsConstructor
12+
public class DataMap<K, V> {
13+
14+
private SizeLimitedHashMap<K, V> map;
15+
16+
public DataMap(final int maxSize) {
17+
map = new SizeLimitedHashMap<>(maxSize);
18+
}
19+
20+
public synchronized DataMap<K, V> put(final K key, final V value) {
21+
map.put(key, value);
22+
return this;
23+
}
24+
25+
public synchronized Collection<V> values() {
26+
return map.values();
27+
}
28+
29+
public synchronized Set<K> keySet() {
30+
return map.keySet();
31+
}
32+
33+
public synchronized Set<Entry<K, V>> entrySet() {
34+
return map.entrySet();
35+
}
36+
37+
public synchronized boolean containsKey(final Object key) {
38+
return map.containsKey(key);
39+
}
40+
41+
public synchronized boolean containsValue(final Object value) {
42+
return map.containsValue(value);
43+
}
44+
45+
public synchronized boolean isEmpty() {
46+
return map.isEmpty();
47+
}
48+
49+
public synchronized void clear() {
50+
map.clear();
51+
}
52+
53+
public synchronized V get(final K key) {
54+
return map.get(key);
55+
}
56+
57+
public synchronized V remove(final K key) {
58+
return map.remove(key);
59+
}
60+
61+
public synchronized int size() {
62+
return map.size();
63+
}
64+
65+
public synchronized Map<K, V> getMapClone() {
66+
return new HashMap<>(map);
67+
}
68+
69+
public synchronized Map<K, V> getMapCloneAndClear() {
70+
Map<K, V> clone;
71+
clone = new HashMap<>(map);
72+
map.clear();
73+
return clone;
74+
}
75+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package info.unterrainer.commons.jreutils.collections;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.List;
6+
7+
import org.apache.commons.collections4.queue.CircularFifoQueue;
8+
9+
public class DataQueue<T> {
10+
11+
private CircularFifoQueue<T> queue;
12+
13+
public DataQueue(final int maxSize) {
14+
this(maxSize, (Collection<T>) null);
15+
}
16+
17+
public DataQueue(final int maxSize, final Collection<T> collection) {
18+
queue = new CircularFifoQueue<>(maxSize);
19+
if (collection != null)
20+
for (T element : collection)
21+
queue.offer(element);
22+
}
23+
24+
public DataQueue(final int maxSize, final T[] array) {
25+
queue = new CircularFifoQueue<>(maxSize);
26+
if (array != null)
27+
for (T element : array)
28+
queue.offer(element);
29+
}
30+
31+
public synchronized DataQueue<T> offer(final T element) {
32+
queue.offer(element);
33+
return this;
34+
}
35+
36+
public synchronized T poll() {
37+
return queue.poll();
38+
}
39+
40+
public synchronized T peek() {
41+
return queue.peek();
42+
}
43+
44+
public synchronized void clear() {
45+
queue.clear();
46+
}
47+
48+
public synchronized List<T> getListClone() {
49+
List<T> list = new ArrayList<>();
50+
list.addAll(queue);
51+
return list;
52+
}
53+
54+
public synchronized List<T> getListCloneAndClear() {
55+
List<T> list = new ArrayList<>();
56+
list.addAll(queue);
57+
queue.clear();
58+
return list;
59+
}
60+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package info.unterrainer.commons.jreutils.collections;
2+
3+
import java.lang.reflect.Array;
4+
import java.util.Collection;
5+
import java.util.HashMap;
6+
import java.util.Set;
7+
import java.util.function.Function;
8+
9+
import lombok.Getter;
10+
import lombok.experimental.Accessors;
11+
12+
@Accessors(fluent = true)
13+
public class DataTable<T> {
14+
15+
private Class<T> clazz;
16+
private int maxEntries;
17+
@Getter
18+
private DataQueue<T> queue;
19+
20+
private HashMap<String, Function<T, Object>> keySuppliers = new HashMap<>();
21+
private HashMap<String, DataMap<Object, T>> maps = new HashMap<>();
22+
23+
public DataTable(final Class<T> clazz, final int maxEntries) {
24+
this.clazz = clazz;
25+
this.maxEntries = maxEntries;
26+
queue = new DataQueue<>(maxEntries);
27+
}
28+
29+
@SuppressWarnings("unchecked")
30+
public <K> DataTable<T> addIndex(final String name, final Function<T, K> keySupplier) {
31+
keySuppliers.put(name, (Function<T, Object>) keySupplier);
32+
maps.put(name, new DataMap<Object, T>(maxEntries));
33+
return this;
34+
}
35+
36+
public synchronized T peek() {
37+
return queue.peek();
38+
}
39+
40+
public synchronized T poll() {
41+
T e = queue.poll();
42+
for (String name : keySuppliers.keySet()) {
43+
Function<T, ?> func = keySuppliers.get(name);
44+
DataMap<Object, T> map = maps.get(name);
45+
map.remove(func.apply(e));
46+
}
47+
return e;
48+
}
49+
50+
public synchronized <K> T get(final String name, final K key) {
51+
return maps.get(name).get(key);
52+
}
53+
54+
public synchronized void add(final T element) {
55+
queue.offer(element);
56+
for (String name : keySuppliers.keySet()) {
57+
Function<T, ?> func = keySuppliers.get(name);
58+
DataMap<Object, T> map = maps.get(name);
59+
Object key = func.apply(element);
60+
map.put(key, element);
61+
}
62+
}
63+
64+
@SuppressWarnings("unchecked")
65+
public synchronized <K> Set<K> keySet(final String name) {
66+
return (Set<K>) maps.get(name).keySet();
67+
}
68+
69+
public synchronized Collection<T> values(final String name) {
70+
return maps.get(name).values();
71+
}
72+
73+
public synchronized boolean containsValue(final String name, final T value) {
74+
return maps.get(name).containsValue(value);
75+
}
76+
77+
public synchronized <K> boolean containsKey(final String name, final K value) {
78+
return maps.get(name).containsKey(value);
79+
}
80+
81+
public synchronized void clear() {
82+
queue.clear();
83+
for (String name : keySuppliers.keySet())
84+
maps.get(name).clear();
85+
}
86+
87+
@SuppressWarnings("unchecked")
88+
public synchronized DataTable<T> load(T[] backingArray) {
89+
if (backingArray == null)
90+
backingArray = (T[]) Array.newInstance(clazz, 0);
91+
92+
queue = new DataQueue<>(maxEntries, backingArray);
93+
94+
for (String name : keySuppliers.keySet()) {
95+
DataMap<Object, T> map = new DataMap<>(maxEntries);
96+
maps.put(name, map);
97+
Function<T, ?> func = keySuppliers.get(name);
98+
for (T s : backingArray)
99+
map.put(func.apply(s), s);
100+
}
101+
return this;
102+
}
103+
104+
@SuppressWarnings("unchecked")
105+
public synchronized T[] toArray() {
106+
T[] zeroArray = (T[]) Array.newInstance(clazz, 0);
107+
return queue.getListClone().toArray(zeroArray);
108+
}
109+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package info.unterrainer.commons.jreutils.collections;
2+
3+
4+
import java.util.LinkedHashMap;
5+
import java.util.Map;
6+
7+
public class SizeLimitedHashMap<K, V> extends LinkedHashMap<K, V> {
8+
private static final long serialVersionUID = 6994714918898609875L;
9+
10+
private final int maxSize;
11+
12+
public SizeLimitedHashMap(final int maxSize) {
13+
this.maxSize = maxSize;
14+
}
15+
16+
@Override
17+
protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
18+
return size() > maxSize;
19+
}
20+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package info.unterrainer.commons.jreutils.collections;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
public class DataTableTests {
8+
9+
@Test
10+
public void peekingWorks() {
11+
DataTable<String> dt = new DataTable<>(String.class, 10);
12+
dt.add("test");
13+
assertThat(dt.peek()).isEqualTo("test");
14+
}
15+
16+
@Test
17+
public void pollingWorks() {
18+
DataTable<String> dt = new DataTable<>(String.class, 10);
19+
dt.add("test");
20+
assertThat(dt.poll()).isEqualTo("test");
21+
}
22+
23+
@Test
24+
public void clearingWorks() {
25+
DataTable<String> dt = new DataTable<>(String.class, 10);
26+
dt.add("test");
27+
dt.clear();
28+
assertThat(dt.peek()).isNull();
29+
assertThat(dt.poll()).isNull();
30+
}
31+
32+
@Test
33+
public void addingIndexWorks() {
34+
DataTable<String> dt = new DataTable<>(String.class, 10);
35+
dt.addIndex("index1", e -> e);
36+
}
37+
38+
@Test
39+
public void addingWorksWithIndex() {
40+
DataTable<String> dt = new DataTable<>(String.class, 10);
41+
dt.addIndex("index1", e -> e);
42+
dt.add("test");
43+
assertThat(dt.get("index1", "test")).isEqualTo("test");
44+
}
45+
46+
@Test
47+
public void addingWorksWithTwoIndexes() {
48+
DataTable<String> dt = new DataTable<>(String.class, 10);
49+
dt.addIndex("index1", e -> e);
50+
dt.addIndex("index2", e -> e);
51+
dt.add("test");
52+
assertThat(dt.get("index1", "test")).isEqualTo("test");
53+
assertThat(dt.get("index2", "test")).isEqualTo("test");
54+
}
55+
56+
@Test
57+
public void deletingFromQueueAlsoDeletesFromAllIndexes() {
58+
DataTable<String> dt = new DataTable<>(String.class, 10);
59+
dt.addIndex("index1", e -> e);
60+
dt.addIndex("index2", e -> e);
61+
dt.add("test");
62+
dt.poll();
63+
assertThat(dt.get("index1", "test")).isNull();
64+
assertThat(dt.get("index2", "test")).isNull();
65+
}
66+
67+
@Test
68+
public void clearingWorksWithTwoIndexes() {
69+
DataTable<String> dt = new DataTable<>(String.class, 10);
70+
dt.addIndex("index1", e -> e);
71+
dt.addIndex("index2", e -> e);
72+
dt.add("test");
73+
dt.clear();
74+
assertThat(dt.peek()).isNull();
75+
assertThat(dt.poll()).isNull();
76+
assertThat(dt.get("index1", "test")).isNull();
77+
assertThat(dt.get("index2", "test")).isNull();
78+
}
79+
}

0 commit comments

Comments
 (0)