KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > store > ClassBaseTableExtent


1 /*
2  * Copyright 2004 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: ClassBaseTableExtent.java,v 1.8 2004/02/01 18:22:42 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.store;
12
13 import com.triactive.jdo.PersistenceManager;
14 import com.triactive.jdo.model.ClassMetaData;
15 import com.triactive.jdo.util.IntArrayList;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import javax.jdo.Extent;
19 import org.apache.log4j.Category;
20
21
22 /**
23  * An Extent of all persistent objects backed by a base table.
24  *
25  * @author <a HREF="mailto:mmartin5@austin.rr.com">Mike Martin</a>
26  * @version $Revision: 1.8 $
27  *
28  * @see Extent
29  */

30
31 class ClassBaseTableExtent implements Extent, Queryable
32 {
33     private static final Category LOG = Category.getInstance(ClassBaseTableExtent.class);
34
35     private final PersistenceManager pm;
36     private final ClassBaseTable table;
37     private final boolean subclasses;
38     private final StoreManager storeMgr;
39     private final DatabaseAdapter dba;
40     private final Query query;
41     private final int[] prefetchFieldNumbers;
42     private final ColumnMapping[] prefetchFieldMappings;
43
44     private HashMap JavaDoc queryResultsByIterator = new HashMap JavaDoc();
45
46
47     public ClassBaseTableExtent(PersistenceManager pm, ClassBaseTable table, boolean subclasses)
48     {
49         this.pm = pm;
50         this.table = table;
51         this.subclasses = subclasses;
52
53         storeMgr = table.getStoreManager();
54         dba = storeMgr.getDatabaseAdapter();
55         query = storeMgr.getQuery(pm, null);
56
57         Class JavaDoc candidateClass = getCandidateClass();
58
59         query.setClass(candidateClass);
60         query.setCandidates(this);
61
62         ClassMetaData cmd = ClassMetaData.forClass(candidateClass);
63         int fieldCount = cmd.getInheritedFieldCount() + cmd.getFieldCount();
64         IntArrayList colfn = new IntArrayList(fieldCount);
65         ColumnMapping[] colfm = new ColumnMapping[fieldCount];
66
67         boolean[] defaultFetchGroupFields = cmd.getDefaultFetchGroupFieldFlags();
68
69         for (int i = 0; i < fieldCount; ++i)
70         {
71             if (defaultFetchGroupFields[i])
72             {
73                 Mapping m = table.getFieldMapping(i);
74
75                 if (m instanceof ColumnMapping)
76                 {
77                     colfn.add(i);
78                     colfm[i] = (ColumnMapping)m;
79                 }
80             }
81         }
82
83         if (colfn.isEmpty())
84         {
85             prefetchFieldNumbers = null;
86             prefetchFieldMappings = null;
87         }
88         else
89         {
90             prefetchFieldNumbers = colfn.toArray();
91             prefetchFieldMappings = colfm;
92         }
93     }
94
95
96     /**
97      * Returns an iterator over all the instances in the Extent.
98      *
99      * @return an iterator over all the instances in the Extent.
100      */

101
102     public Iterator JavaDoc iterator()
103     {
104         QueryResult qr = (QueryResult)query.execute();
105         Iterator JavaDoc i = qr.iterator();
106
107         queryResultsByIterator.put(i, qr);
108
109         return i;
110     }
111
112
113     /**
114      * Returns whether this Extent was defined to contain subclasses.
115      *
116      * @return true if this Extent was defined to contain instances
117      * that are of a subclass type
118      */

119
120     public boolean hasSubclasses()
121     {
122         return subclasses;
123     }
124
125
126     /**
127      * An Extent contains all instances of a particular Class in the data
128      * store; this method returns the Class of the instances
129      *
130      * @return the Class of instances of this Extent
131      */

132
133     public Class JavaDoc getCandidateClass()
134     {
135         return table.getType();
136     }
137
138
139     /**
140      * An Extent is managed by a PersistenceManager; this method gives access
141      * to the owning PersistenceManager.
142      *
143      * @return the owning PersistenceManager
144      */

145
146     public javax.jdo.PersistenceManager getPersistenceManager()
147     {
148         return pm;
149     }
150
151
152     /**
153      * Close an Iterator associated with this Extent instance. Iterators closed
154      * by this method will return false to hasNext() and will throw
155      * NoSuchElementException on next(). The Extent instance can still be used
156      * as a parameter of Query.setCandidates, and to get an Iterator.
157      *
158      * @param it an iterator obtained by the method iterator() on this Extent
159      * instance.
160      */

161
162     public void close(Iterator JavaDoc it)
163     {
164         QueryResult qr = (QueryResult)queryResultsByIterator.remove(it);
165
166         qr.close();
167     }
168
169
170     /**
171      * Close all Iterators associated with this Extent instance. Iterators
172      * closed by this method will return false to hasNext() and will throw
173      * NoSuchElementException on next(). The Extent instance can still be used
174      * as a parameter of Query.setCandidates, and to get an Iterator.
175      */

176
177     public void closeAll()
178     {
179         Iterator JavaDoc i = queryResultsByIterator.values().iterator();
180
181         while (i.hasNext())
182         {
183             QueryResult qr = (QueryResult)i.next();
184
185             qr.close();
186             i.remove();
187         }
188     }
189
190
191     public QueryStatement newQueryStatement(Class JavaDoc candidateClass)
192     {
193         Class JavaDoc extentType = table.getType();
194
195         if (!extentType.isAssignableFrom(candidateClass))
196             throw new IncompatibleQueryElementTypeException(extentType, candidateClass);
197
198         ClassBaseTable candidateTable = storeMgr.getClassBaseTable(candidateClass);
199         QueryStatement stmt = dba.newQueryStatement(candidateTable);
200
201         ColumnMapping idMapping = table.getIDMapping();
202         Column idColumn = idMapping.getColumn();
203
204         if (!subclasses)
205         {
206             if (!table.equals(candidateTable))
207                 LOG.warn("Query over extent will never return results w/o including subclasses: extent = " + this + ", candidate class = " + candidateClass);
208
209             int classID = table.getTableID();
210
211             BooleanExpression filterByClass =
212                 new OIDRangeTestExpression(stmt, stmt.getColumn(idColumn),
213                                            new OID(classID, 0, 0),
214                                            new OID(classID, OID.MAX_OBJIDHI, OID.MAX_OBJIDLO));
215
216             stmt.andCondition(filterByClass);
217         }
218
219         stmt.select(idColumn);
220
221         return stmt;
222     }
223
224
225     public Query.ResultObjectFactory newResultObjectFactory(QueryStatement stmt)
226     {
227         if (stmt.getDistinctResults() || prefetchFieldMappings == null)
228             return new PersistentIDROF(pm, getCandidateClass());
229         else
230         {
231             int[] columnNumbersByField = new int[prefetchFieldMappings.length];
232
233             for (int i = 0; i < prefetchFieldMappings.length; ++i)
234             {
235                 ColumnMapping m = prefetchFieldMappings[i];
236
237                 if (m != null)
238                     columnNumbersByField[i] = stmt.select(m.getColumn());
239             }
240
241             return new PersistentIDROF(pm,
242                                        getCandidateClass(),
243                                        prefetchFieldNumbers,
244                                        prefetchFieldMappings,
245                                        columnNumbersByField);
246         }
247     }
248
249
250     public String JavaDoc toString()
251     {
252         return "Extent of " + getCandidateClass() + (subclasses ? "(including" : "(excluding") + " subclasses)";
253     }
254 }
255
Popular Tags