Package org.apache.ojb.broker.query

Source Code of org.apache.ojb.broker.query.QueryByCriteria

package org.apache.ojb.broker.query;

/* Copyright 2002-2005 The Apache Software Foundation
*
* 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.
*/

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.FieldHelper;
import org.apache.ojb.broker.metadata.MetadataManager;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
import org.apache.ojb.broker.util.logging.LoggerFactory;

/**
* represents a search by criteria.
* "find all articles where article.price > 100"
* could be represented as:
*
* Criteria crit = new Criteria();
* crit.addGreaterThan("price", new Double(100));
* Query qry = new QueryByCriteria(Article.class, crit);
*
* The PersistenceBroker can retrieve Objects by Queries as follows:
*
* PersistenceBroker broker = PersistenceBrokerFactory.createPersistenceBroker();
* Collection col = broker.getCollectionByQuery(qry);
*
* Creation date: (24.01.2001 21:45:46)
* @author Thomas Mahler
* @version $Id: QueryByCriteria.java,v 1.26.2.4 2005/12/21 22:27:09 tomdz Exp $
*/
public class QueryByCriteria extends AbstractQueryImpl
{
    private Criteria m_criteria;
    private boolean m_distinct = false;
    private Map m_pathClasses;
    private Criteria m_havingCriteria;
  private String m_objectProjectionAttribute;

    // holding FieldHelper for orderBy and groupBy
    private List m_orderby = null;
    private List m_groupby = null;

    // list of names of prefetchable relationships
    private List m_prefetchedRelationships = null;

    private Collection m_pathOuterJoins = null;

    /**
     * handy criteria that can be used to select all instances of
     * a class.
     */
    public static final Criteria CRITERIA_SELECT_ALL = null;

    /**
     * Build a Query for class targetClass with criteria.
     * Criteriy may be null (will result in a query returning ALL objects from a table)
     */
    public QueryByCriteria(Class targetClass, Criteria whereCriteria, Criteria havingCriteria, boolean distinct)
    {
        super (targetClass);

        setCriteria(whereCriteria);
        setHavingCriteria(havingCriteria);

        m_distinct = distinct;
        m_pathClasses = new HashMap();
        m_groupby = new ArrayList();
        m_orderby = new ArrayList();
        m_prefetchedRelationships = new ArrayList();
        m_pathOuterJoins = new HashSet();
    }

    /**
     * Build a Query for class targetClass with criteria.
     * Criteriy may be null (will result in a query returning ALL objects from a table)
     */
    public QueryByCriteria(Class targetClass, Criteria whereCriteria, Criteria havingCriteria)
    {
        this(targetClass, whereCriteria, havingCriteria, false);
    }


    /**
     * Build a Query for class targetClass with criteria.
     * Criteriy may be null (will result in a query returning ALL objects from a table)
     */
    public QueryByCriteria(Class targetClass, Criteria criteria)
    {
        this(targetClass, criteria, false);
    }

    /**
     * Build a Query for class targetClass with criteria.
     * Criteriy may be null (will result in a query returning ALL objects from a table)
     */
    public QueryByCriteria(Class targetClass, Criteria criteria, boolean distinct)
    {
        this(targetClass, criteria, null, distinct);
    }

    /**
     * Build a Query based on anObject <br>
     * all non null values are used as EqualToCriteria
     */
    public QueryByCriteria(Object anObject, boolean distinct)
    {
        this(anObject.getClass(), buildCriteria(anObject), distinct);
    }

    /**
     * Build a Query based on anObject <br>
     * all non null values are used as EqualToCriteria
     */
    public QueryByCriteria(Object anObject)
    {
        this(anObject.getClass(), buildCriteria(anObject));
    }

    /**
     * Build a Query based on a Class Object. This
     * Query will return all instances of the given class.
     * @param aClassToSearchFrom the class to search from
     */
    public QueryByCriteria(Class aClassToSearchFrom)
    {
        this(aClassToSearchFrom, CRITERIA_SELECT_ALL);
    }

    /**
     * Build Criteria based on example object<br>
     * all non null values are used as EqualToCriteria
     */
    private static Criteria buildCriteria(Object anExample)
    {
        Criteria criteria = new Criteria();
        ClassDescriptor cld = MetadataManager.getInstance().getRepository().getDescriptorFor(anExample.getClass());
        FieldDescriptor[] fds = cld.getFieldDescriptions();
        PersistentField f;
        Object value;

        for (int i = 0; i < fds.length; i++)
        {
            try
            {
                f = fds[i].getPersistentField();
                value = f.get(anExample);
                if (value != null)
                {
                    criteria.addEqualTo(f.getName(), value);
                }
            }
            catch (Throwable ex)
            {
                LoggerFactory.getDefaultLogger().error(ex);
            }
        }

        return criteria;
    }

    /**
     * Add a hint Class for a path. Used for relationships to extents.<br>
     * SqlStatment will use these hint classes when resolving the path.
     * Without these hints SqlStatment will use the base class the
     * relationship points to ie: Article instead of CdArticle.
     *
     * @param aPath the path segment ie: allArticlesInGroup
     * @param aClass the Class ie: CdArticle
     * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
     */
    public void addPathClass(String aPath, Class aClass)
    {
        List pathClasses = (List) m_pathClasses.get(aPath);
        if(pathClasses == null)
        {
            setPathClass(aPath, aClass);
        }
        else
        {
            pathClasses.add(aClass);
        }
    }

    /**
     * Set the Class for a path. Used for relationships to extents.<br>
     * SqlStatment will use this class when resolving the path.
     * Without this hint SqlStatment will use the base class the
     * relationship points to ie: Article instead of CdArticle.
     * Using this method is the same as adding just one hint
     *
     * @param aPath the path segment ie: allArticlesInGroup
     * @param aClass the Class ie: CdArticle
     * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
     * @see #addPathClass
     */
    public void setPathClass(String aPath, Class aClass)
    {
        List pathClasses = new ArrayList();
        pathClasses.add(aClass);
        m_pathClasses.put(aPath, pathClasses);
    }

    /**
     * Get the a List of Class objects used as hints for a path
     *
     * @param aPath the path segment ie: allArticlesInGroup
     * @return a List o Class objects to be used in SqlStatment
     * @see #addPathClass
     * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
     */
    public List getClassesForPath(String aPath)
    {
        return (List)m_pathClasses.get(aPath);
    }

    /**
     * Answer true if outer join for path should be used.
     * @param aPath the path to query the outer join setting for
     * @return true for outer join
     */
    public boolean isPathOuterJoin(String aPath)
    {
        return getOuterJoinPaths().contains(aPath);
    }

    /**
     * Force outer join for the last segment of the path.
     * ie. path = 'a.b.c' the outer join will be applied only to the relationship from B to C.
     * if multiple segments need an outer join, setPathOuterJoin needs to be called for each segement.
     * @param aPath force outer join to the last segment of this path
     */
    public void setPathOuterJoin(String aPath)
    {
        getOuterJoinPaths().add(aPath);
    }

    /* (non-Javadoc)
     * @see org.apache.ojb.broker.query.Query#getCriteria()
     */
    public Criteria getCriteria()
    {
        return m_criteria;
    }

    /* (non-Javadoc)
     * @see org.apache.ojb.broker.query.Query#getHavingCriteria()
     */
    public Criteria getHavingCriteria()
    {
        return m_havingCriteria;
    }

    /**
     * Insert the method's description here.
     * Creation date: (07.02.2001 22:01:55)
     * @return java.lang.String
     */
    public String toString()
    {
        StringBuffer buf = new StringBuffer("QueryByCriteria from ");
        buf.append(getSearchClass()).append(" ");
        if (getCriteria() != null && !getCriteria().isEmpty())
        {
            buf.append(" where ").append(getCriteria());
        }
        return buf.toString();
    }

    /**
     * Gets the distinct.
     * @return Returns a boolean
     */
    public boolean isDistinct()
    {
        return m_distinct;
    }

    /**
     * Sets the distinct.
     * @param distinct The distinct to set
     */
    public void setDistinct(boolean distinct)
    {
        this.m_distinct = distinct;
    }

    /**
     * Gets the pathClasses.
     * A Map containing hints about what Class to be used for what path segment
     * @return Returns a Map
     */
    public Map getPathClasses()
    {
        return m_pathClasses;
    }

  /**
   * Sets the criteria.
   * @param criteria The criteria to set
   */
  public void setCriteria(Criteria criteria)
  {
    m_criteria = criteria;
        if (m_criteria != null)
        {
            m_criteria.setQuery(this);
        }
  }

  /**
   * Sets the havingCriteria.
   * @param havingCriteria The havingCriteria to set
   */
  public void setHavingCriteria(Criteria havingCriteria)
  {
    m_havingCriteria = havingCriteria;
        if (m_havingCriteria != null)
        {
            m_havingCriteria.setQuery(this);
        }
  }

    /**
     * Adds a groupby fieldName for ReportQueries.
     * @param fieldName The groupby to set
     */
    public void addGroupBy(String fieldName)
    {
        if (fieldName != null)
        {
            m_groupby.add(new FieldHelper(fieldName, false));
        }
    }

    /**
     * Adds a field for groupby
     * @param aField
     */
    public void addGroupBy(FieldHelper aField)
    {
        if (aField != null)
        {
            m_groupby.add(aField);
        }
    }

