package us.kbase.typedobj.idref;

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

import us.kbase.typedobj.idref.IdReferenceHandlerSet.IdReferenceHandler;

/** Builds a set of ID handlers for handling IDs found while validating a
 * typed object. The handler could, for example, check the ID format, check
 * that the ID refers to a valid item in a database, or both.
 * 
 * ID handlers allow associating IDs with a particular object. This is useful
 * for batch processing of typed object, as the IDs can be associated with
 * a particular object but the entire ID set can be processed as a batch.
 * @author gaprice@lbl.gov
 *
 */
public class IdReferenceHandlerSetFactory {
	
	//TODO 1 read through all this & check docs, write any new tests, check coverage.
	//TODO unit tests, docs

	private final Map<IdReferenceType,IdReferenceHandlerFactory> factories = 
			new HashMap<IdReferenceType,IdReferenceHandlerFactory>();
	private final int maxUniqueIdCount;
	
	/** An interface for a factory that creates an ID handler.
	 * @author gaprice@lbl.gov
	 */
	public interface IdReferenceHandlerFactory {
		/** Create a empty, unlocked ID handler from this factory.
		 * @param clazz the class of object to associate with IDs in the
		 * produced ID handler.
		 * @return an ID hander.
		 */
		public <T> IdReferenceHandler<T> createHandler(final Class<T> clazz);
		public IdReferenceType getIDType();
	}
	
	public IdReferenceHandlerSetFactory(final int maxUniqueIdCount) {
		if (maxUniqueIdCount < 0) {
			throw new IllegalArgumentException(
					"maxUniqueIdCount must be at least 0");
		}
		this.maxUniqueIdCount = maxUniqueIdCount;
	}
	
	public IdReferenceHandlerSetFactory addFactory(
			final IdReferenceHandlerFactory factory) {
		if (factory == null) {
			throw new NullPointerException("factory cannot be null");
		}
		if (factory.getIDType() == null) {
			throw new NullPointerException(
					"factory returned null for ID type");
		}
		factories.put(factory.getIDType(), factory);
		return this;
	}
	
	public <T> IdReferenceHandlerSet<T> createHandlers(final Class<T> clazz) {
		final Map<IdReferenceType, IdReferenceHandler<T>> handlers =
				new HashMap<IdReferenceType, IdReferenceHandler<T>>();
		for (final Entry<IdReferenceType, IdReferenceHandlerFactory> e:
				factories.entrySet()) {
			handlers.put(e.getKey(), e.getValue().createHandler(clazz));
		}
		return new IdReferenceHandlerSet<T>(maxUniqueIdCount, handlers);
	}
	
}

@@ -394,16 +394,122 @@
 th.%0A * %0A
+ * The handler builder is expected to build a set of empty handlers that are%0A * ready to process IDs.%0A * %0A
  * ID ha
@@ -617,16 +617,17 @@
 d object
+s
 , as the
@@ -812,91 +812,8 @@
 %7B%0A%09%0A
-%09//TODO 1 read through all this & check docs, write any new tests, check coverage.%0A
 %09//T
@@ -830,14 +830,8 @@
 ests
-, docs
 %0A%0A%09p
@@ -1440,24 +1440,324 @@
 ype();%0A%09%7D%0A%09%0A
+%09/** Create a handler set factory.%0A%09 * @param maxUniqueIdCount - the maximum number of unique IDs allowed in%0A%09 * this handler. The handler implementation defines what non-unique means,%0A%09 * but generally the definition is that the IDs are associated with the%0A%09 * same object and are the same ID.%0A%09 */%0A
 %09public IdRe
@@ -1974,24 +1974,126 @@
 Count;%0A%09%7D%0A%09%0A
+%09/** Add a factory to this factory set.%0A%09 * @param factory the factory to add.%0A%09 * @return this.%0A%09 */%0A
 %09public IdRe
@@ -2449,18 +2449,175 @@
 his;%0A%09%7D%0A
-
 %09%0A
+%09/** Create a set of ID handlers from this factory set.%0A%09 * @param clazz the class of object to associate with IDs.%0A%09 * @return the set of ID handlers.%0A%09 */%0A
 %09public 

Add docs & update TODOs for the id ref handler set factory