1 19 20 package org.apache.cayenne.access; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 import org.apache.cayenne.CayenneRuntimeException; 29 import org.apache.cayenne.DeleteDenyException; 30 import org.apache.cayenne.PersistenceState; 31 import org.apache.cayenne.Persistent; 32 import org.apache.cayenne.map.DeleteRule; 33 import org.apache.cayenne.map.ObjRelationship; 34 import org.apache.cayenne.reflect.ArcProperty; 35 import org.apache.cayenne.reflect.AttributeProperty; 36 import org.apache.cayenne.reflect.ClassDescriptor; 37 import org.apache.cayenne.reflect.PropertyVisitor; 38 import org.apache.cayenne.reflect.ToManyProperty; 39 import org.apache.cayenne.reflect.ToOneProperty; 40 41 47 class DataContextDeleteAction { 48 49 DataContext dataContext; 50 51 DataContextDeleteAction(DataContext context) { 52 this.dataContext = context; 53 } 54 55 58 boolean performDelete(Persistent object) throws DeleteDenyException { 59 int oldState = object.getPersistenceState(); 60 if (oldState == PersistenceState.DELETED 61 || oldState == PersistenceState.TRANSIENT) { 62 63 return false; 68 } 69 70 if (object.getObjectContext() == null) { 71 throw new CayenneRuntimeException( 72 "Attempt to delete unregistered non-TRANSIENT object: " + object); 73 } 74 75 if (object.getObjectContext() != dataContext) { 76 throw new CayenneRuntimeException( 77 "Attempt to delete object registered in a different DataContext. Object: " 78 + object 79 + ", data context: " 80 + dataContext); 81 } 82 83 86 dataContext.prepareForAccess(object, null, false); 87 88 if (oldState == PersistenceState.NEW) { 89 deleteNew(object, oldState); 90 } 91 else { 92 deletePersistent(object, oldState); 93 } 94 95 return true; 96 } 97 98 private void deletePersistent(Persistent object, int oldState) 99 throws DeleteDenyException { 100 101 object.setPersistenceState(PersistenceState.DELETED); 102 dataContext.getObjectStore().nodeRemoved(object.getObjectId()); 103 processDeleteRules(object, oldState); 104 } 105 106 private void deleteNew(Persistent object, int oldState) throws DeleteDenyException { 107 object.setPersistenceState(PersistenceState.TRANSIENT); 108 processDeleteRules(object, oldState); 109 110 112 dataContext.getObjectStore().objectsUnregistered( 113 Collections.singletonList(object)); 114 object.setObjectContext(null); 115 } 116 117 private void processDeleteRules(final Persistent object, int oldState) 118 throws DeleteDenyException { 119 120 ClassDescriptor descriptor = dataContext.getEntityResolver().getClassDescriptor( 121 object.getObjectId().getEntityName()); 122 123 Iterator it = descriptor.getEntity().getRelationships().iterator(); 124 while (it.hasNext()) { 125 ObjRelationship relationship = (ObjRelationship) it.next(); 126 127 boolean processFlattened = relationship.isFlattened() 128 && relationship.isToDependentEntity() && !relationship.isReadOnly(); 129 130 if (relationship.getDeleteRule() == DeleteRule.NO_ACTION && !processFlattened) { 132 continue; 133 } 134 135 List relatedObjects = Collections.EMPTY_LIST; 136 137 ArcProperty property = (ArcProperty) descriptor.getProperty(relationship 138 .getName()); 139 Object related = property.readProperty(object); 140 141 if (relationship.isToMany()) { 142 143 List toMany = (List ) related; 144 if (toMany.size() > 0) { 145 relatedObjects = new ArrayList (toMany); 148 } 149 } 150 else { 151 if (related != null) { 152 relatedObjects = Collections.singletonList(related); 153 } 154 } 155 156 if (relatedObjects.size() == 0) { 158 continue; 159 } 160 161 if (relationship.getDeleteRule() == DeleteRule.DENY) { 163 object.setPersistenceState(oldState); 164 165 String message = relatedObjects.size() == 1 166 ? "1 related object" 167 : relatedObjects.size() + " related objects"; 168 throw new DeleteDenyException(object, relationship.getName(), message); 169 } 170 171 if (processFlattened) { 175 ObjectStore objectStore = dataContext.getObjectStore(); 176 Iterator iterator = relatedObjects.iterator(); 177 while (iterator.hasNext()) { 178 Persistent relatedObject = (Persistent) iterator.next(); 179 objectStore.arcDeleted(object.getObjectId(), relatedObject 180 .getObjectId(), relationship.getName()); 181 } 182 } 183 184 switch (relationship.getDeleteRule()) { 186 case DeleteRule.NO_ACTION: 187 break; 188 case DeleteRule.NULLIFY: 189 ArcProperty reverseArc = property.getComplimentaryReverseArc(); 190 191 if (reverseArc == null) { 192 break; 194 } 195 196 final Collection finalRelatedObjects = relatedObjects; 197 198 reverseArc.visit(new PropertyVisitor() { 199 200 public boolean visitAttribute(AttributeProperty property) { 201 return false; 202 } 203 204 public boolean visitToMany(ToManyProperty property) { 205 Iterator iterator = finalRelatedObjects.iterator(); 206 while (iterator.hasNext()) { 207 Object relatedObject = iterator.next(); 208 property.removeTarget(relatedObject, object, true); 209 } 210 211 return false; 212 } 213 214 public boolean visitToOne(ToOneProperty property) { 215 Iterator iterator = finalRelatedObjects.iterator(); 218 while (iterator.hasNext()) { 219 Object relatedObject = iterator.next(); 220 property.setTarget(relatedObject, null, true); 221 } 222 return false; 223 } 224 }); 225 226 break; 227 case DeleteRule.CASCADE: 228 Iterator iterator = relatedObjects.iterator(); 230 while (iterator.hasNext()) { 231 Persistent relatedObject = (Persistent) iterator.next(); 232 new DataContextDeleteAction(this.dataContext) 233 .performDelete(relatedObject); 234 } 235 236 break; 237 default: 238 object.setPersistenceState(oldState); 239 throw new CayenneRuntimeException("Invalid delete rule " 240 + relationship.getDeleteRule()); 241 } 242 } 243 } 244 } 245 | Popular Tags |