Package com.alvazan.orm.impl.meta.data.collections

Source Code of com.alvazan.orm.impl.meta.data.collections.OurAbstractCollection

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();
    Collection holdersColl = createHolders(c);
    added.retainAll(holdersColl);
    return getHolders().retainAll(holdersColl);
  }

  @Override
  public void clear() {
    removeAll = true;
    added.clear();
    getHolders().clear();
  }

  @Override
  public boolean addAll(Collection<? extends T> c) {
    Collection holdersColl = createHolders(c);
    added.addAll(holdersColl);
    return getHolders().addAll(holdersColl);
  }
 
  @Override
  public boolean add(T e) {
    Holder<T> h = new Holder<T>(metaClass, e);
    added.add(h);
    return getHolders().add(h);
  }

  @Override
  public boolean remove(Object o) {
    loadCacheIfNeeded(); //we have to do this so equals will work
    Holder<T> h = new Holder<T>(metaClass, (T) o);
    added.remove(h);
    return getHolders().remove(h);
  }

  public Collection<T> getToBeRemoved() {
    List<T> removes = new ArrayList<T>();
    if(!removeAll && !cacheLoaded)
      return removes;

    //if they removed all, they coudl have added some back so here we check for what was
    //truly removed in the end
    Collection<Holder<T>> current = getHolders();
    for(Holder<T> holder : originalHolders) {
      if(!current.contains(holder))
        removes.add(holder.getValue());
    }
    return removes;
  }

  public Collection<T> getToBeAdded() {
    List<T> adds = new ArrayList<T>();
    for(Holder<T> h : added) {
      adds.add(h.getValue());
    }
    return adds;
  }
 
    public String toString() {
      String name = getClass().getSimpleName();
        Iterator<T> i = iterator();
    if (! i.hasNext())
        return name+"[]";
 
    StringBuilder sb = new StringBuilder();
    sb.append(name);
    sb.append('[');
    for (;;) {
        T e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
      return sb.append(']').toString();
        sb.append(", ");
    }
    }
}
TOP

Related Classes of com.alvazan.orm.impl.meta.data.collections.OurAbstractCollection

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.