001 /**
002 * Copyright 2005-2012 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 */
016 package org.kuali.rice.krad.service.impl;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.core.api.datetime.DateTimeService;
020 import org.kuali.rice.krad.bo.BusinessObject;
021 import org.kuali.rice.krad.bo.InactivatableFromTo;
022 import org.kuali.rice.krad.service.DataDictionaryService;
023 import org.kuali.rice.krad.service.InactivateableFromToService;
024 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
025 import org.kuali.rice.krad.service.LookupService;
026 import org.kuali.rice.krad.util.BeanPropertyComparator;
027 import org.kuali.rice.krad.util.KRADPropertyConstants;
028 import org.kuali.rice.krad.util.ObjectUtils;
029
030 import java.util.ArrayList;
031 import java.util.Collections;
032 import java.util.Date;
033 import java.util.List;
034 import java.util.Map;
035
036 /**
037 * Implementation of InactivateableFromToService that uses the lookup service for query implementation
038 *
039 * @see org.kuali.rice.krad.service.InactivateableFromToService
040 */
041 public class InactivateableFromToServiceImpl implements InactivateableFromToService {
042
043 protected DateTimeService dateTimeService;
044 protected LookupService lookupService;
045 protected DataDictionaryService dataDictionaryService;
046
047 /**
048 * Uses lookup service which will convert the active criteria to active begin/to field criteria
049 *
050 * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingActive(java.lang.Class, java.util.Map)
051 */
052 public List<InactivatableFromTo> findMatchingActive(Class<? extends InactivatableFromTo> clazz, Map fieldValues) {
053 fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
054
055 return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
056 }
057
058 /**
059 * Uses lookup service which will convert the active criteria to active begin/to field criteria
060 *
061 * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingActiveAsOfDate(java.lang.Class, java.util.Map,
062 * java.util.Date)
063 */
064 public List<InactivatableFromTo> findMatchingActiveAsOfDate(Class<? extends InactivatableFromTo> clazz,
065 Map fieldValues, Date activeAsOfDate) {
066 fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
067 fieldValues.put(KRADPropertyConstants.ACTIVE_AS_OF_DATE, dateTimeService.toDateString(activeAsOfDate));
068
069 return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
070 }
071
072 /**
073 * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonActive(java.util.List)
074 */
075 public List<InactivatableFromTo> filterOutNonActive(List<InactivatableFromTo> filterList) {
076 return filterOutNonActive(filterList, dateTimeService.getCurrentDate());
077 }
078
079 /**
080 * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonActive(java.util.List, java.util.Date)
081 */
082 public List<InactivatableFromTo> filterOutNonActive(List<InactivatableFromTo> filterList, Date activeAsOfDate) {
083 List<InactivatableFromTo> filteredList = new ArrayList<InactivatableFromTo>();
084
085 for (InactivatableFromTo inactivateable : filterList) {
086 inactivateable.setActiveAsOfDate(new java.sql.Timestamp(activeAsOfDate.getTime()));
087 if (inactivateable.isActive()) {
088 filteredList.add(inactivateable);
089 }
090 }
091
092 return filteredList;
093 }
094
095 /**
096 * Uses lookup service which will convert the active and current criteria to active begin/to field criteria
097 *
098 * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingCurrent(java.lang.Class, java.util.Map)
099 */
100 public List<InactivatableFromTo> findMatchingCurrent(Class<? extends InactivatableFromTo> clazz,
101 Map fieldValues) {
102 fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
103 fieldValues.put(KRADPropertyConstants.CURRENT, "true");
104
105 return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
106 }
107
108 /**
109 * Uses lookup service which will convert the active and current criteria to active begin/to field criteria
110 *
111 * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingCurrent(java.lang.Class, java.util.Map, java.util.Date)
112 */
113 public List<InactivatableFromTo> findMatchingCurrent(Class<? extends InactivatableFromTo> clazz,
114 Map fieldValues, Date currentAsOfDate) {
115 fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
116 fieldValues.put(KRADPropertyConstants.CURRENT, "true");
117 fieldValues.put(KRADPropertyConstants.ACTIVE_AS_OF_DATE, dateTimeService.toDateString(currentAsOfDate));
118
119 return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
120 }
121
122 /**
123 * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonCurrent(java.util.List)
124 */
125 public List<InactivatableFromTo> filterOutNonCurrent(List<InactivatableFromTo> filterList) {
126 return filterOutNonCurrent(filterList, dateTimeService.getCurrentDate());
127 }
128
129 /**
130 * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonCurrent(java.util.List, java.util.Date)
131 */
132 public List<InactivatableFromTo> filterOutNonCurrent(List<InactivatableFromTo> filterList, Date currentAsOfDate) {
133 List<InactivatableFromTo> activeList = filterOutNonActive(filterList, currentAsOfDate);
134
135 if (activeList.isEmpty()) {
136 return activeList;
137 }
138
139 List<InactivatableFromTo> currentList = new ArrayList<InactivatableFromTo>();
140
141 List<String> groupByList = getDataDictionaryService().getGroupByAttributesForEffectiveDating(
142 activeList.get(0).getClass());
143 if (groupByList != null) {
144 List<String> sortByList = new ArrayList<String>(groupByList);
145 sortByList.add(KRADPropertyConstants.ACTIVE_FROM_DATE);
146
147 // sort list so we get records together with same group by
148 Collections.sort(activeList, new BeanPropertyComparator(sortByList, true));
149
150 // reverse so we get max active begin date first within the group by
151 Collections.reverse(activeList);
152
153 String previousGroupByString = "";
154 Date previousActiveFromDate = null;
155 for (InactivatableFromTo inactivateable : activeList) {
156 String groupByString = buildGroupByValueString((BusinessObject) inactivateable, groupByList);
157 if (!StringUtils.equals(groupByString, previousGroupByString)) {
158 // always add first record of new group by since list is sorted by active begin date descending
159 currentList.add(inactivateable);
160 }
161 // active from date should not be null here since we are dealing with only active records
162 else if (inactivateable.getActiveFromDate().equals(previousActiveFromDate)) {
163 // have more than one record for the group by key with same active begin date, so they both are current
164 currentList.add(inactivateable);
165 }
166
167 previousGroupByString = groupByString;
168 previousActiveFromDate = inactivateable.getActiveFromDate();
169 }
170 } else {
171 currentList = activeList;
172 }
173
174 return currentList;
175 }
176
177 /**
178 * Builds a string containing the values from the given business object for the fields in the given list, concatenated together using a
179 * bar. Null values are treated as an empty string
180 *
181 * @param businessObject
182 * - business object instance to get values from
183 * @param groupByList
184 * - list of fields to get values for
185 * @return String
186 */
187 protected String buildGroupByValueString(BusinessObject businessObject, List<String> groupByList) {
188 String groupByValueString = "";
189
190 for (String groupByField : groupByList) {
191 Object fieldValue = ObjectUtils.getPropertyValue(businessObject, groupByField);
192 groupByValueString += "|";
193 if (fieldValue != null) {
194 groupByValueString += fieldValue;
195 }
196 }
197
198 return groupByValueString;
199 }
200
201 public void setDateTimeService(DateTimeService dateTimeService) {
202 this.dateTimeService = dateTimeService;
203 }
204
205 public void setLookupService(LookupService lookupService) {
206 this.lookupService = lookupService;
207 }
208
209 protected DataDictionaryService getDataDictionaryService() {
210 if (dataDictionaryService == null) {
211 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
212 }
213 return dataDictionaryService;
214 }
215
216 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
217 this.dataDictionaryService = dataDictionaryService;
218 }
219 }