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