KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 2002 (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: InverseSetStore.java,v 1.9 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.StateManager;
15 import com.triactive.jdo.model.ClassMetaData;
16 import com.triactive.jdo.model.CollectionMetaData;
17 import com.triactive.jdo.model.FieldMetaData;
18 import com.triactive.jdo.util.IntArrayList;
19 import java.lang.reflect.Field JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import javax.jdo.JDOUserException;
23
24
25 class InverseSetStore extends AbstractSetStore
26 {
27     private final int ownerFieldNumber;
28
29     public InverseSetStore(FieldMetaData fmd, StoreManager storeMgr)
30     {
31         this.storeMgr = storeMgr;
32
33         dba = storeMgr.getDatabaseAdapter();
34
35         Field JavaDoc field = fmd.getField();
36         ClassMetaData cmd = fmd.getClassMetaData();
37         CollectionMetaData colmd = fmd.getCollectionMetaData();
38         if (colmd == null)
39             throw new JDOUserException("No collection metadata found in " + fmd);
40
41         elementType = colmd.getElementType();
42         elementsAreEmbedded = false;
43
44         FieldMetaData eofmd = colmd.getOwnerField();
45
46         FieldMetaData omd = eofmd.getOwnedByCollection();
47         if (omd == null || !omd.equals(fmd))
48             throw new InvalidMetaDataRelationshipException(fmd, "owner-field", eofmd, "collection-field");
49
50         String JavaDoc ownerFieldName = eofmd.getName();
51
52         ClassMetaData emd = eofmd.getClassMetaData();
53         ownerFieldNumber = emd.getAbsoluteFieldNumber(ownerFieldName);
54
55         ClassBaseTable elementTable = storeMgr.getClassBaseTable(elementType);
56
57         if (!elementTable.isFieldPersistent(ownerFieldNumber))
58             throw new JDOUserException("Non-persistent field type for collection owner field: " + field.getDeclaringClass().getName() + "." + field.getName());
59
60         Mapping m = elementTable.getFieldMapping(ownerFieldNumber);
61         if (!(m instanceof ColumnMapping) || m instanceof PostWriteProcessing)
62             throw new JDOUserException("Invalid field type for collection owner field: " + field.getDeclaringClass().getName() + "." + field.getName());
63
64         ownerMapping = (ColumnMapping)m;
65         elementMapping = (ColumnMapping)dba.getMapping(elementType);
66
67         setTable = elementTable;
68         setName = "inverseSet";
69
70         ownerColumn = ownerMapping.getColumn();
71         elementColumn = elementTable.getIDMapping().getColumn();
72
73         loadStmt = "SELECT " + elementColumn.getName() +
74                        " FROM " + elementTable.getName() +
75                        " WHERE " + ownerColumn.getName() + " = ?";
76         sizeStmt = "SELECT COUNT(" + elementColumn.getName() + ")" +
77                        " FROM " + elementTable.getName() +
78                        " WHERE " + ownerColumn.getName() + " = ?";
79         containsStmt = "SELECT " + elementColumn.getName() +
80                        " FROM " + elementTable.getName() +
81                        " WHERE " + ownerColumn.getName() + " = ? AND " + elementColumn.getName() + " = ?";
82         addStmt = null;
83         removeStmt = null;
84         clearStmt = null;
85
86         /*
87          * Setup the prefetch field info.
88          */

89         int fieldCount = emd.getInheritedFieldCount() + emd.getFieldCount();
90         IntArrayList colfn = new IntArrayList(fieldCount);
91         ColumnMapping[] colfm = new ColumnMapping[fieldCount];
92
93         boolean[] defaultFetchGroupFields = emd.getDefaultFetchGroupFieldFlags();
94
95         for (int i = 0; i < fieldCount; ++i)
96         {
97             if (defaultFetchGroupFields[i])
98             {
99                 m = elementTable.getFieldMapping(i);
100
101                 if (m instanceof ColumnMapping)
102                 {
103                     colfn.add(i);
104                     colfm[i] = (ColumnMapping)m;
105                 }
106             }
107         }
108
109         if (colfn.isEmpty())
110         {
111             prefetchFieldNumbers = null;
112             prefetchFieldMappings = null;
113         }
114         else
115         {
116             prefetchFieldNumbers = colfn.toArray();
117             prefetchFieldMappings = colfm;
118         }
119     }
120
121
122     public QueryStatement newQueryStatement(StateManager sm, Class JavaDoc candidateClass)
123     {
124         if (!elementType.isAssignableFrom(candidateClass))
125             throw new IncompatibleQueryElementTypeException(elementType, candidateClass);
126
127         ClassBaseTable candidateTable = storeMgr.getClassBaseTable(candidateClass);
128         QueryStatement stmt = dba.newQueryStatement(candidateTable);
129
130         SQLExpression ownerExpr = new ObjectExpression(stmt, stmt.getColumn(ownerColumn));
131         SQLExpression ownerVal = ownerMapping.newSQLLiteral(stmt, sm.getObject());
132
133         stmt.andCondition(ownerExpr.eq(ownerVal));
134
135         stmt.select(elementColumn);
136
137         return stmt;
138     }
139
140
141     public QueryStatement.QueryColumn
142         joinElementsTo(QueryStatement stmt,
143                        QueryStatement.QueryColumn ownerIDColumn,
144                        SQLIdentifier setRangeVar,
145                        Class JavaDoc filteredElementType,
146                        SQLIdentifier elementRangeVar)
147     {
148         if (!elementType.isAssignableFrom(filteredElementType))
149             throw new IncompatibleQueryElementTypeException(elementType, filteredElementType);
150
151         /* Join the element table on the owner ID column. */
152         ClassBaseTable filteredElementTable = storeMgr.getClassBaseTable(filteredElementType);
153
154         stmt.newTableExpression(filteredElementTable, elementRangeVar);
155         stmt.innerJoin(ownerIDColumn, stmt.getColumn(elementRangeVar, ownerColumn));
156
157         Column elementTableIDColumn = filteredElementTable.getIDMapping().getColumn();
158
159         return stmt.getColumn(elementRangeVar, elementTableIDColumn);
160     }
161
162
163     public boolean add(StateManager sm, Object JavaDoc element)
164     {
165         PersistenceManager pm = sm.getPersistenceManager();
166         StateManager esm = pm.findStateManager(element);
167
168         /*
169          * If the object is currently unmanaged (Transient) it first has to
170          * transition to a TransientClean state so we can modify its fields,
171          * then to TransientDirty as we modify the owner field. If the
172          * subsequent makePersistent() attempt fails the object will be restored
173          * on rollback but will be left in a managed state (TransientClean).
174          */

175         if (esm == null)
176         {
177             pm.makeTransactional(element);
178             esm = pm.findStateManager(element);
179         }
180
181         boolean wasPersistent = esm.isPersistent((javax.jdo.spi.PersistenceCapable)element);
182
183         /*
184          * "Add" the new value to the set by updating its owner field to the
185          * appropriate value. This should result in no actual database
186          * activity if the element was already persistent and the field was
187          * already set to the right value.
188          */

189         Object JavaDoc oldOwner = esm.getField(ownerFieldNumber);
190         Object JavaDoc newOwner = sm.getObject();
191         esm.setField(ownerFieldNumber, oldOwner, newOwner);
192         pm.makePersistent(element);
193
194         return !wasPersistent || oldOwner != newOwner;
195     }
196
197
198     public boolean remove(StateManager sm, Object JavaDoc element)
199     {
200         if (!validateElementForReading(sm, element))
201             return false;
202
203         PersistenceManager pm = sm.getPersistenceManager();
204         StateManager esm = pm.findStateManager(element);
205
206         Object JavaDoc oldOwner = esm.getField(ownerFieldNumber);
207
208         if (oldOwner != sm.getObject())
209             return false;
210         else
211         {
212             if (ownerColumn.isNullable())
213                 esm.setField(ownerFieldNumber, oldOwner, null);
214             else
215                 pm.deletePersistent(element);
216
217             return true;
218         }
219     }
220
221
222     public void clear(StateManager sm)
223     {
224         PersistenceManager pm = sm.getPersistenceManager();
225         Collection JavaDoc elements = load(sm);
226
227         if (ownerColumn.isNullable())
228         {
229             Iterator JavaDoc i = elements.iterator();
230
231             while (i.hasNext())
232             {
233                 StateManager esm = pm.findStateManager(i.next());
234                 esm.setField(ownerFieldNumber, esm.getField(ownerFieldNumber), null);
235             }
236         }
237         else
238             pm.deletePersistentAll(elements);
239     }
240 }
241
Popular Tags