Package org.jboss.portal.common.util

Source Code of org.jboss.portal.common.util.TypedMap$ValueCollection

/******************************************************************************
* JBoss, a division of Red Hat                                               *
* Copyright 2006, Red Hat Middleware, LLC, and individual                    *
* contributors as indicated by the @authors tag. See the                     *
* copyright.txt in the distribution for a full listing of                    *
* individual contributors.                                                   *
*                                                                            *
* This is free software; you can redistribute it and/or modify it            *
* under the terms of the GNU Lesser General Public License as                *
* published by the Free Software Foundation; either version 2.1 of           *
* the License, or (at your option) any later version.                        *
*                                                                            *
* This software is distributed in the hope that it will be useful,           *
* but WITHOUT ANY WARRANTY; without even the implied warranty of             *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU           *
* Lesser General Public License for more details.                            *
*                                                                            *
* You should have received a copy of the GNU Lesser General Public           *
* License along with this software; if not, write to the Free                *
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA         *
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.                   *
******************************************************************************/
package org.jboss.portal.common.util;

import org.jboss.portal.common.NotYetImplemented;

import java.util.Map;
import java.util.Set;
import java.util.Collection;
import java.util.Iterator;
import java.util.HashMap;

/**
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
* @version $Revision: 1.1 $
*/
public class TypedMap<EK, EV, IK, IV> implements Map<EK, EV>
{

   public abstract static class Converter<E, I>
   {

      /**
       * Unwraps the key to the the internal key that will be stored in the map. This method calls the
       * <code>assertKeyValidity(Object key)</code> and returns the same key. It can be overriden to provide a customized
       * key that will be used instead of the external key.
       *
       * @param external the key to unwrap
       * @return the unwrapped key
       * @throws ClassCastException       if the class of the specified key prevents it from being stored in this map
       * @throws IllegalArgumentException if some aspect of this key prevents it from being stored in this map
       */
      protected abstract I getInternal(E external) throws IllegalArgumentException, ClassCastException;

      /**
       * Wrap the internal key into its external representation, by default returns the same key. It can be overriden to
       * provide a customized key that will be used instead of the internal key.
       */
      protected abstract E getExternal(I internal);

      public I unwrap(E external) throws IllegalArgumentException, ClassCastException, NullPointerException
      {
         if (external == null)
         {
            throw new NullPointerException("No null key accepted");
         }

         //
         I internal = getInternal(external);

         //
         if (internal == null)
         {
            throw new IllegalArgumentException("The provided key " + external + " was converted to a null key");
         }

         //
         return internal;
      }

      public E wrap(I internal) throws IllegalStateException
      {
         if (internal == null)
         {
            throw new IllegalStateException("Got an internal null key");
         }

         //
         E external = getExternal(internal);

         //
         if (external == null)
         {
            throw new IllegalStateException("Converted an internal key to a null key " + internal);
         }

         //
         return external;
      }

      public boolean safeEquals(I left, I right)
      {
         // Check the internal value, it should not be null
         return !(left == null || right == null) && equals(left, right);
      }

      /**
       * Compare internal values, the passed argument are never null.
       *
       * @param left the left value
       * @param right the right value
       * @return true if the values are equals
       */
      protected abstract boolean equals(I left, I right);
   }

   /** The map accessor. */
   private final MapAccessor<IK, IV> accessor;

   /** The key converter. */
   private final Converter<EK, IK> keyConverter;

   /** The value converter. */
   private final Converter<EV, IV> valueConverter;

   public TypedMap(MapAccessor<IK, IV> accessor, Converter<EK, IK> keyConverter, Converter<EV, IV> valueConverter)
   {
      if (accessor == null)
      {
         throw new IllegalArgumentException();
      }
      if (keyConverter == null)
      {
         throw new IllegalArgumentException();
      }
      if (valueConverter == null)
      {
         throw new IllegalArgumentException();
      }

     
      this.accessor = accessor;
      this.keyConverter = keyConverter;
      this.valueConverter = valueConverter;
   }

   public TypedMap(Map<IK, IV> delegate, Converter<EK, IK> keyConv, Converter<EV, IV> valueConv)
   {
      this(new SimpleMapAccessor<IK, IV>(delegate), keyConv, valueConv);
   }

   public Converter<EK, IK> getKeyConverter()
   {
      return keyConverter;
   }

