All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.map.mapper.MapperCache Maven / Gradle / Ivy

Go to download

Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.

There is a newer version: 9.0.2
Show newest version
package org.simpleflatmapper.map.mapper;

import org.simpleflatmapper.map.FieldKey;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;

public final class MapperCache, M> {

	private static final int SIZE_THRESHOLD = 60;
	@SuppressWarnings("unchecked")
	private final AtomicReference> sortedEntries;

	public MapperCache(MapperKeyComparator comparator) {
		this.sortedEntries =
				new AtomicReference>(
						new SortedEntries(0, comparator));
	}

	@SuppressWarnings("unchecked")
	public void add(final MapperKey key, final M mapper) {
		SortedEntries sortedEntries;
		SortedEntries newSortedEntries;
		do {
			sortedEntries = this.sortedEntries.get();

			final int i = sortedEntries.findInsertionPoint(key);

			if (i >= 0) {
				if (!key.equals(sortedEntries.keys[i])) {
					throw new IllegalStateException("Comparator find key " + key + " to be equal to " + sortedEntries.keys[i] + " but is not");
				}
				return;
			}

			int insertionPoint = -1 - i;

			newSortedEntries = sortedEntries.insertEntry(key, mapper, insertionPoint);

		} while(!this.sortedEntries.compareAndSet(sortedEntries, newSortedEntries));
	}


	@SuppressWarnings("unchecked")
	public M get(MapperKey key) {
		return (M) sortedEntries.get().search(key);
	}

	private static final class SortedEntries> {
		private final MapperKey[] keys;
		private final Object[] values;
		private final boolean bsearch;
		private final MapperKeyComparator comparator;

		@SuppressWarnings("unchecked")
		SortedEntries(int size, MapperKeyComparator comparator) {
			this.comparator = comparator;
			this.keys = new MapperKey[size];
			this.values = new Object[size];
			this.bsearch =  size > SIZE_THRESHOLD;
		}

		SortedEntries(MapperKey[] keys, Object[] values, MapperKeyComparator comparator) {
			this.keys = keys;
			this.values = values;
			this.comparator = comparator;
			this.bsearch = keys.length > SIZE_THRESHOLD;
		}

		Object search(MapperKey key) {
			final int i = findKey(key);
			if (i >= 0) {
				return values[i];
			}
			return null;
		}

		int findKey(MapperKey key) {
			if (bsearch) {
				return Arrays.binarySearch(keys, key, comparator);
			} else {
				return iFindKey(key);
			}
		}

		private int iFindKey(MapperKey key) {
			for(int i = 0; i < keys.length; i++) {
				if (key.equals(keys[i])) {
					return i;
				}
			}
			return - keys.length - 1;
		}

		private int findInsertionPoint(MapperKey key) {
			if (comparator == null) {
				return iFindKey(key);
			} else {
				return Arrays.binarySearch(keys, key, comparator);
			}
		}

		SortedEntries insertEntry(MapperKey key, Object mapper, int insertionPoint) {

			SortedEntries newEntries =
					new SortedEntries(
						Arrays.copyOf(keys, keys.length + 1),
						Arrays.copyOf(values, values.length + 1),
					 	comparator);

			System.arraycopy(newEntries.keys, insertionPoint, newEntries.keys, insertionPoint + 1, keys.length - insertionPoint);
			System.arraycopy(newEntries.values, insertionPoint, newEntries.values, insertionPoint + 1, values.length - insertionPoint);

			newEntries.keys[insertionPoint] = key;
			newEntries.values[insertionPoint] = mapper;

			return newEntries;

		}
	}

	@Override
	public String toString() {
		return "MapperCache{" +
				"sortedEntries=" + Arrays.toString(sortedEntries.get().keys) +
				'}';
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy