View Javadoc

1   /**
2    * Copyright 2005-2012 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.krad.util;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.List;
21  
22  import org.apache.log4j.Logger;
23  import org.kuali.rice.krad.bo.PersistableBusinessObject;
24  import org.springframework.orm.ObjectRetrievalFailureException;
25  
26  /**
27   * Helper object to deal with persisting collections.
28   */
29  public class OjbCollectionHelper {
30  	private static final Logger LOG = Logger.getLogger(OjbCollectionHelper.class);
31      /**
32       * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
33       * business objects that are found in Collections stored in the database but not in memory.
34       * 
35       * @param orig
36       * @param id
37       * @param template
38       */
39      public void processCollections(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
40          if (copy == null) {
41              return;
42          }
43          
44          List<Collection<PersistableBusinessObject>> originalCollections = orig.buildListOfDeletionAwareLists();
45  
46          if (originalCollections != null && !originalCollections.isEmpty()) {
47              /*
48               * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
49               * retrieved version will contain objects that need to be removed:
50               */
51              try {
52                  List<Collection<PersistableBusinessObject>> copyCollections = copy.buildListOfDeletionAwareLists();
53                  int size = originalCollections.size();
54  
55                  if (copyCollections.size() != size) {
56                      throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
57                  }
58  
59                  for (int i = 0; i < size; i++) {
60                      Collection<PersistableBusinessObject> origSource = originalCollections.get(i);
61                      Collection<PersistableBusinessObject> copySource = copyCollections.get(i);
62                      List<PersistableBusinessObject> list = findUnwantedElements(copySource, origSource);
63                      cleanse(template, origSource, list);
64                  }
65              }
66              catch (ObjectRetrievalFailureException orfe) {
67                  // object wasn't found, must be pre-save
68              }
69          }
70      }
71      
72      /**
73       * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
74       * business objects that are found in Collections stored in the database but not in memory.
75       * 
76       * @param orig
77       * @param id
78       * @param template
79       */
80      public void processCollections2(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
81          // if copy is null this is the first time we are saving the object, don't have to worry about updating collections
82          if (copy == null) {
83              return;
84          }
85          
86          List<Collection<PersistableBusinessObject>> originalCollections = orig.buildListOfDeletionAwareLists();
87  
88          if (originalCollections != null && !originalCollections.isEmpty()) {
89              /*
90               * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
91               * retrieved version will contain objects that need to be removed:
92               */
93              try {
94                  List<Collection<PersistableBusinessObject>> copyCollections = copy.buildListOfDeletionAwareLists();
95                  int size = originalCollections.size();
96  
97                  if (copyCollections.size() != size) {
98                      throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
99                  }
100 
101                 for (int i = 0; i < size; i++) {
102                     Collection<PersistableBusinessObject> origSource = originalCollections.get(i);
103                     Collection<PersistableBusinessObject> copySource = copyCollections.get(i);
104                     List<PersistableBusinessObject> list = findUnwantedElements(copySource, origSource);
105                     cleanse(template, origSource, list);
106                 }
107             }
108             catch (ObjectRetrievalFailureException orfe) {
109                 // object wasn't found, must be pre-save
110             }
111         }
112     }
113 
114     /**
115      * This method deletes unwanted objects from the database as well as from the given input List
116      * 
117      * @param origSource - list containing unwanted business objects
118      * @param unwantedItems - business objects to be permanently removed
119      * @param template
120      */
121     private void cleanse(OjbCollectionAware template, Collection<PersistableBusinessObject> origSource, List<PersistableBusinessObject> unwantedItems) {
122         if (unwantedItems.size() > 0) {
123         	for (PersistableBusinessObject unwantedItem : unwantedItems) {
124             	if ( LOG.isDebugEnabled() ) {
125             		LOG.debug( "cleansing " + unwantedItem);
126             	}
127                 template.getPersistenceBrokerTemplate().delete(unwantedItem);
128             }
129         }
130 
131     }
132 
133     /**
134      * This method identifies items in the first List that are not contained in the second List. It is similar to the (optional)
135      * java.util.List retainAll method.
136      * 
137      * @param fromList
138      * @param controlList
139      * @return true iff one or more items were removed
140      */
141     private List<PersistableBusinessObject> findUnwantedElements(Collection<PersistableBusinessObject> fromList, Collection<PersistableBusinessObject> controlList) {
142         List<PersistableBusinessObject> toRemove = new ArrayList<PersistableBusinessObject>();
143 
144         for (PersistableBusinessObject fromObject : fromList) {
145         	if (!ObjectUtils.collectionContainsObjectWithIdentitcalKey(controlList, fromObject)) {
146                 toRemove.add(fromObject);
147             }
148         }
149         return toRemove;
150     }
151 }