All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mysema.query.jdoql.AbstractJDOQLQuery Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2009 Mysema Ltd.
 * All rights reserved.
 *
 */
package com.mysema.query.jdoql;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.mysema.commons.lang.CloseableIterator;
import com.mysema.commons.lang.IteratorAdapter;
import com.mysema.query.DefaultQueryMetadata;
import com.mysema.query.QueryException;
import com.mysema.query.QueryMetadata;
import com.mysema.query.QueryModifiers;
import com.mysema.query.SearchResults;
import com.mysema.query.support.ProjectableQuery;
import com.mysema.query.support.QueryMixin;
import com.mysema.query.types.EntityPath;
import com.mysema.query.types.Expr;
import com.mysema.query.types.FactoryExpression;
import com.mysema.query.types.expr.QTuple;

/**
 * Abstract base class for custom implementations of the JDOQLQuery interface.
 *
 * @author tiwe
 *
 * @param 
 */
public abstract class AbstractJDOQLQuery> extends ProjectableQuery{

    private final Closeable closeable = new Closeable(){
        @Override
        public void close() throws IOException {
            AbstractJDOQLQuery.this.close();            
        }        
    };
    
    private final boolean detach;

    private List orderedConstants = new ArrayList();

    @Nullable
    private final PersistenceManager persistenceManager;

    private List queries = new ArrayList(2);

    private final JDOQLTemplates templates;
    
    private Set fetchGroups = new HashSet();
    
    @Nullable
    private Integer maxFetchDepth;

    public AbstractJDOQLQuery(@Nullable PersistenceManager persistenceManager) {
        this(persistenceManager, JDOQLTemplates.DEFAULT, new DefaultQueryMetadata(), false);
    }

    @SuppressWarnings("unchecked")
    public AbstractJDOQLQuery(
            @Nullable PersistenceManager persistenceManager,
            JDOQLTemplates templates,
            QueryMetadata metadata, boolean detach) {
        super(new QueryMixin(metadata));
        this.queryMixin.setSelf((Q) this);
        this.templates = templates;
        this.persistenceManager = persistenceManager;
        this.detach = detach;
    }

    @SuppressWarnings("unchecked")
    public Q addFetchGroup(String fetchGroupName) {
        fetchGroups.add(fetchGroupName);
        return (Q)this;
    }

    public void close() {
        for (Query query : queries){
            query.closeAll();
        }
    }

    public long count() {
        Query query = createQuery(true);
        query.setUnique(true);
        reset();
        Long rv = (Long) execute(query);
        if (rv != null){
            return rv.longValue();
        }else{
            throw new QueryException("Query returned null");
        }
    }

    private Query createQuery(boolean forCount) {
        Expr source = queryMixin.getMetadata().getJoins().get(0).getTarget();

        // serialize
        JDOQLSerializer serializer = new JDOQLSerializer(getTemplates(), source);
        serializer.serialize(queryMixin.getMetadata(), forCount, false);

        // create Query
        Query query = persistenceManager.newQuery(serializer.toString());
        orderedConstants = serializer.getConstants();
        queries.add(query);

        if (!forCount){
            List> projection = queryMixin.getMetadata().getProjection();
            Class exprType = projection.get(0).getClass();
            if (exprType.equals(QTuple.class)){
                query.setResultClass(JDOTuple.class);
            } else if (FactoryExpression.class.isAssignableFrom(exprType)){
                query.setResultClass(projection.get(0).getType());
            }
            
            if (!fetchGroups.isEmpty()){
                query.getFetchPlan().setGroups(fetchGroups);
            }
            if (maxFetchDepth != null){
                query.getFetchPlan().setMaxFetchDepth(maxFetchDepth);
            }
        }

        return query;
    }

    @SuppressWarnings("unchecked")
    private  T detach(T results){
        if (results instanceof Collection){
            return (T) persistenceManager.detachCopyAll(results);
        }else{
            return persistenceManager.detachCopy(results);
        }
    }

    private Object execute(Query query) {
        Object rv;
        if (!orderedConstants.isEmpty()) {
            rv = query.executeWithArray(orderedConstants.toArray());
        } else {
            rv = query.execute();
        }
        if (isDetach()){
            rv = detach(rv);
        }
        return rv;
    }

    public Q from(EntityPath... args) {
        return queryMixin.from(args);
    }

    public QueryMetadata getMetadata(){
        return queryMixin.getMetadata();
    }

    public JDOQLTemplates getTemplates() {
        return templates;
    }

    public boolean isDetach() {
        return detach;
    }

    public CloseableIterator iterate(Expr[] args) {
        return new IteratorAdapter(list(args).iterator(), closeable);
    }

    public  CloseableIterator iterate(Expr projection) {
        return new IteratorAdapter(list(projection).iterator(), closeable);
    }

    @SuppressWarnings("unchecked")
    public List list(Expr[] args) {
        queryMixin.addToProjection(args);
        Object rv = execute(createQuery(false));
        reset();
        return (rv instanceof List) ? ((List)rv) : Collections.singletonList((Object[])rv);
    }

    @SuppressWarnings("unchecked")
    public  List list(Expr expr) {
        queryMixin.addToProjection(expr);
        Object rv = execute(createQuery(false));
        reset();
        return rv instanceof List ? (List)rv : Collections.singletonList((RT)rv);
    }

    @SuppressWarnings("unchecked")
    public  SearchResults listResults(Expr expr) {
        queryMixin.addToProjection(expr);
        Query countQuery = createQuery(true);
        countQuery.setUnique(true);
        countQuery.setResult("count(this)");
        long total = (Long) execute(countQuery);
        if (total > 0) {
            QueryModifiers modifiers = queryMixin.getMetadata().getModifiers();
            Query query = createQuery(false);
            reset();
            return new SearchResults((List) execute(query), modifiers, total);
        } else {
            reset();
            return SearchResults.emptyResults();
        }
    }

    private void reset(){
        queryMixin.getMetadata().reset();
    }

    @SuppressWarnings("unchecked")
    public Q setMaxFetchDepth(int depth) {
        maxFetchDepth = depth;
        return (Q)this;
    }
    

    @Override
    public String toString(){
        if (!queryMixin.getMetadata().getJoins().isEmpty()){
            Expr source = queryMixin.getMetadata().getJoins().get(0).getTarget();
            JDOQLSerializer serializer = new JDOQLSerializer(getTemplates(), source);
            serializer.serialize(queryMixin.getMetadata(), false, false);
            return serializer.toString().trim();
        }else{
            return super.toString();
        }
    }

    @SuppressWarnings("unchecked")
    public  RT uniqueResult(Expr expr) {
        queryMixin.addToProjection(expr);
        Query query = createQuery(false);
        query.setUnique(true);
        reset();
        return (RT) execute(query);
    }
}