Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 528   Methods: 50
NCLOC: 427   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
CachedListImpl.java 46.4% 54% 60% 52.4%
coverage coverage
 1    /*
 2    * JBoss, the OpenSource J2EE webOS
 3    *
 4    * Distributable under LGPL license.
 5    * See terms of license at gnu.org.
 6    */
 7    package org.jboss.cache.pojo.collection;
 8   
 9    import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
 10   
 11    import java.io.ObjectStreamException;
 12    import java.util.ArrayList;
 13    import java.util.Iterator;
 14    import java.util.LinkedList;
 15    import java.util.List;
 16    import java.util.ListIterator;
 17    import java.util.NoSuchElementException;
 18    import java.util.Set;
 19   
 20    import org.apache.commons.logging.Log;
 21    import org.apache.commons.logging.LogFactory;
 22    import org.jboss.cache.Cache;
 23    import org.jboss.cache.Fqn;
 24    import org.jboss.cache.Node;
 25    import org.jboss.cache.pojo.impl.PojoCacheImpl;
 26    import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
 27    import org.jboss.cache.pojo.util.AopUtil;
 28    import org.jboss.cache.pojo.util.CacheApiUtil;
 29    import org.jboss.cache.pojo.util.Null;
 30   
 31    /**
 32    * List implementation that uses cache as a backend store.
 33    *
 34    * @author Ben Wang
 35    * @author Scott Marlow
 36    */
 37    public class CachedListImpl extends CachedListAbstract
 38    {
 39    private static Log log_ = LogFactory.getLog(CachedListImpl.class.getName());
 40    private Cache<Object, Object> cache;
 41    private PojoCacheImpl pojoCache;
 42    private AbstractCollectionInterceptor interceptor;
 43   
 44  1572 public CachedListImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
 45    {
 46  1572 this.pojoCache = cache;
 47  1572 this.cache = pojoCache.getCache();
 48  1572 this.interceptor = interceptor;
 49    }
 50   
 51  18473 private Fqn getFqn()
 52    {
 53  18473 return interceptor.getFqn();
 54    }
 55   
 56    // implementation of the java.util.List interface
 57   
 58  11466 private Set<Node> getNodeChildren()
 59    {
 60  11466 return CacheApiUtil.getNodeChildren(cache, getFqn());
 61    }
 62   
 63    /**
 64    * Serialize a normal ArrayList
 65    */
 66  0 private Object XwriteReplace() throws ObjectStreamException
 67    {
 68  0 log_.warn("writeReplace(): this calss is not suppored to be serialized." +
 69    " Will substitue with a normal ArryList");
 70   
 71  0 ArrayList toSerialize = new ArrayList();
 72  0 toSerialize.addAll(this);
 73  0 return toSerialize;
 74    }
 75   
 76  723 public Object get(int index)
 77    {
 78  723 checkIndex();
 79  723 return Null.toNullValue(pojoCache.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
 80    }
 81   
 82  5405 private static void checkIndex()
 83    {
 84    // TODO This is too expensive now to check it everytime from the cache (potentially twice).
 85    // It is showing up in the JProfiler. So I am disabling it now.
 86  5405 return;
 87    /*
 88    if(size() == 0) return; // No need to check here.
 89    if( i < 0 || i >= size() ) {
 90    throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " +i
 91    + " but size is " +size());
 92    } */
 93    }
 94   
 95  11466 public int size()
 96    {
 97  11466 Set<Node> children = getNodeChildren();
 98  11466 return children == null ? 0 : children.size();
 99    }
 100   
 101  15 public Object set(int index, Object element)
 102    {
 103  15 if (index != 0)
 104  2 checkIndex(); // Since index can be size().
 105  15 return Null.toNullValue(attach(index, element, "SET"));
 106    }
 107   
 108  3249 public void add(int index, Object element)
 109    {
 110  3249 if (index != 0)
 111  1764 checkIndex(); // Since index can be size().
 112  3249 for (int i = size(); i > index; i--)
 113    {
 114  5 Object obj = detach(i - 1);
 115  5 attach(i, obj);
 116    }
 117  3249 attach(index, element, "ADD");
 118    }
 119   
 120  39 private Object attach(int i, Object obj)
 121    {
 122  39 return attach(i, obj, null);
 123    }
 124   
 125  3303 private Object attach(int i, Object obj, String operation)
 126    {
 127  3303 Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
 128  3303 Object o = pojoCache.attach(fqn, Null.toNullObject(obj));
 129  3303 if (operation != null)
 130  3264 pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
 131   
 132  3303 return o;
 133    }
 134   
 135  39 private Object detach(int i)
 136    {
 137  39 return detach(i, null);
 138    }
 139   
 140  2965 private Object detach(int i, String operation)
 141    {
 142  2965 Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
 143  2965 if (operation != null)
 144  2926 pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
 145  2965 return pojoCache.detach(fqn);
 146    }
 147   
 148  66 public int indexOf(Object o)
 149    {
 150  66 int size = size();
 151  66 if (o == null)
 152    {
 153  6 for (int i = 0; i < size; i++)
 154    {
 155  6 if (null == get(i))
 156  3 return i;
 157    }
 158    } else
 159    {
 160  63 for (int i = 0; i < size; i++)
 161    {
 162  103 if (o.equals(get(i)))
 163  38 return i;
 164    }
 165    }
 166  25 return -1;
 167    }
 168   
 169  1 public int lastIndexOf(Object o)
 170    {
 171  1 if (o == null)
 172    {
 173  1 for (int i = size() - 1; i >= 0; i--)
 174    {
 175  1 if (null == get(i))
 176  1 return i;
 177    }
 178    } else
 179    {
 180  0 for (int i = size() - 1; i >= 0; i--)
 181    {
 182  0 if (o.equals(get(i)))
 183  0 return i;
 184    }
 185    }
 186  0 return -1;
 187    }
 188   
 189  2916 public Object remove(int index)
 190    {
 191  2916 checkIndex();
 192    // Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
 193  2916 int size = size();
 194  2916 Object result = Null.toNullValue(detach(index, "REMOVE"));
 195  2916 if (size == (index + 1))
 196    {
 197  2903 return result; // We are the last one.
 198    }
 199  13 for (int i = index; i < size - 1; i++)
 200    {
 201  22 Object obj = detach(i + 1);
 202  22 attach(i, obj);
 203    }
 204  13 return result;
 205    }
 206   
 207  4 public Iterator iterator()
 208    {
 209    // TODO: check for concurrent modification
 210  4 return new Iterator()
 211    {
 212    // Need to share this
 213    int current = -1;
 214    int size = size();
 215   
 216  20 public boolean hasNext()
 217    {
 218  2 if (size == 0) return false;
 219  18 if (current > size)
 220  0 throw new NoSuchElementException("CachedSetImpl.iterator.hasNext(). " +
 221    " Cursor position " + current + " is greater than the size " + size());
 222   
 223  18 return current < size - 1;
 224    }
 225   
 226  16 public Object next()
 227    {
 228  16 if (current == size)
 229  0 throw new NoSuchElementException("CachedSetImpl.iterator.next(). " +
 230    " Cursor position " + current + " is greater than the size " + size());
 231   
 232  16 return Null.toNullValue(pojoCache.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(++current))));
 233    }
 234   
 235  10 public void remove()
 236    {
 237    // TODO Need optimization here since set does not care about index
 238  0 if (size == 0) return;
 239  10 if (current == size)
 240  0 throw new IllegalStateException("CachedSetImpl.iterator.remove(). " +
 241    " Cursor position " + current + " is greater than the size " + size);
 242  10 if (current < (size - 1))
 243    {
 244    // Need to reshuffle the items.
 245  7 Object last = detach(current, "REMOVE");
 246  7 for (int i = current + 1; i < size; i++)
 247    {
 248  12 last = detach(i);
 249  12 attach(i - 1, last);
 250    }
 251    } else
 252    { // we are the last index.
 253    // Need to move back the cursor.
 254  3 detach(current, "REMOVE");
 255    }
 256  10 current--;
 257  10 size--;
 258    }
 259    };
 260    }
 261   
 262  0 public List subList(int fromIndex, int toIndex)
 263    {
 264  0 if (fromIndex < 0)
 265  0 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
 266  0 if (toIndex > size())
 267  0 throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
 268  0 if (fromIndex > toIndex)
 269  0 throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
 270  0 if (fromIndex == toIndex) // request for empty list?
 271  0 return new LinkedList();
 272  0 return new MyCachedSubListImpl(this, fromIndex, toIndex);
 273    }
 274   
 275  5 public ListIterator listIterator()
 276    {
 277  5 return new MyListIterator(this, 0);
 278    }
 279   
 280  0 public ListIterator listIterator(int index)
 281    {
 282  0 return new MyListIterator(this, index);
 283    }
 284   
 285    static class MyListIterator implements ListIterator
 286    {
 287    int index = 0;
 288    List list_;
 289   
 290  5 public MyListIterator(List list, int index)
 291    {
 292  5 list_ = list;
 293  5 if (index < 0 || index > list_.size())
 294    {
 295  0 throw new IndexOutOfBoundsException("CachedListImpl: MyListIterator construction. " +
 296    " Index is out of bound : " + index);
 297    }
 298  5 this.index = index;
 299    }
 300   
 301  5 public int nextIndex()
 302    {
 303  5 return index;
 304    }
 305   
 306  18 public int previousIndex()
 307    {
 308  18 return index - 1;
 309    }
 310   
 311  3 public void remove()
 312    {
 313  3 int size = list_.size();
 314  0 if (size == 0) return;
 315  3 if (previousIndex() == size)
 316  0 throw new IllegalStateException("CachedSetImpl.MyListIterator.remove(). " +
 317    " Cursor position " + index + " is greater than the size " + size);
 318  3 if (previousIndex() < (size))
 319    {
 320  3 list_.remove(previousIndex());
 321  3 index--;
 322    }
 323    }
 324   
 325  6 public boolean hasNext()
 326    {
 327  6 return (index < list_.size());
 328    }
 329   
 330  1 public boolean hasPrevious()
 331    {
 332  1 return (index != 0);
 333    }
 334   
 335  12 public Object next()
 336    {
 337  12 if (index == list_.size())
 338  1 throw new NoSuchElementException();
 339   
 340  11 index++;
 341  11 return list_.get(index - 1); // pass zero relative index
 342    }
 343   
 344  6 public Object previous()
 345    {
 346  6 if (index == 0)
 347  1 throw new NoSuchElementException();
 348   
 349  5 index--;
 350  5 return list_.get(index);
 351    }
 352   
 353  1 public void add(Object o)
 354    {
 355  1 int size = list_.size();
 356  0 if (size == 0) return;
 357   
 358  1 if (previousIndex() == size)
 359  0 throw new IllegalStateException("CachedSetImpl.MyListIterator.add(). " +
 360    " Cursor position " + index + " is greater than the size " + size);
 361  1 if (previousIndex() < (size))
 362    {
 363  1 list_.add(previousIndex(), o);
 364    }
 365    }
 366   
 367  1 public void set(Object o)
 368    {
 369  1 int size = list_.size();
 370  0 if (size == 0) return;
 371   
 372  1 if (previousIndex() == size)
 373  0 throw new IllegalStateException("CachedSetImpl.MyListIterator.set(). " +
 374    " Cursor position " + index + " is greater than the size " + size);
 375  1 if (previousIndex() < (size))
 376    {
 377  1 list_.set(previousIndex(), o);
 378    }
 379    }
 380    }
 381   
 382    static public class MyCachedSubListImpl extends CachedListAbstract implements List
 383    {
 384   
 385    private List backStore_;
 386    private int fromIndex_;
 387    private int toIndex_;
 388   
 389  0 MyCachedSubListImpl(List backStore, int fromIndex, int toIndex)
 390    {
 391  0 backStore_ = backStore;
 392  0 fromIndex_ = fromIndex;
 393  0 toIndex_ = toIndex;
 394    }
 395   
 396  0 public int size()
 397    {
 398  0 int size = backStore_.size();
 399  0 if (size > toIndex_)
 400  0 size = toIndex_;
 401  0 size -= fromIndex_; // subtract number of items ignored at the start of list
 402  0 return size;
 403    }
 404   
 405  0 public Iterator iterator()
 406    {
 407    // TODO: check for concurrent modification
 408  0 return new Iterator()
 409    {
 410    int current = -1;
 411    Iterator iter_ = initializeIter();
 412   
 413  0 private Iterator initializeIter()
 414    {
 415  0 Iterator iter = backStore_.iterator();
 416  0 for (int looper = 0; looper < fromIndex_; looper++)
 417  0 if (iter.hasNext()) // skip past to where we need to start from
 418  0 iter.next();
 419  0 return iter;
 420    }
 421   
 422  0 public boolean hasNext()
 423    {
 424  0 int size = size();
 425  0 if (size == 0) return false;
 426  0 if (current > size)
 427  0 throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.hasNext(). " +
 428    " Cursor position " + current + " is greater than the size " + size());
 429   
 430  0 return current < size() - 1;
 431    }
 432   
 433  0 public Object next()
 434    {
 435  0 if (current == size())
 436  0 throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.next(). " +
 437    " Cursor position " + current + " is greater than the size " + size());
 438  0 current++;
 439  0 return iter_.next();
 440    }
 441   
 442  0 public void remove()
 443    {
 444  0 iter_.remove();
 445  0 current--;
 446    }
 447    };
 448   
 449    }
 450   
 451  0 public Object get(int index)
 452    {
 453  0 checkIndex(index);
 454  0 return backStore_.get(index + fromIndex_);
 455    }
 456   
 457  0 public Object set(int index, Object element)
 458    {
 459  0 checkIndex(index);
 460  0 return backStore_.set(index + fromIndex_, element);
 461    }
 462   
 463  0 public void add(int index, Object element)
 464    {
 465  0 backStore_.add(index + fromIndex_, element);
 466    }
 467   
 468  0 public Object remove(int index)
 469    {
 470  0 return backStore_.remove(index + fromIndex_);
 471    }
 472   
 473  0 public int indexOf(Object o)
 474    {
 475  0 int index = backStore_.indexOf(o);
 476  0 if (index < fromIndex_ || index >= toIndex_)
 477  0 index = -1;
 478    else
 479  0 index -= fromIndex_; // convert to be relative to our from/to range
 480  0 return index;
 481    }
 482   
 483  0 public int lastIndexOf(Object o)
 484    {
 485  0 int index = backStore_.lastIndexOf(o);
 486  0 if (index < fromIndex_ || index >= toIndex_)
 487  0 index = -1;
 488    else
 489  0 index -= fromIndex_; // convert to be relative to our from/to range
 490  0 return index;
 491    }
 492   
 493  0 public ListIterator listIterator()
 494    {
 495  0 return new MyListIterator(this, 0);
 496    }
 497   
 498  0 public ListIterator listIterator(int index)
 499    {
 500  0 return new MyListIterator(this, index);
 501    }
 502   
 503  0 public List subList(int fromIndex, int toIndex)
 504    {
 505  0 if (fromIndex < 0)
 506  0 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
 507  0 if (toIndex > size())
 508  0 throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
 509  0 if (fromIndex > toIndex)
 510  0 throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
 511  0 if (fromIndex == toIndex) // request for empty list?
 512  0 return new LinkedList();
 513  0 return new MyCachedSubListImpl(this, fromIndex, toIndex);
 514    }
 515   
 516  0 private void checkIndex(int i)
 517    {
 518  0 if (size() == 0) return; // No need to check here.
 519  0 if (i < 0 || i >= size())
 520    {
 521  0 throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " + i
 522    + " but size is " + size());
 523    }
 524    }
 525   
 526    }
 527   
 528    }