gt: 		Collection holdersColl = createHolders(c);
context: package com.alvazan.orm.impl.meta.data.collections;
  
  import java.lang.reflect.Field;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.List;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.alvazan.orm.api.z5api.NoSqlSession;
  import com.alvazan.orm.api.z8spi.KeyValue;
  import com.alvazan.orm.api.z8spi.Row;
  import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
  import com.alvazan.orm.api.z8spi.iter.IndiceToVirtual;
  import com.alvazan.orm.api.z8spi.iter.ListWrappingCursor;
  import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
  import com.alvazan.orm.impl.meta.data.MetaAbstractClass;
  import com.alvazan.orm.impl.meta.data.NoSqlProxy;
  
  @SuppressWarnings({"unchecked", "rawtypes"})
  public abstract class OurAbstractCollection<T> implements Collection<T>, CacheLoadCallback {
  
  	private static final Logger log = LoggerFactory.getLogger(OurAbstractCollection.class);
  	
  	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  	
  	private NoSqlSession session;
  	protected MetaAbstractClass<T> metaClass;
  	
  	private List<byte[]> keys;
  	protected List<Holder<T>> originalHolders = new ArrayList<Holder<T>>();
  	private boolean cacheLoaded = false;
  
  	private boolean removeAll;
  	//cannot be a Set or we may get nullpointer as sometimes the key does not exist yet and doing
  	//key.hashCode results in null as adding to a HashSet will use hashCode and equals while List does not
  	protected List<Holder<T>> added = new ArrayList<Holder<T>>();
  
  	private Object owner;
  	private String field;
  	
      public OurAbstractCollection(Object owner, NoSqlSession session2, MetaAbstractClass<T> classMeta2, List<byte[]> keys, Field field) {
  		this.session = session2;
  		this.metaClass = classMeta2;
  		this.owner = owner;
  		this.keys = keys;
  		
  		this.field = field.getDeclaringClass().getSimpleName();
  		this.field += "."+field.getName();
  	}
      
  	protected abstract Collection<Holder<T>> getHolders();
      
  	//Callback from one of the proxies to load the entire cache based
  	//on a hit of getXXXXX (except for getId which doesn't need to go to database)
  	public void loadCacheIfNeeded() {
  		if(cacheLoaded)
  			return;
  		
  		DboTableMeta metaDbo = metaClass.getMetaDbo();
  		IndiceToVirtual virtKeys = new IndiceToVirtual(metaDbo, new ListWrappingCursor<byte[]>(keys));
  		AbstractCursor<KeyValue<Row>> rows = session.find(metaDbo, virtKeys, false, true, null);
  		String name = getClass().getSimpleName();
  		if (log.isInfoEnabled())
  			log.info(name+":just loaded rows for keylist(next convert to proxies)="+keys.size()+" for field="+field);
  		int counter = 0;
  		while(true) {
  			com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<KeyValue<Row>> holder = rows.nextImpl();
  			if(holder == null)
  				break;
  			KeyValue<Row> kv = holder.getValue();
  			Row row = kv.getValue();
  			if(row != null || metaDbo.isEmbeddable()) {
  				Holder<T> h = (Holder) originalHolders.get(counter);
  				T value = h.getValue();
  				if(value instanceof NoSqlProxy) {
  					//inject the row into the proxy object here to load it's fields
  					metaClass.fillInInstance(row, session, value);
  					//((NoSqlProxy)value).__injectData(row);
  				}
  			}
  			
  			counter++;
  		}
  		cacheLoaded = true;
  	}
      
  	@Override
  	public int size() {
  		return getHolders().size();
  	}
  
  	@Override
  	public boolean isEmpty() {
  		return size() == 0;
  	}
  	
  	@Override
  	public boolean contains(Object o) {
  		Holder<T> h = new Holder<T>(metaClass, (T) o);
  		return getHolders().contains(h);
  	}
  	
      public <E> E[] toArray(E[] a) {
          // Estimate size of array; be prepared to see more or fewer elements
          int size = size();
          E[] r = a;
          if(a.length < size)
          	r = (E[])java.lang.reflect.Array
                      .newInstance(a.getClass().getComponentType(), size);
          
          Iterator<Holder<T>> it = getHolders().iterator();
  
          for (int i = 0; i < r.length; i++) {
              if (! it.hasNext()) { // fewer elements than expected
                  if (a != r)
                      return Arrays.copyOf(r, i);
                  r[i] = null; // null-terminate
                  return r;
              }
              r[i] = (E)it.next().getValue();
          }
          
          if(it.hasNext())
          	return finishToArray(r, it);
          return r;
      }
      
      public Object[] toArray() {
          // Estimate size of array; be prepared to see more or fewer elements
          T[] r = (T[]) new Object[size()];
          Iterator<Holder<T>> it = getHolders().iterator();
          for (int i = 0; i < r.length; i++) {
              if (! it.hasNext()) // fewer elements than expected
                  return Arrays.copyOf(r, i);
              r[i] = it.next().getValue();
          }
          if(it.hasNext())
          	return finishToArray(r, it);
          return r;
      }
  
  	private static <E> E[] finishToArray(E[] r2, Iterator it2) {
  		E[] r = r2;
  		Iterator<Holder<E>> it = it2;
          int i = r.length;
          while (it.hasNext()) {
              int cap = r.length;
              if (i == cap) {
                  int newCap = cap + (cap >> 1) + 1;
                  // overflow-conscious code
                  if (newCap - MAX_ARRAY_SIZE > 0)
                      newCap = hugeCapacity(cap + 1);
                  r = Arrays.copyOf(r, newCap);
              }
              r[i++] = (E)it.next().getValue();
          }
          // trim if overallocated
          if(i == r.length)
          	return r;
          return Arrays.copyOf(r, i);
      }
      
      private static int hugeCapacity(int minCapacity) {
          if (minCapacity < 0) // overflow
              throw new OutOfMemoryError
                  ("Required array size too large");
          if(minCapacity > MAX_ARRAY_SIZE)
          	return Integer.MAX_VALUE;
          return MAX_ARRAY_SIZE;
      }
      
  	private class OurItr implements Iterator<T> {
  		private Iterator delegate;
  		private Holder lastReturned;
  
  		public OurItr(Iterator iter) {
  			delegate = iter;
  		}
  		@Override
  		public boolean hasNext() {
  			return delegate.hasNext();
  		}
  
  		@Override
  		public T next() {
  			Holder holder = (Holder) delegate.next();
  			lastReturned = holder;
  			return (T) holder.getValue();
  		}
  
  		@Override
  		public void remove() {
  			added.remove(lastReturned);
  			delegate.remove();
  		}
  	}
  	
  	@Override
  	public Iterator<T> iterator() {
  		return new OurItr(getHolders().iterator());
  	}
  
  	@Override
  	public boolean containsAll(Collection<?> c) {
  		Collection holdersColl = createHolders(c);
  		return getHolders().containsAll(holdersColl);
  	}
  	
  	protected Collection createHolders(Collection c) {
  		Collection holders = new ArrayList();
  		for(Object val : c) {
  			Holder h = new Holder(metaClass, val);
  			holders.add(h);
  		}
  		return holders;
  	}
  
  	@Override
  	public boolean removeAll(Collection<?> c) {
  		loadCacheIfNeeded();
  		Collection holdersColl = createHolders(c);
  		added.removeAll(holdersColl);
  		return getHolders().removeAll(holdersColl);
  	}
  
  	@Override
  	public boolean retainAll(Collection<?> c) {
  		loadCacheIfNeeded();
  