Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerald Unterrainer committed Jul 12, 2021
2 parents 403abf0 + 795fa25 commit 862dab1
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 4 deletions.
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<modelVersion>4.0.0</modelVersion>
<artifactId>jre-utils</artifactId>
<version>0.1.12</version>
<version>0.2.0</version>
<name>JreUtils</name>
<packaging>jar</packaging>

Expand All @@ -27,6 +27,11 @@
<artifactId>cli-utils</artifactId>
<version>0.2.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class Exceptions {

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

/**
* Swallows any given Exception (checked or unchecked alike) silently.
*
*
* @param <T> the return-value of the {@link Supplier}
* @param supplier the {@link Supplier} that could throw the exception to
* swallow
Expand All @@ -39,7 +39,7 @@ public static <T> T swallowReturning(final Supplier<T> supplier, final Class<?>.
} catch (Exception throwable) {
boolean swallow = false;
for (Class<?> omit : throwables)
if (omit.getClass().isAssignableFrom(throwable.getClass())) {
if (omit.isAssignableFrom(throwable.getClass())) {
swallow = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package info.unterrainer.commons.jreutils.collections;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import lombok.NoArgsConstructor;

@NoArgsConstructor
public class DataMap<K, V> {

private SizeLimitedHashMap<K, V> map;

public DataMap(final int maxSize) {
map = new SizeLimitedHashMap<>(maxSize);
}

public synchronized DataMap<K, V> put(final K key, final V value) {
map.put(key, value);
return this;
}

public synchronized Collection<V> values() {
return map.values();
}

public synchronized Set<K> keySet() {
return map.keySet();
}

public synchronized Set<Entry<K, V>> entrySet() {
return map.entrySet();
}

public synchronized boolean containsKey(final Object key) {
return map.containsKey(key);
}

public synchronized boolean containsValue(final Object value) {
return map.containsValue(value);
}

public synchronized boolean isEmpty() {
return map.isEmpty();
}

public synchronized void clear() {
map.clear();
}

public synchronized V get(final K key) {
return map.get(key);
}

public synchronized V remove(final K key) {
return map.remove(key);
}

public synchronized int size() {
return map.size();
}

public synchronized Map<K, V> getMapClone() {
return new HashMap<>(map);
}

public synchronized Map<K, V> getMapCloneAndClear() {
Map<K, V> clone;
clone = new HashMap<>(map);
map.clear();
return clone;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package info.unterrainer.commons.jreutils.collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.collections4.queue.CircularFifoQueue;

public class DataQueue<T> {

private CircularFifoQueue<T> queue;

public DataQueue(final int maxSize) {
this(maxSize, (Collection<T>) null);
}

public DataQueue(final int maxSize, final Collection<T> collection) {
queue = new CircularFifoQueue<>(maxSize);
if (collection != null)
for (T element : collection)
queue.offer(element);
}

public DataQueue(final int maxSize, final T[] array) {
queue = new CircularFifoQueue<>(maxSize);
if (array != null)
for (T element : array)
queue.offer(element);
}

public synchronized DataQueue<T> offer(final T element) {
queue.offer(element);
return this;
}

public synchronized T poll() {
return queue.poll();
}

public synchronized T peek() {
return queue.peek();
}

public synchronized void clear() {
queue.clear();
}

public synchronized List<T> getListClone() {
List<T> list = new ArrayList<>();
list.addAll(queue);
return list;
}

public synchronized List<T> getListCloneAndClear() {
List<T> list = new ArrayList<>();
list.addAll(queue);
queue.clear();
return list;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package info.unterrainer.commons.jreutils.collections;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Function;

import lombok.Getter;
import lombok.experimental.Accessors;

@Accessors(fluent = true)
public class DataTable<T> {

private Class<T> clazz;
private int maxEntries;
@Getter
private DataQueue<T> queue;

private HashMap<String, Function<T, Object>> keySuppliers = new HashMap<>();
private HashMap<String, DataMap<Object, T>> maps = new HashMap<>();

public DataTable(final Class<T> clazz, final int maxEntries) {
this.clazz = clazz;
this.maxEntries = maxEntries;
queue = new DataQueue<>(maxEntries);
}

@SuppressWarnings("unchecked")
public <K> DataTable<T> addIndex(final String name, final Function<T, K> keySupplier) {
keySuppliers.put(name, (Function<T, Object>) keySupplier);
maps.put(name, new DataMap<Object, T>(maxEntries));
return this;
}

public synchronized T peek() {
return queue.peek();
}

public synchronized T poll() {
T e = queue.poll();
for (String name : keySuppliers.keySet()) {
Function<T, ?> func = keySuppliers.get(name);
DataMap<Object, T> map = maps.get(name);
map.remove(func.apply(e));
}
return e;
}

public synchronized <K> T get(final String name, final K key) {
return maps.get(name).get(key);
}

public synchronized void add(final T element) {
queue.offer(element);
for (String name : keySuppliers.keySet()) {
Function<T, ?> func = keySuppliers.get(name);
DataMap<Object, T> map = maps.get(name);
Object key = func.apply(element);
map.put(key, element);
}
}

@SuppressWarnings("unchecked")
public synchronized <K> Set<K> keySet(final String name) {
return (Set<K>) maps.get(name).keySet();
}

public synchronized Collection<T> values(final String name) {
return maps.get(name).values();
}

public synchronized boolean containsValue(final String name, final T value) {
return maps.get(name).containsValue(value);
}

public synchronized <K> boolean containsKey(final String name, final K value) {
return maps.get(name).containsKey(value);
}

public synchronized void clear() {
queue.clear();
for (String name : keySuppliers.keySet())
maps.get(name).clear();
}

@SuppressWarnings("unchecked")
public synchronized DataTable<T> load(T[] backingArray) {
if (backingArray == null)
backingArray = (T[]) Array.newInstance(clazz, 0);

queue = new DataQueue<>(maxEntries, backingArray);

for (String name : keySuppliers.keySet()) {
DataMap<Object, T> map = new DataMap<>(maxEntries);
maps.put(name, map);
Function<T, ?> func = keySuppliers.get(name);
for (T s : backingArray)
map.put(func.apply(s), s);
}
return this;
}

@SuppressWarnings("unchecked")
public synchronized T[] toArray() {
T[] zeroArray = (T[]) Array.newInstance(clazz, 0);
return queue.getListClone().toArray(zeroArray);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package info.unterrainer.commons.jreutils.collections;


import java.util.LinkedHashMap;
import java.util.Map;

public class SizeLimitedHashMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 6994714918898609875L;

private final int maxSize;

public SizeLimitedHashMap(final int maxSize) {
this.maxSize = maxSize;
}

@Override
protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package info.unterrainer.commons.jreutils.collections;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class DataTableTests {

@Test
public void peekingWorks() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.add("test");
assertThat(dt.peek()).isEqualTo("test");
}

@Test
public void pollingWorks() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.add("test");
assertThat(dt.poll()).isEqualTo("test");
}

@Test
public void clearingWorks() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.add("test");
dt.clear();
assertThat(dt.peek()).isNull();
assertThat(dt.poll()).isNull();
}

@Test
public void addingIndexWorks() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.addIndex("index1", e -> e);
}

@Test
public void addingWorksWithIndex() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.addIndex("index1", e -> e);
dt.add("test");
assertThat(dt.get("index1", "test")).isEqualTo("test");
}

@Test
public void addingWorksWithTwoIndexes() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.addIndex("index1", e -> e);
dt.addIndex("index2", e -> e);
dt.add("test");
assertThat(dt.get("index1", "test")).isEqualTo("test");
assertThat(dt.get("index2", "test")).isEqualTo("test");
}

@Test
public void deletingFromQueueAlsoDeletesFromAllIndexes() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.addIndex("index1", e -> e);
dt.addIndex("index2", e -> e);
dt.add("test");
dt.poll();
assertThat(dt.get("index1", "test")).isNull();
assertThat(dt.get("index2", "test")).isNull();
}

@Test
public void clearingWorksWithTwoIndexes() {
DataTable<String> dt = new DataTable<>(String.class, 10);
dt.addIndex("index1", e -> e);
dt.addIndex("index2", e -> e);
dt.add("test");
dt.clear();
assertThat(dt.peek()).isNull();
assertThat(dt.poll()).isNull();
assertThat(dt.get("index1", "test")).isNull();
assertThat(dt.get("index2", "test")).isNull();
}
}

0 comments on commit 862dab1

Please sign in to comment.