KickJava   Java API By Example, From Geeks To Geeks.

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


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: InverseMapStore.java,v 1.6 2004/01/18 03:01:06 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.FieldMetaData;
17 import com.triactive.jdo.model.MapMetaData;
18 import java.lang.reflect.Field JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import javax.jdo.JDOUserException;
22
23
24 class InverseMapStore extends AbstractMapStore
25 {
26     private final ClassBaseTable valueTable;
27     private final int ownerFieldNumber;
28     private final int keyFieldNumber;
29
30
31     public InverseMapStore(FieldMetaData fmd, StoreManager storeMgr)
32     {
33         this.storeMgr = storeMgr;
34
35         dba = storeMgr.getDatabaseAdapter();
36
37         Field JavaDoc field = fmd.getField();
38         ClassMetaData cmd = fmd.getClassMetaData();
39         MapMetaData mmd = fmd.getMapMetaData();
40         if (mmd == null)
41             throw new JDOUserException("No map metadata found in " + fmd);
42
43         keyType = mmd.getKeyType();
44         valueType = mmd.getValueType();
45
46         FieldMetaData vofmd = mmd.getOwnerField();
47         FieldMetaData vkfmd = mmd.getKeyField();
48
49         FieldMetaData omd = vofmd.getOwnedByMap();
50         if (omd == null || !omd.equals(fmd))
51             throw new InvalidMetaDataRelationshipException(fmd, "owner-field", vofmd, "map-field");
52         if (vkfmd == null)
53             throw new ClassDefinitionException("Missing map \"key-field\" in " + fmd);
54
55         String JavaDoc ownerFieldName = vofmd.getName();
56         String JavaDoc keyFieldName = vkfmd.getName();
57
58         ClassMetaData vmd = vofmd.getClassMetaData();
59
60         ownerFieldNumber = vmd.getAbsoluteFieldNumber(ownerFieldName);
61         keyFieldNumber = vmd.getAbsoluteFieldNumber(keyFieldName);
62
63         valueTable = storeMgr.getClassBaseTable(valueType);
64
65         if (!valueTable.isFieldPersistent(ownerFieldNumber))
66             throw new JDOUserException("Non-persistent field type for map owner field: " + field.getDeclaringClass().getName() + "." + field.getName());
67         if (!valueTable.isFieldPersistent(keyFieldNumber))
68             throw new JDOUserException("Non-persistent field type for map key field: " + field.getDeclaringClass().getName() + "." + field.getName());
69
70         Mapping m = valueTable.getFieldMapping(ownerFieldNumber);
71         if (!(m instanceof ColumnMapping))
72             throw new JDOUserException("Invalid field type for map owner field: " + field.getDeclaringClass().getName() + "." + field.getName());
73
74         ownerMapping = (ColumnMapping)m;
75
76         m = valueTable.getFieldMapping(keyFieldNumber);
77         if (!(m instanceof ColumnMapping))
78             throw new JDOUserException("Invalid field type for map key field: " + field.getDeclaringClass().getName() + "." + field.getName());
79
80         keyMapping = (ColumnMapping)m;
81         valueMapping = (ColumnMapping)dba.getMapping(valueType);
82
83         keysAreEmbedded = !(keyMapping instanceof OIDMapping);
84         valuesAreEmbedded = false;
85
86         ownerColumn = ownerMapping.getColumn();
87         keyColumn = keyMapping.getColumn();
88         valueColumn = valueTable.getIDMapping().getColumn();
89
90         loadStmt = "SELECT " + keyColumn.getName() + ',' + valueColumn.getName() +
91                       " FROM " + valueTable.getName() +
92                      " WHERE " + ownerColumn.getName() + " = ?";
93         getStmt = "SELECT " + valueColumn.getName() +
94                       " FROM " + valueTable.getName() +
95                      " WHERE " + ownerColumn.getName() + " = ? AND "
96                                + keyColumn.getName() + " = ?";
97         sizeStmt = "SELECT COUNT(*)" +
98                       " FROM " + valueTable.getName() +
99                      " WHERE " + ownerColumn.getName() + " = ?";
100         containsValueStmt = "SELECT " + ownerColumn.getName() +
101                              " FROM " + valueTable.getName() +
102                             " WHERE " + ownerColumn.getName() + " = ? AND "
103                                       + valueColumn.getName() + " = ?";
104         containsEntryStmt = "SELECT " + ownerColumn.getName() +
105                              " FROM " + valueTable.getName() +
106                             " WHERE " + ownerColumn.getName() + " = ? AND "
107                                       + keyColumn.getName() + " = ? AND "
108                                       + valueColumn.getName() + " = ?";
109
110         if (keyColumn.isNullable())
111         {
112             String JavaDoc excludeNullKeys = " AND " + keyColumn.getName() + " IS NOT NULL";
113
114             loadStmt += excludeNullKeys;
115             sizeStmt += excludeNullKeys;
116             containsValueStmt += excludeNullKeys;
117         }
118     }
119
120
121     public boolean allowsNullValues()
122     {
123         return false;
124     }
125
126
127     public Object JavaDoc put(StateManager sm, Object JavaDoc newKey, Object JavaDoc newValue)
128     {
129         validateKeyForWriting(sm, newKey);
130
131         /*
132          * See if there's an existing value having the key. If so, remove that
133          * object from the map by nulling out its key field.
134          */

135         Object JavaDoc oldValue = get(sm, newKey);
136
137         if (oldValue != newValue)
138         {
139             if (oldValue != null)
140                 removeValue(sm, newKey, oldValue);
141
142             PersistenceManager pm = sm.getPersistenceManager();
143             StateManager vsm = pm.findStateManager(newValue);
144
145             /*
146              * If the value object is currently unmanaged (Transient) it first
147              * has to transition to a TransientClean state so we can modify its
148              * fields, then to TransientDirty as we modify the owner/key fields.
149              * If the subsequent makePersistent() attempt fails the object will
150              * be restored on rollback but will be left in a managed state
151              * (TransientClean).
152              */

153             if (vsm == null)
154             {
155                 pm.makeTransactional(newValue);
156                 vsm = pm.findStateManager(newValue);
157             }
158
159             /*
160              * "Put" the new value in the map by updating its owner/key fields
161              * to the appropriate values. This should result in no actual
162              * database activity if the object was already persistent and the
163              * fields were already set to the right values.
164              */

165             Object JavaDoc oldOwner = vsm.getField(ownerFieldNumber);
166             Object JavaDoc oldKey = vsm.getField(keyFieldNumber);
167             Object JavaDoc newOwner = sm.getObject();
168             vsm.setField(ownerFieldNumber, oldOwner, newOwner);
169             vsm.setField(keyFieldNumber, oldKey, newKey);
170             pm.makePersistent(newValue);
171         }
172
173         return oldValue;
174     }
175
176
177     public Object JavaDoc remove(StateManager sm, Object JavaDoc key)
178     {
179         Object JavaDoc oldValue = get(sm, key);
180
181         if (oldValue != null)
182             removeValue(sm, key, oldValue);
183
184         return oldValue;
185     }
186
187
188     private void removeValue(StateManager sm, Object JavaDoc key, Object JavaDoc oldValue)
189     {
190         PersistenceManager pm = sm.getPersistenceManager();
191
192         if (keyColumn.isNullable())
193         {
194             StateManager vsm = pm.findStateManager(oldValue);
195             vsm.setField(keyFieldNumber, key, null);
196         }
197         else
198             pm.deletePersistent(oldValue);
199     }
200
201
202     public boolean removeEntry(StateManager sm, Object JavaDoc key, Object JavaDoc value)
203     {
204         if (!validateValueForReading(sm, value))
205             return false;
206
207         PersistenceManager pm = sm.getPersistenceManager();
208         StateManager vsm = pm.findStateManager(value);
209         Object JavaDoc actualKey = vsm.getField(keyFieldNumber);
210
211         if (!key.equals(actualKey))
212             return false;
213
214         if (keyColumn.isNullable())
215             vsm.setField(keyFieldNumber, key, null);
216         else
217             pm.deletePersistent(value);
218
219         return true;
220     }
221
222
223     public void clear(StateManager sm)
224     {
225         PersistenceManager pm = sm.getPersistenceManager();
226         Collection JavaDoc values = load(sm).values();
227
228         if (keyColumn.isNullable())
229         {
230             Iterator JavaDoc i = values.iterator();
231
232             while (i.hasNext())
233             {
234                 StateManager vsm = pm.findStateManager(i.next());
235                 vsm.setField(keyFieldNumber, vsm.getField(keyFieldNumber), null);
236             }
237         }
238         else
239             pm.deletePersistentAll(values);
240     }
241 }
242
Popular Tags