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 org.joda.time.DateTime;
019    import org.kuali.hr.lm.leaveblock.LeaveBlock;
020    import org.kuali.hr.lm.util.LeaveBlockAggregate;
021    import org.kuali.hr.time.earncode.EarnCode;
022    import org.kuali.hr.time.service.base.TkServiceLocator;
023    import org.kuali.hr.time.timeblock.TimeBlock;
024    import org.kuali.hr.time.util.TkConstants;
025    import org.kuali.hr.time.util.TkTimeBlockAggregate;
026    
027    import java.util.ArrayList;
028    import java.util.List;
029    import java.util.Map;
030    
031    public class TkCalendar extends CalendarParent {
032        private CalendarEntries payCalEntry;
033        private DateTime beginDateTime;
034        private DateTime endDateTime;
035    
036        public TkCalendar() {}
037    
038        public TkCalendar(CalendarEntries calendarEntry) {
039            super(calendarEntry);
040        }
041    
042        public static TkCalendar getCalendar(TkTimeBlockAggregate tbAggregate, LeaveBlockAggregate lbAggregate) {
043            TkCalendar tc = new TkCalendar();
044             
045            if (tbAggregate != null && lbAggregate != null) {
046                    if(tbAggregate.getDayTimeBlockList().size() != lbAggregate.getDayLeaveBlockList().size()){
047                            throw new RuntimeException("TimeBlockAggregate and LeaveBlockAggregate should have the same size of Day Blocks List");
048                    }
049                            
050                    List<CalendarWeek> weeks = new ArrayList<CalendarWeek>();
051                    tc.setPayCalEntry(tbAggregate.getPayCalendarEntry());
052            
053                     int firstDay = 0;
054                     if (tc.getBeginDateTime().getDayOfWeek() != 7) {
055                         firstDay = 0 - tc.getBeginDateTime().getDayOfWeek();   // always render calendar weeks from Sundays
056                     }
057                     for (int i = 0; i < tbAggregate.numberOfAggregatedWeeks(); i++) {
058                         TkCalendarWeek week = new TkCalendarWeek();
059                         List<List<TimeBlock>> weekBlocks = tbAggregate.getWeekTimeBlocks(i);
060                         List<List<LeaveBlock>> weekLeaveBlocks = lbAggregate.getWeekLeaveBlocks(i);
061                         List<CalendarDay> days = new ArrayList<CalendarDay>(7);
062            
063                         for (int j = 0; j < weekBlocks.size(); j++) {
064                             List<TimeBlock> dayBlocks = weekBlocks.get(j);
065                             List<LeaveBlock> dayLeaveBlocks = weekLeaveBlocks.get(j);
066                             // Create the individual days.
067                             TkCalendarDay day = new TkCalendarDay();
068                             day.setTimeblocks(dayBlocks);
069                             day.setLeaveBlocks(dayLeaveBlocks);
070                             day.setDayNumberString(tc.getDayNumberString(i * 7 + j + firstDay));
071                             day.setDayNumberDelta(i * 7 + j + firstDay);
072                             day.setDateString(tc.getDateString(day.getDayNumberDelta()));
073                             assignDayLunchLabel(day);
074                             int dayIndex = i * 7 + j + firstDay;
075                             DateTime beginDateTemp = tc.getBeginDateTime().plusDays(dayIndex);
076                             day.setGray(false);
077                             if (beginDateTemp.isBefore(tc.getBeginDateTime().getMillis())
078                                     || beginDateTemp.isAfter(tc.getEndDateTime().getMillis())) {
079                                 day.setGray(true);
080                             }
081                             if (tc.getEndDateTime().getHourOfDay() == 0 && beginDateTemp.equals(tc.getEndDateTime())) {
082                                 day.setGray(true);
083                             }
084                             days.add(day);
085                         }
086                         week.setDays(days);
087                         weeks.add(week);
088                     }
089                     tc.setWeeks(weeks);
090                 } else {
091                     return null;
092                 }
093    
094            return tc;
095        }
096        
097        public static TkCalendar getCalendar(TkTimeBlockAggregate aggregate) {
098            TkCalendar tc = new TkCalendar();
099    
100            if (aggregate != null) {
101                List<CalendarWeek> weeks = new ArrayList<CalendarWeek>();
102                tc.setPayCalEntry(aggregate.getPayCalendarEntry());
103    
104                int firstDay = 0;
105                if (tc.getBeginDateTime().getDayOfWeek() != 7) {
106                    firstDay = 0 - tc.getBeginDateTime().getDayOfWeek();   // always render calendar weeks from Sundays
107                }
108                for (int i = 0; i < aggregate.numberOfAggregatedWeeks(); i++) {
109                    TkCalendarWeek week = new TkCalendarWeek();
110                    List<List<TimeBlock>> weekBlocks = aggregate.getWeekTimeBlocks(i);
111                    List<CalendarDay> days = new ArrayList<CalendarDay>(7);
112    
113                    for (int j = 0; j < weekBlocks.size(); j++) {
114                        List<TimeBlock> dayBlocks = weekBlocks.get(j);
115                        // Create the individual days.
116                        TkCalendarDay day = new TkCalendarDay();
117                        day.setTimeblocks(dayBlocks);
118                        day.setDayNumberString(tc.getDayNumberString(i * 7 + j + firstDay));
119                        day.setDayNumberDelta(i * 7 + j + firstDay);
120                        day.setDateString(tc.getDateString(day.getDayNumberDelta()));
121                        assignDayLunchLabel(day);
122                        int dayIndex = i * 7 + j + firstDay;
123                        DateTime beginDateTemp = tc.getBeginDateTime().plusDays(dayIndex);
124                        day.setGray(false);
125                        if (beginDateTemp.isBefore(tc.getBeginDateTime().getMillis())
126                                || beginDateTemp.isAfter(tc.getEndDateTime().getMillis())) {
127                            day.setGray(true);
128                        }
129                        if (tc.getEndDateTime().getHourOfDay() == 0 && beginDateTemp.equals(tc.getEndDateTime())) {
130                            day.setGray(true);
131                        }
132                        days.add(day);
133                    }
134                    week.setDays(days);
135                    weeks.add(week);
136                }
137                tc.setWeeks(weeks);
138            } else {
139                return null;
140            }
141    
142            return tc;
143        }
144    
145        public static void assignDayLunchLabel(TkCalendarDay day) {
146            EarnCode ec = null;
147            String label = "";
148            String id = "";
149            for (TimeBlockRenderer tbr : day.getBlockRenderers()) {
150                for (TimeHourDetailRenderer thdr : tbr.getDetailRenderers()) {
151                    if (thdr.getTitle().equals(TkConstants.LUNCH_EARN_CODE)) {
152                        ec = TkServiceLocator.getEarnCodeService().getEarnCode(thdr.getTitle(), tbr.getTimeBlock().getBeginDate());
153                        if (ec != null) {
154                            label = ec.getDescription() + " : " + thdr.getHours() + " hours";
155                            id = thdr.getTkTimeHourDetailId();
156                        }
157                    }
158                }
159                tbr.setLunchLabel(label);
160                tbr.setLunchLabelId(id);
161    
162                label = "";
163            }
164        }
165    
166        
167        public void assignAssignmentStyle(Map<String, String> styleMap) {
168            for (CalendarWeek aWeek : this.getWeeks()) {
169                for (CalendarDay aDay : aWeek.getDays()) {
170                    for (TimeBlockRenderer tbr : ((TkCalendarDay)aDay).getBlockRenderers()) {
171                        String assignmentKey = tbr.getTimeBlock().getAssignmentKey();
172                        if (assignmentKey != null && styleMap.containsKey(assignmentKey)) {
173                            tbr.setAssignmentClass(styleMap.get(assignmentKey));
174                        } else {
175                            tbr.setAssignmentClass("");
176                        }
177                    }
178                    for (LeaveBlockRenderer lbr : ((TkCalendarDay)aDay).getLeaveBlockRenderers()) {
179                        String assignmentKey = lbr.getLeaveBlock().getAssignmentKey();
180                        if (assignmentKey != null && styleMap.containsKey(assignmentKey)) {
181                            lbr.setAssignmentClass(styleMap.get(assignmentKey));
182                        } else {
183                            lbr.setAssignmentClass("");
184                        }
185                    } 
186                    
187                }
188            }
189        }
190    
191        public CalendarEntries getPayCalEntry() {
192            return payCalEntry;
193        }
194    
195        public void setPayCalEntry(CalendarEntries payCalEntry) {
196            this.payCalEntry = payCalEntry;
197            // Relative time, with time zone added.
198            this.beginDateTime = payCalEntry.getBeginLocalDateTime().toDateTime(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
199            this.endDateTime = payCalEntry.getEndLocalDateTime().toDateTime(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback());
200        }
201    
202        public DateTime getBeginDateTime() {
203            return beginDateTime;
204        }
205    
206        public DateTime getEndDateTime() {
207            return endDateTime;
208        }
209    
210        /**
211         * Provides the calendar title / heading. If the Pay Calendar entry spans
212         * multiple months, you get Abbreviated Month name + year of both the
213         * beginning month and the ending month.
214         *
215         * @return String for calendar title use.
216         */
217        public String getCalendarTitle() {
218            StringBuilder sb = new StringBuilder();
219    
220            if (getBeginDateTime().getMonthOfYear() == getEndDateTime().getMonthOfYear() ||
221                    (getBeginDateTime().getMonthOfYear() != getEndDateTime().getMonthOfYear()
222                            && getEndDateTime().getDayOfMonth() == 1 && getEndDateTime().getSecondOfDay() == 0)) {
223                sb.append(getBeginDateTime().toString("MMMM y"));
224            } else {
225                sb.append(getBeginDateTime().toString("MMM y"));
226                sb.append(" - ");
227                sb.append(getEndDateTime().toString("MMM y"));
228            }
229    
230            return sb.toString();
231        }
232    
233        /**
234         * Assumption of 7 "days" per week, or 7 "blocks" per row.
235         *
236         * @return A list of string titles for each row block (day)
237         */
238        public List<String> getCalendarDayHeadings() {
239            List<String> dayStrings = new ArrayList<String>(7);
240            // always render from Sunday
241            int firstDay = 0 - getBeginDateTime().getDayOfWeek();
242            int lastDay = firstDay + 7;
243    
244            if (getBeginDateTime().getMinuteOfDay() == 0) {
245                // "Standard" days.
246                for (int i = firstDay; i < lastDay; i++) {
247                    DateTime currDay = getBeginDateTime().plusDays(i);
248                    dayStrings.add(currDay.toString("E"));
249                }
250            } else {
251                // Day Split Strings
252    
253                for (int i = firstDay; i < lastDay; i++) {
254                    StringBuilder builder = new StringBuilder("");
255                    DateTime currStart = getBeginDateTime().plusDays(i);
256                    DateTime currEnd = getBeginDateTime().plusDays(i);
257    
258                    builder.append(currStart.toString("E HH:mm"));
259                    builder.append(" - ");
260                    builder.append(currEnd.toString("E HH:mm"));
261    
262                    dayStrings.add(builder.toString());
263                }
264            }
265    
266            return dayStrings;
267        }
268    
269        public String getCalenadrYear() {
270            return getBeginDateTime().toString("yyyy");
271        }
272    
273        public String getCalendarMonth() {
274            return getBeginDateTime().toString("M");
275        }
276    
277        private String getDayNumberString(int dayDelta) {
278            StringBuilder b = new StringBuilder();
279    
280            if (getBeginDateTime().getMinuteOfDay() == 0) {
281                DateTime currStart = getBeginDateTime().plusDays(dayDelta);
282                b.append(currStart.toString("d"));
283            } else {
284                DateTime currStart = getBeginDateTime().plusDays(dayDelta);
285                DateTime currEnd = getBeginDateTime().plusDays(dayDelta);
286    
287                b.append(currStart.toString("d HH:mm"));
288                b.append(" - ");
289                //TODO: should this be currEnd???
290                b.append(currStart.toString("d HH:mm"));
291            }
292    
293            return b.toString();
294        }
295    
296        private String getDateString(int dayDelta) {
297            return getBeginDateTime().plusDays(dayDelta).toString("M/d/yyyy");
298        }
299    
300    }