View Javadoc
1   /**
2    * Copyright 2005-2014 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.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.datetime.DateTimeService;
20  import org.kuali.rice.krad.bo.BusinessObject;
21  import org.kuali.rice.krad.bo.InactivatableFromTo;
22  import org.kuali.rice.krad.data.KradDataServiceLocator;
23  import org.kuali.rice.krad.service.DataDictionaryService;
24  import org.kuali.rice.krad.service.InactivateableFromToService;
25  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
26  import org.kuali.rice.krad.service.LookupService;
27  import org.kuali.rice.krad.util.BeanPropertyComparator;
28  import org.kuali.rice.krad.util.KRADPropertyConstants;
29  
30  import java.util.ArrayList;
31  import java.util.Collections;
32  import java.util.Date;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * Implementation of InactivateableFromToService that uses the lookup service for query implementation
38   *
39   * @see org.kuali.rice.krad.service.InactivateableFromToService
40   */
41  public class InactivateableFromToServiceImpl implements InactivateableFromToService {
42  
43      protected DateTimeService dateTimeService;
44      protected LookupService lookupService;
45      protected DataDictionaryService dataDictionaryService;
46  
47      /**
48       * Uses lookup service which will convert the active criteria to active begin/to field criteria
49       *
50       * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingActive(java.lang.Class, java.util.Map)
51       */
52      public List<InactivatableFromTo> findMatchingActive(Class<? extends InactivatableFromTo> clazz, Map fieldValues) {
53          fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
54  
55          return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
56      }
57  
58      /**
59       * Uses lookup service which will convert the active criteria to active begin/to field criteria
60       *
61       * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingActiveAsOfDate(java.lang.Class, java.util.Map,
62       *      java.util.Date)
63       */
64      public List<InactivatableFromTo> findMatchingActiveAsOfDate(Class<? extends InactivatableFromTo> clazz,
65              Map fieldValues, Date activeAsOfDate) {
66          fieldValues.put(KRADPropertyConstants.ACTIVE, "true");
67          fieldValues.put(KRADPropertyConstants.ACTIVE_AS_OF_DATE, dateTimeService.toDateString(activeAsOfDate));
68  
69          return (List<InactivatableFromTo>) lookupService.findCollectionBySearchUnbounded(clazz, fieldValues);
70      }
71  
72      /**
73       * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonActive(java.util.List)
74       */
75      public List<InactivatableFromTo> filterOutNonActive(List<InactivatableFromTo> filterList) {
76          return filterOutNonActive(filterList, dateTimeService.getCurrentDate());
77      }
78  
79      /**
80       * @see org.kuali.rice.krad.service.InactivateableFromToService#filterOutNonActive(java.util.List, java.util.Date)
81       */
82      public List<InactivatableFromTo> filterOutNonActive(List<InactivatableFromTo> filterList, Date activeAsOfDate) {
83          List<InactivatableFromTo> filteredList = new ArrayList<InactivatableFromTo>();
84  
85          for (InactivatableFromTo inactivateable : filterList) {
86              inactivateable.setActiveAsOfDate(new java.sql.Timestamp(activeAsOfDate.getTime()));
87              if (inactivateable.isActive()) {
88                  filteredList.add(inactivateable);
89              }
90          }
91  
92          return filteredList;
93      }
94  
95      /**
96       * Uses lookup service which will convert the active and current criteria to active begin/to field criteria
97       *
98       * @see org.kuali.rice.krad.service.InactivateableFromToService#findMatchingCurrent(java.lang.Class, java.util.Map)
99       */
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 = KradDataServiceLocator.getDataObjectService().wrap(businessObject).getPropertyValueNullSafe(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 }