package org.mammon.sandbox;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.mammon.messaging.DualIdentityTransitionable;
import org.mammon.messaging.Identifiable;
import org.mammon.messaging.ObjectStorage;
import org.mammon.messaging.Transitionable;

public class ExampleObjectStorage<I> implements ObjectStorage<I> {

	private Map<Class, Class> storableInterfaces = new HashMap<Class, Class>();

	private Map<I, Identifiable<I>> objectMap = new HashMap<I, Identifiable<I>>();

	private Set<I> secondaryIdentities = new HashSet<I>();

	@Override
	public synchronized Identifiable<I> get(I identity) {
		return objectMap.get(identity);
	}

	@Override
	public <C> void registerClass(Class<C> iface, Class<? extends C> clazz) {
		if (storableInterfaces.containsKey(iface)) {
			throw new IllegalArgumentException("Interface " + iface + " already known");
		}
		storableInterfaces.put(iface, clazz);
	}

	@Override
	public synchronized void remove(I identity) {
		if (secondaryIdentities.contains(identity)) {
			throw new IllegalArgumentException("Argument must be primary identity");
		}
		Identifiable<I> object = objectMap.get(identity);
		if (object != null) {
			objectMap.remove(object.getIdentity());
			if (object instanceof DualIdentityTransitionable<?>) {
				Transitionable<I> secT = ((DualIdentityTransitionable<I>) object).getSecondaryTransitionable();
				objectMap.remove(secT.getIdentity());
				secondaryIdentities.remove(secT.getIdentity());
			}
		}
	}

	@Override
	public synchronized void replace(I identity, Identifiable<I> object) {
		objectMap.remove(identity);
		objectMap.put(object.getIdentity(), object);
	}

	@Override
	public synchronized void store(Identifiable<I> object) {
		int countInterfaces = 0;
		Class<?> clazz = null;
		for (Class<?> c : storableInterfaces.keySet()) {
			if (c.isAssignableFrom(object.getClass())) {
				if (++countInterfaces == 1) {
					clazz = c;
				} else if (c != clazz) {
					throw new IllegalArgumentException("Object has ambiguous class registration for "
							+ object.getClass());
				}
			}
		}
		if (countInterfaces == 0) {
			throw new IllegalArgumentException("No object interface has been registered for " + object.getClass());
		}

		if (objectMap.containsKey(object.getIdentity())) {
			throw new IllegalArgumentException("Object with this identity already exists, use replace()");
		}
		Transitionable<I> secT = null;
		if (object instanceof DualIdentityTransitionable<?>) {
			secT = ((DualIdentityTransitionable<I>) object).getSecondaryTransitionable();
			if (objectMap.containsKey(secT.getIdentity())) {
				throw new IllegalArgumentException(
						"Object with identity of secondary transitionable exists, use replace()");
			}
		}

		objectMap.put(object.getIdentity(), object);
		if (secT != null) {
			objectMap.put(secT.getIdentity(), secT);
			secondaryIdentities.add(secT.getIdentity());
		}
	}

}

@@ -1761,35 +1761,8 @@
 ) %7B%0A
-%09%09int countInterfaces = 0;%0A
 %09%09Cl
@@ -1893,30 +1893,21 @@
 if (
-++countInterfaces == 1
+clazz == null
 ) %7B%0A
@@ -1947,24 +1947,126 @@
 != clazz) %7B%0A
+%09%09%09%09%09if (clazz.isAssignableFrom(c)) %7B%0A%09%09%09%09%09%09clazz = c;%0A%09%09%09%09%09%7D else if (!c.isAssignableFrom(clazz)) %7B%0A%09
 %09%09%09%09%09throw n
@@ -2147,16 +2147,17 @@
 %0A%09%09%09%09%09%09%09
+%09
 + object
@@ -2166,24 +2166,31 @@
 etClass());%0A
+%09%09%09%09%09%7D%0A
 %09%09%09%09%7D%0A%09%09%09%7D%0A%09
@@ -2203,27 +2203,20 @@
 f (c
-ountInterfaces == 0
+lazz == null
 ) %7B%0A
@@ -2836,16 +2836,123 @@
 %09%7D%0A%09%09%7D%0A%0A
+%09%09System.out.println(%22Storing %22 + object.getIdentity() + %22 (%22 + object.getClass() + %22 as %22 + clazz + %22)%22);%0A
 %09%09object

Allow classes with overlapping type hierarchy to be register in the ExampleObjectStorage (e.g. Bank+BankPrivate)