Hello, We added a new feature to the method buildCriteria() which enables it to create criteria of objects that have nested properties. It's not efficient but it works great.
The altered code can be found between lines 151 and 190 . Cheers, Luis Cruz & João Mota
package org.apache.ojb.broker.query; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache ObjectRelationalBridge" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Vector; import org.apache.commons.beanutils.PropertyUtils; import org.apache.ojb.broker.metadata.ClassDescriptor; import org.apache.ojb.broker.metadata.DescriptorRepository; import org.apache.ojb.broker.metadata.FieldDescriptor; import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor; import org.apache.ojb.broker.metadata.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 * */ public class QueryByCriteria extends AbstractQueryImpl implements Query { private Class clazz; private Criteria criteria; private boolean distinct = false; private HashMap pathClasses; /** * 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.clazz = targetClass; this.criteria = criteria; this.distinct = distinct; this.pathClasses = new HashMap(); } /** * Build a Query based on anObject <br> * all non null values are used as EqualToCriteria * @param anObject * @param distinct * @return a QueryByCriteria */ 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 * @param anObject * @return a QueryByCriteria */ public QueryByCriteria(Object anObject) { this (anObject.getClass(), buildCriteria(anObject)); } /** * ############################################################ * BEGINING OF ALTERED CODE */ /** * Build Criteria based on example object<br> * all non null values are used as EqualToCriteria * Now Supports nested properties. */ private static Criteria buildCriteria(Object obj) { return buildCriteria(new Criteria(), "", obj); } /** * Build Criteria based on example object<br> * all non null values are used as EqualToCriteria */ private static Criteria buildCriteria(Criteria criteria,String path,Object anExample) { ClassDescriptor cld = DescriptorRepository.getDefaultInstance().getDescriptorFor(anExample.getClass()); FieldDescriptor[] fds = cld.getFieldDescriptions(); PersistentField f; Object value; Vector ref = cld.getObjectReferenceDescriptors(); Criteria crit = criteria; for (int j = 0; j < ref.size(); j++){ ObjectReferenceDescriptor objref = (ObjectReferenceDescriptor) ref.get(j); PropertyDescriptor[] xpto = PropertyUtils.getPropertyDescriptors(anExample.getClass()); for (int k = 0; k < xpto.length; k++) { Method getM = xpto[k].getReadMethod(); if (xpto[k].getName().equals(objref.getAttributeName())) { try { Object propValue = getM.invoke(anExample, null); if (propValue != null) { crit = buildCriteria( criteria, path + objref.getAttributeName() + ".", propValue); } } catch (IllegalAccessException ex) { LoggerFactory.getDefaultLogger().error(ex); } catch (InvocationTargetException ex) { LoggerFactory.getDefaultLogger().error(ex); } } } } /** * END OF ALTERED CODE * ############################################################ */ for (int i = 0; i < fds.length; i++) { try { f = fds[i].getPersistentField(); value = f.get(anExample); if (value != null) { crit.addEqualTo(path+f.getName(), value); } } catch (Throwable ex) { LoggerFactory.getDefaultLogger().error(ex); } } return crit; } /** * 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. * * @param the path segment ie: allArticlesInGroup * @param the Class ie: CdArticle * @see org.apache.ojb.broker.QueryTest#testInversePathExpression() */ public void addPathClass(String aPath, Class aClass) { getPathClasses().put(aPath, aClass); } /** * Get the Class for a path * * @param the path segment ie: allArticlesInGroup * @return the class to be used in SqlStatment * @see addPathClass() * @see org.apache.ojb.broker.QueryTest#testInversePathExpression() */ public Class getClassForPath(String aPath) { return (Class)getPathClasses().get(aPath); } /** * Method declaration * * * @return * * */ public Criteria getCriteria() { return criteria; } /** * Method declaration * * * @return * * */ public java.lang.Object getExampleObject() { return null; } /** * Method declaration * * * @return * * */ public java.lang.Class getSearchClass() { return clazz; } /** * Insert the method's description here. * Creation date: (07.02.2001 22:01:55) * @return java.lang.String */ public String toString() { return "Query from " + clazz + " where " + criteria; } /** * Gets the distinct. * @return Returns a boolean */ public boolean isDistinct() { return distinct; } /** * Sets the distinct. * @param distinct The distinct to set */ public void setDistinct(boolean distinct) { this.distinct = distinct; } /** * Gets the pathClasses. * @return Returns a HashMap */ protected HashMap getPathClasses() { return pathClasses; } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
