1 19 20 package org.apache.cayenne.access; 21 22 import org.apache.cayenne.DataRow; 23 import org.apache.cayenne.ObjectId; 24 import org.apache.cayenne.PersistenceState; 25 import org.apache.cayenne.Persistent; 26 import org.apache.cayenne.map.DbRelationship; 27 import org.apache.cayenne.map.ObjAttribute; 28 import org.apache.cayenne.map.ObjEntity; 29 import org.apache.cayenne.map.ObjRelationship; 30 import org.apache.cayenne.reflect.ArcProperty; 31 import org.apache.cayenne.reflect.AttributeProperty; 32 import org.apache.cayenne.reflect.ClassDescriptor; 33 import org.apache.cayenne.reflect.PropertyVisitor; 34 import org.apache.cayenne.reflect.ToManyProperty; 35 import org.apache.cayenne.reflect.ToOneProperty; 36 import org.apache.cayenne.util.Util; 37 38 45 class DataRowUtils { 46 47 52 static void mergeObjectWithSnapshot( 53 DataContext context, 54 ClassDescriptor descriptor, 55 Persistent object, 56 DataRow snapshot) { 57 58 int state = object.getPersistenceState(); 59 60 if (state == PersistenceState.HOLLOW || descriptor.getEntity().isReadOnly()) { 61 refreshObjectWithSnapshot(descriptor, object, snapshot, true); 62 } 63 else if (state != PersistenceState.COMMITTED) { 64 forceMergeWithSnapshot(context, descriptor, object, snapshot); 65 } 66 else { 67 refreshObjectWithSnapshot(descriptor, object, snapshot, false); 70 } 71 } 72 73 77 static void refreshObjectWithSnapshot( 78 ClassDescriptor descriptor, 79 final Persistent object, 80 final DataRow snapshot, 81 final boolean invalidateToManyRelationships) { 82 83 final boolean[] isPartialSnapshot = new boolean[1]; 84 85 descriptor.visitProperties(new PropertyVisitor() { 86 87 public boolean visitAttribute(AttributeProperty property) { 88 ObjAttribute attr = property.getAttribute(); 89 String dbAttrPath = attr.getDbAttributePath(); 90 91 Object value = snapshot.get(dbAttrPath); 92 property.writePropertyDirectly(object, null, value); 93 94 if (value == null && !snapshot.containsKey(dbAttrPath)) { 98 isPartialSnapshot[0] = true; 99 } 100 return true; 101 } 102 103 public boolean visitToMany(ToManyProperty property) { 104 if (invalidateToManyRelationships) { 107 property.invalidate(object); 108 } 109 110 return true; 111 } 112 113 public boolean visitToOne(ToOneProperty property) { 114 property.invalidate(object); 115 return true; 116 } 117 }); 118 119 object.setPersistenceState(isPartialSnapshot[0] 120 ? PersistenceState.HOLLOW 121 : PersistenceState.COMMITTED); 122 } 123 124 static void forceMergeWithSnapshot( 125 final DataContext context, 126 ClassDescriptor descriptor, 127 final Persistent object, 128 final DataRow snapshot) { 129 130 final ObjectDiff diff = (ObjectDiff) context 131 .getObjectStore() 132 .getChangesByObjectId() 133 .get(object.getObjectId()); 134 135 descriptor.visitProperties(new PropertyVisitor() { 136 137 public boolean visitAttribute(AttributeProperty property) { 138 String dbAttrPath = property.getAttribute().getDbAttributePath(); 139 140 Object newValue = snapshot.get(dbAttrPath); 145 if (newValue != null || snapshot.containsKey(dbAttrPath)) { 146 147 Object curValue = property.readPropertyDirectly(object); 148 Object oldValue = diff != null ? diff.getSnapshotValue(property 149 .getName()) : null; 150 151 if (Util.nullSafeEquals(curValue, oldValue) 154 && !Util.nullSafeEquals(newValue, curValue)) { 155 property.writePropertyDirectly(object, oldValue, newValue); 156 } 157 } 158 return true; 159 } 160 161 public boolean visitToMany(ToManyProperty property) { 162 return true; 164 } 165 166 public boolean visitToOne(ToOneProperty property) { 167 ObjRelationship relationship = property.getRelationship(); 168 if (relationship.isToPK()) { 169 172 if (!isToOneTargetModified(property, object, diff)) { 175 176 DbRelationship dbRelationship = (DbRelationship) relationship 177 .getDbRelationships() 178 .get(0); 179 180 ObjectId id = snapshot.createTargetObjectId(relationship 181 .getTargetEntityName(), dbRelationship); 182 183 if (diff == null 184 || !diff.containsArcSnapshot(relationship.getName()) 185 || !Util.nullSafeEquals(id, diff 186 .getArcSnapshotValue(relationship.getName()))) { 187 188 if (id == null) { 189 property.writeProperty(object, null, null); 190 } 191 else { 192 ObjEntity targetEntity = (ObjEntity) relationship 195 .getTargetEntity(); 196 if (context.getEntityResolver().lookupInheritanceTree( 197 targetEntity) != null) { 198 property.invalidate(object); 199 } 200 else { 201 property.writeProperty(object, null, context 202 .localObject(id, null)); 203 } 204 } 205 } 206 } 207 } 208 return true; 209 } 210 }); 211 } 212 213 216 static boolean isToOneTargetModified( 217 ArcProperty property, 218 Persistent object, 219 ObjectDiff diff) { 220 221 if (object.getPersistenceState() != PersistenceState.MODIFIED || diff == null) { 222 return false; 223 } 224 225 if (property.isFault(object)) { 226 return false; 227 } 228 229 Persistent toOneTarget = (Persistent) property.readPropertyDirectly(object); 230 ObjectId currentId = (toOneTarget != null) ? toOneTarget.getObjectId() : null; 231 232 if (currentId != null && currentId.isTemporary()) { 235 return true; 236 } 237 238 if (!diff.containsArcSnapshot(property.getName())) { 239 return false; 240 } 241 242 ObjectId targetId = diff.getArcSnapshotValue(property.getName()); 243 return !Util.nullSafeEquals(currentId, targetId); 244 } 245 246 DataRowUtils() { 248 } 249 } 250 | Popular Tags |