001    /**
002     * Copyright 2004-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.hr.time.calendar;
017    
018    import java.sql.Date;
019    import java.util.*;
020    
021    import edu.emory.mathcs.backport.java.util.Arrays;
022    import org.apache.commons.collections.CollectionUtils;
023    import org.apache.commons.lang.time.DateUtils;
024    import org.joda.time.DateTime;
025    import org.joda.time.DateTimeConstants;
026    import org.joda.time.LocalDate;
027    import org.kuali.hr.lm.leaveblock.LeaveBlock;
028    import org.kuali.hr.time.service.base.TkServiceLocator;
029    import org.kuali.hr.time.util.TKContext;
030    import org.kuali.hr.time.util.TKUser;
031    import org.kuali.hr.time.util.TKUtils;
032    import org.kuali.hr.time.util.TkConstants;
033    import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
034    
035    import com.google.common.collect.HashMultimap;
036    import com.google.common.collect.Multimap;
037    
038    public class LeaveCalendar extends CalendarParent {
039    
040        private Map<String, String> earnCodeList;
041        
042        public LeaveCalendar(String principalId, CalendarEntries calendarEntry, List<String> assignmentKeys) {
043            super(calendarEntry);
044    
045            DateTime currentDisplayDateTime = getBeginDateTime();
046            DateTime endDisplayDateTime = getEndDateTime();
047    
048            // Fill in the days if the first day or end day is in the middle of the week
049            if (currentDisplayDateTime.getDayOfWeek() != DateTimeConstants.SUNDAY) {
050                currentDisplayDateTime = currentDisplayDateTime.minusDays(currentDisplayDateTime.getDayOfWeek());
051            }
052            if (endDisplayDateTime.getDayOfWeek() != DateTimeConstants.SATURDAY) {
053                endDisplayDateTime = endDisplayDateTime.plusDays(DateTimeConstants.SATURDAY - endDisplayDateTime.getDayOfWeek());
054            }
055    
056            LeaveCalendarWeek leaveCalendarWeek = new LeaveCalendarWeek();
057            Integer dayNumber = 0;
058            List<LeaveBlock> blocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate());
059            Map<String, List<LeaveBlock>> leaveBlockMap = new HashMap<String, List<LeaveBlock>>();
060            for (LeaveBlock lb : blocks) {
061                String key = new LocalDate(lb.getLeaveDate()).toString();
062                if (leaveBlockMap.containsKey(key)) {
063                    leaveBlockMap.get(key).add(lb);
064                } else {
065                    leaveBlockMap.put(key, createNewLeaveBlockList(lb));
066                }
067            }
068    
069            while (currentDisplayDateTime.isBefore(endDisplayDateTime) || currentDisplayDateTime.isEqual(endDisplayDateTime)) {
070                LeaveCalendarDay leaveCalendarDay = new LeaveCalendarDay();
071                
072                // If the day is not within the current pay period, mark them as read only (gray)
073                if (currentDisplayDateTime.isBefore(getBeginDateTime()) 
074                            || currentDisplayDateTime.isEqual(getEndDateTime()) 
075                            || currentDisplayDateTime.isAfter(getEndDateTime())) {
076                    leaveCalendarDay.setGray(true);
077                } else {
078                    // This is for the div id of the days on the calendar.
079                    // It creates a day id like day_11/01/2011 which will make day parsing easier in the javascript.
080    //                leaveCalendarDay.setDayNumberDelta(currDateTime.toString(TkConstants.DT_BASIC_DATE_FORMAT));
081    //                leaveCalendarDay.setDayNumberDelta(currDateTime.getDayOfMonth());
082                    leaveCalendarDay.setDayNumberDelta(dayNumber);
083        
084                   java.util.Date leaveDate = TKUtils.getTimelessDate(currentDisplayDateTime.toLocalDate().toDateMidnight().toDate());
085                   List<LeaveBlock> lbs = leaveBlockMap.get(currentDisplayDateTime.toLocalDate().toString());
086                   if (lbs == null) {
087                       lbs = Collections.emptyList();
088                   }
089                   // use given assignmentKeys to control leave blocks displayed on the calendar
090                   if(CollectionUtils.isNotEmpty(lbs) && CollectionUtils.isNotEmpty(assignmentKeys)) {
091                       List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().filterLeaveBlocksForLeaveCalendar(lbs, assignmentKeys);
092                       leaveCalendarDay.setLeaveBlocks(leaveBlocks);
093                   } else {
094                       leaveCalendarDay.setLeaveBlocks(lbs);
095                   }
096                   
097                   if (TkServiceLocator.getPermissionsService().canViewLeaveTabsWithNEStatus()) {
098                           TimesheetDocumentHeader tdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeaderForDate(principalId, leaveDate);
099                           if (tdh != null) {
100                               if (DateUtils.isSameDay(leaveDate, tdh.getEndDate()) || leaveDate.after(tdh.getEndDate())) {
101                                       leaveCalendarDay.setDayEditable(true);
102                               }
103                           } else {
104                               leaveCalendarDay.setDayEditable(true);
105                           }
106                   } else {
107                       leaveCalendarDay.setDayEditable(true);
108                   }
109                   
110                   dayNumber++;
111                }
112                leaveCalendarDay.setDayNumberString(currentDisplayDateTime.dayOfMonth().getAsShortText());
113                leaveCalendarDay.setDateString(currentDisplayDateTime.toString(TkConstants.DT_BASIC_DATE_FORMAT));
114    
115                leaveCalendarWeek.getDays().add(leaveCalendarDay);
116                
117                if (leaveCalendarWeek.getDays().size() == DateTimeConstants.DAYS_PER_WEEK) {
118                    getWeeks().add(leaveCalendarWeek);
119                    leaveCalendarWeek = new LeaveCalendarWeek();
120                }
121    
122                currentDisplayDateTime = currentDisplayDateTime.plusDays(1);
123            }
124    
125            if (!leaveCalendarWeek.getDays().isEmpty()) {
126                getWeeks().add(leaveCalendarWeek);
127            }
128    
129            boolean isPlanningCal = TkServiceLocator.getLeaveCalendarService().isLeavePlanningCalendar(principalId, calendarEntry.getBeginPeriodDateTime(), calendarEntry.getEndPeriodDateTime());
130            Map<String, String> earnCodes = TkServiceLocator.getEarnCodeService().getEarnCodesForDisplay(principalId, isPlanningCal);
131            setEarnCodeList(earnCodes);
132        }
133    
134        private List<LeaveBlock> createNewLeaveBlockList(LeaveBlock lb){
135            List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
136            leaveBlocks.add(lb);
137            return leaveBlocks;
138        }
139        
140        private Multimap<Date, LeaveBlock> leaveBlockAggregator(String documentId) {
141            List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForDocumentId(documentId);
142            Multimap<Date, LeaveBlock> leaveBlockAggregrate = HashMultimap.create();
143            for (LeaveBlock leaveBlock : leaveBlocks) {
144                leaveBlockAggregrate.put(leaveBlock.getLeaveDate(), leaveBlock);
145            }
146    
147            return leaveBlockAggregrate;
148        }
149    
150            public Map<String, String> getEarnCodeList() {
151                    return earnCodeList;
152            }
153    
154            public void setEarnCodeList(Map<String, String> earnCodeList) {
155                    this.earnCodeList = earnCodeList;
156            }
157    }