View Javadoc

1   /**
2    * Copyright 2004-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.hr.time.util;
17  
18  import java.sql.Time;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.Comparator;
22  import java.util.List;
23  
24  import org.joda.time.DateTime;
25  import org.joda.time.DateTimeZone;
26  import org.joda.time.Interval;
27  import org.joda.time.LocalDateTime;
28  import org.joda.time.LocalTime;
29  import org.kuali.hr.time.calendar.Calendar;
30  import org.kuali.hr.time.calendar.CalendarEntries;
31  import org.kuali.hr.time.flsa.FlsaDay;
32  import org.kuali.hr.time.flsa.FlsaWeek;
33  import org.kuali.hr.time.service.base.TkServiceLocator;
34  import org.kuali.hr.time.timeblock.TimeBlock;
35  
36  public class TkTimeBlockAggregate {
37  	public List<List<TimeBlock>> dayTimeBlockList = new ArrayList<List<TimeBlock>>();
38  	private CalendarEntries payCalendarEntry;
39  	private Calendar payCalendar;
40  
41      /**
42       * Defaults to using SYSTEM time zone.
43       *
44       * @param timeBlocks
45       * @param payCalendarEntry
46       */
47  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry){
48  		this(timeBlocks, payCalendarEntry, TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry.getHrCalendarId()));
49  	}
50  
51      /**
52       * Defaults to using SYSTEM time zone.
53       *
54       * @param timeBlocks
55       * @param payCalendarEntry
56       * @param payCalendar
57       */
58  	public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar) {
59          this(timeBlocks, payCalendarEntry, payCalendar, false);
60      }
61  
62      /**
63       * Provides the option to refer to the time zone adjusted time for the current
64       * user.
65       * @param timeBlocks
66       * @param payCalendarEntry
67       * @param payCalendar
68       * @param useUserTimeZone
69       */
70      public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone) {
71  		this.payCalendarEntry = payCalendarEntry;
72  		this.payCalendar = payCalendar;
73  
74  		List<Interval> dayIntervals = TKUtils.getDaySpanForCalendarEntry(payCalendarEntry);
75  		for(Interval dayInt : dayIntervals){
76  			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
77  			for(TimeBlock timeBlock : timeBlocks){
78  
79                  // Assumption: Timezones can only be switched at pay period end boundaries.
80                  // If the above assumption becomes false, the logic below will need to
81                  // accommodate virtual chopping of time blocks to have them fit nicely
82                  // in the "days" that are displayed to users.
83  
84  				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
85  				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
86  				if(dayInt.contains(beginTime)){
87  					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
88  						// determine if the time block needs to be pushed forward / backward
89  						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
90  							timeBlock.setPushBackward(true);
91  						}
92  
93  						dayTimeBlocks.add(timeBlock);
94  					}
95  				}
96  			}
97  			dayTimeBlockList.add(dayTimeBlocks);
98  		}
99  	}
100 
101     public TkTimeBlockAggregate(List<TimeBlock> timeBlocks, CalendarEntries payCalendarEntry, Calendar payCalendar, boolean useUserTimeZone, List<Interval> dayIntervals) {
102     	this.payCalendarEntry = payCalendarEntry;
103 		this.payCalendar = payCalendar;
104 		
105 		for(Interval dayInt : dayIntervals){
106 			List<TimeBlock> dayTimeBlocks = new ArrayList<TimeBlock>();
107 			for(TimeBlock timeBlock : timeBlocks){
108 
109                 // Assumption: Timezones can only be switched at pay period end boundaries.
110                 // If the above assumption becomes false, the logic below will need to
111                 // accommodate virtual chopping of time blocks to have them fit nicely
112                 // in the "days" that are displayed to users.
113 
114 				DateTime beginTime = useUserTimeZone ? timeBlock.getBeginTimeDisplay() : new DateTime(timeBlock.getBeginTimestamp(), TKUtils.getSystemDateTimeZone());
115 				DateTime endTime = useUserTimeZone ? timeBlock.getEndTimeDisplay() :  new DateTime(timeBlock.getEndTimestamp(), TKUtils.getSystemDateTimeZone());
116 				if(dayInt.contains(beginTime)){
117 					if(dayInt.contains(endTime) || endTime.compareTo(dayInt.getEnd()) == 0){
118 						// determine if the time block needs to be pushed forward / backward
119 						if(beginTime.getHourOfDay() < dayInt.getStart().getHourOfDay()) {
120 							timeBlock.setPushBackward(true);
121 						}
122 
123 						dayTimeBlocks.add(timeBlock);
124 					}
125 				}
126 			}
127 			dayTimeBlockList.add(dayTimeBlocks);
128 		}
129 		
130     }
131     
132     
133 	public List<TimeBlock> getFlattenedTimeBlockList(){
134 		List<TimeBlock> lstTimeBlocks = new ArrayList<TimeBlock>();
135 		for(List<TimeBlock> timeBlocks : dayTimeBlockList){
136 			lstTimeBlocks.addAll(timeBlocks);
137 		}
138 
139 		Collections.sort(lstTimeBlocks, new Comparator<TimeBlock>() { // Sort the Time Blocks
140 			public int compare(TimeBlock tb1, TimeBlock tb2) {
141 				if (tb1 != null && tb2 != null)
142 					return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
143 				return 0;
144 			}
145 		});
146 
147 		return lstTimeBlocks;
148 	}
149 
150 	/**
151 	 * Provides a way to access all of the time blocks for a given week.
152 	 *
153 	 * Outer list is 0 indexed list representing days in a week.
154 	 * Inner List are all of the time blocks for that day.
155 	 *
156 	 * Ex.
157 	 *
158 	 * List<List<TimeBlock>> week0 = getWeekTimeBlocks(0);
159 	 * List<TimeBlock> day0 = week0.get(0);
160 	 *
161 	 * @param week
162 	 * @return
163 	 */
164 	public List<List<TimeBlock>> getWeekTimeBlocks(int week){
165 		int startIndex = week*7;
166 		int endIndex = (week*7)+7;
167 		endIndex = endIndex > dayTimeBlockList.size() ? dayTimeBlockList.size() : endIndex;
168 
169         // Need to sort each day by clock time.
170         List<List<TimeBlock>> wList = dayTimeBlockList.subList(startIndex, endIndex);
171         for (List<TimeBlock> dList : wList) {
172             Collections.sort(dList, new Comparator<TimeBlock>() { // Sort the Time Blocks
173                 public int compare(TimeBlock tb1, TimeBlock tb2) {
174                     if (tb1 != null && tb2 != null)
175                         return tb1.getBeginTimestamp().compareTo(tb2.getBeginTimestamp());
176                     return 0;
177                 }
178             });
179         }
180 
181 		return wList;
182 	}
183 
184 	/**
185 	 * When consuming these weeks, you must be aware that you could be on a
186 	 * virtual day, ie noon to noon schedule and have your FLSA time start
187 	 * before the virtual day start,
188 	 * but still have a full 7 days for your week.
189      *
190      * @param zone The TimeZone to use when constructing this relative sorting.
191 	 */
192 	public List<FlsaWeek> getFlsaWeeks(DateTimeZone zone){
193 		int flsaDayConstant = payCalendar.getFlsaBeginDayConstant();
194 		Time flsaBeginTime  = payCalendar.getFlsaBeginTime();
195 
196 		// We can use these to build our interval, we have to make sure we
197 		// place them on the proper day when we construct it.
198 		LocalTime flsaBeginLocalTime = LocalTime.fromDateFields(flsaBeginTime);
199 
200 		// Defines both the start date and the start virtual time.
201 		// We will add 1 day to this to move over all days.
202 		//
203 		// FLSA time is set.  This is an FLSA start date.
204         LocalDateTime startLDT = payCalendarEntry.getBeginLocalDateTime();
205 //		DateTime startDate = new DateTime(payCalendarEntry.getBeginPeriodDateTime());
206 //		startDate = startDate.toLocalDate().toDateTime(flsaBeginLocalTime,TKUtils.getSystemDateTimeZone());
207 
208 		List<FlsaWeek> flsaWeeks = new ArrayList<FlsaWeek>();
209 		List<TimeBlock> flatSortedBlockList = getFlattenedTimeBlockList();
210 		FlsaWeek currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, LocalTime.fromDateFields(payCalendarEntry.getBeginPeriodDateTime()));
211 //		commented additional week addition, as causing an extra day on UI
212 		flsaWeeks.add(currentWeek);
213 
214 		for (int i = 0; i<dayTimeBlockList.size(); i++) {
215 			LocalDateTime currentDate = startLDT.plusDays(i);
216 			FlsaDay flsaDay = new FlsaDay(currentDate, flatSortedBlockList, zone);
217 
218 			if (currentDate.getDayOfWeek() == flsaDayConstant) {
219 				currentWeek = new FlsaWeek(flsaDayConstant, flsaBeginLocalTime, flsaBeginLocalTime);
220 				flsaWeeks.add(currentWeek);
221 				
222 				currentWeek.addFlsaDay(flsaDay);
223 			} else {
224 				// add to existing week.
225 				currentWeek.addFlsaDay(flsaDay);
226 			}
227 		}
228 
229 		return flsaWeeks;
230 	}
231 
232 	/**
233 	 * @return the total number of weeks that this object represents.
234 	 */
235 	public int numberOfAggregatedWeeks() {
236 		int weeks = 0;
237 
238 		if (this.dayTimeBlockList.size() > 0) {
239 			weeks = this.dayTimeBlockList.size() / 7;
240 			if (this.dayTimeBlockList.size() % 7 > 0)
241 				weeks++;
242 		}
243 
244 		return weeks;
245 	}
246 
247 	public List<List<TimeBlock>> getDayTimeBlockList() {
248 		return dayTimeBlockList;
249 	}
250 
251 	public CalendarEntries getPayCalendarEntry() {
252 		return payCalendarEntry;
253 	}
254 
255 	public void setPayCalendarEntry(CalendarEntries payCalendarEntry) {
256 		this.payCalendarEntry = payCalendarEntry;
257 	}
258 
259 	public Calendar getPayCalendar() {
260 		return payCalendar;
261 	}
262 
263 	public void setPayCalendar(Calendar payCalendar) {
264 		this.payCalendar = payCalendar;
265 	}
266 
267 }