   public Converter<EV, IV> getValueConverter()
   {
      return valueConverter;
   }

   public final int size()
   {
      return accessor.getMap(false).size();
   }

   public final void clear()
   {
      if (!isEmpty())
      {
         accessor.getMap(true).clear();
      }
   }

   public final boolean isEmpty()
   {
      return accessor.getMap(false).isEmpty();
   }

   public final boolean containsKey(Object key)
   {
      EK ek = (EK)key;
      IK ik = keyConverter.unwrap(ek);
      return accessor.getMap(false).containsKey(ik);
   }

   public final Set<EK> keySet()
   {
      return new KeySet();
   }

   public EV put(EK ek, EV ev)
   {
      IK ik = keyConverter.unwrap(ek);
      IV iv = valueConverter.unwrap(ev);
      iv = accessor.getMap(true).put(ik, iv);
      return iv == null ? null : valueConverter.wrap(iv);
   }

   public final EV get(Object key)
   {
      EK ek = (EK)key;
      IK ik = keyConverter.unwrap(ek);
      IV iv = accessor.getMap(false).get(ik);
      return iv == null ? null : valueConverter.wrap(iv);
   }

   public final EV remove(Object key)
   {
      EK ek = (EK)key;
      IK ik = keyConverter.unwrap(ek);
      IV iv = null;
      if (!isEmpty())
      {
         iv = accessor.getMap(true).remove(ik);
      }
      return iv == null ? null : valueConverter.wrap(iv);
   }

   public final boolean containsValue(Object value)
   {
      EV ev = (EV)value;
      IV iv = valueConverter.unwrap(ev);
      return accessor.getMap(false).containsValue(iv);
   }

   public final Set<Entry<EK, EV>> entrySet()
   {
      return new TypedEntrySet();
   }

   public void putAll(Map<? extends EK, ? extends EV> em)
   {
      Map<IK, IV> im = convert(em);
      accessor.getMap(true).putAll(im);
   }

   public Collection<EV> values()
   {
      return new ValueCollection();
   }

   /** Compare to parameters objects. */
   public boolean equals(Object o)
   {
      if (o == this)
      {
         return true;
      }
      if (o instanceof Map)
      {
         Map<EK, EV> that = (Map<EK,EV>)o;
         Map<IK, IV> delegate = this.accessor.getMap(false);

         // Must have same sizes
         if (that.size() != delegate.size())
         {
            return false;
         }

         //
         for (Entry<EK, EV> thatEntry : that.entrySet())
         {

            EK thatKey = thatEntry.getKey();
            EV thatValue = thatEntry.getValue();

            //
            try
            {
               // Unwrap key, mostly for checking its type is correct
               keyConverter.unwrap(thatKey);

               // Unwrap value
               IV iv = valueConverter.unwrap(thatValue);

               // Get the internal value
               IV internalValue = delegate.get(thatKey);

               // Perform value comparison
               if (!valueConverter.safeEquals(internalValue, iv))
               {
                  return false;
               }
            }
            catch (IllegalArgumentException e)
            {
               return false;
            }
            catch (ClassCastException e)
            {
               return false;
            }
            catch (NullPointerException e)
            {
               return false;
            }
         }

         //
         return true;
      }

      //
      return false;
   }

   public String toString()
   {
      return accessor.getMap(false).toString();
   }

   /**
    * Validates and unwraps the map.
    *
    * @param t
    * @return
    * @throws IllegalArgumentException
    * @throws NullPointerException
    * @throws ClassCastException
    */
   protected final Map<IK, IV> convert(Map<? extends EK, ? extends EV> t) throws IllegalArgumentException, NullPointerException, ClassCastException
   {
      if (t == null)
      {
         throw new NullPointerException("No null map can be accepted");
      }
      Map<IK, IV> u = new HashMap<IK, IV>(t.size());
      for (Entry<? extends EK, ? extends EV> entry : t.entrySet())
      {
         IK ik = keyConverter.unwrap(entry.getKey());
         IV iv = valueConverter.unwrap(entry.getValue());
         u.put(ik, iv);
      }
      return u;
   }

