package org.simpleflatmapper.map; import org.simpleflatmapper.map.mapper.MapperKey; import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; public final class T2ArraysMapperCache<K extends FieldKey<K>, M> implements IMapperCache<K, M> { @SuppressWarnings("unchecked") private final AtomicReference<Entries<K>> sortedEntries = new AtomicReference<Entries<K>>(new Entries<K>(0)); public T2ArraysMapperCache() { } @SuppressWarnings("unchecked") public void add(final MapperKey<K> key, final M mapper) { Entries<K> entries; Entries<K> newEntries; do { entries = this.sortedEntries.get(); final int i = entries.findKey(key); if (i >= 0) { if (!key.equals(entries.keys[i])) { throw new IllegalStateException("Comparator find key " + key + " to be equal to " + entries.keys[i] + " but is not"); } return; } int insertionPoint = -1 - i; newEntries = entries.insertEntry(key, mapper, insertionPoint); } while(!this.sortedEntries.compareAndSet(entries, newEntries)); } @SuppressWarnings("unchecked") public M get(MapperKey<K> key) { return (M) sortedEntries.get().search(key); } @Override public int size() { return sortedEntries.get().keys.length; } public static class Entries<K extends FieldKey<K>> { private final MapperKey<K>[] keys; private final Object[] values; @SuppressWarnings("unchecked") Entries(int size) { this.keys = new MapperKey[size]; this.values = new Object[size]; } Object search(MapperKey<K> key) { final int i = findKey(key); if (i >= 0) { return values[i]; } return null; } int findKey(MapperKey<K> key) { for(int i = 0; i < keys.length; i++) { if (key.equals(keys[i])) { return i; } } return - keys.length - 1; } Entries<K> insertEntry(MapperKey<K> key, Object mapper, int insertionPoint) { Entries<K> newEntries = new Entries<K>(keys.length + 1); System.arraycopy(keys, 0, newEntries.keys, 0, insertionPoint); System.arraycopy(values, 0, newEntries.values, 0, insertionPoint); newEntries.keys[insertionPoint] = key; newEntries.values[insertionPoint] = mapper; System.arraycopy(keys, insertionPoint, newEntries.keys, insertionPoint + 1, keys.length - insertionPoint); System.arraycopy(values, insertionPoint, newEntries.values, insertionPoint + 1, keys.length - insertionPoint); return newEntries; } } @Override public String toString() { return "Sorted2ArraysMapperCache{" + "sortedEntries=" + Arrays.toString(sortedEntries.get().keys) + '}'; } }