1 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 ; 19 import java.util.Collection ; 20 import java.util.Iterator ; 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 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 ownerFieldName = vofmd.getName(); 56 String 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 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 put(StateManager sm, Object newKey, Object newValue) 128 { 129 validateKeyForWriting(sm, newKey); 130 131 135 Object 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 153 if (vsm == null) 154 { 155 pm.makeTransactional(newValue); 156 vsm = pm.findStateManager(newValue); 157 } 158 159 165 Object oldOwner = vsm.getField(ownerFieldNumber); 166 Object oldKey = vsm.getField(keyFieldNumber); 167 Object 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 remove(StateManager sm, Object key) 178 { 179 Object 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 key, Object 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 key, Object value) 203 { 204 if (!validateValueForReading(sm, value)) 205 return false; 206 207 PersistenceManager pm = sm.getPersistenceManager(); 208 StateManager vsm = pm.findStateManager(value); 209 Object 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 values = load(sm).values(); 227 228 if (keyColumn.isNullable()) 229 { 230 Iterator 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 |