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 2005/01/06 22:00:06 UTC

cvs commit: db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql TableAliasHandler.java

brj         2005/01/06 13:00:06

  Modified:    src/schema ojbtest-schema.xml
               src/java/org/apache/ojb/broker/core
                        PersistenceBrokerImpl.java
                        QueryReferenceBroker.java
               src/java/org/apache/ojb/broker/accesslayer
                        CollectionPrefetcher.java ReferencePrefetcher.java
                        RelationshipPrefetcherImpl.java
               src/test/org/apache/ojb repository_junit.xml repository.dtd
               src/java/org/apache/ojb/broker/metadata
                        CollectionDescriptor.java RepositoryTags.java
                        RepositoryElements.java
                        DiscriminatorFieldDescriptor.java
                        RepositoryXmlHandler.java
                        ObjectReferenceDescriptor.java
               src/java/org/apache/ojb/broker/util BrokerHelper.java
               .        release-notes.txt
               src/java/org/apache/ojb/broker/accesslayer/sql
                        TableAliasHandler.java
  Added:       src/test/org/apache/ojb/broker NoPkReferenceTest.java
  Log:
  new feature to support non-pk-fields as target-fields in 1:1 and 1:n relationships
  
  Revision  Changes    Path
  1.1                  db-ojb/src/test/org/apache/ojb/broker/NoPkReferenceTest.java
  
  Index: NoPkReferenceTest.java
  ===================================================================
  package org.apache.ojb.broker;
  
  /* Copyright 2002-2004 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.Iterator;
  import java.util.List;
  
  import org.apache.ojb.broker.query.Criteria;
  import org.apache.ojb.broker.query.Query;
  import org.apache.ojb.broker.query.QueryFactory;
  import org.apache.ojb.junit.PBTestCase;
  
  /**
   * Test for relationships based on non-pk-attributes
   *
   * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
   * @version $Id: NoPkReferenceTest.java,v 1.1 2005/01/06 21:00:00 brj Exp $
   */
  public class NoPkReferenceTest extends PBTestCase
  {
  
      public static void main(String[] args)
      {
          String[] arr = {NoPkReferenceTest.class.getName()};
          junit.textui.TestRunner.main(arr);
      }
      
      private ProductGroup_2 createProductGroup(String groupName)
      {
          ProductGroup_2 pg;
          Article_2 a1;
          Article_2 a2;
          List articles = new ArrayList();
          
          pg = new ProductGroup_2(groupName, "This is Group " + groupName);
          a1 = new Article_2("Art-" + groupName + "-1");
          a2 = new Article_2("Art-" + groupName + "-2");
  
          a1.setProductGroup(pg);
          a2.setProductGroup(pg);
          articles.add(a1);
          articles.add(a2);
          pg.setAllArticlesInGroup(articles);
  
          return pg;
      }
      
      /**
       * Insert a ProductGroup with 2 Articles
       */
      public void testInsert()
      {
          Criteria crit;
          Query q;
          Collection result;
          Iterator iter;
          Identity pgIdentity;
  
          String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
          ProductGroup_2 pg = createProductGroup(name);
          Article_2 article;
          
          broker.beginTransaction();
          broker.store(pg);        
          broker.commitTransaction();
          pgIdentity = broker.serviceIdentity().buildIdentity(pg);
          
          broker.clearCache();      
          
          // check existence of ProductGroup
          pg = (ProductGroup_2) broker.getObjectByIdentity(pgIdentity);
          assertNotNull(pg);
          assertEquals(name, pg.getGroupName());
          assertEquals(2, pg.getAllArticlesInGroup().size());
          
          broker.clearCache();
  
          // check existence of Articles
          crit = new Criteria();
          crit.addEqualTo("productGroupName", name);
          q = QueryFactory.newQuery(Article_2.class, crit);
          result = broker.getCollectionByQuery(q);
          assertEquals(2, result.size());
  
          iter = result.iterator();
          while (iter.hasNext())
          {
              article = (Article_2) iter.next();
              assertEquals(name, article.getProductGroup().getName());
          }
          
      }
  
      public void testQueryNoJoin()
      {
          Criteria crit;
          Query q;
          Collection result;
          Iterator iter;
  
          String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
          ProductGroup_2 pg = createProductGroup(name);
          Article_2 article;
          
          broker.beginTransaction();
          broker.store(pg);        
          broker.commitTransaction();
          
          broker.clearCache();       
          
          // look for Articles using attribute of ProductGroup
          // no join required because groupName is the target for the fk
          crit = new Criteria();
          crit.addEqualTo("productGroup.groupName", name);
          q = QueryFactory.newQuery(Article_2.class, crit);
          result = broker.getCollectionByQuery(q);
          assertEquals(2, result.size());
  
          iter = result.iterator();
          while (iter.hasNext())
          {
              article = (Article_2) iter.next();
              assertEquals(name, article.getProductGroup().getName());
          }
      }
  
      public void testQueryJoin()
      {
          Criteria crit;
          Query q;
          Collection result;
          Iterator iter;
          Integer pgId;
  
          String name = "Grp-NoPkReferenceTest" + System.currentTimeMillis();
          ProductGroup_2 pg = createProductGroup(name);
          Article_2 article;
          
          broker.beginTransaction();
          broker.store(pg);        
          broker.commitTransaction();
          pgId = pg.getGroupId();
          
          broker.clearCache();       
          
          // look for Articles using attribute of ProductGroup
          // join is required 
          crit = new Criteria();
          crit.addEqualTo("productGroup.groupId", pgId);
          q = QueryFactory.newQuery(Article_2.class, crit);
          result = broker.getCollectionByQuery(q);
          assertEquals(2, result.size());
  
          iter = result.iterator();
          while (iter.hasNext())
          {
              article = (Article_2) iter.next();
              assertEquals(name, article.getProductGroup().getName());
          }
      }
  
      //
      // Testclasses ----------------------------------------------
      //
      public static class ProductGroup_2 extends ProductGroup
      {
          public ProductGroup_2()
          {
              super();
          }
  
          /**
           * @param pGroupId
           * @param pGroupName
           * @param pDescription
           */
          public ProductGroup_2(String pGroupName, String pDescription)
          {
              super(null, pGroupName, pDescription);
          }
  }
      
      public static class Article_2 extends Article
      {
          private String productGroupName;
          
          public Article_2()
          {
              super();
          }
  
          public Article_2(String articleName)
          {
              super();
              setArticleId(null);
              setArticleName(articleName);
          }
          
          /**
           * @return Returns the groupName.
           */
          
          public String getProductGroupName()
          {
              return productGroupName;
          }
          /**
           * @param groupName The groupName to set.
           */
          public void setProductGroupName(String groupName)
          {
              this.productGroupName = groupName;
          }
      }
  }
  
  
  
  1.91      +42 -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.90
  retrieving revision 1.91
  diff -u -r1.90 -r1.91
  --- ojbtest-schema.xml	18 Dec 2004 19:28:47 -0000	1.90
  +++ ojbtest-schema.xml	6 Jan 2005 21:00:00 -0000	1.91
  @@ -1537,6 +1537,47 @@
   
   	<!-- ************ Object Factory tests * END -->
   
  +	<!-- Tables with references using non-pk-field -->
  +  <table name="Kategorien_2"
  +         	javaName="ProductGroup_2">
  +    <column name="Kategorie_Nr" required="true" primaryKey="true" type="INTEGER"
  +            javaName="groupId"/>
  +    <column name="Kategorie_Name" type="VARCHAR" size="150"
  +            javaName="groupName"/>
  +    <column name="Beschreibung" type="VARCHAR" size="150"
  +            javaName="description"/>
  +	<unique name="Unique_Name">
  +		<unique-column name="Kategorie_Name"/>
  +    </unique>
  +  </table>
  +
  +
  +  <table name="Artikel_2"
  +         	javaName="Article_2">
  +    <column name="Artikel_Nr" required="true" primaryKey="true" type="INTEGER"
  +            javaName="articleId"/>
  +    <column name="Artikelname" type="VARCHAR" size="150"
  +            javaName="articleName"/>
  +    <column name="Lieferanten_Nr" type="INTEGER"
  +            javaName="supplierId"/>
  +    <column name="KatName" type="VARCHAR"
  +            javaName="productGroupName"/>
  +    <column name="Liefereinheit" type="VARCHAR" size="150"
  +            javaName="unit"/>
  +    <column name="Einzelpreis" type="FLOAT"
  +            javaName="price"/>
  +    <column name="Lagerbestand" type="INTEGER"
  +            javaName="stock"/>
  +    <column name="BestellteEinheiten" type="INTEGER"
  +            javaName="orderedUnits"/>
  +    <column name="MindestBestand" type="INTEGER"
  +            javaName="minimumStock"/>
  +    <column name="Auslaufartikel" type="INTEGER"
  +            javaName="inSelloutArticle"/>
  +    <foreign-key foreignTable="Kategorien_2">
  +      	<reference local="KatName" foreign="Kategorie_Name"/>
  +    </foreign-key>
  +  </table>
   
   
   </database>
  
  
  
  1.108     +2 -4      db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
  
  Index: PersistenceBrokerImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java,v
  retrieving revision 1.107
  retrieving revision 1.108
  diff -u -r1.107 -r1.108
  --- PersistenceBrokerImpl.java	26 Dec 2004 20:57:30 -0000	1.107
  +++ PersistenceBrokerImpl.java	6 Jan 2005 21:00:00 -0000	1.108
  @@ -1237,9 +1237,7 @@
           }
           else
           {
  -            Class refClass = ProxyHelper.getRealClass(referencedObject);
  -            ClassDescriptor refCld = getClassDescriptor(refClass);
  -            refPkValues = brokerHelper.getKeyValues(refCld, referencedObject, false);
  +            refPkValues = brokerHelper.getFkTargetValuesForObject(rds, referencedObject, false);
           }
           for (int i = 0; i < objFkFields.length; i++)
           {
  
  
  
  1.28      +25 -19    db-ojb/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
  
  Index: QueryReferenceBroker.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- QueryReferenceBroker.java	10 Dec 2004 22:40:42 -0000	1.27
  +++ QueryReferenceBroker.java	6 Jan 2005 21:00:00 -0000	1.28
  @@ -48,6 +48,7 @@
   import org.apache.ojb.broker.query.Query;
   import org.apache.ojb.broker.query.QueryByCriteria;
   import org.apache.ojb.broker.query.QueryFactory;
  +import org.apache.ojb.broker.util.BrokerHelper;
   import org.apache.ojb.broker.util.collections.ManageableListImpl;
   import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
   import org.apache.ojb.broker.util.logging.Logger;
  @@ -110,7 +111,7 @@
               // now iterate over all elements and add them to the new collection
               iter = pb.getIteratorFromQuery(query, cld);
   
  -            // BRJ : get fullSizefor Query
  +            // BRJ : get fullSize for Query
               // to be removed when Query.fullSize is removed
               if (iter instanceof PagingIterator)
               {
  @@ -442,7 +443,10 @@
        */
       private Identity getReferencedObjectIdentity(Object obj, ObjectReferenceDescriptor rds, ClassDescriptor cld)
       {
  -        Object[] fkValues = rds.getForeignKeyValues(obj, cld);
  +        BrokerHelper helper = pb.serviceBrokerHelper();
  +        FieldDescriptor[] fds = rds.getForeignKeyFieldDescriptors(cld);
  +        Object[] fkValues = helper.extractValueArray(helper.getValuesForObject(fds, obj, false));
  +        
           FieldDescriptor[] fkFieldDescriptors = rds.getForeignKeyFieldDescriptors(cld);
           boolean hasNullifiedFKValue = hasNullifiedFK(fkFieldDescriptors, fkValues);
           /*
  @@ -641,12 +645,12 @@
   
       /**
        * Answer the foreign key query to retrieve the collection
  -     * defined by CollectionDescriptor
  +     * defined by CollectionDescriptor.
        *
  -     * @param obj
  -     * @param cld
  -     * @param cds
  -     * @return
  +     * @param obj the owner of the relationship
  +     * @param cld the ClassDescriptor for the owner
  +     * @param cod the CollectionDescriptor
  +     * @return org.apache.ojb.broker.query.Query
        */
       private Query getFKQuery(Object obj, ClassDescriptor cld, CollectionDescriptor cds)
       {
  @@ -685,17 +689,18 @@
           return fkQuery;
       }
   
  -        /**
  -     * Get Foreign key query for m:n <br>
  -     * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria
  -     * @return org.apache.ojb.broker.query.QueryByCriteria
  +    /**
  +     * Get Foreign key query for m:n relationship <br>
  +     * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria.
  +     * 
        * @param obj the owner of the relationship
        * @param cld the ClassDescriptor for the owner
        * @param cod the CollectionDescriptor
  +     * @return org.apache.ojb.broker.query.QueryByCriteria
        */
       private QueryByCriteria getFKQueryMtoN(Object obj, ClassDescriptor cld, CollectionDescriptor cod)
       {
  -        ValueContainer[] values = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  +        ValueContainer[] values = pb.serviceBrokerHelper().getFkTargetValuesForObject(cod, obj ,false);
           Object[] thisClassFks = cod.getFksToThisClass();
           Object[] itemClassFks = cod.getFksToItemClass();
           ClassDescriptor refCld = cod.getItemClassDescriptor();
  @@ -716,15 +721,16 @@
       }
   
       /**
  -     * Get Foreign key query for 1:n
  +     * Get Foreign key query for 1:n relationship.
  +     * 
  +     * @param obj the owner of the relationship
  +     * @param cld the ClassDescriptor for the owner
  +     * @param cod the CollectionDescriptor
        * @return org.apache.ojb.broker.query.QueryByCriteria
  -     * @param obj
  -     * @param cld
  -     * @param cod
        */
       private QueryByCriteria getFKQuery1toN(Object obj, ClassDescriptor cld, CollectionDescriptor cod)
       {
  -        ValueContainer[] container = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  +        ValueContainer[] values = pb.serviceBrokerHelper().getFkTargetValuesForObject(cod, obj ,false);
           ClassDescriptor refCld = cod.getItemClassDescriptor();
           FieldDescriptor[] fields = cod.getForeignKeyFieldDescriptors(refCld);
           Criteria criteria = new Criteria();
  @@ -732,7 +738,7 @@
           for (int i = 0; i < fields.length; i++)
           {
               FieldDescriptor fld = fields[i];
  -            criteria.addEqualTo(fld.getAttributeName(), container[i].getValue());
  +            criteria.addEqualTo(fld.getAttributeName(), values[i].getValue());
           }
   
           return QueryFactory.newQuery(refCld.getClassOfObject(), criteria);
  
  
  
  1.34      +9 -9      db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java
  
  Index: CollectionPrefetcher.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionPrefetcher.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- CollectionPrefetcher.java	5 Dec 2004 12:31:01 -0000	1.33
  +++ CollectionPrefetcher.java	6 Jan 2005 21:00:00 -0000	1.34
  @@ -74,7 +74,6 @@
           IdentityFactory idFactory = pb.serviceIdentity();
           ClassDescriptor cld = getOwnerClassDescriptor();
           Class topLevelClass = pb.getTopLevelClass(cld.getClassOfObject());
  -        BrokerHelper helper = pb.serviceBrokerHelper();
           Collection queries = new ArrayList(owners.size());
           Collection idsSubset = new HashSet(owners.size());
           Object[] fkValues;
  @@ -85,7 +84,8 @@
           while (iter.hasNext())
           {
               owner = iter.next();
  -            fkValues = helper.extractValueArray(helper.getKeyValues(cld, owner));
  +            fkValues = getFkTargetValuesForObject(owner);
  +            
               id = idFactory.buildIdentity(null, topLevelClass, fkValues);
               idsSubset.add(id);
               if (idsSubset.size() == pkLimit)
  @@ -156,17 +156,16 @@
           for (Iterator it = owners.iterator(); it.hasNext();)
           {
               Object owner = it.next();
  -            ownerIdsToLists.put(new Identity(owner, pb), new ArrayList());
  +            Object[] targetValues = getFkTargetValuesForObject(owner);
  +            Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
  +            ownerIdsToLists.put(ownerId, new ArrayList());
           }
   
           // build the children lists for the owners
           for (Iterator it = children.iterator(); it.hasNext();)
           {
               Object child = it.next();
  -            // BRJ: use cld for real class, relatedObject could be Proxy
  -            ClassDescriptor cld = getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(child));
  -
  -            Object[] fkValues = cds.getForeignKeyValues(child, cld);             
  +            Object[] fkValues = getFkValuesForObject(child);             
               Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, fkValues);
               
               List list = (List) ownerIdsToLists.get(ownerId);
  @@ -181,7 +180,8 @@
           {
               Object result;
               Object owner = it.next();
  -            Identity ownerId = new Identity(owner, pb);
  +            Object[] targetValues = getFkTargetValuesForObject(owner);
  +            Identity ownerId = idFactory.buildIdentity(null, ownerTopLevelClass, targetValues);
               List list = (List) ownerIdsToLists.get(ownerId);
   
               if ((collectionClass == null) && field.getType().isArray())
  
  
  
  1.23      +24 -16    db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java
  
  Index: ReferencePrefetcher.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/ReferencePrefetcher.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- ReferencePrefetcher.java	14 Sep 2004 16:03:33 -0000	1.22
  +++ ReferencePrefetcher.java	6 Jan 2005 21:00:00 -0000	1.23
  @@ -22,14 +22,17 @@
   import java.util.Iterator;
   
   import org.apache.ojb.broker.Identity;
  +import org.apache.ojb.broker.IdentityFactory;
   import org.apache.ojb.broker.PersistenceBroker;
   import org.apache.ojb.broker.cache.LocalCache;
   import org.apache.ojb.broker.core.PersistenceBrokerImpl;
   import org.apache.ojb.broker.metadata.ClassDescriptor;
  +import org.apache.ojb.broker.metadata.FieldDescriptor;
   import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
   import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
   import org.apache.ojb.broker.query.Query;
   
  +
   /**
    * Relationship Prefetcher for References.
    *
  @@ -56,34 +59,32 @@
       protected void associateBatched(Collection owners, Collection children)
       {
           ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
  -        ClassDescriptor cld = getOwnerClassDescriptor();
  -        Object owner;
  -        Object relatedObject;
  -        Object fkValues[];
  -        Identity id;
           PersistenceBroker pb = getBroker();
           PersistentField field = ord.getPersistentField();
           Class topLevelClass = pb.getTopLevelClass(ord.getItemClass());
           HashMap childrenMap = new HashMap(children.size());
  +        IdentityFactory idFactory = pb.serviceIdentity();
   
   
           for (Iterator it = children.iterator(); it.hasNext(); )
           {
  -            relatedObject = it.next();
  -            childrenMap.put(new Identity(relatedObject, pb), relatedObject);
  +            Object relatedObject = it.next();
  +            Object[] targetValues = getFkTargetValuesForObject(relatedObject);
  +            Identity id = idFactory.buildIdentity(null, topLevelClass, targetValues);
  +            childrenMap.put(id, relatedObject);
           }
   
           for (Iterator it = owners.iterator(); it.hasNext(); )
           {
  -            owner = it.next();
  -            fkValues = ord.getForeignKeyValues(owner,cld);
  +            Object owner = it.next();
  +            Object[] fkValues = getFkValuesForObject(owner);
               if (isNull(fkValues))
               {
                   field.set(owner, null);
                   continue;
               }
  -            id = new Identity(null, topLevelClass, fkValues);
  -            relatedObject = childrenMap.get(id);
  +            Identity id = idFactory.buildIdentity(null, topLevelClass, fkValues);
  +            Object relatedObject = childrenMap.get(id);
               field.set(owner, relatedObject);
           }
       }
  @@ -107,7 +108,6 @@
        */
       protected Query[] buildPrefetchQueries(Collection owners, Collection children)
       {
  -        ClassDescriptor cld = getOwnerClassDescriptor();
           ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
           Collection queries = new ArrayList(owners.size());
           Collection idsSubset = new HashSet(owners.size());
  @@ -118,16 +118,18 @@
           Identity id;
           PersistenceBrokerImpl pb = getBroker();
           LocalCache cache = pb.ojbLocalCache();
  +        IdentityFactory idFactory = pb.serviceIdentity();
   
           while (iter.hasNext())
           {
               owner = iter.next();
  -            fkValues = ord.getForeignKeyValues(owner,cld);
  +            fkValues = getFkValuesForObject(owner);
  +            
               if (isNull(fkValues))
               {
                   continue;
               }
  -            id = new Identity(null, topLevelClass, fkValues);
  +            id = idFactory.buildIdentity(null, topLevelClass, fkValues);
               if (cache.lookup(id) != null)
               {
                   children.add(pb.getObjectByIdentity(id));
  @@ -154,6 +156,12 @@
        */
       protected Query buildPrefetchQuery(Collection ids)
       {
  -        return buildPrefetchQuery(ids, getItemClassDescriptor().getPkFields());
  +        ClassDescriptor cld = getItemClassDescriptor();
  +        FieldDescriptor fds[];
  +        
  +//        fds = cld.getPkFields();
  +        fds = getObjectReferenceDescriptor().getForeignKeyTargetFieldDescriptors(cld);
  +        
  +        return buildPrefetchQuery(ids, fds);
       }
   }
  
  
  
  1.15      +38 -2     db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java
  
  Index: RelationshipPrefetcherImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RelationshipPrefetcherImpl.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- RelationshipPrefetcherImpl.java	10 Dec 2004 22:40:42 -0000	1.14
  +++ RelationshipPrefetcherImpl.java	6 Jan 2005 21:00:00 -0000	1.15
  @@ -15,10 +15,14 @@
    * limitations under the License.
    */
   
  +import org.apache.ojb.broker.PersistenceBroker;
  +import org.apache.ojb.broker.PersistenceBrokerException;
   import org.apache.ojb.broker.core.PersistenceBrokerImpl;
  +import org.apache.ojb.broker.core.ValueContainer;
   import org.apache.ojb.broker.metadata.ClassDescriptor;
   import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
  -
  +import org.apache.ojb.broker.util.BrokerHelper;
  + 
   /**
    * Abstract Relationship Prefetchers.
    * Each Prefetcher handles a single Relationship (1:1 or 1:n)
  @@ -104,4 +108,36 @@
       {
           this.cascadeRetrieve = cascadeRetrieve;
       }
  +    
  +    
  +    /**
  +     * Get the values of the fk-target-fields for an obj.
  +     * @param objOrProxy
  +     * @throws PersistenceBrokerException
  +     */
  +    protected Object[] getFkTargetValuesForObject(Object objOrProxy) throws PersistenceBrokerException
  +    {
  +        PersistenceBroker pb = getBroker();
  +        BrokerHelper helper = pb.serviceBrokerHelper();
  +        ObjectReferenceDescriptor rds = getObjectReferenceDescriptor();
  +        
  +        ValueContainer[] values = helper.getFkTargetValuesForObject(rds, objOrProxy, false);
  +        return helper.extractValueArray(values);
  +    } 
  +
  +    /**
  +     * Get the values of the fk-fields for an obj. 
  +     * @param objOrProxy
  +     * @throws PersistenceBrokerException
  +     */
  +    protected Object[] getFkValuesForObject(Object objOrProxy) throws PersistenceBrokerException
  +    {
  +        PersistenceBroker pb = getBroker();
  +        BrokerHelper helper = pb.serviceBrokerHelper();
  +        ObjectReferenceDescriptor rds = getObjectReferenceDescriptor();
  +
  +        ValueContainer[] values = helper.getFkValuesForObject(rds, objOrProxy, false);
  +        return helper.extractValueArray(values);
  +    } 
  +    
   }
  
  
  
  1.129     +105 -4    db-ojb/src/test/org/apache/ojb/repository_junit.xml
  
  Index: repository_junit.xml
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository_junit.xml,v
  retrieving revision 1.128
  retrieving revision 1.129
  diff -u -r1.128 -r1.129
  --- repository_junit.xml	18 Dec 2004 14:01:18 -0000	1.128
  +++ repository_junit.xml	6 Jan 2005 21:00:01 -0000	1.129
  @@ -153,7 +153,7 @@
         >
            <orderby name="articleId" sort="DESC"/>
   
  -         <inverse-foreignkey field-ref="productGroupId"/>
  +         <inverse-foreignkey field-ref="productGroupId" target-field-ref="groupId"/>
         </collection-descriptor>
      </class-descriptor>
   
  @@ -1529,7 +1529,7 @@
            name="productGroup"
            class-ref="org.apache.ojb.broker.ProductGroup"
         >
  -         <foreignkey field-ref="productGroupId"/>
  +         <foreignkey field-ref="productGroupId" target-field-ref="groupId"/>
         </reference-descriptor>
      </class-descriptor>
   
  @@ -3717,11 +3717,112 @@
               name="productGroup"
               class-ref="org.apache.ojb.broker.ProductGroup"
   	        auto-retrieve="true"
  -    	    auto-update="true"           
  +    	    auto-update="true"
         >
            <documentation>this is the reference to an articles productgroup</documentation>
            <foreignkey field-ref="productGroupId"/>
         </reference-descriptor>
  +   </class-descriptor>
  +
  +<!-- Test classes using non-pk-fields for relationships-->
  +
  +   <class-descriptor
  +   	  class="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
  +   	  table="Artikel_2"
  +   >
  +      <field-descriptor
  +         name="articleId"
  +         column="Artikel_Nr"
  +         jdbc-type="INTEGER"
  +         primarykey="true"
  +         autoincrement="true"
  +      />
  +      <field-descriptor
  +         name="articleName"
  +         column="Artikelname"
  +         jdbc-type="VARCHAR"
  +      />
  +      <field-descriptor
  +         name="supplierId"
  +         column="Lieferanten_Nr"
  +         jdbc-type="INTEGER"
  +      />
  +      <field-descriptor
  +         name="productGroupName"
  +         column="KatName"
  +         jdbc-type="VARCHAR"
  +      />
  +      <field-descriptor
  +         name="unit"
  +         column="Liefereinheit"
  +         jdbc-type="VARCHAR"
  +      />
  +      <field-descriptor
  +         name="price"
  +         column="Einzelpreis"
  +         jdbc-type="FLOAT"
  +      />
  +      <field-descriptor
  +         name="stock"
  +         column="Lagerbestand"
  +         jdbc-type="INTEGER"
  +      />
  +      <field-descriptor
  +         name="orderedUnits"
  +         column="BestellteEinheiten"
  +         jdbc-type="INTEGER"
  +      />
  +      <field-descriptor
  +         name="minimumStock"
  +         column="MindestBestand"
  +         jdbc-type="INTEGER"
  +      />
  +      <field-descriptor
  +         name="isSelloutArticle"
  +         column="Auslaufartikel"
  +         jdbc-type="INTEGER"
  +         conversion="org.apache.ojb.broker.accesslayer.conversions.Boolean2IntFieldConversion"
  +      >
  +      </field-descriptor>
  +
  +      <reference-descriptor
  +            name="productGroup"
  +            class-ref="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
  +      >
  +         <foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
  +      </reference-descriptor>
  +   </class-descriptor>
  +
  +   <class-descriptor
  +   	  class="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
  +   	  table="Kategorien_2"
  +   >
  +      <field-descriptor
  +         name="groupId"
  +         column="Kategorie_Nr"
  +         jdbc-type="INTEGER"
  +         primarykey="true"
  +         autoincrement="true"
  +      />
  +      <field-descriptor
  +         name="groupName"
  +         column="Kategorie_Name"
  +         jdbc-type="VARCHAR"
  +      />
  +      <field-descriptor
  +         name="description"
  +         column="Beschreibung"
  +         jdbc-type="VARCHAR"
  +      />
  +      <collection-descriptor
  +         name="allArticlesInGroup"
  +         element-class-ref="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
  +         auto-retrieve="true"
  +         auto-update="true"
  +         auto-delete="false"
  +      >
  +         <inverse-foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
  +      </collection-descriptor>
      </class-descriptor>
   
   <!-- Mapping of classes used in junit tests and tutorials ends here -->
  
  
  
  1.60      +2 -0      db-ojb/src/test/org/apache/ojb/repository.dtd
  
  Index: repository.dtd
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/repository.dtd,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- repository.dtd	14 Sep 2004 16:51:04 -0000	1.59
  +++ repository.dtd	6 Jan 2005 21:00:01 -0000	1.60
  @@ -608,6 +608,7 @@
   <!ATTLIST foreignkey
   	field-id-ref CDATA #IMPLIED
   	field-ref CDATA #IMPLIED
  +	target-field-ref CDATA #IMPLIED	
   >
   
   
  @@ -740,6 +741,7 @@
   <!ATTLIST inverse-foreignkey
   	field-id-ref CDATA #IMPLIED
   	field-ref CDATA #IMPLIED
  +	target-field-ref CDATA #IMPLIED
   >
   
   <!--
  
  
  
  1.33      +96 -40    db-ojb/src/java/org/apache/ojb/broker/metadata/CollectionDescriptor.java
  
  Index: CollectionDescriptor.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/CollectionDescriptor.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- CollectionDescriptor.java	10 Dec 2004 22:40:42 -0000	1.32
  +++ CollectionDescriptor.java	6 Jan 2005 21:00:02 -0000	1.33
  @@ -204,77 +204,122 @@
       public String toXML()
       {
           String eol = SystemUtils.LINE_SEPARATOR;
  +        StringBuffer result = new StringBuffer(1024);
   
           // write opening tag
  -        String result = "      " + RepositoryTags.getOpeningTagNonClosingById(COLLECTION_DESCRIPTOR) + eol;
  +        result.append("      ");
  +        result.append(RepositoryTags.getOpeningTagNonClosingById(COLLECTION_DESCRIPTOR));
  +        result.append(eol);
   
           // write attributes
           // name
  -        result       += "        " + RepositoryTags.getAttribute(FIELD_NAME,this.getAttributeName()) + eol;
  +        result.append("      ");
  +        result.append(RepositoryTags.getAttribute(FIELD_NAME, getAttributeName()));
  +        result.append(eol);
   
           // collection class is optional
           if (getCollectionClassName() != null)
           {
  -            result       += "        " + RepositoryTags.getAttribute(COLLECTION_CLASS,this.getCollectionClassName()) + eol;
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(COLLECTION_CLASS, getCollectionClassName()));
  +            result.append(eol);
           }
   
           // element-class-ref
  -         result       += "        " + RepositoryTags.getAttribute(ITEMS_CLASS,this.getItemClassName()) + eol;
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(ITEMS_CLASS, getItemClassName()));
  +        result.append(eol);
   
           // indirection-table is optional
           if (isMtoNRelation())
           {
  -             result += "        " + RepositoryTags.getAttribute(INDIRECTION_TABLE,getIndirectionTable()) + eol;
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(INDIRECTION_TABLE, getIndirectionTable()));
  +            result.append(eol);
           }
   
           // proxyReference is optional, disabled by default
           if (isLazy())
           {
  -            result       += "        " + RepositoryTags.getAttribute(PROXY_REFERENCE,"true") + eol;
  -            result       += "        " + RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit()) + eol;
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(PROXY_REFERENCE, "true"));
  +            result.append(eol);
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, String
  +                    .valueOf(getProxyPrefetchingLimit())));
  +            result.append(eol);
           }
   
           //reference refresh is optional, disabled by default
           if (isRefresh())
           {
  -             result       += "        " + RepositoryTags.getAttribute(REFRESH,"true") + eol;
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(REFRESH, "true"));
  +            result.append(eol);
           }
   
           //auto retrieve
  -        result += "        " + RepositoryTags.getAttribute(AUTO_RETRIEVE, "" + getCascadeRetrieve()) + eol;
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_RETRIEVE, String.valueOf(getCascadeRetrieve())));
  +        result.append(eol);
   
           //auto update
  -        result += "        " + RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())) + eol;
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())));
  +        result.append(eol);
   
           //auto delete
  -        result += "        " + RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())) + eol;
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())));
  +        result.append(eol);
   
           //otm-dependent is optional, disabled by default
           if (getOtmDependent())
           {
  -            result += "        " + RepositoryTags.getAttribute(OTM_DEPENDENT, "true") + eol;
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(OTM_DEPENDENT, "true"));
  +            result.append(eol);
           }
   
           // close opening tag
  -        result       += "      >" + eol;
  +        result.append("      >");
  +        result.append(eol);
   
           // write elements
  -         // inverse fk elements
  -        for (int i=0;i<getForeignKeyFields().size();i++)
  -        {
  -        Object obj = getForeignKeyFields().get(i);
  -        if (obj instanceof Integer)
  +        // inverse fk elements
  +        for (int i = 0; i < getForeignKeyFields().size(); i++)
           {
  +            ForeignKey obj = (ForeignKey) getForeignKeyFields().get(i);
  +            if (obj.fkField instanceof Integer)
  +            {
                   String fkId = obj.toString();
  -            result += "        " + RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
  -                result += RepositoryTags.getAttribute(FIELD_ID_REF, fkId) + "/>" + eol;
  -        }
  -        else
  -        {
  -                String fk = (String) obj;
  -            result += "        " + RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
  -                result += RepositoryTags.getAttribute(FIELD_REF, fk) + "/>" + eol;
  -        }
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(FIELD_ID_REF, fkId));
  +                if (obj.targetField != null)
  +                {
  +                    result.append(" ");
  +                    result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
  +                }
  +                result.append("/>");
  +                result.append(eol);
  +            }
  +            else
  +            {
  +                String fk = (String) obj.fkField;
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(INVERSE_FK));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(FIELD_REF, fk));
  +                if (obj.targetField != null)
  +                {
  +                    result.append(" ");
  +                    result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
  +                }
  +                result.append("/>");
  +                result.append(eol);
  +            }
           }
   
           // write optional M:N elements
  @@ -282,25 +327,36 @@
           if (isMtoNRelation())
           {
               // foreign keys to this class
  -             for (int i=0;i<getFksToThisClass().length;i++)
  -             {
  +            for (int i = 0; i < getFksToThisClass().length; i++)
  +            {
                   String fkId = getFksToThisClass()[i];
  -                result += "        " + RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_THIS_CLASS) + " ";
  -                result += RepositoryTags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
  -             }
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_THIS_CLASS));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(COLUMN_NAME, fkId));
  +                result.append("/>");
  +                result.append(eol);
  +            }
   
               // foreign keys to item class
  -             for (int i=0;i<getFksToItemClass().length;i++)
  -             {
  +            for (int i = 0; i < getFksToItemClass().length; i++)
  +            {
                   String fkId = getFksToItemClass()[i];
  -                result += "        " + RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_ITEMS_CLASS) + " ";
  -                result += RepositoryTags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
  -             }
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(FK_POINTING_TO_ITEMS_CLASS));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(COLUMN_NAME, fkId));
  +                result.append("/>");
  +                result.append(eol);
  +            }
           }
   
           // closing tag
  -        result       += "      " + RepositoryTags.getClosingTagById(COLLECTION_DESCRIPTOR) + eol;
  -        return result;
  +        result.append("      ");
  +        result.append(RepositoryTags.getClosingTagById(COLLECTION_DESCRIPTOR));
  +        result.append(eol);
  +
  +        return result.toString();
       }
   
   	/**
  
  
  
  1.40      +1 -0      db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java
  
  Index: RepositoryTags.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- RepositoryTags.java	26 Oct 2004 15:27:40 -0000	1.39
  +++ RepositoryTags.java	6 Jan 2005 21:00:02 -0000	1.40
  @@ -147,6 +147,7 @@
           table.put("id", new Integer(ID));
           table.put("field-id-ref", new Integer(FIELD_ID_REF));
           table.put("field-ref", new Integer(FIELD_REF));
  +        table.put("target-field-ref", new Integer(TARGET_FIELD_REF));
           table.put("attribute", new Integer(ATTRIBUTE));
           table.put("attribute-name", new Integer(ATTRIBUTE_NAME));
           table.put("attribute-value", new Integer(ATTRIBUTE_VALUE));
  
  
  
  1.40      +2 -1      db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java
  
  Index: RepositoryElements.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- RepositoryElements.java	26 Oct 2004 15:27:40 -0000	1.39
  +++ RepositoryElements.java	6 Jan 2005 21:00:02 -0000	1.40
  @@ -110,6 +110,7 @@
       public static final int ID = 69;
       public static final int FIELD_ID_REF = 70;
       public static final int FIELD_REF = 84;
  +    public static final int TARGET_FIELD_REF = 122;
       public static final int ATTRIBUTE = 71;
       public static final int ATTRIBUTE_NAME = 72;
       public static final int ATTRIBUTE_VALUE = 73;
  @@ -148,7 +149,7 @@
   	public static final int USE_OBJECT_FACTORY = 121;
   
       // maintain a next id to keep track where we are
  -    static final int _NEXT = 120;
  +    static final int _NEXT = 123;
   
       // String constants
       public static final String TAG_ACCESS = "access";
  
  
  
  1.2       +5 -1      db-ojb/src/java/org/apache/ojb/broker/metadata/DiscriminatorFieldDescriptor.java
  
  Index: DiscriminatorFieldDescriptor.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/DiscriminatorFieldDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DiscriminatorFieldDescriptor.java	15 Aug 2004 12:42:28 -0000	1.1
  +++ DiscriminatorFieldDescriptor.java	6 Jan 2005 21:00:02 -0000	1.2
  @@ -39,6 +39,8 @@
    */
   public class DiscriminatorFieldDescriptor extends FieldDescriptor
   {
  +    private static final long serialVersionUID = 3978989851393995062L;
  +
       private String m_value;
   
       /**
  @@ -150,6 +152,8 @@
        */
       private class DiscriminatorPersistentField implements PersistentField
       {
  +        private static final long serialVersionUID = 4051328942017689655L;
  + 
           /**
            * Return the value of the discriminator.
            * @param ignoreObj the object is not used
  
  
  
  1.67      +23 -5     db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
  
  Index: RepositoryXmlHandler.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -r1.66 -r1.67
  --- RepositoryXmlHandler.java	14 Nov 2004 09:36:10 -0000	1.66
  +++ RepositoryXmlHandler.java	6 Jan 2005 21:00:02 -0000	1.67
  @@ -623,8 +623,17 @@
                           else
                           {
                               String fieldRef = atts.getValue(RepositoryTags.getTagById(FIELD_REF));
  -                            if (isDebug) logger.debug("      " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
  -                            m_CurrentORD.addForeignKeyField(fieldRef);
  +                            String targetFieldRef = atts.getValue(RepositoryTags.getTagById(TARGET_FIELD_REF));
  +                            
  +                            if (isDebug)
  +                            {
  +                                logger.debug("      " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
  +                                if (targetFieldRef != null)
  +                                {
  +                                    logger.debug("      " + RepositoryTags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);                                    
  +                                }
  +                            }
  +                            m_CurrentORD.addForeignKeyField(fieldRef, targetFieldRef);
                           }
                           break;
                       }
  @@ -765,8 +774,17 @@
                           else
                           {
                               String fieldRef = atts.getValue(RepositoryTags.getTagById(FIELD_REF));
  -                            if (isDebug) logger.debug("      " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
  -                            m_CurrentCOD.addForeignKeyField(fieldRef);
  +                            String targetFieldRef = atts.getValue(RepositoryTags.getTagById(TARGET_FIELD_REF));
  +                           
  +                            if (isDebug)
  +                            {
  +                                logger.debug("      " + RepositoryTags.getTagById(FIELD_REF) + ": " + fieldRef);
  +                                if (targetFieldRef != null)
  +                                {
  +                                    logger.debug("      " + RepositoryTags.getTagById(TARGET_FIELD_REF) + ": " + targetFieldRef);                                    
  +                                }
  +                         }    
  +                            m_CurrentCOD.addForeignKeyField(fieldRef, targetFieldRef);
                           }
                           break;
                       }
  
  
  
  1.42      +253 -158  db-ojb/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java
  
  Index: ObjectReferenceDescriptor.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/ObjectReferenceDescriptor.java,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- ObjectReferenceDescriptor.java	10 Dec 2004 22:40:41 -0000	1.41
  +++ ObjectReferenceDescriptor.java	6 Jan 2005 21:00:02 -0000	1.42
  @@ -15,8 +15,11 @@
    * limitations under the License.
    */
   
  -import java.util.Hashtable;
  -import java.util.Iterator;
  +import java.io.Serializable;
  +import java.util.ArrayList;
  +import java.util.HashMap;
  +import java.util.List;
  +import java.util.Map;
   import java.util.Vector;
   
   import org.apache.commons.lang.builder.ToStringBuilder;
  @@ -56,9 +59,14 @@
       private boolean multiMappedClass = false;
   
       /**
  -     * holds the foreign-key field descriptor array for a specified class
  +     * holds the foreign-key field descriptor array for a specified class.
        */
  -    private Hashtable fkFieldMap = new Hashtable();
  +    private Map m_fkFieldMap = new HashMap();
  +    /**
  +     * holds the foreign-key target-field descriptor array for a specified class.
  +     */
  +    private Map m_fkTargetFieldMap = new HashMap();
  +    
       /**
        * define loading strategy of the resulting object
        */
  @@ -89,88 +97,124 @@
           }
           return m_ProxyOfItems;
       }
  -
  +   
       /**
  -     *
  +     * Answer the FieldDescriptors for the Foreignkey-Fields.
  +     * @param cld the classdescriptor to get the fields from
        */
  -	public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor mif)
  -	{
  -		FieldDescriptor[] foreignKeyFieldDescriptors = null;
  -		if ((foreignKeyFieldDescriptors = (FieldDescriptor[]) fkFieldMap.get(mif)) == null)
  -		{
  -			// 1. collect vector of indices of Fk-Fields
  -			Vector v = getForeignKeyFields();
  -			// 2. get FieldDescriptor for each index from Class-descriptor
  -			// 2A. In a many-to-many relationship foreignkeyfields vector will be null.
  -			if (v != null)
  -			{
  -				Vector ret;
  -				if (mif.isInterface())
  -				{
  -					//exchange interface class descriptor with first concrete
  -					//class
  -					Vector extents = mif.getExtentClasses();
  +    public FieldDescriptor[] getForeignKeyFieldDescriptors(ClassDescriptor cld)
  +    {
  +        FieldDescriptor[] fkFieldDescriptors = (FieldDescriptor[]) m_fkFieldMap.get(cld);
  +        
  +        if (fkFieldDescriptors == null)
  +        {
  +            List fkFields = getForeignKeyFields();
  +            
  +            // get FieldDescriptor for each index from Class-descriptor
  +            // In a many-to-many relationship Fk-Fields vector will be null.
  +            if (fkFields != null)
  +            {
  +                if (cld.isInterface())
  +                {
  +                    //exchange interface class descriptor with first concrete class
  +                    Vector extents = cld.getExtentClasses();
                       // TODO: Check for side-effects
  -					Class firstConcreteClass = (Class) extents.get(0);
  -					mif = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
  -				}
  -				ret = new Vector();
  -
  -				Iterator iter = v.iterator();
  -				while (iter.hasNext())
  -				{
  -					Object fk = iter.next();
  -					FieldDescriptor fkfd;
  -					if (fk instanceof Integer)
  -					{
  -						Integer index = (Integer) fk;
  -						fkfd = mif.getFieldDescriptorByIndex(index.intValue());
  -					}
  -					else
  -					{
  -						fkfd = mif.getFieldDescriptorByName((String) fk);
  -					}
  -					if (fkfd == null)
  -					{
  -						throw new OJBRuntimeException("Incorrect or not found field reference name '"
  -                                + fk + "' in descriptor " + this + " for class-descriptor '"
  -                                + mif.getClassNameOfObject() + "'");
  -					}
  -					ret.add(fkfd);
  -				}
  -				foreignKeyFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
  -				fkFieldMap.put(mif, foreignKeyFieldDescriptors);
  -			}
  -		}
  -		return foreignKeyFieldDescriptors;
  -	}
  -
  -    /**
  -     * @throws MetadataException if an error occours while accessing ForeingKey values on obj
  -     */
  -    public Object[] getForeignKeyValues(Object obj, ClassDescriptor mif)
  -            throws PersistenceBrokerException
  -    {
  -        FieldDescriptor[] fks = getForeignKeyFieldDescriptors(mif);
  -        Object[] result = new Object[fks.length];
  -        for (int i = 0; i < result.length; i++)
  -        {
  -            FieldDescriptor fmd = fks[i];
  -            PersistentField f = fmd.getPersistentField();
  -
  -            // BRJ: do NOT convert.
  -            // conversion is done when binding the sql-statement
  -            //
  -            // FieldConversion fc = fmd.getFieldConversion();
  -            // Object val = fc.javaToSql(f.get(obj));
  -
  -            Object val = f.get(obj);
  -            result[i] = val;
  +                    Class firstConcreteClass = (Class) extents.get(0);
  +                    cld = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
  +                }
  +                List ret = new ArrayList();
  +
  +                for (int i = 0; i < fkFields.size(); i++)
  +                {
  +                    ForeignKey fk = (ForeignKey) fkFields.get(i);
  +                    FieldDescriptor fkfd;
  +                    if (fk.fkField instanceof Integer)
  +                    {
  +                        Integer index = (Integer) fk.fkField;
  +                        fkfd = cld.getFieldDescriptorByIndex(index.intValue());
  +                    }
  +                    else
  +                    {
  +                        fkfd = cld.getFieldDescriptorByName((String) fk.fkField);
  +                    }
  +                    if (fkfd == null)
  +                    {
  +                        throw new OJBRuntimeException("Incorrect or not found field reference name '"
  +                                + fk.fkField + "' in descriptor " + this + " for class-descriptor '"
  +                                + cld.getClassNameOfObject() + "'");
  +                    }
  +                                       
  +                    ret.add(fkfd);
  +                }
  +                
  +                fkFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
  +                m_fkFieldMap.put(cld, fkFieldDescriptors);
  +            }
           }
  -        return result;
  +        return fkFieldDescriptors;
       }
   
       /**
  +     * Answer the FieldDescriptors for the Foreignkey-Target-Fields.
  +     * These Fields are the Primarykey-Fields of the targetCld in most cases
  +     * @param targetCld the classdescriptor to get the fields from
  +     */
  +    public FieldDescriptor[] getForeignKeyTargetFieldDescriptors(ClassDescriptor targetCld)
  +    {
  +        FieldDescriptor[] fkFieldDescriptors = (FieldDescriptor[]) m_fkTargetFieldMap.get(targetCld);
  +        
  +        if (fkFieldDescriptors == null)
  +        {
  +            List fkFields = getForeignKeyFields();
  +            FieldDescriptor pkFields[] = targetCld.getPkFields();
  +            
  +            // get FieldDescriptor for each index from Class-descriptor
  +            // In a many-to-many relationship Fk-Fields vector will be null.
  +            if (fkFields != null)
  +            {
  +                if (targetCld.isInterface())
  +                {
  +                    //exchange interface class descriptor with first concrete class
  +                    Vector extents = targetCld.getExtentClasses();
  +                    // TODO: Check for side-effects
  +                    Class firstConcreteClass = (Class) extents.get(0);
  +                    targetCld = getClassDescriptor().getRepository().getDescriptorFor(firstConcreteClass);
  +                }
  +                List ret = new ArrayList();
  +
  +                for (int i = 0; i < fkFields.size(); i++)
  +                {
  +                    ForeignKey fk = (ForeignKey) fkFields.get(i);
  +                    FieldDescriptor fkfd;
  +                    
  +                    // if a target-field-ref is available use it
  +                    if (fk.targetField != null)
  +                    {
  +                        fkfd = targetCld.getFieldDescriptorByName(fk.targetField);
  +                        if (fkfd == null)
  +                        {
  +                            throw new OJBRuntimeException("Incorrect or not found target-field reference name '"
  +                                    + fk.targetField + "' in descriptor " + this + " for class-descriptor '"
  +                                    + targetCld.getClassNameOfObject() + "'");
  +                        }
  +                    }
  +                    // otherwise use the pks of the target class
  +                    else
  +                    {
  +                        fkfd = pkFields[i];
  +                    }
  +                                      
  +                    ret.add(fkfd);
  +                }
  +                
  +                fkFieldDescriptors = (FieldDescriptor[]) ret.toArray(new FieldDescriptor[ret.size()]);
  +                m_fkTargetFieldMap.put(targetCld, fkFieldDescriptors);
  +            }
  +        }
  +        return fkFieldDescriptors;
  +    }
  +    
  +    /**
        * Answer the ItemClass.
        */
       public Class getItemClass()
  @@ -226,25 +270,29 @@
       /**
        * add a foreign key field ID
        */
  -    public void addForeignKeyField(int newId)
  +    public void addForeignKeyField(int fkId)
       {
  -        if (m_ForeignKeyFields == null)
  -        {
  -            m_ForeignKeyFields = new Vector();
  -        }
  -        m_ForeignKeyFields.add(new Integer(newId));
  +        addForeignKeyField(new Integer(fkId), null);
       }
   
       /**
        * add a foreign key field
        */
  -    public void addForeignKeyField(String newField)
  +    public void addForeignKeyField(String fkField)
  +    {
  +        addForeignKeyField(fkField, null);
  +    }
  +
  +    /**
  +     * add a foreign key field
  +     */
  +    public void addForeignKeyField(Object fkField, String targetField)
       {
           if (m_ForeignKeyFields == null)
           {
               m_ForeignKeyFields = new Vector();
           }
  -        m_ForeignKeyFields.add(newField);
  +        m_ForeignKeyFields.add(new ForeignKey(fkField, targetField));
       }
   
       /**
  @@ -389,15 +437,15 @@
   
       protected int getCascadeStoreValue(String cascade)
       {
  -        if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
  +        if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_NONE_STR))
           {
               return CASCADE_NONE;
           }
  -        else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
  +        else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_LINK_STR))
           {
               return CASCADE_LINK;
           }
  -        else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
  +        else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_OBJECT_STR))
           {
               return CASCADE_OBJECT;
           }
  @@ -417,23 +465,23 @@
           else
           {
               throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
  -                    + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
  -                    + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
  +                    + "', expected values are: " + RepositoryElements.CASCADE_NONE_STR + ", "
  +                    + RepositoryElements.CASCADE_LINK_STR + ", " + RepositoryElements.CASCADE_OBJECT_STR
                       + " ('false' and 'true' are deprecated but still valid)");
           }
       }
   
       protected int getCascadeDeleteValue(String cascade)
       {
  -        if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_NONE_STR))
  +        if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_NONE_STR))
           {
               return CASCADE_NONE;
           }
  -        else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_LINK_STR))
  +        else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_LINK_STR))
           {
               return CASCADE_LINK;
           }
  -        else if(cascade.equalsIgnoreCase(RepositoryTags.CASCADE_OBJECT_STR))
  +        else if(cascade.equalsIgnoreCase(RepositoryElements.CASCADE_OBJECT_STR))
           {
               return CASCADE_OBJECT;
           }
  @@ -448,8 +496,8 @@
           else
           {
               throw new OJBRuntimeException("Invalid value! Given value was '" + cascade
  -                    + "', expected values are: " + RepositoryTags.CASCADE_NONE_STR + ", "
  -                    + RepositoryTags.CASCADE_LINK_STR + ", " + RepositoryTags.CASCADE_OBJECT_STR
  +                    + "', expected values are: " + RepositoryElements.CASCADE_NONE_STR + ", "
  +                    + RepositoryElements.CASCADE_LINK_STR + ", " + RepositoryElements.CASCADE_OBJECT_STR
                       + " ('false' and 'true' are deprecated but still valid)");
           }
       }
  @@ -460,13 +508,13 @@
           switch(cascade)
           {
               case CASCADE_NONE:
  -                result = RepositoryTags.CASCADE_NONE_STR;
  +                result = RepositoryElements.CASCADE_NONE_STR;
                   break;
               case CASCADE_LINK:
  -                result = RepositoryTags.CASCADE_LINK_STR;
  +                result = RepositoryElements.CASCADE_LINK_STR;
                   break;
               case CASCADE_OBJECT:
  -                result = RepositoryTags.CASCADE_OBJECT_STR;
  +                result = RepositoryElements.CASCADE_OBJECT_STR;
                   break;
           }
           return result;
  @@ -511,7 +559,7 @@
       public void setPersistentField(PersistentField field)
       {
           super.setPersistentField(field);
  -        if ((field.getName() != null) && field.getName().equals(RepositoryTags.TAG_SUPER))
  +        if ((field.getName() != null) && field.getName().equals(RepositoryElements.TAG_SUPER))
           {
               setMultiMappedClass(true);
           }
  @@ -538,107 +586,154 @@
        */
       public String toXML()
       {
  -        String eol = System.getProperty( "line.separator" );
  +        String eol = System.getProperty("line.separator");
   
           // opening tag
  -        StringBuffer result = new StringBuffer( 1024 );
  -        result.append( "      " );
  -        result.append( RepositoryTags.getOpeningTagNonClosingById( REFERENCE_DESCRIPTOR ) );
  -        result.append( eol );
  +        StringBuffer result = new StringBuffer(1024);
  +        result.append("      ");
  +        result.append(RepositoryTags.getOpeningTagNonClosingById(REFERENCE_DESCRIPTOR));
  +        result.append(eol);
   
           // attributes
           // name
           String name = this.getAttributeName();
  -        if( name == null )
  +        if (name == null)
           {
               name = RepositoryElements.TAG_SUPER;
           }
  -        result.append( "        " );
  -        result.append( RepositoryTags.getAttribute( FIELD_NAME, name ) );
  -        result.append( eol );
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(FIELD_NAME, name));
  +        result.append(eol);
   
           // class-ref
  -        result.append( "        " );
  -        result.append( RepositoryTags.getAttribute( REFERENCED_CLASS, this.getItemClassName() ) );
  -        result.append( eol );
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(REFERENCED_CLASS, getItemClassName()));
  +        result.append(eol);
   
           // proxyReference is optional
  -        if( isLazy() )
  +        if (isLazy())
           {
  -            result.append( "        " );
  -            result.append( RepositoryTags.getAttribute( PROXY_REFERENCE, "true" ) );
  -            result.append( eol );
  -            result.append( "        " );
  -            result.append( RepositoryTags.getAttribute( PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit() ) );
  -            result.append( eol );
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(PROXY_REFERENCE, "true"));
  +            result.append(eol);
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(PROXY_PREFETCHING_LIMIT, String
  +                    .valueOf(getProxyPrefetchingLimit())));
  +            result.append(eol);
           }
   
           //reference refresh is optional, disabled by default
  -        if( isRefresh() )
  +        if (isRefresh())
           {
  -            result.append( "        " );
  -            result.append( RepositoryTags.getAttribute( REFRESH, "true" ) );
  -            result.append( eol );
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(REFRESH, "true"));
  +            result.append(eol);
           }
   
           //auto retrieve
  -        result.append( "        " );
  -        result.append( RepositoryTags.getAttribute( AUTO_RETRIEVE, "" + getCascadeRetrieve() ) );
  -        result.append( eol );
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_RETRIEVE, String.valueOf(getCascadeRetrieve())));
  +        result.append(eol);
   
           //auto update
  -        result.append( "        " );
  -        result.append( RepositoryTags.getAttribute( AUTO_UPDATE, getCascadeAsString( getCascadingStore() ) ) );
  -        result.append( eol );
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())));
  +        result.append(eol);
   
           //auto delete
  -        result.append( "        " );
  -        result.append( RepositoryTags.getAttribute( AUTO_DELETE, getCascadeAsString( getCascadingDelete() ) ) );
  -        result.append( eol );
  +        result.append("        ");
  +        result.append(RepositoryTags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())));
  +        result.append(eol);
   
           //otm-dependent is optional, disabled by default
  -        if( getOtmDependent() )
  +        if (getOtmDependent())
           {
  -            result.append( "        " );
  -            result.append( RepositoryTags.getAttribute( OTM_DEPENDENT, "true" ) );
  -            result.append( eol );
  +            result.append("        ");
  +            result.append(RepositoryTags.getAttribute(OTM_DEPENDENT, "true"));
  +            result.append(eol);
           }
   
           // close opening tag
  -        result.append( "      >" );
  -        result.append( eol );
  +        result.append("      >");
  +        result.append(eol);
   
           // elements
           // write foreignkey elements
  -        for( int i = 0; i < getForeignKeyFields().size(); i++ )
  +        for (int i = 0; i < getForeignKeyFields().size(); i++)
           {
  -            Object obj = getForeignKeyFields().get( i );
  -            if( obj instanceof Integer )
  +            ForeignKey obj = (ForeignKey) getForeignKeyFields().get(i);
  +            if (obj.fkField instanceof Integer)
               {
                   String fkId = obj.toString();
  -                result.append( "        " );
  -                result.append( RepositoryTags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
  -                result.append( " " );
  -                result.append( RepositoryTags.getAttribute( FIELD_ID_REF, fkId ) );
  -                result.append( "/>" );
  -                result.append( eol );
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(FOREIGN_KEY));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(FIELD_ID_REF, fkId));
  +                if (obj.targetField != null)
  +                {
  +                    result.append(" ");
  +                    result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
  +                }
  +                result.append("/>");
  +                result.append(eol);
               }
               else
               {
  -                String fk = ( String ) obj;
  -                result.append( "        " );
  -                result.append( RepositoryTags.getOpeningTagNonClosingById( FOREIGN_KEY ) );
  -                result.append( " " );
  -                result.append( RepositoryTags.getAttribute( FIELD_REF, fk ) );
  -                result.append( "/>" );
  -                result.append( eol );
  +                String fk = (String) obj.fkField;
  +                result.append("        ");
  +                result.append(RepositoryTags.getOpeningTagNonClosingById(FOREIGN_KEY));
  +                result.append(" ");
  +                result.append(RepositoryTags.getAttribute(FIELD_REF, fk));
  +                if (obj.targetField != null)
  +                {
  +                    result.append(" ");
  +                    result.append(RepositoryTags.getAttribute(TARGET_FIELD_REF, obj.targetField));
  +                }
  +                result.append("/>");
  +                result.append(eol);
               }
           }
   
           // closing tag
  -        result.append( "      " );
  -        result.append( RepositoryTags.getClosingTagById( REFERENCE_DESCRIPTOR ) );
  -        result.append( eol );
  +        result.append("      ");
  +        result.append(RepositoryTags.getClosingTagById(REFERENCE_DESCRIPTOR));
  +        result.append(eol);
  +
           return result.toString();
       }
  +    
  +    /**
  +     * Helper to store the fkField and the field it's referencing.
  +     */
  +    protected static class ForeignKey implements Serializable
  +    {
  +        private static final long serialVersionUID = 3256718468362482741L;
  +
  +        Object fkField;
  +        String targetField;
  +
  +        ForeignKey(Object fkField, String targetField)
  +        {
  +            this.fkField = fkField;
  +            this.targetField = targetField;
  +        }
  +    }
  +
  +    /**
  +     * Helper to store the FieldDescriptor for the fkField and the field it's referencing.
  +     */
  +    protected static class FkFieldDescriptor implements Serializable
  +    {
  +        private static final long serialVersionUID = 3689348819137475895L;
  +
  +        FieldDescriptor fkField;
  +        FieldDescriptor targetField;
  +
  +        FkFieldDescriptor(FieldDescriptor fkField, FieldDescriptor targetField)
  +        {
  +            this.fkField = fkField;
  +            this.targetField = targetField;
  +        }
  +    }
  +
   }
  
  
  
  1.75      +56 -3     db-ojb/src/java/org/apache/ojb/broker/util/BrokerHelper.java
  
  Index: BrokerHelper.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/util/BrokerHelper.java,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- BrokerHelper.java	13 Dec 2004 19:49:12 -0000	1.74
  +++ BrokerHelper.java	6 Jan 2005 21:00:03 -0000	1.75
  @@ -16,6 +16,7 @@
    */
   
   import java.util.ArrayList;
  +import java.util.Arrays;
   import java.util.Collection;
   import java.util.HashMap;
   import java.util.Iterator;
  @@ -329,15 +330,67 @@
       }
   
       /**
  +     * Get the values of the fk-target-fields for an obj.
  +     * @param rds
  +     * @param objOrProxy
  +     * @throws PersistenceBrokerException
  +     */
  +    public ValueContainer[] getFkTargetValuesForObject(ObjectReferenceDescriptor rds, Object objOrProxy, boolean convertToSql) throws PersistenceBrokerException
  +    {
  +        Class refClass = ProxyHelper.getRealClass(objOrProxy);
  +        ClassDescriptor refCld = m_broker.getClassDescriptor(refClass);
  +        FieldDescriptor pkFd[] = refCld.getPkFields();
  +        FieldDescriptor targetFd[] = rds.getForeignKeyTargetFieldDescriptors(refCld);
  +        
  +        // use the values of the key-fields
  +        if (targetFd.length == 0 || Arrays.equals(pkFd,targetFd))
  +        {
  +            return getKeyValues(refCld, objOrProxy, convertToSql);
  +        }
  +        // use the values of the target-fields
  +        else
  +        {
  +            Object obj = ProxyHelper.getRealObject(objOrProxy);
  +            return getValuesForObject(targetFd, obj, convertToSql);
  +        }
  +    } 
  +
  +    /**
  +     * Get the values of the fk-fields for an obj.
  +     * @param rds
  +     * @param objOrProxy
  +     * @throws PersistenceBrokerException
  +     */
  +    public ValueContainer[] getFkValuesForObject(ObjectReferenceDescriptor rds, Object objOrProxy, boolean convertToSql) throws PersistenceBrokerException
  +    {
  +        Class refClass = ProxyHelper.getRealClass(objOrProxy);
  +        ClassDescriptor refCld = m_broker.getClassDescriptor(refClass);
  +        FieldDescriptor pkFd[] = refCld.getPkFields();
  +        FieldDescriptor targetFd[] = rds.getForeignKeyFieldDescriptors(refCld);
  +        
  +        // use the values of the key-fields
  +        if (targetFd.length == 0 || Arrays.equals(pkFd,targetFd))
  +        {
  +            return getKeyValues(refCld, objOrProxy, convertToSql);
  +        }
  +        // use the values of the target-fields
  +        else
  +        {
  +            Object obj = ProxyHelper.getRealObject(objOrProxy);
  +            return getValuesForObject(targetFd, obj, convertToSql);
  +        }
  +    } 
  +    
  +    /**
        * Get the values of the fields for an obj
        * @param fields
  -     * @param obj
  +     * @param objOrProxy
        * @throws PersistenceBrokerException
        */
       public ValueContainer[] getValuesForObject(FieldDescriptor[] fields, Object obj, boolean convertToSql) throws PersistenceBrokerException
       {
           ValueContainer[] result = new ValueContainer[fields.length];
  -
  +        
           for(int i = 0; i < fields.length; i++)
           {
               FieldDescriptor fd = fields[i];
  
  
  
  1.75      +62 -1     db-ojb/release-notes.txt
  
  Index: release-notes.txt
  ===================================================================
  RCS file: /home/cvs/db-ojb/release-notes.txt,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- release-notes.txt	18 Dec 2004 14:14:04 -0000	1.74
  +++ release-notes.txt	6 Jan 2005 21:00:04 -0000	1.75
  @@ -17,6 +17,67 @@
     New ant-target ojb-quickstart creates archives of ready-to-run apps for tutorials 1 and 2
     complete with pre-created Hsqldb databases (based on ojb-blank).
     These archives are also available in the binary download area.
  +- Relationships based on non primarykey fields. These fields are defined in the new 
  +  attribute "target-field-ref" of inverse-foreignkey and foreignkey in collection- and
  +  referenceDescriptor. If the target-field-ref is missing the primary key of the referenced
  +  class is used.
  +  
  +     <class-descriptor
  +         class="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
  +         table="Artikel_2" >
  +      <field-descriptor
  +         name="articleId"
  +         column="Artikel_Nr"
  +         jdbc-type="INTEGER"
  +         primarykey="true"
  +         autoincrement="true"
  +      />
  +	  ...
  +      <field-descriptor
  +         name="productGroupName"
  +         column="KatName"
  +         jdbc-type="VARCHAR"
  +      />
  +	  ...
  +      <reference-descriptor
  +            name="productGroup"
  +            class-ref="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
  +      >
  +         <foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
  +      </reference-descriptor>
  +   </class-descriptor>
  +
  +   <class-descriptor
  +         class="org.apache.ojb.broker.NoPkReferenceTest$ProductGroup_2"
  +         table="Kategorien_2" >
  +      <field-descriptor
  +         name="groupId"
  +         column="Kategorie_Nr"
  +         jdbc-type="INTEGER"
  +         primarykey="true"
  +         autoincrement="true"
  +      />
  +      <field-descriptor
  +         name="groupName"
  +         column="Kategorie_Name"
  +         jdbc-type="VARCHAR"
  +      />
  +      <field-descriptor
  +         name="description"
  +         column="Beschreibung"
  +         jdbc-type="VARCHAR"
  +      />
  +      <collection-descriptor
  +         name="allArticlesInGroup"
  +		 element-class-ref="org.apache.ojb.broker.NoPkReferenceTest$Article_2"
  +         auto-retrieve="true"
  +         auto-update="true"
  +         auto-delete="false"
  +      >
  +         <inverse-foreignkey field-ref="productGroupName" target-field-ref="groupName"/>
  +      </collection-descriptor>
  +   </class-descriptor>
  +  
   
   NOTES:
   --
  
  
  
  1.7       +7 -7      db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/TableAliasHandler.java
  
  Index: TableAliasHandler.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/TableAliasHandler.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TableAliasHandler.java	2 Dec 2004 21:37:46 -0000	1.6
  +++ TableAliasHandler.java	6 Jan 2005 21:00:06 -0000	1.7
  @@ -344,7 +344,7 @@
   
   				if (!cod.isMtoNRelation())
   				{
  -					prevKeys = prev.cld.getPkFields();
  +                    prevKeys = cod.getForeignKeyTargetFieldDescriptors(prev.cld);
   					keys = cod.getForeignKeyFieldDescriptors(cld);
   				}
   				else
  @@ -380,7 +380,7 @@
   				}	
   
   				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  -				keys = cld.getPkFields();
  +                keys = ord.getForeignKeyTargetFieldDescriptors(cld);
   
   				// [olegnitz]
   				// a special case: the last element of the path is
  @@ -388,7 +388,7 @@
   				// use the correspondent foreign key field, don't add the join
   				if ((fieldRef != null) && (i == (pathLength - 1)))
   				{
  -					FieldDescriptor[] pk = cld.getPkFields();
  +                    FieldDescriptor[] pk = ord.getForeignKeyTargetFieldDescriptors(cld);
   
   					for (int j = 0; j < pk.length; j++)
   					{
  @@ -695,11 +695,11 @@
           while (objRefs.hasNext())
           {
               ObjectReferenceDescriptor objRef = (ObjectReferenceDescriptor) objRefs.next();
  -            FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
  -
  -            ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
  +            
               if (objRef.getPersistentField() instanceof AnonymousPersistentFieldForInheritance)
               {
  +                FieldDescriptor[] leftFields = objRef.getForeignKeyFieldDescriptors(cld);
  +                ClassDescriptor refCld = cld.getRepository().getDescriptorFor(objRef.getItemClassName());
                   TableAlias base_alias = getTableAliasForPath(name, null);
   
                   String aliasName = String.valueOf(getAliasChar()) + m_aliasCount++;
  
  
  

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