1 /*
2 * Copyright 2005-2007 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.kns.util;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.List;
22
23 import org.apache.log4j.Logger;
24 import org.kuali.rice.kns.bo.PersistableBusinessObject;
25 import org.springframework.orm.ObjectRetrievalFailureException;
26
27 /**
28 * Helper object to deal with persisting collections.
29 */
30 public class OjbCollectionHelper {
31 private static final Logger LOG = Logger.getLogger(OjbCollectionHelper.class);
32 /**
33 * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
34 * business objects that are found in Collections stored in the database but not in memory.
35 *
36 * @param orig
37 * @param id
38 * @param template
39 */
40 public void processCollections(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
41 if (copy == null) {
42 return;
43 }
44
45 List originalCollections = orig.buildListOfDeletionAwareLists();
46
47 if (originalCollections != null && !originalCollections.isEmpty()) {
48 /*
49 * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
50 * retrieved version will contain objects that need to be removed:
51 */
52 try {
53 List copyCollections = copy.buildListOfDeletionAwareLists();
54 int size = originalCollections.size();
55
56 if (copyCollections.size() != size) {
57 throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
58 }
59
60 for (int i = 0; i < size; i++) {
61 Collection origSource = (Collection) originalCollections.get(i);
62 Collection copySource = (Collection) copyCollections.get(i);
63 List list = findUnwantedElements(copySource, origSource);
64 cleanse(template, origSource, list);
65 }
66 }
67 catch (ObjectRetrievalFailureException orfe) {
68 // object wasn't found, must be pre-save
69 }
70 }
71 }
72
73 /**
74 * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
75 * business objects that are found in Collections stored in the database but not in memory.
76 *
77 * @param orig
78 * @param id
79 * @param template
80 */
81 public void processCollections2(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
82 // if copy is null this is the first time we are saving the object, don't have to worry about updating collections
83 if (copy == null) {
84 return;
85 }
86
87 List originalCollections = orig.buildListOfDeletionAwareLists();
88
89 if (originalCollections != null && !originalCollections.isEmpty()) {
90 /*
91 * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
92 * retrieved version will contain objects that need to be removed:
93 */
94 try {
95 List copyCollections = copy.buildListOfDeletionAwareLists();
96 int size = originalCollections.size();
97
98 if (copyCollections.size() != size) {
99 throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
100 }
101
102 for (int i = 0; i < size; i++) {
103 Collection origSource = (Collection) originalCollections.get(i);
104 Collection copySource = (Collection) copyCollections.get(i);
105 List list = findUnwantedElements(copySource, origSource);
106 cleanse(template, origSource, list);
107 }
108 }
109 catch (ObjectRetrievalFailureException orfe) {
110 // object wasn't found, must be pre-save
111 }
112 }
113 }
114
115 /**
116 * This method deletes unwanted objects from the database as well as from the given input List
117 *
118 * @param origSource - list containing unwanted business objects
119 * @param unwantedItems - business objects to be permanently removed
120 * @param template
121 */
122 private void cleanse(OjbCollectionAware template, Collection origSource, List unwantedItems) {
123 if (unwantedItems.size() > 0) {
124 Iterator iter = unwantedItems.iterator();
125 while (iter.hasNext()) {
126 Object obj = iter.next();
127 if ( LOG.isDebugEnabled() ) {
128 LOG.debug( "cleansing " + obj);
129 }
130 template.getPersistenceBrokerTemplate().delete(obj);
131 }
132 }
133
134 }
135
136 /**
137 * This method identifies items in the first List that are not contained in the second List. It is similar to the (optional)
138 * java.util.List retainAll method.
139 *
140 * @param fromList
141 * @param controlList
142 * @return true iff one or more items were removed
143 */
144 private List findUnwantedElements(Collection fromList, Collection controlList) {
145 List toRemove = new ArrayList();
146
147 Iterator iter = fromList.iterator();
148 while (iter.hasNext()) {
149 PersistableBusinessObject line = (PersistableBusinessObject) iter.next();
150 if (!ObjectUtils.collectionContainsObjectWithIdentitcalKey(controlList, line)) {
151 toRemove.add(line);
152 }
153 }
154 return toRemove;
155 }
156 }