1 19 20 package org.apache.cayenne.access; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.apache.commons.collections.Factory; 30 import org.apache.cayenne.CayenneRuntimeException; 31 import org.apache.cayenne.DataObject; 32 import org.apache.cayenne.DataRow; 33 import org.apache.cayenne.ObjectId; 34 import org.apache.cayenne.Persistent; 35 import org.apache.cayenne.graph.CompoundDiff; 36 import org.apache.cayenne.graph.NodeIdChangeOperation; 37 import org.apache.cayenne.map.DbEntity; 38 import org.apache.cayenne.map.ObjAttribute; 39 import org.apache.cayenne.map.ObjEntity; 40 import org.apache.cayenne.reflect.AttributeProperty; 41 import org.apache.cayenne.reflect.ClassDescriptor; 42 43 49 abstract class DataDomainSyncBucket { 50 51 final Map objectsByDescriptor; 52 final DataDomainFlushAction parent; 53 54 List dbEntities; 55 Map descriptorsByDbEntity; 56 57 DataDomainSyncBucket(DataDomainFlushAction parent) { 58 this.objectsByDescriptor = new HashMap (); 59 this.parent = parent; 60 } 61 62 boolean isEmpty() { 63 return objectsByDescriptor.isEmpty(); 64 } 65 66 abstract void appendQueriesInternal(Collection queries); 67 68 71 void appendQueries(Collection queries) { 72 73 if (!objectsByDescriptor.isEmpty()) { 74 groupObjEntitiesBySpannedDbEntities(); 75 appendQueriesInternal(queries); 76 } 77 } 78 79 void checkReadOnly(ObjEntity entity) throws CayenneRuntimeException { 80 81 if (entity.isReadOnly()) { 82 83 StringBuffer message = new StringBuffer (); 84 message 85 .append("Attempt to modify object(s) mapped to a read-only entity: ") 86 .append(entity.getName()); 87 88 if (entity != null) { 89 message.append(" '").append(entity.getName()).append("'"); 90 } 91 92 message.append(". Can't commit changes."); 93 throw new CayenneRuntimeException(message.toString()); 94 } 95 } 96 97 private void groupObjEntitiesBySpannedDbEntities() { 98 99 dbEntities = new ArrayList (objectsByDescriptor.size()); 100 descriptorsByDbEntity = new HashMap (objectsByDescriptor.size() * 2); 101 102 Iterator i = objectsByDescriptor.keySet().iterator(); 103 while (i.hasNext()) { 104 ClassDescriptor descriptor = (ClassDescriptor) i.next(); 105 DbEntity dbEntity = descriptor.getEntity().getDbEntity(); 106 107 List objEntitiesForDbEntity = (List ) descriptorsByDbEntity.get(dbEntity); 108 if (objEntitiesForDbEntity == null) { 109 objEntitiesForDbEntity = new ArrayList (1); 110 dbEntities.add(dbEntity); 111 descriptorsByDbEntity.put(dbEntity, objEntitiesForDbEntity); 112 } 113 114 if (!objEntitiesForDbEntity.contains(descriptor)) { 115 objEntitiesForDbEntity.add(descriptor); 116 } 117 118 Iterator j = descriptor.getEntity().getAttributeMap().values().iterator(); 121 while (j.hasNext()) { 122 Object next = j.next(); 123 124 if (!(next instanceof ObjAttribute)) { 126 continue; 127 } 128 129 ObjAttribute objAttribute = (ObjAttribute) next; 130 if (!objAttribute.isCompound()) { 131 continue; 132 } 133 134 dbEntity = (DbEntity) objAttribute.getDbAttribute().getEntity(); 135 objEntitiesForDbEntity = (List ) descriptorsByDbEntity.get(dbEntity); 136 137 if (objEntitiesForDbEntity == null) { 138 objEntitiesForDbEntity = new ArrayList (1); 139 dbEntities.add(dbEntity); 140 descriptorsByDbEntity.put(dbEntity, objEntitiesForDbEntity); 141 } 142 143 if (!objEntitiesForDbEntity.contains(descriptor)) { 144 objEntitiesForDbEntity.add(descriptor); 145 } 146 } 147 } 148 } 149 150 void addDirtyObject(Object object, ClassDescriptor descriptor) { 151 152 Collection objects = (Collection ) objectsByDescriptor.get(descriptor); 153 if (objects == null) { 154 155 objects = new ArrayList (); 156 objectsByDescriptor.put(descriptor, objects); 157 } 158 159 objects.add(object); 160 } 161 162 void postprocess() { 163 164 if (!objectsByDescriptor.isEmpty()) { 165 166 CompoundDiff result = parent.getResultDiff(); 167 Map modifiedSnapshots = parent.getResultModifiedSnapshots(); 168 Collection deletedIds = parent.getResultDeletedIds(); 169 170 Iterator it = objectsByDescriptor.entrySet().iterator(); 171 while (it.hasNext()) { 172 173 Map.Entry entry = (Map.Entry ) it.next(); 174 ClassDescriptor descriptor = (ClassDescriptor) entry.getKey(); 175 176 Iterator objects = ((Collection ) entry.getValue()).iterator(); 177 while (objects.hasNext()) { 178 Persistent object = (Persistent) objects.next(); 179 ObjectId id = object.getObjectId(); 180 181 ObjectId finalId; 182 183 if (id.isReplacementIdAttached()) { 185 186 Map replacement = id.getReplacementIdMap(); 187 Iterator idProperties = descriptor.getIdProperties(); 188 while (idProperties.hasNext()) { 189 AttributeProperty property = (AttributeProperty) idProperties 190 .next(); 191 Object value = replacement.get(property 192 .getAttribute() 193 .getDbAttributeName()); 194 195 if (value != null) { 198 property.writePropertyDirectly(object, null, value); 199 } 200 } 201 202 ObjectId replacementId = id.createReplacementId(); 203 204 result.add(new NodeIdChangeOperation(id, replacementId)); 205 206 if (!id.isTemporary()) { 209 deletedIds.add(id); 210 } 211 212 finalId = replacementId; 213 } 214 else if (id.isTemporary()) { 215 throw new CayenneRuntimeException( 216 "Temporary ID hasn't been replaced on commit: " + object); 217 } 218 else { 219 finalId = id; 220 221 } 222 223 DataRow dataRow = parent.getContext().currentSnapshot(object); 226 227 if (object instanceof DataObject) { 228 DataObject dataObject = (DataObject) object; 229 dataRow.setReplacesVersion(dataObject.getSnapshotVersion()); 230 dataObject.setSnapshotVersion(dataRow.getVersion()); 231 } 232 233 modifiedSnapshots.put(finalId, dataRow); 234 } 235 } 236 } 237 } 238 239 final static class PropagatedValueFactory implements Factory { 241 242 ObjectId masterID; 243 String masterKey; 244 245 PropagatedValueFactory(ObjectId masterID, String masterKey) { 246 this.masterID = masterID; 247 this.masterKey = masterKey; 248 } 249 250 public Object create() { 251 Object value = masterID.getIdSnapshot().get(masterKey); 252 if (value == null) { 253 throw new CayenneRuntimeException("Can't extract a master key. " 254 + "Missing key (" 255 + masterKey 256 + "), master ID (" 257 + masterID 258 + ")"); 259 } 260 261 return value; 262 } 263 } 264 } 265 | Popular Tags |