001    package org.apache.ojb.broker.accesslayer;
002    
003    /* Copyright 2003-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.util.ArrayList;
019    import java.util.Collection;
020    import java.util.HashMap;
021    import java.util.HashSet;
022    import java.util.Iterator;
023    import java.util.Map;
024    
025    import org.apache.ojb.broker.Identity;
026    import org.apache.ojb.broker.PersistenceBroker;
027    import org.apache.ojb.broker.cache.ObjectCache;
028    import org.apache.ojb.broker.core.PersistenceBrokerImpl;
029    import org.apache.ojb.broker.core.proxy.IndirectionHandler;
030    import org.apache.ojb.broker.core.proxy.ProxyHelper;
031    import org.apache.ojb.broker.query.Query;
032    
033    /**
034     * Prefetcher for plain list of objects (no relations).
035     *
036     * @author <a href="mailto:olegnitz@apache.org">Oleg Nitz</a>
037     * @version $Id: PlainPrefetcher.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
038     */
039    public class PlainPrefetcher extends BasePrefetcher
040    {
041    
042        public PlainPrefetcher(PersistenceBrokerImpl aBroker, Class anItemClass)
043        {
044            super(aBroker, anItemClass);
045        }
046    
047        public void prepareRelationshipSettings()
048        {
049            // no op
050        }
051    
052        public void restoreRelationshipSettings()
053        {
054            // no op
055        }
056    
057        protected void associateBatched(Collection proxies, Collection realSubjects)
058        {
059            PersistenceBroker pb = getBroker();
060            IndirectionHandler handler;
061            Identity id;
062            Object proxy;
063            Object realSubject;
064            HashMap realSubjectsMap = new HashMap(realSubjects.size());
065    
066            for (Iterator it = realSubjects.iterator(); it.hasNext(); )
067            {
068                realSubject = it.next();
069                realSubjectsMap.put(pb.serviceIdentity().buildIdentity(realSubject), realSubject);
070            }
071    
072            for (Iterator it = proxies.iterator(); it.hasNext(); )
073            {
074                proxy = it.next();
075                handler = ProxyHelper.getIndirectionHandler(proxy);
076    
077                if (handler == null)
078                {
079                    continue;
080                }
081    
082                id = handler.getIdentity();
083                realSubject = realSubjectsMap.get(id);
084                if (realSubject != null)
085                {
086                    handler.setRealSubject(realSubject);
087                }
088            }
089        }
090    
091        /**
092         * Build the multiple queries for one relationship because of limitation of IN(...)
093         * @param proxies Collection containing all proxy objects to load
094         * @param realSubjects Collection where real subjects found in the cache should be added.
095         */
096        protected Query[] buildPrefetchQueries(Collection proxies, Collection realSubjects)
097        {
098            Collection queries = new ArrayList();
099            Collection idsSubset;
100            Object proxy;
101            IndirectionHandler handler;
102            Identity id;
103            Class realClass;
104            HashMap classToIds = new HashMap();
105            Class topLevelClass = getItemClassDescriptor().getClassOfObject();
106            PersistenceBroker pb = getBroker();
107            ObjectCache cache = pb.serviceObjectCache();
108    
109            for (Iterator it = proxies.iterator(); it.hasNext(); )
110            {
111                proxy = it.next();
112                handler = ProxyHelper.getIndirectionHandler(proxy);
113    
114                if (handler == null)
115                {
116                    continue;
117                }
118                
119                id = handler.getIdentity();
120                if (cache.lookup(id) != null)
121                {
122                    realSubjects.add(pb.getObjectByIdentity(id));
123                    continue;
124                }
125                realClass = id.getObjectsRealClass();
126                if (realClass == null)
127                {
128                    realClass = Object.class; // to remember that the real class is unknown
129                }
130                idsSubset = (HashSet) classToIds.get(realClass);
131                if (idsSubset == null)
132                {
133                    idsSubset = new HashSet();
134                    classToIds.put(realClass, idsSubset);
135                }
136                idsSubset.add(id);
137                if (idsSubset.size() == pkLimit)
138                {
139                    Query query;
140                    if (realClass == Object.class)
141                    {
142                        query = buildPrefetchQuery(topLevelClass, idsSubset, true);
143                    }
144                    else
145                    {
146                        query = buildPrefetchQuery(realClass, idsSubset, false);
147                    }
148                    queries.add(query);
149                    idsSubset.clear();
150                }
151            }
152    
153            for (Iterator it = classToIds.entrySet().iterator(); it.hasNext(); )
154            {
155                Map.Entry entry = (Map.Entry) it.next();
156                realClass = (Class) entry.getKey();
157                idsSubset = (HashSet) entry.getValue();
158                if (idsSubset.size() > 0)
159                {
160                    Query query;
161                    if (realClass == Object.class)
162                    {
163                        query = buildPrefetchQuery(topLevelClass, idsSubset, true);
164                    }
165                    else
166                    {
167                        query = buildPrefetchQuery(realClass, idsSubset, false);
168                    }
169                    queries.add(query);
170                }
171            }
172    
173            return (Query[]) queries.toArray(new Query[queries.size()]);
174        }
175    
176        protected Query buildPrefetchQuery(Class clazz, Collection ids, boolean withExtents)
177        {
178            Query query = buildPrefetchQuery(clazz, ids,
179                    getDescriptorRepository().getDescriptorFor(clazz).getPkFields());
180            query.setWithExtents(withExtents);
181            return query;
182        }
183    }