KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > ObjectContextDeleteAction


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Iterator JavaDoc;
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 /**
39  * A CayenneContext helper that processes object deletion.
40  *
41  * @since 1.2
42  * @author Andrus Adamchik
43  */

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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc iterator = relatedObjects.iterator();
159                         while (iterator.hasNext()) {
160                             Object JavaDoc relatedObject = iterator.next();
161                             ((ToManyProperty) reverseArc).removeTarget(
162                                     relatedObject,
163                                     object,
164                                     true);
165                         }
166                     }
167                     else {
168                         Iterator JavaDoc iterator = relatedObjects.iterator();
169                         while (iterator.hasNext()) {
170                             Object JavaDoc 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 JavaDoc iterator = relatedObjects.iterator();
183                 while (iterator.hasNext()) {
184                     Persistent relatedObject = (Persistent) iterator.next();
185
186                     // this action object is stateless, so we can use 'performDelete'
187
// recursively.
188
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 JavaDoc relatedObjects(Object JavaDoc object, Property property) {
199         Object JavaDoc related = property.readProperty(object);
200
201         if (related == null) {
202             return Collections.EMPTY_LIST;
203         }
204         // return collections by copy, to allow removal of objects from the underlying
205
// relationship inside the iterator
206
else if (property instanceof ToManyProperty) {
207             Collection JavaDoc relatedCollection = (Collection JavaDoc) related;
208             return relatedCollection.isEmpty() ? Collections.EMPTY_LIST : new ArrayList JavaDoc(
209                     relatedCollection);
210         }
211         else {
212             return Collections.singleton(related);
213         }
214     }
215 }
216
Popular Tags