   /**
    * Replace the content with the new map which is validated before replacement.
    *
    * @param map the replacement map
    * @throws ClassCastException
    * @throws NullPointerException
    * @throws IllegalArgumentException
    */
   public void replace(Map<EK, EV> map) throws ClassCastException, NullPointerException, IllegalArgumentException
   {
      if (!map.isEmpty())
      {
         Map<IK, IV> tmp = convert(map);

         //
         Map<IK, IV> delegate = accessor.getMap(true);
         delegate.clear();
         delegate.putAll(tmp);
      }
   }

   /**
    * Validate the content.
    *
    * @throws ClassCastException
    * @throws NullPointerException
    * @throws IllegalArgumentException
    */
   public void validate() throws ClassCastException, NullPointerException, IllegalArgumentException
   {
      for (Entry<IK, IV> entry : accessor.getMap(false).entrySet())
      {
         keyConverter.wrap(entry.getKey());
         valueConverter.wrap(entry.getValue());
      }
   }

   public class KeySet implements Set<EK>
   {

      /** . */
      private final Set<IK> delegate;

      public KeySet()
      {
         this.delegate = TypedMap.this.accessor.getMap(false).keySet();
      }

      public int size()
      {
         return delegate.size();
      }

      public void clear()
      {
         if (!isEmpty())
         {
            delegate.clear();
         }
      }

      public boolean isEmpty()
      {
         return delegate.isEmpty();
      }

      public boolean contains(Object o)
      {
         EK ek;
         try
         {
            ek = (EK)o;
         }
         catch (ClassCastException e)
         {
            return false;
         }
         try
         {
            IK ik = keyConverter.getInternal(ek);
            return TypedMap.this.accessor.getMap(false).containsKey(ik);
         }
         catch (IllegalArgumentException e)
         {
            return false;
         }
         catch (ClassCastException e)
         {
            return false;
         }
         catch (NullPointerException e)
         {
            return false;
         }
      }

      public Object[] toArray()
      {
         throw new NotYetImplemented("TypedEntrySet.toArray()");
      }

      public boolean add(EK ek)
      {
         throw new NotYetImplemented("TypedEntrySet.add(Object o)");
      }

      public boolean remove(Object o)
      {
         throw new NotYetImplemented("TypedEntrySet.remove(Object o)");
      }

      public boolean containsAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.addAll(Collection c)");
      }

      public boolean addAll(Collection<? extends EK> eks)
      {
         throw new NotYetImplemented("TypedEntrySet.containsAll(Collection c)");
      }

