Package com.spaceprogram.simplejpa

Source Code of com.spaceprogram.simplejpa.LazyList$LazyListIterator

package com.spaceprogram.simplejpa;

import java.io.Serializable;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.PersistenceException;

import com.amazonaws.AmazonClientException;
import com.amazonaws.services.simpledb.model.Item;
import com.amazonaws.services.simpledb.model.SelectResult;
import com.spaceprogram.simplejpa.query.JPAQuery;
import com.spaceprogram.simplejpa.query.QueryImpl;

import org.apache.commons.collections.list.GrowthList;

/**
* Loads objects in the list on demand from SimpleDB. <p/> <p/> User: treeder Date: Feb 10, 2008 Time: 9:06:16 PM
*/
@SuppressWarnings("unchecked")
public class LazyList<E> extends AbstractList<E> implements Serializable {
    private static Logger logger = Logger.getLogger(LazyList.class.getName());

    private transient EntityManagerSimpleJPA em;
    private Class genericReturnType;
    private QueryImpl origQuery;

    /**
     * Stores the actual objects for this list
     */
    private List<E> backingList;
    private String nextToken;
    private int count = -1;
    private String realQuery;
    private String domainName;
    private int maxResults = -1;
    private int maxResultsPerToken = QueryImpl.MAX_RESULTS_PER_REQUEST;
    private boolean consistentRead = true;

    public LazyList(EntityManagerSimpleJPA em, Class tClass, QueryImpl query) {
        this.em = em;
        this.genericReturnType = tClass;
        this.origQuery = query;
        this.maxResults = query.getMaxResults();
        this.consistentRead = query.isConsistentRead();
        AnnotationInfo ai = em.getAnnotationManager().getAnnotationInfo(genericReturnType);
        try {
            domainName = em.getDomainName(ai.getRootClass());
            if (domainName == null) {
                logger.warning("Domain does not exist for " + ai.getRootClass());
                backingList = new GrowthList(0);
            } else {
                // Do not include the limit in the query since will specify in loadAtLeastItems()
                realQuery = query.createAmazonQuery(false).getValue();
            }
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    public int size() {
        if (count > -1)
            return count;

        if (backingList != null && nextToken == null) {
            count = backingList.size();
        } else {
            try {
                if (logger.isLoggable(Level.FINER))
                    logger.finer("Getting size.");
                JPAQuery queryClone = (JPAQuery) origQuery.getQ().clone();
                queryClone.setResult("count(*)");
                QueryImpl query2 = new QueryImpl(em, queryClone);
                query2.setParameters(origQuery.getParameters());
                query2.setForeignIds(origQuery.getForeignIds());
                List results = query2.getResultList();
                int resultCount = ((Long) results.get(0)).intValue();
                if (logger.isLoggable(Level.FINER))
                    logger.finer("Got:" + resultCount);

                if (maxResults >= 0 && resultCount > maxResults) {
                    if (logger.isLoggable(Level.FINER))
                        logger.finer("Too much, adjusting to maxResults: " + maxResults);
                    count = maxResults;
                } else {
                    count = resultCount;
                }
            } catch (CloneNotSupportedException e) {
                throw new PersistenceException(e);
            }
        }
        return count;
    }

    public int getFetchedSize() {
        return backingList == null ? 0 : backingList.size();
    }

    public void add(int index, E element) {
        backingList.add(index, element);
    }

    public E set(int index, E element) {
        return backingList.set(index, element);
    }

    public E remove(int index) {
        return backingList.remove(index);
    }

    public void setMaxResultsPerToken(int maxResultsPerToken) {
        // SimpleDB currently has a maximum limit of 2500
        this.maxResultsPerToken = Math.min(maxResultsPerToken, QueryImpl.MAX_RESULTS_PER_REQUEST);
    }

    public int getMaxResultsPerToken() {
        return maxResultsPerToken;
    }

    public E get(int i) {
        if (logger.isLoggable(Level.FINER))
            logger.finer("getting from lazy list at index=" + i);
        loadAtleastItems(i);
        return backingList.get(i);
    }

    private synchronized void loadAtleastItems(int index) {
        if ((backingList != null && nextToken == null) || (!noLimit() && index >= maxResults)) {
            return;
        }

        if (backingList == null) {
            backingList = new GrowthList();
        }

        while (backingList.size() <= index) {
            SelectResult qr;
            try {
                if (logger.isLoggable(Level.FINER))
                    logger.finer("query for lazylist=" + origQuery);

                int limit = maxResults - backingList.size();
                String limitQuery = realQuery + " limit " + (noLimit() ? maxResultsPerToken : Math.min(maxResultsPerToken, limit));
                if (em.getFactory().isPrintQueries())
                    System.out.println("query in lazylist=" + limitQuery);
                qr = DomainHelper.selectItems(this.em.getSimpleDb(), limitQuery, nextToken, isConsistentRead());

                if (logger.isLoggable(Level.FINER))
                    logger.finer("got items for lazylist=" + qr.getItems().size());

                for (Item item : qr.getItems()) {
                    backingList.add((E) em.buildObject(genericReturnType, item.getName(), item.getAttributes()));
                }

                if (qr.getNextToken() == null || (!noLimit() && qr.getItems().size() == limit)) {
                    nextToken = null;
                    break;
                }

                if (!noLimit() && qr.getItems().size() > limit) {
                    throw new PersistenceException("Got more results than the limit.");
                }

                nextToken = qr.getNextToken();
            } catch (AmazonClientException e) {
                throw new PersistenceException("Query failed: Domain=" + domainName + " -> " + origQuery, e);
            }
        }

    }

    private boolean noLimit() {
        return maxResults < 0;
    }

    @Override
    public Iterator<E> iterator() {
        return new LazyListIterator();
    }

    public void setConsistentRead(boolean consistentRead) {
        this.consistentRead = consistentRead;
    }

    public boolean isConsistentRead() {
        return consistentRead;
    }

    private class LazyListIterator implements Iterator<E> {
        private int iNext = 0;

        public boolean hasNext() {
            loadAtleastItems(iNext);
            return backingList.size() > iNext;
        }

        public E next() {
            return get(iNext++);
        }

        public void remove() {
            LazyList.this.remove(iNext - 1);
        }
    }
}
TOP

Related Classes of com.spaceprogram.simplejpa.LazyList$LazyListIterator

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.