001 /** 002 * Copyright 2005-2013 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 }