View Javadoc

1   package org.apache.ojb.broker.accesslayer;
2   
3   /* Copyright 2002-2005 The Apache Software Foundation
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  
24  import org.apache.ojb.broker.Identity;
25  import org.apache.ojb.broker.PersistenceBroker;
26  import org.apache.ojb.broker.cache.ObjectCache;
27  import org.apache.ojb.broker.core.PersistenceBrokerImpl;
28  import org.apache.ojb.broker.metadata.ClassDescriptor;
29  import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
30  import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
31  import org.apache.ojb.broker.query.Query;
32  
33  /**
34   * Relationship Prefetcher for References.
35   *
36   * @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
37   * @version $Id: ReferencePrefetcher.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
38   */
39  public class ReferencePrefetcher extends RelationshipPrefetcherImpl
40  {
41  
42      /**
43      * Constructor for ReferencePrefetcher.
44      * @param aBroker
45      * @param anOrd
46      */
47      public ReferencePrefetcher(PersistenceBrokerImpl aBroker, ObjectReferenceDescriptor anOrd)
48      {
49          super(aBroker, anOrd);
50      }
51  
52      /**
53       * Associate the batched Children with their owner object.
54       * Loop over owners
55       */
56      protected void associateBatched(Collection owners, Collection children)
57      {
58          ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
59          ClassDescriptor cld = getOwnerClassDescriptor();
60          Object owner;
61          Object relatedObject;
62          Object fkValues[];
63          Identity id;
64          PersistenceBroker pb = getBroker();
65          PersistentField field = ord.getPersistentField();
66          Class topLevelClass = pb.getTopLevelClass(ord.getItemClass());
67          HashMap childrenMap = new HashMap(children.size());
68  
69  
70          for (Iterator it = children.iterator(); it.hasNext(); )
71          {
72              relatedObject = it.next();
73              childrenMap.put(pb.serviceIdentity().buildIdentity(relatedObject), relatedObject);
74          }
75  
76          for (Iterator it = owners.iterator(); it.hasNext(); )
77          {
78              owner = it.next();
79              fkValues = ord.getForeignKeyValues(owner,cld);
80              if (isNull(fkValues))
81              {
82                  field.set(owner, null);
83                  continue;
84              }
85              id = pb.serviceIdentity().buildIdentity(null, topLevelClass, fkValues);
86              relatedObject = childrenMap.get(id);
87              field.set(owner, relatedObject);
88          }
89      }
90  
91      private boolean isNull(Object[] arr)
92      {
93          for (int i = 0; i < arr.length; i++)
94          {
95              if (arr[i] != null)
96              {
97                  return false;
98              }
99          }
100         return true;
101     }
102     
103     /**
104      * Build the multiple queries for one relationship because of limitation of IN(...)
105      * @param owners Collection containing all objects of the ONE side
106      * @param children Collection where related objects found in the cache should be added.
107      */
108     protected Query[] buildPrefetchQueries(Collection owners, Collection children)
109     {
110         ClassDescriptor cld = getOwnerClassDescriptor();
111         ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
112         Collection queries = new ArrayList(owners.size());
113         Collection idsSubset = new HashSet(owners.size());
114         Iterator iter = owners.iterator();
115         Class topLevelClass = getBroker().getTopLevelClass(ord.getItemClass());
116         Object[] fkValues;
117         Object owner;
118         Identity id;
119         PersistenceBroker pb = getBroker();
120         ObjectCache cache = pb.serviceObjectCache();
121 
122         while (iter.hasNext())
123         {
124             owner = iter.next();
125             fkValues = ord.getForeignKeyValues(owner,cld);
126             if (isNull(fkValues))
127             {
128                 continue;
129             }
130             id = pb.serviceIdentity().buildIdentity(null, topLevelClass, fkValues);
131             if (cache.lookup(id) != null)
132             {
133                 children.add(pb.getObjectByIdentity(id));
134                 continue;
135             }
136             idsSubset.add(id);
137             if (idsSubset.size() == pkLimit)
138             {
139                 queries.add(buildPrefetchQuery(idsSubset));
140                 idsSubset.clear();
141             }
142         }
143 
144         if (idsSubset.size() > 0)
145         {
146             queries.add(buildPrefetchQuery(idsSubset));
147         }
148 
149         return (Query[]) queries.toArray(new Query[queries.size()]);
150     }
151 
152     /**
153      * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcherImpl#buildPrefetchCriteria(java.util.Collection, org.apache.ojb.broker.metadata.FieldDescriptor[])
154      */
155     protected Query buildPrefetchQuery(Collection ids)
156     {
157         return buildPrefetchQuery(ids, getItemClassDescriptor().getPkFields());
158     }
159 }