package com.jsonde.util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
public class ObjectIdGenerator<T> {
private AtomicLong sequence = new AtomicLong();
private Map<ObjectWrapper<T>, Long> objectIds = new HashMap<ObjectWrapper<T>, Long>();
public synchronized long getId(T object) {
ObjectWrapper<T> objectWrapper = wrap(object);
if (!objectIds.containsKey(objectWrapper)) {
objectIds.put(objectWrapper, sequence.getAndIncrement());
}
return objectIds.get(objectWrapper);
}
public synchronized long pollId(T object) throws ObjectIsAbsentException {
ObjectWrapper<T> objectWrapper = wrap(object);
if (objectIds.containsKey(objectWrapper)) {
return objectIds.get(objectWrapper);
} else {
throw new ObjectIsAbsentException();
}
}
@SuppressWarnings("unchecked")
private ObjectWrapper<T> wrap(T object) {
if (object instanceof ObjectWrapper) {
return (ObjectWrapper<T>) object;
} else {
return new ObjectWrapper<T>(object);
}
}
public static <M, N> Pair<M, N> pair(M m, N n) {
return new Pair<M, N>(m, n);
}
public static class Pair<M, N> extends ObjectWrapper<Pair<M, N>> {
private final M m;
private final N n;
private Pair(M m, N n) {
this.m = m;
this.n = n;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
if (m != null ? m != pair.m : pair.m != null) return false;
if (n != null ? n != pair.n : pair.n != null) return false;
return true;
}
@Override
public int hashCode() {
int result = m != null ? System.identityHashCode(m) : 0;
result = 31 * result + (n != null ? System.identityHashCode(n) : 0);
return result;
}
}
private static class ObjectWrapper<T> {
private final T object;
private ObjectWrapper(T object) {
this.object = object;
}
@SuppressWarnings("unchecked")
protected ObjectWrapper() {
object = (T) this;
}
@Override
public int hashCode() {
return System.identityHashCode(object);
}
@Override
public boolean equals(Object obj) {
if (null == object) {
return null == obj;
} else {
return object == obj;
}
}
}
}