Package org.slim3.datastore

Source Code of org.slim3.datastore.ModelQuery

/*
* Copyright 2004-2010 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.slim3.datastore;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slim3.util.ConversionUtil;

import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.QueryResultIterator;
import com.google.appengine.api.datastore.QueryResultList;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.Query.FilterOperator;

/**
* A query class for select.
*
* @author higa
* @param <M>
*            the model type
* @since 1.0.0
*
*/
public class ModelQuery<M> extends AbstractQuery<ModelQuery<M>> {

    /**
     * The meta data of model.
     */
    protected ModelMeta<M> modelMeta;

    /**
     * The in-memory filter criteria.
     */
    protected List<InMemoryFilterCriterion> inMemoryFilterCriteria =
        new ArrayList<InMemoryFilterCriterion>();

    /**
     * The in-memory sort orders.
     */
    protected List<InMemorySortCriterion> inMemorySortCriteria =
        new ArrayList<InMemorySortCriterion>();

    /**
     * Constructor.
     *
     * @param modelMeta
     *            the meta data of model
     * @throws NullPointerException
     *             if the modelMeta parameter is null
     */
    public ModelQuery(ModelMeta<M> modelMeta) throws NullPointerException {
        if (modelMeta == null) {
            throw new NullPointerException("The modelMeta parameter is null.");
        }
        this.modelMeta = modelMeta;
        setUpQuery(modelMeta.getKind());
    }

    /**
     * Constructor.
     *
     * @param modelMeta
     *            the meta data of model
     * @param ancestorKey
     *            the ancestor key
     * @throws NullPointerException
     *             if the modelMeta parameter is null or if the ancestorKey
     *             parameter is null
     */
    public ModelQuery(ModelMeta<M> modelMeta, Key ancestorKey)
            throws NullPointerException {
        if (modelMeta == null) {
            throw new NullPointerException("The modelMeta parameter is null.");
        }
        if (ancestorKey == null) {
            throw new NullPointerException("The ancestorKey parameter is null.");
        }
        this.modelMeta = modelMeta;
        setUpQuery(modelMeta.getKind(), ancestorKey);
    }

    /**
     * Constructor.
     *
     * @param tx
     *            the transaction
     * @param modelMeta
     *            the meta data of model
     * @param ancestorKey
     *            the ancestor key
     * @throws NullPointerException
     *             if the modelMeta parameter is null or if the ancestorKey
     *             parameter is null
     */
    public ModelQuery(Transaction tx, ModelMeta<M> modelMeta, Key ancestorKey)
            throws NullPointerException {
        if (modelMeta == null) {
            throw new NullPointerException("The modelMeta parameter is null.");
        }
        if (ancestorKey == null) {
            throw new NullPointerException("The ancestorKey parameter is null.");
        }
        setTx(tx);
        this.modelMeta = modelMeta;
        setUpQuery(modelMeta.getKind(), ancestorKey);
    }

    /**
     * Adds the filter criteria.
     *
     * @param criteria
     *            the filter criteria
     * @return this instance
     * @throws NullPointerException
     *             if the element of the criteria parameter is null
     */
    public ModelQuery<M> filter(FilterCriterion... criteria)
            throws NullPointerException {
        for (FilterCriterion c : criteria) {
            if (c == null) {
                throw new NullPointerException(
                    "The element of the criteria parameter must not be null.");
            }
            for (Filter f : c.getFilters()) {
                query.addFilter(f.getPropertyName(), f.getOperator(), f
                    .getValue());
            }
        }
        return this;
    }

    /**
     * Adds the in-memory filter criteria.
     *
     * @param criteria
     *            the in-memory filter criteria
     * @return this instance
     * @throws NullPointerException
     *             if the element of the criteria parameter is null
     */
    public ModelQuery<M> filterInMemory(InMemoryFilterCriterion... criteria)
            throws NullPointerException {
        for (InMemoryFilterCriterion c : criteria) {
            if (c == null) {
                throw new NullPointerException(
                    "The element of the criteria parameter must not be null.");
            }
            inMemoryFilterCriteria.add(c);
        }
        return this;
    }

