/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.media.util.registry;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.jboss.logging.Logger;

/**
 * A synchronized Map based registry with non-null keys or values.
 *
 * @version <tt>$Revision: 1.2 $</tt>
 * @author <a href="mailto:ricardoarguello@users.sourceforge.net">Ricardo Argüello</a>
 */
public class MapRegistry implements Registry
{
   private static final Logger log = Logger.getLogger(MapRegistry.class);

   private static final Map entries =
      Collections.synchronizedMap(new HashMap());

   public MapRegistry()
   {
   }

   public MapRegistry(Map initialEntries) throws ObjectAlreadyBoundException
   {
      this();

      Iterator keys = initialEntries.keySet().iterator();

      while (keys.hasNext())
      {
         Object key = keys.next();
         Object value = initialEntries.get(key);
         bind(key, value);
      }
   }

   public void bind(final Object key, final Object value)
      throws ObjectAlreadyBoundException
   {
      if (key == null || value == null)
      {
         throw new NullPointerException();
      }

      if (entries.containsKey(key))
      {
         throw new ObjectAlreadyBoundException();
      }

      entries.put(key, value);

      if (log.isTraceEnabled())
         log.trace("bound " + key + "=" + value);
   }

   public void rebind(final Object key, final Object value)
   {
      if (key == null || value == null)
      {
         throw new NullPointerException();
      }

      entries.put(key, value);

      if (log.isTraceEnabled())
         log.trace("rebind " + key + "=" + value);
   }

   public Object unbind(final Object key) throws ObjectNotBoundException
   {
      if (key == null)
      {
         throw new NullPointerException();
      }

      if (!entries.containsKey(key))
      {
         throw new ObjectNotBoundException();
      }

      Object object = entries.remove(key);

      if (log.isTraceEnabled())
         log.trace("unbound " + key + "=" + object);

      return object;
   }

   public Object lookup(final Object key) throws ObjectNotBoundException
   {
      if (!entries.containsKey(key))
      {
         throw new ObjectNotBoundException();
      }

      Object object = entries.get(key);

      if (log.isTraceEnabled())
         log.trace("lookup " + key + "=" + object);

      return object;
   }

   public Iterator keyIterator()
   {
      synchronized (entries)
      {
         return entries.keySet().iterator();
      }
   }
}