    /**
     * Adds an array of groupby fieldNames for ReportQueries.
     * @param fieldNames The groupby to set
     */
    public void addGroupBy(String[] fieldNames)
    {
        for (int i = 0; i < fieldNames.length; i++)
        {
            addGroupBy(fieldNames[i]);
        }
    }

  /**
   * @see org.apache.ojb.broker.query.Query#getGroupBy()
   */
  public List getGroupBy()
  {
        // BRJ:
        // combine data from query and criteria
        // TODO: to be removed when Criteria#addGroupBy is removed
        ArrayList temp = new ArrayList();
        temp.addAll(m_groupby);

        if (getCriteria() != null)
        {
            temp.addAll(getCriteria().getGroupby());
        }

        return temp;
  }

    /**
     * Adds a field for orderBy
     * @param  fieldName    The field name to be used
     * @param  sortAscending    true for ASCENDING, false for DESCENDING
     */
    public void addOrderBy(String fieldName, boolean sortAscending)
    {
        if (fieldName != null)
        {
            m_orderby.add(new FieldHelper(fieldName, sortAscending));
        }
    }

    /**
     * Adds a field for orderBy, order is ASCENDING
     * @param  fieldName    The field name to be used
     * @deprecated use #addOrderByAscending(String fieldName)
     */
    public void addOrderBy(String fieldName)
    {
        addOrderBy(fieldName, true);
    }

    /**
     * Adds a field for orderBy
     * @param aField
     */
    public void addOrderBy(FieldHelper aField)
    {
        if (aField != null)
        {
            m_orderby.add(aField);
        }
    }

    /**
     * Adds a field for orderBy ASCENDING
     * @param  fieldName    The field name to be used
     */
    public void addOrderByAscending(String fieldName)
    {
        addOrderBy(fieldName, true);
    }

    /**
     * Adds a field for orderBy DESCENDING
     * @param  fieldName    The field name to be used
     */
    public void addOrderByDescending(String fieldName)
    {
        addOrderBy(fieldName, false);
    }

  /**
   * @see org.apache.ojb.broker.query.Query#getOrderBy()
   */
  public List getOrderBy()
  {
        // BRJ:
        // combine data from query and criteria
        // TODO: to be removed when Criteria#addOrderBy is removed
        ArrayList temp = new ArrayList();
        temp.addAll(m_orderby);

        if (getCriteria() != null)
        {
            temp.addAll(getCriteria().getOrderby());
        }

        return temp;
  }

    /**
     * add the name of aRelationship for prefetched read
     */
    public void addPrefetchedRelationship(String aName)
    {
        m_prefetchedRelationships.add(aName);
    }

  /* (non-Javadoc)
   * @see org.apache.ojb.broker.query.Query#getPrefetchedRelationships()
   */
  public List getPrefetchedRelationships()
  {
        // BRJ:
        // combine data from query and criteria
        // TODO: to be removed when Criteria#addPrefetchedRelationship is removed
        ArrayList temp = new ArrayList();
        temp.addAll(m_prefetchedRelationships);

        if (getCriteria() != null)
        {
            temp.addAll(getCriteria().getPrefetchedRelationships());
        }

        return temp;
    }

  /**
     * Get a Collection containing all Paths having an Outer-Joins-Setting
     * @return a Collection containing the Paths (Strings)
   */
    public Collection getOuterJoinPaths()
    {
        return m_pathOuterJoins;
    }

    public String getObjectProjectionAttribute()
    {
        return m_objectProjectionAttribute;
    }

    /**
     * Use this method to query some related class by object references,
     * for example query.setObjectProjectionAttribute("ref1.ref2.ref3");
     */
    public void setObjectProjectionAttribute(String objectProjectionAttribute)
    {
        ClassDescriptor baseCld = MetadataManager.getInstance().getRepository().getDescriptorFor(m_baseClass);
        ArrayList descs = baseCld.getAttributeDescriptorsForPath(objectProjectionAttribute);
        int pathLen = descs.size();

        if ((pathLen > 0) && (descs.get(pathLen - 1) instanceof ObjectReferenceDescriptor))
        {
            ObjectReferenceDescriptor ord =
                    ((ObjectReferenceDescriptor) descs.get(pathLen - 1));
            setObjectProjectionAttribute(objectProjectionAttribute,
                                         ord.getItemClass());
        }
    }

    public void setObjectProjectionAttribute(String objectProjectionAttribute,
                                             Class objectProjectionClass)
    {
        m_objectProjectionAttribute = objectProjectionAttribute;
        m_searchClass = objectProjectionClass;
  }
}
TOP

Related Classes of org.apache.ojb.broker.query.QueryByCriteria

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.