    /**
     * Adds the sort criteria.
     *
     * @param criteria
     *            the sort criteria
     * @return this instance
     * @throws NullPointerException
     *             if the element of the criteria parameter is null
     */
    public ModelQuery<M> sort(SortCriterion... criteria)
            throws NullPointerException {
        for (SortCriterion c : criteria) {
            if (c == null) {
                throw new NullPointerException(
                    "The element of the criteria parameter must not be null.");
            }
            Sort s = c.getSort();
            query.addSort(s.getPropertyName(), s.getDirection());
        }
        return this;
    }

    /**
     * Adds the in-memory sort criteria.
     *
     * @param criteria
     *            the in-memory sort criteria
     * @return this instance
     * @throws NullPointerException
     *             if the element of the criteria parameter is null
     */
    public ModelQuery<M> sortInMemory(InMemorySortCriterion... criteria)
            throws NullPointerException {
        for (InMemorySortCriterion c : criteria) {
            if (c == null) {
                throw new NullPointerException(
                    "The element of the criteria parameter must not be null.");
            }
            inMemorySortCriteria.add(c);
        }
        return this;
    }

    /**
     * Returns the result as a list.
     *
     * @return the result as a list
     */
    public List<M> asList() {
        addFilterIfPolyModel();
        List<Entity> entityList = asEntityList();
        List<M> ret = new ArrayList<M>(entityList.size());
        for (Entity e : entityList) {
            ModelMeta<M> mm = DatastoreUtil.getModelMeta(modelMeta, e);
            ret.add(mm.entityToModel(e));
        }
        ret = DatastoreUtil.filterInMemory(ret, inMemoryFilterCriteria);
        return DatastoreUtil.sortInMemory(ret, inMemorySortCriteria);
    }

    /**
     * Returns a query result list.
     *
     * @return a query result list
     */
    public S3QueryResultList<M> asQueryResultList() {
        if (inMemoryFilterCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of asQueryResultList(), you cannot specify filterInMemory().");
        }
        if (inMemorySortCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of asQueryResultList(), you cannot specify sortInMemory().");
        }
        addFilterIfPolyModel();
        List<M> modelList = null;
        boolean hasNext = false;
        Cursor cursor = null;
        int limit = fetchOptions.getLimit();
        if (limit == Integer.MAX_VALUE) {
            QueryResultList<Entity> entityList = asQueryResultEntityList();
            modelList = new ArrayList<M>(entityList.size());
            for (Entity e : entityList) {
                ModelMeta<M> mm = DatastoreUtil.getModelMeta(modelMeta, e);
                modelList.add(mm.entityToModel(e));
            }
            cursor = entityList.getCursor();
        } else {
            fetchOptions.limit(limit + 1);
            modelList = new ArrayList<M>();
            QueryResultIterator<Entity> ite = asQueryResultEntityIterator();
            while (true) {
                hasNext = ite.hasNext();
                if (!hasNext || modelList.size() == limit) {
                    cursor = ite.getCursor();
                    break;
                }
                Entity e = ite.next();
                ModelMeta<M> mm = DatastoreUtil.getModelMeta(modelMeta, e);
                modelList.add(mm.entityToModel(e));
            }
        }
        return new S3QueryResultList<M>(
            modelList,
            cursor.toWebSafeString(),
            getEncodedFilters(),
            getEncodedSorts(),
            hasNext);
    }

    /**
     * Returns the single result or null if no entities match.
     *
     * @return the single result
     * @throws PreparedQuery.TooManyResultsException
     *             if the number of the results are more than 1 entity.
     *
     */
    public M asSingle() throws PreparedQuery.TooManyResultsException {
        List<M> list = asList();
        if (list.size() == 0) {
            return null;
        }
        if (list.size() > 1) {
            throw new PreparedQuery.TooManyResultsException();
        }
        return list.get(0);
    }