      public boolean removeAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.removeAll(Collection c)");
      }

      public boolean retainAll(Collection<?> c)
      {
         if (c == null)
         {
            throw new NullPointerException();
         }

         //
         boolean changed = false;
         for (Iterator i = iterator(); i.hasNext();)
         {
            Object key = i.next();
            if (!c.contains(key))
            {
               i.remove();
               changed = true;
            }
         }
         return changed;
      }

      public Iterator<EK> iterator()
      {
         return new KeyIterator();
      }

      public <EK> EK[] toArray(EK a[])
      {
         throw new NotYetImplemented("TypedEntrySet.toArray(Object a[])");
      }

      public class KeyIterator implements Iterator<EK>
      {

         /** . */
         private final Iterator<IK> delegate;

         public KeyIterator()
         {
            this.delegate = KeySet.this.delegate.iterator();
         }

         public void remove()
         {
            delegate.remove();
         }

         public boolean hasNext()
         {
            return delegate.hasNext();
         }

         public EK next()
         {
            IK ik = delegate.next();
            return keyConverter.wrap(ik);
         }
      }
   }

   public class ValueCollection implements Collection<EV>
   {

      /** . */
      private final Collection<IV> delegate;

      public ValueCollection()
      {
         this.delegate = TypedMap.this.accessor.getMap(false).values();
      }

      public int size()
      {
         return delegate.size();
      }

      public void clear()
      {
         delegate.clear();
      }

      public boolean isEmpty()
      {
         return delegate.isEmpty();
      }

      public Object[] toArray()
      {
         throw new NotYetImplemented("TypedEntrySet.toArray()");
      }

      public boolean add(EV ev)
      {
         throw new NotYetImplemented("TypedEntrySet.add(Object o)");
      }

      public boolean contains(Object o)
      {
         throw new NotYetImplemented("TypedEntrySet.contains(Object o)");
      }

      public boolean remove(Object o)
      {
         throw new NotYetImplemented("TypedEntrySet.remove(Object o)");
      }

      public boolean addAll(Collection<? extends EV> evs)
      {
         throw new NotYetImplemented("TypedEntrySet.addAll(Collection c)");
      }

      public boolean containsAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.containsAll(Collection c)");
      }

      public boolean removeAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.removeAll(Collection c)");
      }

      public boolean retainAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.retainAll(Collection c)");
      }

      public <T> T[] toArray(T[] ts)
      {
         throw new NotYetImplemented("TypedEntrySet.toArray(Object a[])");
      }

      public Iterator<EV> iterator()
      {
         return new ValueIterator();
      }

      public class ValueIterator implements Iterator<EV>
      {

         /** . */
         private final Iterator<IV> delegate;

         public ValueIterator()
         {
            this.delegate = ValueCollection.this.delegate.iterator();
         }

         public void remove()
         {
            delegate.remove();
         }

         public boolean hasNext()
         {
            return delegate.hasNext();
         }

         public EV next()
         {
            IV iv = delegate.next();
            return valueConverter.wrap(iv);
         }
      }
   }

   public class TypedEntrySet implements Set<Entry<EK, EV>>
   {

      /** . */
      private final Set<Entry<IK, IV>> delegate;

      public TypedEntrySet()
      {
         this.delegate = TypedMap.this.accessor.getMap(false).entrySet();
      }

      public int size()
      {
         return delegate.size();
      }

      public void clear()
      {
         if (!isEmpty())
         {
            delegate.clear();
         }
      }

      public boolean isEmpty()
      {
         return delegate.isEmpty();
      }

      public Object[] toArray()
      {
         throw new NotYetImplemented("TypedEntrySet.toArray()");
      }

      public boolean add(Entry<EK, EV> ekevEntry)
      {
         throw new NotYetImplemented("TypedEntrySet.add(Object o)");
      }

      public boolean contains(Object o)
      {
         throw new NotYetImplemented("TypedEntrySet.contains(Object o)");
      }

      public boolean remove(Object o)
      {
         throw new NotYetImplemented("TypedEntrySet.remove(Object o)");
      }

      public boolean addAll(Collection<? extends Entry<EK, EV>> entries)
      {
         throw new NotYetImplemented("TypedEntrySet.addAll(Collection c)");
      }

      public boolean containsAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.containsAll(Collection c)");
      }

      public boolean removeAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.removeAll(Collection c)");
      }

      public boolean retainAll(Collection<?> objects)
      {
         throw new NotYetImplemented("TypedEntrySet.retainAll(Collection c)");
      }

      public <T> T[] toArray(T[] ts)
      {
         throw new NotYetImplemented("TypedEntrySet.toArray(Object a[])");
      }

      public Iterator<Entry<EK, EV>> iterator()
      {
         return new TypedEntryIterator();
      }

      public class TypedEntryIterator implements Iterator<Entry<EK, EV>>
      {

         /** . */
         private final Iterator<Entry<IK, IV>> delegate;

         public TypedEntryIterator()
         {
            this.delegate = TypedEntrySet.this.delegate.iterator();
         }

         public void remove()
         {
            delegate.remove();
         }

         public boolean hasNext()
         {
            return delegate.hasNext();
         }

         public Entry<EK, EV> next()
         {
            Entry<IK, IV> entry = delegate.next();
            return new TypedEntry(entry);
         }
      }

      public class TypedEntry implements Entry<EK, EV>
      {

         /** . */
         private final Entry<IK, IV> delegate;

         public TypedEntry(Entry<IK, IV> delegate)
         {
            this.delegate = delegate;
         }

         public int hashCode()
         {
            return delegate.hashCode();
         }

         public boolean equals(Object obj)
         {
            return delegate.equals(obj);
         }

         public String toString()
         {
            return delegate.toString();
         }

         public EK getKey()
         {
            IK ik = delegate.getKey();
            return keyConverter.wrap(ik);
         }

         public EV getValue()
         {
            IV iv = delegate.getValue();
            return valueConverter.wrap(iv);
         }

         public EV setValue(Object value)
         {
            EV ev = (EV)value;
            IV iv = valueConverter.unwrap(ev);
            iv = delegate.setValue(iv);
            return valueConverter.wrap(iv);
         }
      }
   }
}
TOP

Related Classes of org.jboss.portal.common.util.TypedMap$ValueCollection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.