View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.portals.bridges.jsf;
    18
    19  import java.util.AbstractSet;
    20  import java.util.ArrayList;
    21  import java.util.Collection;
    22  import java.util.Enumeration;
    23  import java.util.Iterator;
    24  import java.util.List;
    25  import java.util.Map;
    26  import java.util.NoSuchElementException;
    27  import java.util.Set;
    28
    29  /***
    30   * <p>
    31   * Helper Map implementation for use with different Attribute Maps.
    32   * </p>
    33   * <p>
    34   * See MyFaces project for servlet implementation.
    35   * </p>
    36   *
    37   * @author <a href="dlestrat@apache.org">David Le Strat </a>
    38   *
    39   */
    40  public abstract class AbstractAttributeMap implements Map
    41  {
    42      private Set keySet;
    43
    44      private Collection values;
    45
    46      private Set entrySet;
    47
    48      /***
    49       * @see java.util.Map#clear()
    50       */
    51      public void clear()
    52      {
    53          List names = new ArrayList();
    54          for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
    55          {
    56              names.add(e.nextElement());
    57          }
    58
    59          for (Iterator it = names.iterator(); it.hasNext();)
    60          {
    61              removeAttribute((String) it.next());
    62          }
    63      }
    64
    65      /***
    66       * @see java.util.Map#containsKey(java.lang.Object)
    67       */
    68      public boolean containsKey(Object key)
    69      {
    70          return getAttribute(key.toString()) != null;
    71      }
    72
    73      /***
    74       * @see java.util.Map#containsValue(java.lang.Object)
    75       */
    76      public boolean containsValue(Object findValue)
    77      {
    78          if (findValue == null)
    79          {
    80              return false;
    81          }
    82
    83          for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
    84          {
    85              Object value = getAttribute((String) e.nextElement());
    86              if (findValue.equals(value))
    87              {
    88                  return true;
    89              }
    90          }
    91
    92          return false;
    93      }
    94
    95      /***
    96       * @see java.util.Map#entrySet()
    97       */
    98      public Set entrySet()
    99      {
    100         return (entrySet != null) ? entrySet : (entrySet = new EntrySet());
    101     }
    102
    103     /***
    104      * @see java.util.Map#get(java.lang.Object)
    105      */
    106     public Object get(Object key)
    107     {
    108         return getAttribute(key.toString());
    109     }
    110
    111     /***
    112      * @see java.util.Map#isEmpty()
    113      */
    114     public boolean isEmpty()
    115     {
    116         return !getAttributeNames().hasMoreElements();
    117     }
    118
    119     /***
    120      * @see java.util.Map#keySet()
    121      */
    122     public Set keySet()
    123     {
    124         return (keySet != null) ? keySet : (keySet = new KeySet());
    125     }
    126
    127     /***
    128      * @see java.util.Map#put(java.lang.Object, java.lang.Object)
    129      */
    130     public Object put(Object key, Object value)
    131     {
    132         String localKey = key.toString();
    133         Object retval = getAttribute(localKey);
    134         setAttribute(localKey, value);
    135         return retval;
    136     }
    137
    138     /***
    139      * @see java.util.Map#putAll(java.util.Map)
    140      */
    141     public void putAll(Map t)
    142     {
    143         for (Iterator it = t.entrySet().iterator(); it.hasNext();)
    144         {
    145             Entry entry = (Entry) it.next();
    146             setAttribute(entry.getKey().toString(), entry.getValue());
    147         }
    148     }
    149
    150     /***
    151      * @see java.util.Map#remove(java.lang.Object)
    152      */
    153     public Object remove(Object key)
    154     {
    155         String localKey = key.toString();
    156         Object retval = getAttribute(localKey);
    157         removeAttribute(localKey);
    158         return retval;
    159     }
    160
    161     /***
    162      * @see java.util.Map#size()
    163      */
    164     public int size()
    165     {
    166         int size = 0;
    167         for (Enumeration e = getAttributeNames(); e.hasMoreElements();)
    168         {
    169             size++;
    170             e.nextElement();
    171         }
    172         return size;
    173     }
    174
    175     /***
    176      * @see java.util.Map#values()
    177      */
    178     public Collection values()
    179     {
    180         return (values != null) ? values : (values = new Values());
    181     }
    182
    183     /***
    184      * <p>
    185      * Gets an attribute given a key.
    186      * </p>
    187      *
    188      * @param key The key.
    189      * @return The attribute.
    190      */
    191     abstract protected Object getAttribute(String key);
    192
    193     /***
    194      * <p>
    195      * Sets an attribute given a key/value.
    196      * </p>
    197      *
    198      * @param key The key.
    199      * @param value The value.
    200      */
    201     abstract protected void setAttribute(String key, Object value);
    202
    203     /***
    204      * <p>
    205      * Removes an attribute.
    206      * </p>
    207      *
    208      * @param key The key.
    209      */
    210     abstract protected void removeAttribute(String key);
    211
    212     /***
    213      * <p>
    214      * Gets the attributes names.
    215      * </p>
    216      *
    217      * @return An enumeration of attributes names.
    218      */
    219     abstract protected Enumeration getAttributeNames();
    220
    221     private class KeySet extends AbstractSet
    222     {
    223         public Iterator iterator()
    224         {
    225             return new KeyIterator();
    226         }
    227
    228         public boolean isEmpty()
    229         {
    230             return AbstractAttributeMap.this.isEmpty();
    231         }
    232
    233         public int size()
    234         {
    235             return AbstractAttributeMap.this.size();
    236         }
    237
    238         public boolean contains(Object o)
    239         {
    240             return AbstractAttributeMap.this.containsKey(o);
    241         }
    242
    243         public boolean remove(Object o)
    244         {
    245             return AbstractAttributeMap.this.remove(o) != null;
    246         }
    247
    248         public void clear()
    249         {
    250             AbstractAttributeMap.this.clear();
    251         }
    252     }
    253
    254     private class KeyIterator implements Iterator
    255     {
    256         protected final Enumeration _e = getAttributeNames();
    257
    258         protected Object _currentKey;
    259
    260         public void remove()
    261         {
    262             // remove() may cause ConcurrentModificationException.
    263             // We could throw an exception here, but not throwing an exception
    264             //   allows one call to remove() to succeed
    265             if (_currentKey == null)
    266             {
    267                 throw new NoSuchElementException("You must call next() at least once");
    268             }
    269             AbstractAttributeMap.this.remove(_currentKey);
    270         }
    271
    272         public boolean hasNext()
    273         {
    274             return _e.hasMoreElements();
    275         }
    276
    277         public Object next()
    278         {
    279             return _currentKey = _e.nextElement();
    280         }
    281     }
    282
    283     private class Values extends KeySet
    284     {
    285         public Iterator iterator()
    286         {
    287             return new ValuesIterator();
    288         }
    289
    290         public boolean contains(Object o)
    291         {
    292             return AbstractAttributeMap.this.containsValue(o);
    293         }
    294
    295         public boolean remove(Object o)
    296         {
    297             if (o == null)
    298             {
    299                 return false;
    300             }
    301
    302             for (Iterator it = iterator(); it.hasNext();)
    303             {
    304                 if (o.equals(it.next()))
    305                 {
    306                     it.remove();
    307                     return true;
    308                 }
    309             }
    310
    311             return false;
    312         }
    313     }
    314
    315     private class ValuesIterator extends KeyIterator
    316     {
    317         public Object next()
    318         {
    319             super.next();
    320             return AbstractAttributeMap.this.get(_currentKey);
    321         }
    322     }
    323
    324     private class EntrySet extends KeySet
    325     {
    326         public Iterator iterator()
    327         {
    328             return new EntryIterator();
    329         }
    330
    331         public boolean contains(Object o)
    332         {
    333             if (!(o instanceof Entry))
    334             {
    335                 return false;
    336             }
    337
    338             Entry entry = (Entry) o;
    339             Object key = entry.getKey();
    340             Object value = entry.getValue();
    341             if (key == null || value == null)
    342             {
    343                 return false;
    344             }
    345
    346             return value.equals(AbstractAttributeMap.this.get(key));
    347         }
    348
    349         public boolean remove(Object o)
    350         {
    351             if (!(o instanceof Entry))
    352             {
    353                 return false;
    354             }
    355
    356             Entry entry = (Entry) o;
    357             Object key = entry.getKey();
    358             Object value = entry.getValue();
    359             if (key == null || value == null || !value.equals(AbstractAttributeMap.this.get(key)))
    360             {
    361                 return false;
    362             }
    363
    364             return AbstractAttributeMap.this.remove(((Entry) o).getKey()) != null;
    365         }
    366     }
    367
    368     /***
    369      * Not very efficient since it generates a new instance of
    370      * <code>Entry</code> for each element and still internaly uses the
    371      * <code>KeyIterator</code>. It is more efficient to use the
    372      * <code>KeyIterator</code> directly.
    373      */
    374     private class EntryIterator extends KeyIterator
    375     {
    376         public Object next()
    377         {
    378             super.next();
    379             // Must create new Entry every time--value of the entry must stay
    380             // linked to the same attribute name
    381             return new EntrySetEntry(_currentKey);
    382         }
    383     }
    384
    385     private class EntrySetEntry implements Entry
    386     {
    387         private final Object _currentKey;
    388
    389         public EntrySetEntry(Object currentKey)
    390         {
    391             _currentKey = currentKey;
    392         }
    393
    394         public Object getKey()
    395         {
    396             return _currentKey;
    397         }
    398
    399         public Object getValue()
    400         {
    401             return AbstractAttributeMap.this.get(_currentKey);
    402         }
    403
    404         public Object setValue(Object value)
    405         {
    406             return AbstractAttributeMap.this.put(_currentKey, value);
    407         }
    408     }
    409 }