    /**
     * Returns a list of keys.
     *
     * @return a list of keys
     * @throws IllegalStateException
     *             if in-memory filers are specified
     */
    @Override
    public List<Key> asKeyList() throws IllegalStateException {
        if (inMemoryFilterCriteria.size() > 0) {
            throw new IllegalStateException(
                "In the case of asKeyList(), you cannot specify filterInMemory().");
        }
        addFilterIfPolyModel();
        List<Key> keys = super.asKeyList();
        if (inMemorySortCriteria.size() > 0 && inMemorySortCriteria.size() == 1) {
            InMemorySortCriterion c = inMemorySortCriteria.get(0);
            if (c instanceof AbstractCriterion) {
                if (((AbstractCriterion) c).attributeMeta.name
                    .equals(Entity.KEY_RESERVED_PROPERTY)) {
                    if (c instanceof AscCriterion) {
                        Collections.sort(keys);
                    } else {
                        Collections.sort(keys, KeyDescComparator.INSTANCE);
                    }
                    return keys;
                }
            }
            throw new IllegalStateException(
                "In the case of asKeyList(), you cannot specify sortInMemory() except for primary key.");
        }
        return keys;
    }

    /**
     * Return a minimum value of the property. The value does not include null.
     *
     * @param <A>
     *            the attribute type
     * @param attributeMeta
     *            the meta data of attribute
     * @return a minimum value of the property
     * @throws NullPointerException
     *             if the attributeMeta parameter is null
     * @throws IllegalStateException
     *             if in-memory filers are specified or if in-memory sorts are
     *             specified
     */
    @SuppressWarnings("unchecked")
    public <A> A min(CoreAttributeMeta<M, A> attributeMeta)
            throws NullPointerException, IllegalStateException {
        if (attributeMeta == null) {
            throw new NullPointerException(
                "The attributeMeta parameter is null.");
        }
        if (inMemoryFilterCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of min(), you cannot specify filterInMemory().");
        }
        if (inMemorySortCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of min(), you cannot specify sortInMemory().");
        }
        addFilterIfPolyModel();
        Object value = super.min(attributeMeta.getName());
        return (A) ConversionUtil.convert(value, attributeMeta
            .getAttributeClass());
    }

    /**
     * Return a maximum value of the property.
     *
     * @param <A>
     *            the attribute type
     * @param attributeMeta
     *            the meta data of attribute
     * @return a maximum value of the property
     * @throws NullPointerException
     *             if the attributeMeta parameter is null
     * @throws IllegalStateException
     *             if in-memory filters are specified or if in-memory sorts are
     *             specified
     */
    @SuppressWarnings("unchecked")
    public <A> A max(CoreAttributeMeta<M, A> attributeMeta)
            throws NullPointerException, IllegalStateException {
        if (attributeMeta == null) {
            throw new NullPointerException(
                "The attributeMeta parameter is null.");
        }
        if (inMemoryFilterCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of max(), you cannot specify filterInMemory().");
        }
        if (inMemorySortCriteria.size() > 0) {
            throw new IllegalStateException(
                "In case of max(), you cannot specify sortInMemory().");
        }
        addFilterIfPolyModel();
        Object value = super.max(attributeMeta.getName());
        return (A) ConversionUtil.convert(value, attributeMeta
            .getAttributeClass());
    }

    /**
     * Returns a number of entities.
     *
     * @return a number of entities
     */
    @Override
    public int count() {
        inMemorySortCriteria.clear();
        addFilterIfPolyModel();
        if (inMemoryFilterCriteria.size() > 0) {
            return asList().size();
        }
        return super.count();
    }

    /**
     * Adds a filter for polymorphic model.
     */
    protected void addFilterIfPolyModel() {
        if (modelMeta.getClassHierarchyList().isEmpty()) {
            return;
        }
        query.addFilter(
            modelMeta.getClassHierarchyListName(),
            FilterOperator.EQUAL,
            modelMeta.getModelClass().getName());
    }
}
TOP

Related Classes of org.slim3.datastore.ModelQuery

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.