Coverage Report - org.apache.ojb.broker.accesslayer.CollectionPrefetcher
 
Classes in this File Line Coverage Branch Coverage Complexity
CollectionPrefetcher
N/A
N/A
5.167
 
 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.lang.reflect.Array;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collection;
 21  
 import java.util.HashMap;
 22  
 import java.util.HashSet;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 
 26  
 import org.apache.ojb.broker.Identity;
 27  
 import org.apache.ojb.broker.ManageableCollection;
 28  
 import org.apache.ojb.broker.OJBRuntimeException;
 29  
 import org.apache.ojb.broker.PersistenceBroker;
 30  
 import org.apache.ojb.broker.IdentityFactory;
 31  
 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
 32  
 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
 33  
 import org.apache.ojb.broker.core.proxy.ProxyHelper;
 34  
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 35  
 import org.apache.ojb.broker.metadata.CollectionDescriptor;
 36  
 import org.apache.ojb.broker.metadata.FieldHelper;
 37  
 import org.apache.ojb.broker.metadata.MetadataException;
 38  
 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
 39  
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
 40  
 import org.apache.ojb.broker.query.Query;
 41  
 import org.apache.ojb.broker.query.QueryByCriteria;
 42  
 import org.apache.ojb.broker.util.BrokerHelper;
 43  
 import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
 44  
 import org.apache.ojb.broker.util.collections.RemovalAwareList;
 45  
 import org.apache.ojb.broker.util.collections.RemovalAwareSet;
 46  
 
 47  
 /**
 48  
  * Relationship Prefetcher for Collections.
 49  
  *
 50  
  * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
 51  
  * @version $Id: CollectionPrefetcher.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
 52  
  */
 53  
 public class CollectionPrefetcher extends RelationshipPrefetcherImpl
 54  
 {
 55  
 
 56  
     /**
 57  
      * Constructor for CollectionPrefetcher.
 58  
      *
 59  
      * @param aBroker
 60  
      * @param anOrd
 61  
      */
 62  
     public CollectionPrefetcher(PersistenceBrokerImpl aBroker, ObjectReferenceDescriptor anOrd)
 63  
     {
 64  
         super(aBroker, anOrd);
 65  
     }
 66  
 
 67  
     /**
 68  
      * Build the multiple queries for one relationship because of limitation of IN(...)
 69  
      *
 70  
      * @param owners Collection containing all objects of the ONE side
 71  
      */
 72  
     protected Query[] buildPrefetchQueries(Collection owners, Collection children)
 73  
     {
 74  
         ClassDescriptor cld = getOwnerClassDescriptor();
 75  
         Class topLevelClass = getBroker().getTopLevelClass(cld.getClassOfObject());
 76  
         BrokerHelper helper = getBroker().serviceBrokerHelper();
 77  
         Collection queries = new ArrayList(owners.size());
 78  
         Collection idsSubset = new HashSet(owners.size());
 79  
         Object[] fkValues;
 80  
         Object owner;
 81  
         Identity id;
 82  
 
 83  
         Iterator iter = owners.iterator();
 84  
         while (iter.hasNext())
 85  
         {
 86  
             owner = iter.next();
 87  
             fkValues = helper.extractValueArray(helper.getKeyValues(cld, owner));
 88  
             id = getBroker().serviceIdentity().buildIdentity(null, topLevelClass, fkValues);
 89  
             idsSubset.add(id);
 90  
             if (idsSubset.size() == pkLimit)
 91  
             {
 92  
                 queries.add(buildPrefetchQuery(idsSubset));
 93  
                 idsSubset.clear();
 94  
             }
 95  
         }
 96  
 
 97  
         if (idsSubset.size() > 0)
 98  
         {
 99  
             queries.add(buildPrefetchQuery(idsSubset));
 100  
         }
 101  
 
 102  
         return (Query[]) queries.toArray(new Query[queries.size()]);
 103  
     }
 104  
 
 105  
     /**
 106  
      * Build the query to perform a batched read get orderBy settings from CollectionDescriptor
 107  
      *
 108  
      * @param ids Collection containing all identities of objects of the ONE side
 109  
      */
 110  
     protected Query buildPrefetchQuery(Collection ids)
 111  
     {
 112  
         CollectionDescriptor cds = getCollectionDescriptor();
 113  
         QueryByCriteria query = buildPrefetchQuery(ids, cds.getForeignKeyFieldDescriptors(getItemClassDescriptor()));
 114  
 
 115  
         // check if collection must be ordered
 116  
         if (!cds.getOrderBy().isEmpty())
 117  
         {
 118  
             Iterator iter = cds.getOrderBy().iterator();
 119  
             while (iter.hasNext())
 120  
             {
 121  
                 query.addOrderBy((FieldHelper) iter.next());
 122  
             }
 123  
         }
 124  
 
 125  
         return query;
 126  
     }
 127  
 
 128  
     /**
 129  
      * associate the batched Children with their owner object loop over children
 130  
      */
 131  
     protected void associateBatched(Collection owners, Collection children)
 132  
     {
 133  
         CollectionDescriptor cds = getCollectionDescriptor();
 134  
         PersistentField field = cds.getPersistentField();
 135  
         PersistenceBroker pb = getBroker();
 136  
         Class ownerTopLevelClass = pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject());
 137  
         Class collectionClass = cds.getCollectionClass(); // this collection type will be used:
 138  
         HashMap ownerIdsToLists = new HashMap(owners.size());
 139  
 
 140  
         IdentityFactory identityFactory = pb.serviceIdentity();
 141  
         // initialize the owner list map
 142  
         for (Iterator it = owners.iterator(); it.hasNext();)
 143  
         {
 144  
             Object owner = it.next();
 145  
             ownerIdsToLists.put(identityFactory.buildIdentity(getOwnerClassDescriptor(), owner), new ArrayList());
 146  
         }
 147  
 
 148  
         // build the children lists for the owners
 149  
         for (Iterator it = children.iterator(); it.hasNext();)
 150  
         {
 151  
             Object child = it.next();
 152  
             // BRJ: use cld for real class, relatedObject could be Proxy
 153  
             ClassDescriptor cld = getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(child));
 154  
 
 155  
             Object[] fkValues = cds.getForeignKeyValues(child, cld);
 156  
             Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, fkValues);
 157  
             List list = (List) ownerIdsToLists.get(ownerId);
 158  
             if (list != null)
 159  
             {
 160  
                 list.add(child);
 161  
             }
 162  
         }
 163  
 
 164  
         // connect children list to owners
 165  
         for (Iterator it = owners.iterator(); it.hasNext();)
 166  
         {
 167  
             Object result;
 168  
             Object owner = it.next();
 169  
             Identity ownerId = identityFactory.buildIdentity(owner);
 170  
             List list = (List) ownerIdsToLists.get(ownerId);
 171  
 
 172  
             if ((collectionClass == null) && field.getType().isArray())
 173  
             {
 174  
                 int length = list.size();
 175  
                 Class itemtype = field.getType().getComponentType();
 176  
                 result = Array.newInstance(itemtype, length);
 177  
                 for (int j = 0; j < length; j++)
 178  
                 {
 179  
                     Array.set(result, j, list.get(j));
 180  
                 }
 181  
             }
 182  
             else
 183  
             {
 184  
                 ManageableCollection col = createCollection(cds, collectionClass);
 185  
                 for (Iterator it2 = list.iterator(); it2.hasNext();)
 186  
                 {
 187  
                     col.ojbAdd(it2.next());
 188  
                 }
 189  
                 result = col;
 190  
             }
 191  
 
 192  
             Object value = field.get(owner);
 193  
             if ((value instanceof CollectionProxyDefaultImpl) && (result instanceof Collection))
 194  
             {
 195  
                 ((CollectionProxyDefaultImpl) value).setData((Collection) result);
 196  
             }
 197  
             else
 198  
             {
 199  
                 field.set(owner, result);
 200  
             }
 201  
         }
 202  
     }
 203  
 
 204  
     /**
 205  
      * Create a collection object of the given collection type. If none has been given,
 206  
      * OJB uses RemovalAwareList, RemovalAwareSet, or RemovalAwareCollection depending
 207  
      * on the field type. 
 208  
      * 
 209  
      * @param desc            The collection descriptor
 210  
      * @param collectionClass The collection class specified in the collection-descriptor
 211  
      * @return The collection object
 212  
      */
 213  
     protected ManageableCollection createCollection(CollectionDescriptor desc, Class collectionClass)
 214  
     {
 215  
         Class                fieldType = desc.getPersistentField().getType();
 216  
         ManageableCollection col;
 217  
 
 218  
         if (collectionClass == null)
 219  
         {
 220  
             if (ManageableCollection.class.isAssignableFrom(fieldType))
 221  
             {
 222  
                 try
 223  
                 {
 224  
                     col = (ManageableCollection)fieldType.newInstance();
 225  
                 }
 226  
                 catch (Exception e)
 227  
                 {
 228  
                     throw new OJBRuntimeException("Cannot instantiate the default collection type "+fieldType.getName()+" of collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
 229  
                 }
 230  
             }
 231  
             else if (fieldType.isAssignableFrom(RemovalAwareCollection.class))
 232  
             {
 233  
                 col = new RemovalAwareCollection();
 234  
             }
 235  
             else if (fieldType.isAssignableFrom(RemovalAwareList.class))
 236  
             {
 237  
                 col = new RemovalAwareList();
 238  
             }
 239  
             else if (fieldType.isAssignableFrom(RemovalAwareSet.class))
 240  
             {
 241  
                 col = new RemovalAwareSet();
 242  
             }
 243  
             else
 244  
             {
 245  
                 throw new MetadataException("Cannot determine a default collection type for collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
 246  
             }
 247  
         }
 248  
         else
 249  
         {
 250  
             try
 251  
             {
 252  
                 col = (ManageableCollection)collectionClass.newInstance();
 253  
             }
 254  
             catch (Exception e)
 255  
             {
 256  
                 throw new OJBRuntimeException("Cannot instantiate the collection class "+collectionClass.getName()+" of collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
 257  
             }
 258  
         }
 259  
         return col;
 260  
     }
 261  
 
 262  
     protected CollectionDescriptor getCollectionDescriptor()
 263  
     {
 264  
         return (CollectionDescriptor) getObjectReferenceDescriptor();
 265  
     }
 266  
 }