You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by br...@apache.org on 2004/04/24 10:25:38 UTC

cvs commit: db-ojb/src/test/org/apache/ojb/broker PathTest.java AllTests.java

brj         2004/04/24 01:25:38

  Modified:    src/schema ojbtest-schema.xml
               src/java/org/apache/ojb/broker/query BetweenCriteria.java
                        Criteria.java SelectionCriteria.java
               src/java/org/apache/ojb/broker/accesslayer/sql
                        SqlQueryStatement.java SqlSelectStatement.java
               src/test/org/apache/ojb repository.xml
               src/test/org/apache/ojb/broker AllTests.java
  Added:       src/test/org/apache/ojb repository_junit_pathClass.xml
               src/test/org/apache/ojb/broker PathTest.java
  Log:
  support pathClass-hints per Criteria (patch by Phil Warrick)
  
  Revision  Changes    Path
  1.75      +35 -1     db-ojb/src/schema/ojbtest-schema.xml
  
  Index: ojbtest-schema.xml
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/schema/ojbtest-schema.xml,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- ojbtest-schema.xml	19 Apr 2004 16:23:26 -0000	1.74
  +++ ojbtest-schema.xml	24 Apr 2004 08:25:37 -0000	1.75
  @@ -1314,4 +1314,38 @@
               javaName="personId" />
     </table>
   
  -</database>
  +    <!-- ************************************************* -->
  +    <!--      Classes for path tests				       -->
  +    <!-- ************************************************* -->
  +
  +  <table name="P_A_TABLE">
  +    <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
  +    <column name="A_ATTRIB" type="INTEGER" required="false"/>
  +  </table>
  +
  +  <table name="P_B_TABLE">
  +    <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
  +    <column name="B_ATTRIB" type="INTEGER" required="false"/>
  +    <column name="A_ID" type="BIGINT" required="true"/>
  +    <foreign-key foreignTable="P_A_TABLE">
  +      <reference local="A_ID" foreign="ID"/>
  +    </foreign-key>
  +  </table>
  +
  +  <table name="P_C_TABLE">
  +    <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
  +    <column name="C_ATTRIB" type="INTEGER" required="false"/>
  +    <column name="C1_ATTRIB" type="INTEGER" required="false"/>
  +    <column name="B_ID" type="BIGINT" required="true"/>
  +    <column name="D_ID" type="BIGINT" required="false"/>
  +    <foreign-key foreignTable="P_B_TABLE">
  +      <reference local="B_ID" foreign="ID"/>
  +    </foreign-key>
  +  </table>
  +
  +  <table name="P_D_TABLE">
  +    <column name="ID" required="true" primaryKey="true" type="BIGINT"/>
  +    <column name="D_ATTRIB" type="INTEGER" required="false"/>
  +  </table>
  +
  +</database>
  \ No newline at end of file
  
  
  
  1.9       +8 -0      db-ojb/src/java/org/apache/ojb/broker/query/BetweenCriteria.java
  
  Index: BetweenCriteria.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/BetweenCriteria.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- BetweenCriteria.java	4 Apr 2004 23:53:36 -0000	1.8
  +++ BetweenCriteria.java	24 Apr 2004 08:25:37 -0000	1.9
  @@ -77,5 +77,13 @@
   		return (getValue() == null && getValue2() == null);
   	}
   
  +	// PAW
  +	/**
  +	 * String representation
  +	 */
  +	public String toString()
  +	{
  +		return super.toString() + " AND " + value2;
  +	}
   }
   
  
  
  
  1.44      +102 -1    db-ojb/src/java/org/apache/ojb/broker/query/Criteria.java
  
  Index: Criteria.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/Criteria.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Criteria.java	21 Apr 2004 17:11:12 -0000	1.43
  +++ Criteria.java	24 Apr 2004 08:25:37 -0000	1.44
  @@ -18,8 +18,10 @@
   import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Enumeration;
  +import java.util.HashMap;
   import java.util.Iterator;
   import java.util.List;
  +import java.util.Map;
   import java.util.Vector;
   
   import org.apache.ojb.broker.PersistenceBrokerFactory;
  @@ -76,6 +78,10 @@
       private QueryByCriteria m_query;
       private Criteria m_parentCriteria;
   
  +    // PAW
  +	// hint classes for paths of this criteria
  +	private Map m_pathClasses;
  +
       /**
        * Constructor declaration
        */
  @@ -87,6 +93,8 @@
           prefetchedRelationships = new ArrayList();
           m_type = NONE;
           m_embraced = false;
  +        // PAW
  +		m_pathClasses = new HashMap();
       }
   
       /**
  @@ -1065,5 +1073,98 @@
       {
           m_negative = negative;
       }
  +
  +	// PAW    
  +	/**
  +	 * 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)
  +	{
  +		Object pathClasses = m_pathClasses.get(aPath);
  +		if(pathClasses == null)
  +		{
  +			setPathClass(aPath,aClass);
  +		}
  +		else
  +		{
  +			List hints = (List)pathClasses;
  +			hints.add(aClass);
  +			m_pathClasses.put(aPath, hints);
  +		}
  +	}
  +
  +	/**
  +	 * 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(1);
  +		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)getPathClasses().get(aPath);
  +	}
  +	
  +	/**
  +	 * Gets the pathClasses.
  +	 * A Map containing hints about what Class to be used for what path segment
  +	 * If local instance not set, try parent Criteria's instance.  If this is 
  +	 * the top-level Criteria, try the m_query's instance
  +	 * @return Returns a Map
  +	 */
  +	public Map getPathClasses()
  +	{
  +		if (m_pathClasses.isEmpty())
  +		{
  +			if (m_parentCriteria == null)
  +			{
  +				if (m_query == null)
  +				{
  +					return m_pathClasses;
  +				}
  +				else
  +				{
  +					return m_query.getPathClasses();
  +				}
  +			}
  +			else
  +			{
  +				return m_parentCriteria.getPathClasses();
  +			}
  +		}
  +		else
  +		{
  +			return m_pathClasses;
  +		}
  +	}
  +
  +	
   
   }
  
  
  
  1.16      +28 -0     db-ojb/src/java/org/apache/ojb/broker/query/SelectionCriteria.java
  
  Index: SelectionCriteria.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/query/SelectionCriteria.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- SelectionCriteria.java	4 Apr 2004 23:53:36 -0000	1.15
  +++ SelectionCriteria.java	24 Apr 2004 08:25:37 -0000	1.16
  @@ -1,5 +1,8 @@
   package org.apache.ojb.broker.query;
   
  +import java.util.List;
  +import java.util.Map;
  +
   /* Copyright 2002-2004 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
  @@ -234,5 +237,30 @@
               return null;
           }
       }
  +    
  +	/**
  +	 * Gets the pathClasses from the parent Criteria.
  +	 * A Map containing hints about what Class to be used for what path segment
  +	 * @return Returns a Map
  +	 */
  +	// PAW
  +	public Map getPathClasses()
  +	{
  +		return getCriteria().getPathClasses();
  +	}
  +
  +	/**
  +	 * 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 getCriteria().getClassesForPath(aPath);
  +	}
  +    
   
   }
  
  
  
  1.72      +292 -285  db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java
  
  Index: SqlQueryStatement.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlQueryStatement.java,v
  retrieving revision 1.71
  retrieving revision 1.72
  diff -u -r1.71 -r1.72
  --- SqlQueryStatement.java	4 Apr 2004 23:53:32 -0000	1.71
  +++ SqlQueryStatement.java	24 Apr 2004 08:25:37 -0000	1.72
  @@ -114,7 +114,7 @@
           }
           else
           {
  -            m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null);
  +			m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null, m_query.getPathClasses());
           }
   
           // Walk the super reference-descriptor
  @@ -139,71 +139,72 @@
           return m_searchCld;
       }
   
  -    /**
  -     * Return the TableAlias and the PathInfo for an Attribute name<br>
  -     * field names in functions (ie: sum(name) ) are tried to resolve ie: name
  -     * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
  -     * also resolve pathExpression adress.city or owner.konti.saldo
  -     * @param attr
  -     * @param useOuterJoins
  -     * @param aUserAlias
  -     * @return ColumnInfo
  -     */
  -    protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, String aUserAlias)
  -    {
  -        AttributeInfo result = new AttributeInfo();
  -        TableAlias tableAlias = null;
  -        SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
  -        String colName = pathInfo.column;
  -        int sp;
  -
  -        // BRJ:
  -        // check if we refer to an attribute in the parent query
  -        // this prefix is temporary !
  -        if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
  -        {
  -            String[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
  -            return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias);
  -        }
  -
  -        sp = colName.lastIndexOf(".");
  -        if (sp == -1)
  -        {
  -            tableAlias = getRoot();
  -        }
  -        else
  -        {
  -            String pathName = colName.substring(0, sp);
  -            String[] fieldNameRef = {colName.substring(sp + 1)};
  -
  -            tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef);
  -            /**
  -             * if we have not found an alias by the pathName or
  -             * aliasName (if given), try again because pathName
  -             * may be an aliasname. it can be only and only if it is not
  -             * a path, which means there may be no path separators (,)
  -             * in the pathName.
  -             */
  -            if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
  -            {
  -                /**
  -                 * pathName might be an alias, so check this first
  -                 */
  -                tableAlias = getTableAlias(null, useOuterJoins, pathName, null);
  -            }
  -
  -            if (tableAlias != null)
  -            {
  -                // correct column name to match the alias
  -                // productGroup.groupName -> groupName
  -                pathInfo.column = fieldNameRef[0];
  -            }
  -        }
  -
  -        result.tableAlias = tableAlias;
  -        result.pathInfo = pathInfo;
  -        return result;
  -    }
  +	/**
  +	 * Return the TableAlias and the PathInfo for an Attribute name<br>
  +	 * field names in functions (ie: sum(name) ) are tried to resolve ie: name
  +	 * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
  +	 * also resolve pathExpression adress.city or owner.konti.saldo
  +	 * @param attr
  +	 * @param useOuterJoins
  +	 * @param aUserAlias
  +	 * @param pathClasses
  +	 * @return ColumnInfo
  +	 */
  +	protected AttributeInfo getAttributeInfo(String attr, boolean useOuterJoins, String aUserAlias, Map pathClasses)
  +	{
  +		AttributeInfo result = new AttributeInfo();
  +		TableAlias tableAlias = null;
  +		SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
  +		String colName = pathInfo.column;
  +		int sp;
  +
  +		// BRJ:
  +		// check if we refer to an attribute in the parent query
  +		// this prefix is temporary !
  +		if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
  +		{
  +			String[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
  +			return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias, pathClasses);
  +		}
  +
  +		sp = colName.lastIndexOf(".");
  +		if (sp == -1)
  +		{
  +			tableAlias = getRoot();
  +		}
  +		else
  +		{
  +			String pathName = colName.substring(0, sp);
  +			String[] fieldNameRef = {colName.substring(sp + 1)};
  +
  +			tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
  +			/**
  +			 * if we have not found an alias by the pathName or
  +			 * aliasName (if given), try again because pathName
  +			 * may be an aliasname. it can be only and only if it is not
  +			 * a path, which means there may be no path separators (,)
  +			 * in the pathName.
  +			 */
  +			if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
  +			{
  +				/**
  +				 * pathName might be an alias, so check this first
  +				 */
  +				tableAlias = getTableAlias(null, useOuterJoins, pathName, null, pathClasses);
  +			}
  +
  +			if (tableAlias != null)
  +			{
  +				// correct column name to match the alias
  +				// productGroup.groupName -> groupName
  +				pathInfo.column = fieldNameRef[0];
  +			}
  +		}
  +
  +		result.tableAlias = tableAlias;
  +		result.pathInfo = pathInfo;
  +		return result;
  +	}
   
       /**
        * Answer the column name for alias and path info<br>
  @@ -420,7 +421,8 @@
        */
       protected boolean appendColName(String attr, boolean useOuterJoins, String aUserAlias, StringBuffer buf)
       {
  -        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias);
  +		// PAW: is this correct for pathClasses ?
  +		AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
           TableAlias tableAlias = attrInfo.tableAlias;
   
           return appendColName(tableAlias, attrInfo.pathInfo, true, buf);
  @@ -444,7 +446,8 @@
       protected boolean appendColName(String attr, String attrAlias, boolean useOuterJoins, String aUserAlias,
               StringBuffer buf)
       {
  -        AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias);
  +		// PAW: is this correct for pathClasses ?
  +		AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
           TableAlias tableAlias = attrInfo.tableAlias;
           PathInfo pi = attrInfo.pathInfo;
   
  @@ -822,7 +825,7 @@
               return;
           }
   
  -        AttributeInfo attrInfo = getAttributeInfo((String) c.getAttribute(), false, c.getAlias());
  +		AttributeInfo attrInfo = getAttributeInfo((String) c.getAttribute(), false, c.getAlias(), c.getPathClasses());
           TableAlias alias = attrInfo.tableAlias;
   
           if (alias != null)
  @@ -908,156 +911,157 @@
           return sql;
       }
   
  -    /**
  -     * Get TableAlias by the path from the target table of the query.
  -     * @param aPath the path from the target table of the query to this TableAlias.
  -     * @param useOuterJoins use outer join to join this table with the previous
  -     * table in the path.
  -     * @param aUserAlias
  -     * @param fieldRef String[1] contains the field name.
  -     * In the case of related table's primary key the "related.pk" attribute
  -     * must not add new join, but use the value of foreign key
  -     */
  -    private TableAlias getTableAlias(String aPath, boolean useOuterJoins, String aUserAlias, String[] fieldRef)
  -    {
  -        TableAlias curr, prev, indirect;
  -        String attr, attrPath = null;
  -        ObjectReferenceDescriptor ord;
  -        CollectionDescriptor cod;
  -        ClassDescriptor cld = null;
  -        Object[] prevKeys = null;
  -        Object[] keys = null;
  -        ArrayList descriptors;
  -        boolean outer = useOuterJoins;
  -        int pathLength;
  -
  -        curr = getTableAliasForPath(aPath, aUserAlias);
  -
  -        if (curr != null)
  -        {
  -            return curr;
  -        }
  -
  -        descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, getQuery().getPathClasses());
  -        prev = getRoot();
  -
  -        if (descriptors == null || descriptors.size() == 0)
  -        {
  -            if (prev.hasJoins())
  -            {
  -                for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
  -                {
  -                    prev = ((Join) itr.next()).left;
  -                    descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, getQuery().getPathClasses());
  -                    if (descriptors.size() > 0)
  -                    {
  -                        break;
  -                    }
  -                }
  -            }
  -        }
  -
  -        pathLength = descriptors.size();
  -        for (int i = 0; i < pathLength; i++)
  -        {
  -            if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
  -            {
  -                // only use Collection- and ObjectReferenceDescriptor
  -                continue;
  -            }
  -
  -            ord = (ObjectReferenceDescriptor) descriptors.get(i);
  -            attr = ord.getAttributeName();
  -            if (attrPath == null)
  -            {
  -                attrPath = attr;
  -            }
  -            else
  -            {
  -                attrPath = attrPath + "." + attr;
  -            }
  -
  -            // look for outer join hint
  -            outer = outer || getQuery().isPathOuterJoin(attr);
  -
  -            // look for 1:n or m:n
  -            if (ord instanceof CollectionDescriptor)
  -            {
  -                cod = (CollectionDescriptor) ord;
  -                cld = getItemClassDescriptor(cod, attrPath);
  -
  -                if (!cod.isMtoNRelation())
  -                {
  -                    prevKeys = prev.cld.getPkFields();
  -                    keys = cod.getForeignKeyFieldDescriptors(cld);
  -                }
  -                else
  -                {
  -                    String mnAttrPath = attrPath + "*";
  -                    String mnPath = aPath + "*";
  -                    String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
  -                    indirect = getTableAliasForPath(mnAttrPath, mnUserAlias, mnPath);
  -                    if (indirect == null)
  -                    {
  -                        indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias, mnPath);
  -
  -                        // we need two Joins for m:n
  -                        // 1.) prev class to indirectionTable
  -                        prevKeys = prev.cld.getPkFields();
  -                        keys = cod.getFksToThisClass();
  -                        addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
  -                    }
  -                    // 2.) indirectionTable to the current Class
  -                    prev = indirect;
  -                    prevKeys = cod.getFksToItemClass();
  -                    keys = cld.getPkFields();
  -                }
  -            }
  -            else
  -            {
  -                // must be n:1 or 1:1
  -                cld = getItemClassDescriptor(ord, attrPath);
  -
  -                prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  -                keys = cld.getPkFields();
  -
  -                // [olegnitz]
  -                // a special case: the last element of the path is
  -                // reference and the field is one of PK fields =>
  -                // use the correspondent foreign key field, don't add the join
  -                if ((fieldRef != null) && (i == (pathLength - 1)))
  -                {
  -                    FieldDescriptor[] pk = cld.getPkFields();
  -
  -                    for (int j = 0; j < pk.length; j++)
  -                    {
  -                        if (pk[j].getAttributeName().equals(fieldRef[0]))
  -                        {
  -                            fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
  -                            return prev;
  -                        }
  -                    }
  -                }
  -            }
  +	/**
  +	 * Get TableAlias by the path from the target table of the query.
  +	 * @param aPath the path from the target table of the query to this TableAlias.
  +	 * @param useOuterJoins use outer join to join this table with the previous
  +	 * table in the path.
  +	 * @param aUserAlias if specified, overrides alias in crit
  +	 * @param fieldRef String[1] contains the field name.
  +	 * In the case of related table's primary key the "related.pk" attribute
  +	 * must not add new join, but use the value of foreign key
  +	 * @param pathClasses the hints 
  +	 */
  +	private TableAlias getTableAlias(String aPath, boolean useOuterJoins, String aUserAlias, String[] fieldRef, Map pathClasses)
  +	{
  +		TableAlias curr, prev, indirect;
  +		String attr, attrPath = null;
  +		ObjectReferenceDescriptor ord;
  +		CollectionDescriptor cod;
  +		ClassDescriptor cld = null;
  +		Object[] prevKeys = null;
  +		Object[] keys = null;
  +		ArrayList descriptors;
  +		boolean outer = useOuterJoins;
  +		int pathLength;
  +
  +		curr = getTableAliasForPath(aPath, aUserAlias);
  +
  +		if (curr != null)
  +		{
  +			return curr;
  +		}
  +
  +		descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  +		prev = getRoot();
  +
  +		if (descriptors == null || descriptors.size() == 0)
  +		{
  +			if (prev.hasJoins())
  +			{
  +				for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
  +				{
  +					prev = ((Join) itr.next()).left;
  +					descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  +					if (descriptors.size() > 0)
  +					{
  +						break;
  +					}
  +				}
  +			}
  +		}
  +
  +		pathLength = descriptors.size();
  +		for (int i = 0; i < pathLength; i++)
  +		{
  +			if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
  +			{
  +				// only use Collection- and ObjectReferenceDescriptor
  +				continue;
  +			}
  +
  +			ord = (ObjectReferenceDescriptor) descriptors.get(i);
  +			attr = ord.getAttributeName();
  +			if (attrPath == null)
  +			{
  +				attrPath = attr;
  +			}
  +			else
  +			{
  +				attrPath = attrPath + "." + attr;
  +			}
  +
  +			// look for outer join hint
  +			outer = outer || getQuery().isPathOuterJoin(attr);
  +
  +			// look for 1:n or m:n
  +			if (ord instanceof CollectionDescriptor)
  +			{
  +				cod = (CollectionDescriptor) ord;
  +				cld = getItemClassDescriptor(cod, attrPath, pathClasses);
  +
  +				if (!cod.isMtoNRelation())
  +				{
  +					prevKeys = prev.cld.getPkFields();
  +					keys = cod.getForeignKeyFieldDescriptors(cld);
  +				}
  +				else
  +				{
  +					String mnAttrPath = attrPath + "*";
  +					String mnPath = aPath + "*";
  +					String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
  +					indirect = getTableAliasForPath(mnAttrPath, mnUserAlias, mnPath);
  +					if (indirect == null)
  +					{
  +						indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias, mnPath);
  +
  +						// we need two Joins for m:n
  +						// 1.) prev class to indirectionTable
  +						prevKeys = prev.cld.getPkFields();
  +						keys = cod.getFksToThisClass();
  +						addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
  +					}
  +					// 2.) indirectionTable to the current Class
  +					prev = indirect;
  +					prevKeys = cod.getFksToItemClass();
  +					keys = cld.getPkFields();
  +				}
  +			}
  +			else
  +			{
  +				// must be n:1 or 1:1
  +				cld = getItemClassDescriptor(ord, attrPath, pathClasses);
  +
  +				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  +				keys = cld.getPkFields();
  +
  +				// [olegnitz]
  +				// a special case: the last element of the path is
  +				// reference and the field is one of PK fields =>
  +				// use the correspondent foreign key field, don't add the join
  +				if ((fieldRef != null) && (i == (pathLength - 1)))
  +				{
  +					FieldDescriptor[] pk = cld.getPkFields();
  +
  +					for (int j = 0; j < pk.length; j++)
  +					{
  +						if (pk[j].getAttributeName().equals(fieldRef[0]))
  +						{
  +							fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
  +							return prev;
  +						}
  +					}
  +				}
  +			}
  +
  +			curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
  +
  +			if (curr == null)
  +			{
  +				List hintClasses = (List) pathClasses.get(aPath);
  +				curr = createTableAlias(cld, attrPath, aUserAlias, aPath, hintClasses);
  +
  +				outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
  +				addJoin(prev, prevKeys, curr, keys, outer, attr);
   
  -            curr = getTableAliasForPath(attrPath, aUserAlias, aPath);
  +				buildSuperJoinTree(curr, cld, aPath);
  +			}
   
  -            if (curr == null)
  -            {
  -                List hintClasses = (List) getQuery().getPathClasses().get(aPath);
  -                curr = createTableAlias(cld, attrPath, aUserAlias, aPath, hintClasses);
  +			prev = curr;
  +		}
   
  -                outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
  -                addJoin(prev, prevKeys, curr, keys, outer, attr);
  -
  -                buildSuperJoinTree(curr, cld, aPath);
  -            }
  -
  -            prev = curr;
  -        }
  -
  -        return curr;
  -    }
  +		return curr;
  +	}
   
       /**
        * add a join between two aliases
  @@ -1168,14 +1172,14 @@
       private TableAlias createTableAlias(ClassDescriptor aCld, String aPath, String aUserAlias, String anOriginalPath,
               List hints)
       {
  -        if (aUserAlias == null || !anOriginalPath.equals(aPath))
  -        {
  -            return createTableAlias(aCld, hints, aPath);
  -        }
  -        else
  -        {
  -            return createTableAlias(aCld, hints, aUserAlias);
  -        }
  +		if (aUserAlias == null)
  +		{
  +			return createTableAlias(aCld, hints, aPath);
  +		}
  +		else
  +		{
  +			return createTableAlias(aCld, hints, aUserAlias + aPath);
  +		}
       }
   
       /**
  @@ -1211,14 +1215,14 @@
        */
       private TableAlias createTableAlias(String aTable, String aPath, String aUserAlias, String anOriginalPath)
       {
  -        if (aUserAlias == null || !anOriginalPath.equals(aPath))
  -        {
  -            return createTableAlias(aTable, aPath);
  -        }
  -        else
  -        {
  -            return createTableAlias(aTable, aUserAlias);
  -        }
  +		if (aUserAlias == null)
  +		{
  +			return createTableAlias(aTable, aPath);
  +		}
  +		else
  +		{
  +			return createTableAlias(aTable, aUserAlias + aPath);
  +		}
       }
   
       /**
  @@ -1266,7 +1270,7 @@
           }
           else
           {
  -            return getTableAliasForPath(aUserAlias);
  +			return getTableAliasForPath(aUserAlias + aPath);
           }
       }
   
  @@ -1287,42 +1291,46 @@
           }
           else
           {
  -            return getTableAliasForPath(aUserAlias);
  +			return getTableAliasForPath(aUserAlias + aPath);
           }
       }
   
  -    /**
  -     * TODO: add super ClassDescriptor
  -     * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
  -     * check optional hint;
  -     */
  -    private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr)
  -    {
  -        List itemClasses = null;
  -        Query q = getQuery();
  -
  -        if (q instanceof QueryByCriteria)
  -        {
  -            itemClasses = ((QueryByCriteria) q).getClassesForPath(attr);
  -        }
  -
  -        if (itemClasses == null)
  -        {
  -            itemClasses = new ArrayList();
  -            itemClasses.add(ord.getItemClass());
  -        }
  -
  -        List classDescriptors = new ArrayList(itemClasses.size());
  -        DescriptorRepository repo = ord.getClassDescriptor().getRepository();
  -
  -        for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
  -        {
  -            Class clazz = (Class) iter.next();
  -            classDescriptors.add(repo.getDescriptorFor(clazz));
  -        }
  -        return (ClassDescriptor) classDescriptors.get(0);
  +	/**
  +	 * TODO: add super ClassDescriptor
  +	 * answer the ClassDescriptor for itemClass for an ObjectReferenceDescriptor
  +	 * check optional hint;
  +	 */
  +	private ClassDescriptor getItemClassDescriptor(ObjectReferenceDescriptor ord, String attr, Map pathClasses)
  +	{
  +		/* PAW
  +		List itemClasses = null;
  +		Query q = getQuery();
  +
  +		if (q instanceof QueryByCriteria)
  +		{
  +			  itemClasses = ((QueryByCriteria) q).getClassesForPath(attr);
  +		}
  +		*/
  +	    
  +		List itemClasses = (List)pathClasses.get(attr);
  +
  +		if (itemClasses == null)
  +		{
  +			itemClasses = new ArrayList();
  +			itemClasses.add(ord.getItemClass());
  +		}
  +
  +		List classDescriptors = new ArrayList(itemClasses.size());
  +		DescriptorRepository repo = ord.getClassDescriptor().getRepository();
  +
  +		for (Iterator iter = itemClasses.iterator(); iter.hasNext();)
  +		{
  +			Class clazz = (Class) iter.next();
  +			classDescriptors.add(repo.getDescriptorFor(clazz));
  +		}
   
  -    }
  +		return (ClassDescriptor) classDescriptors.get(0);
  +	}
   
       /**
        * Appends to the statement the ORDER BY clause for the Query
  @@ -1552,34 +1560,33 @@
                   // BRJ: do not build join tree for subQuery attribute                  
                   if (c.getAttribute() != null && c.getAttribute() instanceof String)
                   {
  -                    buildJoinTreeForColumn((String) c.getAttribute(), useOuterJoin, c.getAlias());
  +					buildJoinTreeForColumn((String) c.getAttribute(), useOuterJoin, c.getAlias(), c.getPathClasses());
                   }
                   if (c instanceof FieldCriteria)
                   {
                       FieldCriteria cc = (FieldCriteria) c;
  -                    buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, c.getAlias());
  +					buildJoinTreeForColumn((String) cc.getValue(), useOuterJoin, c.getAlias(), c.getPathClasses());
                   }
               }
           }
       }
   
  -    /**
  -     * build the Join-Information for name
  -     * functions and the last segment are removed
  -     * ie: avg(accounts.amount) -> accounts
  -     */
  -    private void buildJoinTreeForColumn(String aColName, boolean useOuterJoin, String aUserAlias)
  -    {
  -        String pathName = SqlHelper.cleanPath(aColName);
  -        int sepPos = pathName.lastIndexOf(".");
  -
  -        if (sepPos >= 0)
  -        {
  -            getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias, new String[]{pathName
  -                    .substring(sepPos + 1)});
  -        }
  -
  -    }
  +	/**
  +	 * build the Join-Information for name
  +	 * functions and the last segment are removed
  +	 * ie: avg(accounts.amount) -> accounts
  +	 */
  +	private void buildJoinTreeForColumn(String aColName, boolean useOuterJoin, String aUserAlias, Map pathClasses)
  +	{
  +		String pathName = SqlHelper.cleanPath(aColName);
  +		int sepPos = pathName.lastIndexOf(".");
  +
  +		if (sepPos >= 0)
  +		{
  +			getTableAlias(pathName.substring(0, sepPos), useOuterJoin, aUserAlias,
  +						  new String[]{pathName.substring(sepPos + 1)}, pathClasses);
  +		}
  +	}
   
       /**
        * build the Join-Information if a super reference exists
  
  
  
  1.22      +4 -2      db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
  
  Index: SqlSelectStatement.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- SqlSelectStatement.java	4 Apr 2004 23:53:32 -0000	1.21
  +++ SqlSelectStatement.java	24 Apr 2004 08:25:38 -0000	1.22
  @@ -209,7 +209,9 @@
               {
                   for (int i = 0; i < joinAttributes.length; i++)
                   {
  -                    getAttributeInfo(joinAttributes[i], false, null);
  +                	// PAW: correct for pathClasses?
  +					//getAttributeInfo(joinAttributes[i], false, null);
  +					getAttributeInfo(joinAttributes[i], false, null, getQuery().getPathClasses());
                   }
               }
   
  
  
  
  1.23      +2 -0      db-ojb/src/test/org/apache/ojb/repository.xml
  
  Index: repository.xml
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository.xml,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- repository.xml	5 Apr 2004 13:58:59 -0000	1.22
  +++ repository.xml	24 Apr 2004 08:25:38 -0000	1.23
  @@ -47,6 +47,7 @@
   <!ENTITY junit_meta_seq SYSTEM "repository_junit_meta_seq.xml">
   <!ENTITY junit_model SYSTEM "repository_junit_model.xml">
   <!ENTITY junit_cloneable SYSTEM "repository_junit_cloneable.xml">
  +<!ENTITY junit_pathClass SYSTEM "repository_junit_pathClass.xml">
   
   <!ENTITY user SYSTEM "repository_user.xml">
   <!ENTITY ejb SYSTEM "repository_ejb.xml">
  @@ -77,6 +78,7 @@
       &junit_meta_seq;
       &junit_model;
       &junit_cloneable;
  +    &junit_pathClass;
   
   
   
  
  
  
  1.1                  db-ojb/src/test/org/apache/ojb/repository_junit_pathClass.xml
  
  Index: repository_junit_pathClass.xml
  ===================================================================
  <!-- ojb test pathClass classes -->
  	<class-descriptor class="org.apache.ojb.broker.PathTest$A" table="P_A_TABLE">
  	<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
  	<field-descriptor name="aAttrib" column="A_ATTRIB" jdbc-type="INTEGER"/>
        <collection-descriptor
           name="bSet"
           element-class-ref="org.apache.ojb.broker.PathTest$B"
           auto-retrieve="true"
           auto-update="false"
        >
        <inverse-foreignkey field-ref="aId"/>
        </collection-descriptor>
  	</class-descriptor>
  
  	<class-descriptor class="org.apache.ojb.broker.PathTest$B" table="P_B_TABLE">
  	<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
  	<field-descriptor name="bAttrib" column="B_ATTRIB" jdbc-type="INTEGER"/>
  	<field-descriptor name="aId" column="A_ID" jdbc-type="BIGINT"/>
  	<reference-descriptor name="a" class-ref="org.apache.ojb.broker.PathTest$A"><foreignkey field-ref="aId"/></reference-descriptor>
        <collection-descriptor
           name="cSet"
           element-class-ref="org.apache.ojb.broker.PathTest$C"
           auto-retrieve="true"
           auto-update="false"
        >
        <inverse-foreignkey field-ref="bId"/>
        </collection-descriptor>
  	</class-descriptor>
  
  	<class-descriptor class="org.apache.ojb.broker.PathTest$C" table="P_C_TABLE">
  	<extent-class class-ref="org.apache.ojb.broker.PathTest$C1" />
  	<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
  	<field-descriptor name="cAttrib" column="C_ATTRIB" jdbc-type="INTEGER"/>
  	<field-descriptor name="bId" column="B_ID" jdbc-type="BIGINT"/>
  	<reference-descriptor name="b" class-ref="org.apache.ojb.broker.PathTest$B"><foreignkey field-ref="bId"/></reference-descriptor>
  	<field-descriptor name="dId" column="D_ID" jdbc-type="BIGINT"/>
  	<reference-descriptor name="d" class-ref="org.apache.ojb.broker.PathTest$D"><foreignkey field-ref="dId"/></reference-descriptor>
  	</class-descriptor>
  
  	<class-descriptor class="org.apache.ojb.broker.PathTest$C1" table="P_C_TABLE">
  	<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
  	<field-descriptor name="cAttrib" column="C_ATTRIB" jdbc-type="INTEGER"/>
  	<field-descriptor name="c1Attrib" column="C1_ATTRIB" jdbc-type="INTEGER"/>
  	<field-descriptor name="bId" column="B_ID" jdbc-type="BIGINT"/>
  	<reference-descriptor name="b" class-ref="org.apache.ojb.broker.PathTest$B"><foreignkey field-ref="bId"/></reference-descriptor>
  	<field-descriptor name="dId" column="D_ID" jdbc-type="BIGINT"/>
  	<reference-descriptor name="d" class-ref="org.apache.ojb.broker.PathTest$D"><foreignkey field-ref="dId"/></reference-descriptor>
  	</class-descriptor>
  
  	<class-descriptor class="org.apache.ojb.broker.PathTest$D" table="P_D_TABLE">
  	<field-descriptor name="id" column="ID" jdbc-type="BIGINT" primarykey="true" autoincrement="true"/>
  	<field-descriptor name="dAttrib" column="D_ATTRIB" jdbc-type="INTEGER"/>
  	</class-descriptor>
  
  <!-- ojb test pathClass classes -->
  
  
  1.45      +1 -0      db-ojb/src/test/org/apache/ojb/broker/AllTests.java
  
  Index: AllTests.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/broker/AllTests.java,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -r1.44 -r1.45
  --- AllTests.java	19 Apr 2004 16:31:15 -0000	1.44
  +++ AllTests.java	24 Apr 2004 08:25:38 -0000	1.45
  @@ -91,6 +91,7 @@
           suite.addTestSuite(CollectionTest2.class);
           suite.addTestSuite(NumberAccuracyTest.class);
           suite.addTestSuite(AutoIncrementTest.class);
  +        suite.addTestSuite(PathTest.class);
           return suite;
       }
   
  
  
  
  1.1                  db-ojb/src/test/org/apache/ojb/broker/PathTest.java
  
  Index: PathTest.java
  ===================================================================
  package org.apache.ojb.broker;
  
  /**
   * TestClasses for Per-Criteria-Path-Hints
   * @author PAW
   *
   */
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  
  import junit.framework.TestCase;
  
  import org.apache.ojb.broker.query.Criteria;
  import org.apache.ojb.broker.query.Query;
  import org.apache.ojb.broker.query.QueryByCriteria;
  import org.apache.ojb.broker.query.QueryFactory;
  
  public class PathTest extends TestCase
  {
  
      private static Class CLASS = PathTest.class;
      private int COUNT = 10;
      private int id_filter = 10000;
      private PersistenceBroker broker = null;
  
      public static void main(String[] args)
      {
          String[] arr = {CLASS.getName()};
          junit.textui.TestRunner.main(arr);
      }
  
      /**
       * Insert the method's description here.
       * Creation date: (06.12.2000 21:58:53)
       */
      public void setUp()
      {
          try
          {
              broker = PersistenceBrokerFactory.defaultPersistenceBroker();
          }
          catch (PBFactoryException e)
          {
          }
      }
  
      /**
       * Insert the method's description here.
       * Creation date: (06.12.2000 21:59:14)
       */
      public void tearDown()
      {
          broker.close();
      }
  
      public PathTest(String name)
      {
          super(name);
      }
  
      public void testDeleteData() throws Exception
      {
          broker.beginTransaction();
          Criteria crit = new Criteria();
  
          Query query = QueryFactory.newQuery(D.class, crit);
          Collection Ds = broker.getCollectionByQuery(query);
          for (Iterator iterator = Ds.iterator(); iterator.hasNext();)
          {
              broker.delete(iterator.next());
          }
          query = QueryFactory.newQuery(C.class, crit);
          Collection Cs = broker.getCollectionByQuery(query);
          for (Iterator iterator = Cs.iterator(); iterator.hasNext();)
          {
              broker.delete(iterator.next());
          }
          query = QueryFactory.newQuery(B.class, crit);
          Collection Bs = broker.getCollectionByQuery(query);
          for (Iterator iterator = Bs.iterator(); iterator.hasNext();)
          {
              broker.delete(iterator.next());
          }
          query = QueryFactory.newQuery(A.class, crit);
          Collection As = broker.getCollectionByQuery(query);
          for (Iterator iterator = As.iterator(); iterator.hasNext();)
          {
              broker.delete(iterator.next());
          }
          broker.commitTransaction();
      }
  
      private static int NUM_A = 1;
      private static int NUM_B_PER_A = 4;
      private static int NUM_C_PER_B = 2;
      private static int NUM_C1_PER_B = 3;
      private static int NUM_D_PER_C = 1;
  
      private static int A_OFFSET = 10000;
      private static int B_OFFSET = 1000;
      private static int C_OFFSET = 100;
      private static int D_OFFSET = 10;
  
      public void testCreateData() throws Exception
      {
          broker.beginTransaction();
          A a = new A(A_OFFSET);
          broker.store(a);
          for (int i = 0; i < NUM_B_PER_A; i++)
          {
              B b = new B(A_OFFSET + B_OFFSET * i);
              b.setA(a);
              broker.store(b);
              for (int j = 0; j < NUM_C_PER_B; j++)
              {
                  C c = new C(A_OFFSET + B_OFFSET * i + C_OFFSET * j);
                  c.setB(b);
                  D d = new D(A_OFFSET + B_OFFSET * i + C_OFFSET * j + D_OFFSET);
                  c.setD(d);
                  broker.store(d);
                  broker.store(c);
              }
              for (int j = 0; j < NUM_C1_PER_B; j++)
              {
                  C1 c1 = new C1(A_OFFSET + B_OFFSET * i + C_OFFSET * j);
                  c1.setB(b);
                  D d = new D(A_OFFSET + B_OFFSET * i + C_OFFSET * j + D_OFFSET);
                  c1.setD(d);
                  c1.setC1Attrib(c1.getCAttrib() + 1);
                  broker.store(d);
                  broker.store(c1);
              }
          }
          broker.commitTransaction();
  
          broker.clearCache();
  
          Criteria crit = new Criteria();
  
          Query query = QueryFactory.newQuery(A.class, crit);
          Collection As = broker.getCollectionByQuery(query);
          assertEquals(As.size(), NUM_A);
  
          query = QueryFactory.newQuery(B.class, crit);
          Collection Bs = broker.getCollectionByQuery(query);
          int numB = NUM_A * NUM_B_PER_A;
          assertEquals(Bs.size(), numB);
  
          query = QueryFactory.newQuery(C.class, crit);
          Collection Cs = broker.getCollectionByQuery(query);
          int numC = numB * (NUM_C_PER_B + NUM_C1_PER_B);
          assertEquals(Cs.size(), numC);
  
          query = QueryFactory.newQuery(D.class, crit);
          Collection Ds = broker.getCollectionByQuery(query);
          int numD = numC * NUM_D_PER_C;
          assertEquals(Ds.size(), numD);
  
      }
  
      public void testPathClassPerCriteria() throws Exception
      {
          try
          {
              // one EDBranch
              Criteria crit1 = new Criteria();
              crit1.setAlias("alias1");
              crit1.addEqualTo("cSet.cAttrib", new Integer("10200"));
              crit1.addPathClass("cSet", C.class);
  
              // one EDLeaf
              Criteria crit2 = new Criteria();
              crit2.setAlias("alias2");
              crit2.addEqualTo("cSet.c1Attrib", new Integer("10001"));
              crit2.addPathClass("cSet", C1.class);
  
              crit1.addAndCriteria(crit2);
  
              Query query = new QueryByCriteria(B.class, crit1);
  
              Collection allBs = broker.getCollectionByQuery(query);
  
              java.util.Iterator itr = allBs.iterator();
  
              assertEquals(allBs.size(), 1);
              System.out.println("testPathClassPerCriteria() iteration size:" + allBs.size());
              while (itr.hasNext())
              {
                  B b = (B) itr.next();
                  System.out.println("Found B:  " + b.getId() + " " + b.getBAttrib());
              }
          }
          catch (Throwable t)
          {
              t.printStackTrace(System.out);
              fail("testPathClassPerCriteria: " + t.getMessage());
          }
      }
  
      // Inner Classes
  
      public static class A
      {
          private long id;
          private int aAttrib;
          private Collection bSet;
  
          public A()
          {
          }
  
          public A(int aAttrib)
          {
              this.aAttrib = aAttrib;
              this.bSet = new ArrayList();
          }
  
          /**
           * @return
           */
          public int getAAttrib()
          {
              return aAttrib;
          }
  
          /**
           * @return
           */
          public Collection getBSet()
          {
              return bSet;
          }
  
          /**
           * @return
           */
          public long getId()
          {
              return id;
          }
  
          /**
           * @param i
           */
          public void setAAttrib(int i)
          {
              aAttrib = i;
          }
  
          /**
           * @param collection
           */
          public void setBSet(Collection collection)
          {
              bSet = collection;
          }
  
          /**
           * @param l
           */
          public void setId(long l)
          {
              id = l;
          }
  
      }
  
      public static class B
      {
          private long id;
          private long aId;
          private int bAttrib;
          private A a;
          private Collection cSet;
  
          public B()
          {
          }
  
          public B(int bAttrib)
          {
              this.bAttrib = bAttrib;
              this.cSet = new ArrayList();
          }
  
          /**
           * @return
           */
          public int getBAttrib()
          {
              return bAttrib;
          }
  
          /**
           * @return
           */
          public Collection getCSet()
          {
              return cSet;
          }
  
          /**
           * @return
           */
          public long getId()
          {
              return id;
          }
  
          /**
           * @param i
           */
          public void setBAttrib(int i)
          {
              bAttrib = i;
          }
  
          /**
           * @param collection
           */
          public void setCSet(Collection collection)
          {
              cSet = collection;
          }
  
          /**
           * @param l
           */
          public void setId(long l)
          {
              id = l;
          }
  
          /**
           * @return
           */
          public A getA()
          {
              return a;
          }
  
          /**
           * @param a
           */
          public void setA(A a)
          {
              this.a = a;
              a.getBSet().add(this);
          }
  
      }
  
      public static class C
      {
          private long id;
          private long bId;
          private B b;
          private long dId;
          private D d;
          private int cAttrib;
  
          public C()
          {
          }
  
          public C(int cAttrib)
          {
              this.cAttrib = cAttrib;
          }
  
          /**
           * @return
           */
          public int getCAttrib()
          {
              return cAttrib;
          }
  
          /**
           * @return
           */
          public D getD()
          {
              return d;
          }
  
          /**
           * @return
           */
          public long getId()
          {
              return id;
          }
  
          /**
           * @param i
           */
          public void setCAttrib(int i)
          {
              cAttrib = i;
          }
  
          /**
           * @param collection
           */
          public void setD(D d)
          {
              this.d = d;
          }
  
          /**
           * @param l
           */
          public void setId(long l)
          {
              id = l;
          }
  
          /**
           * @return
           */
          public B getB()
          {
              return b;
          }
  
          /**
           * @param b
           */
          public void setB(B b)
          {
              this.b = b;
              b.getCSet().add(this);
          }
  
      }
  
      public static class C1 extends C
      {
  
          private int c1Attrib;
  
          /**
           * @param cAttrib
           */
  
          public C1()
          {
          }
  
          public C1(int cAttrib)
          {
              super(cAttrib);
          }
  
          /**
           * @return
           */
          public int getC1Attrib()
          {
              return c1Attrib;
          }
  
          /**
           * @param i
           */
          public void setC1Attrib(int i)
          {
              c1Attrib = i;
          }
  
      }
  
      public static class D
      {
          private long id;
          private int dAttrib;
  
          public D()
          {
          }
  
          public D(int dAttrib)
          {
              this.dAttrib = dAttrib;
          }
  
          /**
           * @return
           */
          public int getDAttrib()
          {
              return dAttrib;
          }
  
          /**
           * @return
           */
          public long getId()
          {
              return id;
          }
  
          /**
           * @param i
           */
          public void setDAttrib(int i)
          {
              dAttrib = i;
          }
  
          /**
           * @param l
           */
          public void setId(long l)
          {
              id = l;
          }
  
      }
  
  }
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org