001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.service.util;
017
018import org.apache.log4j.Logger;
019import org.kuali.rice.krad.bo.PersistableBusinessObject;
020import org.kuali.rice.krad.util.ObjectUtils;
021import org.springframework.orm.ObjectRetrievalFailureException;
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.List;
026
027/**
028 * Helper object to deal with persisting collections
029 *
030 * @author Kuali Rice Team (rice.collab@kuali.org)
031 */
032@Deprecated
033public class OjbCollectionHelper {
034        private static final Logger LOG = Logger.getLogger(OjbCollectionHelper.class);
035
036    /**
037     * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
038     * business objects that are found in Collections stored in the database but not in memory.
039     * 
040     * @param orig
041     * @param id
042     * @param template
043     */
044    public void processCollections(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
045        if (copy == null) {
046            return;
047        }
048        
049        List<Collection<PersistableBusinessObject>> originalCollections = orig.buildListOfDeletionAwareLists();
050
051        if (originalCollections != null && !originalCollections.isEmpty()) {
052            /*
053             * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
054             * retrieved version will contain objects that need to be removed:
055             */
056            try {
057                List<Collection<PersistableBusinessObject>> copyCollections = copy.buildListOfDeletionAwareLists();
058                int size = originalCollections.size();
059
060                if (copyCollections.size() != size) {
061                    throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
062                }
063
064                for (int i = 0; i < size; i++) {
065                    Collection<PersistableBusinessObject> origSource = originalCollections.get(i);
066                    Collection<PersistableBusinessObject> copySource = copyCollections.get(i);
067                    List<PersistableBusinessObject> list = findUnwantedElements(copySource, origSource);
068                    cleanse(template, origSource, list);
069                }
070            }
071            catch (ObjectRetrievalFailureException orfe) {
072                // object wasn't found, must be pre-save
073            }
074        }
075    }
076    
077    /**
078     * OJB RemovalAwareLists do not survive through the response/request lifecycle. This method is a work-around to forcibly remove
079     * business objects that are found in Collections stored in the database but not in memory.
080     * 
081     * @param orig
082     * @param id
083     * @param template
084     */
085    public void processCollections2(OjbCollectionAware template, PersistableBusinessObject orig, PersistableBusinessObject copy) {
086        // if copy is null this is the first time we are saving the object, don't have to worry about updating collections
087        if (copy == null) {
088            return;
089        }
090        
091        List<Collection<PersistableBusinessObject>> originalCollections = orig.buildListOfDeletionAwareLists();
092
093        if (originalCollections != null && !originalCollections.isEmpty()) {
094            /*
095             * Prior to being saved, the version in the database will not yet reflect any deleted collections. So, a freshly
096             * retrieved version will contain objects that need to be removed:
097             */
098            try {
099                List<Collection<PersistableBusinessObject>> copyCollections = copy.buildListOfDeletionAwareLists();
100                int size = originalCollections.size();
101
102                if (copyCollections.size() != size) {
103                    throw new RuntimeException("size mismatch while attempting to process list of Collections to manage");
104                }
105
106                for (int i = 0; i < size; i++) {
107                    Collection<PersistableBusinessObject> origSource = originalCollections.get(i);
108                    Collection<PersistableBusinessObject> copySource = copyCollections.get(i);
109                    List<PersistableBusinessObject> list = findUnwantedElements(copySource, origSource);
110                    cleanse(template, origSource, list);
111                }
112            }
113            catch (ObjectRetrievalFailureException orfe) {
114                // object wasn't found, must be pre-save
115            }
116        }
117    }
118
119    /**
120     * This method deletes unwanted objects from the database as well as from the given input List
121     * 
122     * @param origSource - list containing unwanted business objects
123     * @param unwantedItems - business objects to be permanently removed
124     * @param template
125     */
126    private void cleanse(OjbCollectionAware template, Collection<PersistableBusinessObject> origSource, List<PersistableBusinessObject> unwantedItems) {
127        if (unwantedItems.size() > 0) {
128                for (PersistableBusinessObject unwantedItem : unwantedItems) {
129                if ( LOG.isDebugEnabled() ) {
130                        LOG.debug( "cleansing " + unwantedItem);
131                }
132                template.getPersistenceBrokerTemplate().delete(unwantedItem);
133            }
134        }
135
136    }
137
138    /**
139     * This method identifies items in the first List that are not contained in the second List. It is similar to the (optional)
140     * java.util.List retainAll method.
141     * 
142     * @param fromList
143     * @param controlList
144     * @return true iff one or more items were removed
145     */
146    private List<PersistableBusinessObject> findUnwantedElements(Collection<PersistableBusinessObject> fromList, Collection<PersistableBusinessObject> controlList) {
147        List<PersistableBusinessObject> toRemove = new ArrayList<PersistableBusinessObject>();
148
149        for (PersistableBusinessObject fromObject : fromList) {
150                if (!ObjectUtils.collectionContainsObjectWithIdentitcalKey(controlList, fromObject)) {
151                toRemove.add(fromObject);
152            }
153        }
154        return toRemove;
155    }
156}