1 19 20 package org.apache.cayenne; 21 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 27 import org.apache.cayenne.map.DeleteRule; 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.Property; 34 import org.apache.cayenne.reflect.PropertyVisitor; 35 import org.apache.cayenne.reflect.ToManyProperty; 36 import org.apache.cayenne.reflect.ToOneProperty; 37 38 44 class ObjectContextDeleteAction { 45 46 private ObjectContext context; 47 48 ObjectContextDeleteAction(ObjectContext context) { 49 this.context = context; 50 } 51 52 boolean performDelete(Persistent object) throws DeleteDenyException { 53 54 int oldState = object.getPersistenceState(); 55 56 if (oldState == PersistenceState.TRANSIENT 57 || oldState == PersistenceState.DELETED) { 58 return false; 59 } 60 61 if (object.getObjectContext() == null) { 62 throw new CayenneRuntimeException( 63 "Attempt to delete unregistered non-TRANSIENT object: " + object); 64 } 65 66 if (object.getObjectContext() != context) { 67 throw new CayenneRuntimeException( 68 "Attempt to delete object regsitered in a different ObjectContext. Object: " 69 + object 70 + ", context: " 71 + context); 72 } 73 74 if (oldState == PersistenceState.NEW) { 75 deleteNew(object); 76 } 77 else { 78 deletePersistent(object); 79 } 80 81 return true; 82 } 83 84 private void deleteNew(Persistent object) { 85 object.setPersistenceState(PersistenceState.TRANSIENT); 86 processDeleteRules(object, PersistenceState.NEW); 87 context.getGraphManager().unregisterNode(object.getObjectId()); 88 } 89 90 private void deletePersistent(Persistent object) { 91 int oldState = object.getPersistenceState(); 92 object.setPersistenceState(PersistenceState.DELETED); 93 processDeleteRules(object, oldState); 94 context.getGraphManager().nodeRemoved(object.getObjectId()); 95 } 96 97 private void processDeleteRules(final Persistent object, final int oldState) { 98 99 String entityName = object.getObjectId().getEntityName(); 100 final ObjEntity entity = context.getEntityResolver().getObjEntity(entityName); 101 ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor( 102 entityName); 103 104 descriptor.visitProperties(new PropertyVisitor() { 105 106 public boolean visitToMany(ToManyProperty property) { 107 ObjRelationship relationship = (ObjRelationship) entity 108 .getRelationship(property.getName()); 109 110 processRules(object, property, relationship.getDeleteRule(), oldState); 111 return true; 112 } 113 114 public boolean visitToOne(ToOneProperty property) { 115 ObjRelationship relationship = (ObjRelationship) entity 116 .getRelationship(property.getName()); 117 118 processRules(object, property, relationship.getDeleteRule(), oldState); 119 return true; 120 } 121 122 public boolean visitAttribute(AttributeProperty property) { 123 return true; 124 } 125 }); 126 } 127 128 private void processRules( 129 Persistent object, 130 ArcProperty property, 131 int deleteRule, 132 int oldState) { 133 134 if (deleteRule == DeleteRule.NO_ACTION) { 135 return; 136 } 137 138 Collection relatedObjects = relatedObjects(object, property); 139 if (relatedObjects.isEmpty()) { 140 return; 141 } 142 143 switch (deleteRule) { 144 145 case DeleteRule.DENY: 146 object.setPersistenceState(oldState); 147 String message = relatedObjects.size() == 1 148 ? "1 related object" 149 : relatedObjects.size() + " related objects"; 150 throw new DeleteDenyException(object, property.getName(), message); 151 152 case DeleteRule.NULLIFY: 153 ArcProperty reverseArc = property.getComplimentaryReverseArc(); 154 155 if (reverseArc != null) { 156 157 if (reverseArc instanceof ToManyProperty) { 158 Iterator iterator = relatedObjects.iterator(); 159 while (iterator.hasNext()) { 160 Object relatedObject = iterator.next(); 161 ((ToManyProperty) reverseArc).removeTarget( 162 relatedObject, 163 object, 164 true); 165 } 166 } 167 else { 168 Iterator iterator = relatedObjects.iterator(); 169 while (iterator.hasNext()) { 170 Object relatedObject = iterator.next(); 171 ((ToOneProperty) reverseArc).setTarget( 172 relatedObject, 173 null, 174 true); 175 } 176 } 177 } 178 179 break; 180 case DeleteRule.CASCADE: 181 182 Iterator iterator = relatedObjects.iterator(); 183 while (iterator.hasNext()) { 184 Persistent relatedObject = (Persistent) iterator.next(); 185 186 performDelete(relatedObject); 189 } 190 191 break; 192 default: 193 object.setPersistenceState(oldState); 194 throw new CayenneRuntimeException("Invalid delete rule: " + deleteRule); 195 } 196 } 197 198 private Collection relatedObjects(Object object, Property property) { 199 Object related = property.readProperty(object); 200 201 if (related == null) { 202 return Collections.EMPTY_LIST; 203 } 204 else if (property instanceof ToManyProperty) { 207 Collection relatedCollection = (Collection ) related; 208 return relatedCollection.isEmpty() ? Collections.EMPTY_LIST : new ArrayList ( 209 relatedCollection); 210 } 211 else { 212 return Collections.singleton(related); 213 } 214 } 215 } 216 | Popular Tags |