View Javadoc

1   /**
2    * Copyright 2012 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * Created by Daniel on 3/28/12
16   */
17  package org.kuali.student.enrollment.class2.appointment.service.impl;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.criteria.Predicate;
21  import org.kuali.rice.core.api.criteria.PredicateFactory;
22  import org.kuali.rice.core.api.criteria.QueryByCriteria;
23  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
24  import org.kuali.rice.krad.uif.container.CollectionGroup;
25  import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
26  import org.kuali.rice.krad.uif.view.View;
27  import org.kuali.rice.krad.util.GlobalVariables;
28  import org.kuali.rice.krad.util.KRADConstants;
29  import org.kuali.student.enrollment.class2.acal.util.CommonUtils;
30  import org.kuali.student.enrollment.class2.appointment.dto.AppointmentWindowWrapper;
31  import org.kuali.student.enrollment.class2.appointment.form.RegistrationWindowsManagementForm;
32  import org.kuali.student.enrollment.class2.appointment.service.AppointmentViewHelperService;
33  import org.kuali.student.enrollment.class2.appointment.util.AppointmentConstants;
34  import org.kuali.student.enrollment.class2.appointment.util.AppointmentSlotRuleTypeConversion;
35  import org.kuali.student.enrollment.class2.population.util.PopulationConstants;
36  import org.kuali.student.mock.utilities.TestHelper;
37  import org.kuali.student.r2.common.dto.ContextInfo;
38  import org.kuali.student.r2.common.dto.LocaleInfo;
39  import org.kuali.student.r2.common.exceptions.DataValidationErrorException;
40  import org.kuali.student.r2.common.exceptions.DoesNotExistException;
41  import org.kuali.student.r2.common.exceptions.InvalidParameterException;
42  import org.kuali.student.r2.common.exceptions.MissingParameterException;
43  import org.kuali.student.r2.common.exceptions.OperationFailedException;
44  import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
45  import org.kuali.student.r2.common.exceptions.ReadOnlyException;
46  import org.kuali.student.r2.common.exceptions.VersionMismatchException;
47  import org.kuali.student.r2.common.util.date.DateFormatters;
48  import org.kuali.student.r2.core.acal.dto.KeyDateInfo;
49  import org.kuali.student.r2.core.acal.dto.TermInfo;
50  import org.kuali.student.r2.core.acal.service.AcademicCalendarService;
51  import org.kuali.student.r2.core.appointment.constants.AppointmentServiceConstants;
52  import org.kuali.student.r2.core.appointment.dto.AppointmentWindowInfo;
53  import org.kuali.student.r2.core.appointment.service.AppointmentService;
54  import org.kuali.student.r2.core.class1.type.dto.TypeTypeRelationInfo;
55  import org.kuali.student.r2.core.class1.type.service.TypeService;
56  import org.kuali.student.r2.core.constants.AcademicCalendarServiceConstants;
57  import org.kuali.student.r2.core.constants.PopulationServiceConstants;
58  import org.kuali.student.r2.core.constants.TypeServiceConstants;
59  import org.kuali.student.r2.core.population.dto.PopulationInfo;
60  import org.kuali.student.r2.core.population.service.PopulationService;
61  
62  import javax.xml.namespace.QName;
63  import java.util.ArrayList;
64  import java.util.Date;
65  import java.util.HashMap;
66  import java.util.List;
67  import java.util.Locale;
68  import java.util.Map;
69  
70  /**
71   * This class //TODO ...
72   *
73   * @author Kuali Student Team
74   */
75  public class AppointmentViewHelperServiceImpl extends ViewHelperServiceImpl implements AppointmentViewHelperService {
76      private static final long serialVersionUID = 1L;
77      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AppointmentViewHelperServiceImpl.class);
78  
79      private transient AcademicCalendarService academicCalendarService;
80      private transient TypeService typeService;
81      private transient AppointmentService appointmentService;
82      private transient PopulationService populationService;
83  
84      @Override
85      public void searchForTerm(String typeKey, String year, RegistrationWindowsManagementForm form) throws Exception {
86  
87          //Parse the year to a date and the next year's date to compare against the startTerm
88          Date minBoundDate = DateFormatters.DEFULT_YEAR_FORMATTER.parse(year);
89          Date maxBoundDate = DateFormatters.DEFULT_YEAR_FORMATTER.parse(Integer.toString(Integer.parseInt(year) + 1));
90  
91          //Build up a term search criteria
92          QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
93          qbcBuilder.setPredicates(PredicateFactory.and(
94                  PredicateFactory.equal("atpType", typeKey),
95                  PredicateFactory.greaterThanOrEqual("startDate", minBoundDate),
96                  PredicateFactory.lessThan("startDate", maxBoundDate)));
97  
98          QueryByCriteria criteria = qbcBuilder.build();
99  
100         //Perform Term Search with Service Call
101         AcademicCalendarService academicCalendarService = getAcalService();
102         List<TermInfo> terms = academicCalendarService.searchForTerms(criteria, null);
103 
104         //Check for exceptions
105         if (terms == null || terms.isEmpty()) {
106             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_TERMS_FOUND);
107             return; //Nothing found
108         }
109 
110         if (terms.size() > 1) {
111             LOG.error("Too many terms!");
112         }
113 
114         TermInfo term = terms.get(0);
115 
116         //Populate the result form
117         form.setTermInfo(term);
118 
119         //Get the milestones and filter out anything that is not registration period
120         List<KeyDateInfo> keyDates = academicCalendarService.getKeyDatesForTerm(term.getId(), null);
121         if (keyDates != null) {
122 
123             //Get the valid period types
124             List<TypeTypeRelationInfo> milestoneTypeRelations = getTypeService().getTypeTypeRelationsByOwnerAndType("kuali.milestone.type.group.appt.regperiods", "kuali.type.type.relation.type.group", new ContextInfo());
125             List<String> validMilestoneTypes = new ArrayList<String>();
126             for (TypeTypeRelationInfo milestoneTypeRelation : milestoneTypeRelations) {
127                 validMilestoneTypes.add(milestoneTypeRelation.getRelatedTypeKey());
128             }
129 
130             //Add in only valid milestones that are registration periods
131             List<KeyDateInfo> periodMilestones = new ArrayList<KeyDateInfo>();
132             for (KeyDateInfo keyDate : keyDates) {
133                 if (validMilestoneTypes.contains(keyDate.getTypeKey())) {
134                     periodMilestones.add(keyDate);
135                 }
136             }
137             form.setPeriodMilestones(periodMilestones);
138 
139         }
140 
141         //Check if there are no periods (might want to handle this somewhere else and surface to the user)
142         if (form.getPeriodMilestones() == null || form.getPeriodMilestones().isEmpty()) {
143             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
144             //GlobalVariables.getMessageMap().putErrorForSectionId("KS-RegistrationWindowsManagement-SelectTermPage", AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
145             //GlobalVariables.getMessageMap().putError("termType", AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
146         }
147 
148     }
149 
150     public void loadTermAndPeriods(String termId, RegistrationWindowsManagementForm form) throws Exception {
151         ContextInfo context = TestHelper.getContext1();
152         TermInfo term = getAcalService().getTerm(termId, context);
153 
154         if (term.getId() != null && !term.getId().isEmpty()) {
155             form.setTermInfo(term);
156             loadPeriods(termId, form);
157         }
158 
159     }
160 
161     public void loadPeriods(String termId, RegistrationWindowsManagementForm form) throws Exception {
162         ContextInfo context = TestHelper.getContext1();
163         List<KeyDateInfo> periodMilestones = new ArrayList<KeyDateInfo>();
164         List<KeyDateInfo> keyDateInfoList = getAcalService().getKeyDatesForTerm(termId, context);
165         List<TypeTypeRelationInfo> relations = getTypeService().getTypeTypeRelationsByOwnerAndType("kuali.milestone.type.group.appt.regperiods", "kuali.type.type.relation.type.group", context);
166         for (KeyDateInfo keyDateInfo : keyDateInfoList) {
167             for (TypeTypeRelationInfo relationInfo : relations) {
168                 String relatedTypeKey = relationInfo.getRelatedTypeKey();
169                 if (keyDateInfo.getTypeKey().equals(relatedTypeKey)) {
170                     periodMilestones.add(keyDateInfo);
171                     break;
172                 }
173             }
174         }
175 
176         form.setPeriodMilestones(periodMilestones);
177     }
178 
179     public boolean validateApptWidnow(AppointmentWindowWrapper apptWindow) {
180         return validateApptWidnow(apptWindow, true);
181     }
182 
183     public boolean validateApptWidnow(AppointmentWindowWrapper apptWindow, boolean validateForUniqueness) {
184         boolean isValid = true;
185         //  1) a window end date is not required for a One-Slot or Max Number Slot Allocation Method/Window Type
186         //  2) a window end date is required for uniform
187         String windowTypeKey = apptWindow.getWindowTypeKey();
188 
189         // Check to make sure the Window name is not duplicated with in the period
190         if (validateForUniqueness) {
191             try {
192                 QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
193                 qbcBuilder.setPredicates(PredicateFactory.and(PredicateFactory.equal("periodMilestoneId", apptWindow.getPeriodKey()), PredicateFactory.equal("name", apptWindow.getWindowName())));
194                 QueryByCriteria criteria = qbcBuilder.build();
195                 if (getAppointmentService().searchForAppointmentWindows(criteria, new ContextInfo()).size() > 0) {
196                     GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].appointmentWindowInfo.name",
197                             AppointmentConstants.APPOINTMENT_MSG_ERROR_DUPLICATE_WINDOW_FOR_PERIOD);
198                     isValid = false;
199                 }
200             } catch (Exception e) {
201                 throw new RuntimeException("Failed to search appointment windows by criteria", e);
202             }
203         }
204 
205         if (AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_SLOTTED_UNIFORM_KEY.equals(windowTypeKey)) {
206             if (apptWindow.getEndDate() == null) {
207                 GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endDate",
208                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_REQUIRED_FOR_UNIFORM);
209                 isValid = false;
210             }
211             if (apptWindow.getEndTime() == null) {
212                 GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endTime",
213                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
214                 isValid = false;
215             }
216             if (apptWindow.getEndTime().isEmpty()) {
217                 GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endTimeAmPm",
218                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
219                 isValid = false;
220             }
221         }
222 
223 
224         if (apptWindow.getStartDate() == null || StringUtils.isEmpty(apptWindow.getStartTime()) || StringUtils.isEmpty(apptWindow.getStartTimeAmPm())) {
225             if (apptWindow.getStartDate() == null) {
226                 GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].startDate",
227                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_REQUIRED_FIELD);
228             } else if (apptWindow.getStartDate() == null) {
229                 GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].startTime",
230                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_REQUIRED_FIELD);
231             } else {
232                 GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].startTimeAmPm",
233                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_AM_PM_REQUIRED_FIELD);
234             }
235             isValid = false;
236         } else {
237             // 4) when end date is not null, start/end date should be in the date range of the selected period
238             // Aslo check to make sure the end date is not before the start date
239             String periodId = apptWindow.getPeriodKey();
240             try {
241                 KeyDateInfo period = getAcalService().getKeyDate(periodId, getContextInfo());
242                 Date periodStartDate = DateFormatters.DEFAULT_DATE_FORMATTER.parse(DateFormatters.DEFAULT_DATE_FORMATTER.format(period.getStartDate()));
243                 Date periodEndDate = DateFormatters.DEFAULT_DATE_FORMATTER.parse(DateFormatters.DEFAULT_DATE_FORMATTER.format(period.getEndDate()));
244 
245                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().before(apptWindow.getStartDate())) {
246                     GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].endDate",
247                             AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_IS_BEFORE_START_DATE);
248                     isValid = false;
249                 }
250                 if (periodStartDate.after(apptWindow.getStartDate()) || periodEndDate.before(apptWindow.getStartDate())) {
251                     GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].startDate",
252                             AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_OUT_OF_RANGE);
253                     isValid = false;
254                 }
255                 if (apptWindow.getEndDate() != null && !apptWindow.getEndDate().toString().isEmpty()) {
256                     if (periodStartDate.after(apptWindow.getEndDate()) || periodEndDate.before(apptWindow.getEndDate())) {
257                         GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endDate",
258                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_OUT_OF_RANGE);
259                         isValid = false;
260                     }
261                 }
262 
263                 // 5) when end date is not null, end time cannot be before the start time
264                 //if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm())) {
265                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && ((apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm()) || (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) ))) {
266                     Date start = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getStartTime());
267                     Date end = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getEndTime());
268                     if (end.before(start)) {
269                         GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].endTime",
270                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_BEFORE_START_TIME);
271                         isValid = false;
272                     }
273 
274                     // 6) when end date is not null, end time AM-PM cannot be before the start time
275                     if (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) {
276                         GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endTimeAmPm",
277                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_AM_PM_BEFORE_START_TIME_AM_PM);
278                         isValid = false;
279                     }
280                 }
281             } catch (Exception e) {
282                 LOG.error("Fail to find periods for a selected term.", e);
283                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
284                 isValid = false;
285             }
286         }
287 
288         try {
289             Map<String, String> fieldValues = new HashMap<String, String>();
290             fieldValues.put("name", apptWindow.getAssignedPopulationName());
291             QueryByCriteria qbc = buildQueryByCriteria(fieldValues);
292             List<PopulationInfo> populationInfoList = getPopulationService().searchForPopulations(qbc, getContextInfo());
293 
294             if (populationInfoList == null || populationInfoList.isEmpty()) {
295                 GlobalVariables.getMessageMap().putErrorForSectionId("addRegistrationWindowCollection", PopulationConstants.POPULATION_MSG_ERROR_POPULATION_NOT_FOUND, apptWindow.getAssignedPopulationName());
296                 isValid = false;
297             } else {
298                 apptWindow.setAssignedPopulationName(populationInfoList.get(0).getName());
299                 apptWindow.getAppointmentWindowInfo().setAssignedPopulationId(populationInfoList.get(0).getId());
300             }
301 
302         } catch (Exception e) {
303             throw new RuntimeException(e);
304         }
305 
306         return isValid;
307     }
308 
309     public boolean validateApptWidnow(AppointmentWindowWrapper apptWindow, int windowIndex) {
310         boolean isValid = true;
311         //  1) a window end date is not required for a One-Slot or Max Number Slot Allocation Method/Window Type
312         //  2) a window end date is required for uniform
313         String windowTypeKey = apptWindow.getWindowTypeKey();
314 
315         if (AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_SLOTTED_UNIFORM_KEY.equals(windowTypeKey)) {
316             if (apptWindow.getEndDate() == null) {
317                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
318                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_REQUIRED_FOR_UNIFORM);
319                 isValid = false;
320             }
321             if (apptWindow.getEndTime() == null) {
322                 GlobalVariables.getMessageMap().putError("appointmentWindows[windowIndex].endTime",
323                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
324                 isValid = false;
325             }
326             if (apptWindow.getEndTime().isEmpty()) {
327                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTimeAmPm",
328                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
329                 isValid = false;
330             }
331         }
332 
333         // 3) start date, time and AmPm are a required field
334         if (apptWindow.getStartDate() == null || StringUtils.isEmpty(apptWindow.getStartTime()) || StringUtils.isEmpty(apptWindow.getStartTimeAmPm())) {
335             if (apptWindow.getStartDate() == null) {
336                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startDate",
337                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_REQUIRED_FIELD);
338             } else if (apptWindow.getStartDate() == null) {
339                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startTime",
340                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_REQUIRED_FIELD);
341             } else {
342                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startTimeAmPm",
343                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_AM_PM_REQUIRED_FIELD);
344             }
345             isValid = false;
346         } else {
347             // 4) when end date is not null, start/end date should be in the date range of the selected period
348             // Aslo check to make sure the end date is not before the start date
349             String periodId = apptWindow.getPeriodKey();
350             try {
351                 KeyDateInfo period = getAcalService().getKeyDate(periodId, getContextInfo());
352                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().before(apptWindow.getStartDate())) {
353                     GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
354                             AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_IS_BEFORE_START_DATE);
355                     isValid = false;
356                 }
357                 if (period.getStartDate().after(apptWindow.getStartDate()) || period.getEndDate().before(apptWindow.getStartDate())) {
358                     GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startDate",
359                             AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_OUT_OF_RANGE);
360                     isValid = false;
361                 }
362                 if (apptWindow.getEndDate() != null && !apptWindow.getEndDate().toString().isEmpty()) {
363                     if (period.getStartDate().after(apptWindow.getEndDate()) || period.getEndDate().before(apptWindow.getEndDate())) {
364                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
365                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_OUT_OF_RANGE);
366                         isValid = false;
367                     }
368                 }
369 
370                 // 5) when end date is not null, end time cannot be before the start time
371                 //if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm())) {
372                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && ((apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm()) || (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) ))) {
373                     Date start = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getStartTime());
374                     Date end = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getEndTime());
375                     if (end.before(start)) {
376                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTime",
377                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_BEFORE_START_TIME);
378                         isValid = false;
379                     }
380 
381                     // 6) when end date is not null, end time AM-PM cannot be before the start time
382                     if (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) {
383                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTimeAmPm",
384                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_AM_PM_BEFORE_START_TIME_AM_PM);
385                         isValid = false;
386                     }
387                 }
388 
389             } catch (Exception e) {
390                 LOG.error("Fail to find periods for a selected term.", e);
391                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
392                 isValid = false;
393             }
394         }
395 
396         try {
397             Map<String, String> fieldValues = new HashMap<String, String>();
398             fieldValues.put("name", apptWindow.getAssignedPopulationName());
399             QueryByCriteria qbc = buildQueryByCriteria(fieldValues);
400             List<PopulationInfo> populationInfoList = getPopulationService().searchForPopulations(qbc, getContextInfo());
401 
402             if (populationInfoList == null || populationInfoList.isEmpty()) {
403                 GlobalVariables.getMessageMap().putErrorForSectionId("addRegistrationWindowCollection", PopulationConstants.POPULATION_MSG_ERROR_POPULATION_NOT_FOUND, apptWindow.getAssignedPopulationName());
404                 isValid = false;
405             } else {
406                 apptWindow.setAssignedPopulationName(populationInfoList.get(0).getName());
407                 apptWindow.getAppointmentWindowInfo().setAssignedPopulationId(populationInfoList.get(0).getId());
408             }
409 
410         } catch (Exception e) {
411             throw new RuntimeException(e);
412         }
413 
414         return isValid;
415     }
416 
417     private QueryByCriteria buildQueryByCriteria(Map<String, String> fieldValues) {
418         String populationName = fieldValues.get("name");
419 
420         List<Predicate> predicates = new ArrayList<Predicate>();
421         if (StringUtils.isNotBlank(populationName)) {
422             predicates.add(PredicateFactory.equalIgnoreCase("name", populationName));
423             predicates.add(PredicateFactory.and(PredicateFactory.equal("populationState", PopulationServiceConstants.POPULATION_ACTIVE_STATE_KEY)));
424         }
425 
426         QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
427         qbcBuilder.setPredicates(predicates.toArray(new Predicate[predicates.size()]));
428         QueryByCriteria qbc = qbcBuilder.build();
429 
430         return qbc;
431     }
432 
433     protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
434         if (addLine instanceof AppointmentWindowWrapper) {
435             //in the AddLine (/inputLine) when the periodId is not all, need to set the selected periodId and periodName
436             // in the addLine
437             RegistrationWindowsManagementForm form = (RegistrationWindowsManagementForm) model;
438             AppointmentWindowWrapper newCollectionLine = (AppointmentWindowWrapper) form.getNewCollectionLines().get("appointmentWindows");
439             String periodId = form.getPeriodId();
440             if (periodId != "all" && !periodId.isEmpty()) {
441                 newCollectionLine.setPeriodName(form.getPeriodName());
442                 newCollectionLine.setPeriodKey(form.getPeriodId());
443             }
444         }
445     }
446 
447     public boolean saveApptWindow(AppointmentWindowWrapper appointmentWindowWrapper) throws InvalidParameterException, DataValidationErrorException, MissingParameterException, DoesNotExistException, ReadOnlyException, PermissionDeniedException, OperationFailedException, VersionMismatchException {
448         boolean isSave = true;
449         //Copy the form data from the wrapper to the bean.
450         AppointmentWindowInfo appointmentWindowInfo = appointmentWindowWrapper.getAppointmentWindowInfo();
451         appointmentWindowInfo.setTypeKey(appointmentWindowWrapper.getWindowTypeKey());
452         appointmentWindowInfo.setPeriodMilestoneId(appointmentWindowWrapper.getPeriodKey());
453         appointmentWindowInfo.setStartDate(CommonUtils.getDateWithTime(appointmentWindowWrapper.getStartDate(), appointmentWindowWrapper.getStartTime(), appointmentWindowWrapper.getStartTimeAmPm()));
454         appointmentWindowInfo.setEndDate(CommonUtils.getDateWithTime(appointmentWindowWrapper.getEndDate(), appointmentWindowWrapper.getEndTime(), appointmentWindowWrapper.getEndTimeAmPm()));
455 
456         //TODO Default to some value if nothing is entered(Service team needs to make up some real types or make not nullable)
457         if (appointmentWindowInfo.getAssignedOrderTypeKey() == null || appointmentWindowInfo.getAssignedOrderTypeKey().isEmpty()) {
458             appointmentWindowInfo.setAssignedOrderTypeKey("DUMMY_ID");
459         }
460 
461         //Default to single slot type if nothing is entered
462         if (appointmentWindowInfo.getTypeKey() == null || appointmentWindowInfo.getTypeKey().isEmpty()) {
463             appointmentWindowInfo.setTypeKey(AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY);
464         }
465 
466         if (appointmentWindowInfo.getId() == null || appointmentWindowInfo.getId().isEmpty()) {
467             //Default the state to active
468             appointmentWindowInfo.setStateKey(AppointmentServiceConstants.APPOINTMENT_WINDOW_STATE_DRAFT_KEY);
469 
470             //Converting appointment rule type code to AppointmentSlotRuleInfo object when apptWindowInfo..getTypeKey != AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY
471             if (!AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY.equals(appointmentWindowInfo.getTypeKey())) {
472                 appointmentWindowInfo.setSlotRule(AppointmentSlotRuleTypeConversion.convToAppointmentSlotRuleInfo(appointmentWindowWrapper.getSlotRuleEnumType()));
473             }
474             //appointmentWindowInfo.getSlotRule().setWeekdays(new ArrayList<Integer>());
475             //appointmentWindowInfo.getSlotRule().getWeekdays().add(1);
476             appointmentWindowInfo = getAppointmentService().createAppointmentWindow(appointmentWindowInfo.getTypeKey(), appointmentWindowInfo, new ContextInfo());
477         } else {
478             appointmentWindowInfo = getAppointmentService().updateAppointmentWindow(appointmentWindowInfo.getId(), appointmentWindowInfo, new ContextInfo());
479         }
480 
481         //Reset the windowInfo from the service's returned value
482         appointmentWindowWrapper.setAppointmentWindowInfo(appointmentWindowInfo);
483         appointmentWindowWrapper.setId(appointmentWindowInfo.getId());
484         appointmentWindowWrapper.setWindowName(appointmentWindowInfo.getName());
485 
486         return isSave;
487 
488     }
489 
490     public boolean saveWindows(RegistrationWindowsManagementForm form) throws InvalidParameterException, DataValidationErrorException, MissingParameterException, DoesNotExistException, ReadOnlyException, PermissionDeniedException, OperationFailedException, VersionMismatchException {
491         boolean isApptWindowSaved = true;
492         boolean allWindowsSaved = true;
493         if (form.getAppointmentWindows() != null) {
494             int windowIndex = 0;
495             for (AppointmentWindowWrapper appointmentWindowWrapper : form.getAppointmentWindows()) {
496                 boolean isValid = validateApptWidnow(appointmentWindowWrapper, windowIndex);
497                 if (isValid) {
498                     isApptWindowSaved = saveApptWindow(appointmentWindowWrapper);
499                     if (!isApptWindowSaved)
500                         allWindowsSaved = isApptWindowSaved;
501                 }
502                 windowIndex++;
503             }
504             //Add a success message
505             if (isApptWindowSaved)
506                 GlobalVariables.getMessageMap().addGrowlMessage("", AppointmentConstants.APPOINTMENT_MSG_INFO_SAVED);
507         }
508         return allWindowsSaved;
509     }
510 
511     protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
512         if (addLine instanceof AppointmentWindowWrapper) {
513             RegistrationWindowsManagementForm form = (RegistrationWindowsManagementForm) model;
514             List<KeyDateInfo> periodMilestones = form.getPeriodMilestones();
515             String periodKey = ((AppointmentWindowWrapper) addLine).getPeriodKey();
516             for (KeyDateInfo period : periodMilestones) {
517                 if (periodKey.equals(period.getId())) {
518                     if (period.getName() != null && !period.getName().isEmpty()) {
519                         ((AppointmentWindowWrapper) addLine).setPeriodName(period.getName());
520                     } else {
521                         ((AppointmentWindowWrapper) addLine).setPeriodName(periodKey);
522                     }
523                     break;
524                 }
525             }
526             String windowName = ((AppointmentWindowWrapper) addLine).getAppointmentWindowInfo().getName();
527             ((AppointmentWindowWrapper) addLine).setWindowName(windowName);
528         }
529     }
530 
531     protected boolean performAddLineValidation(View view, CollectionGroup collectionGroup, Object model,
532                                                Object addLine) {
533         boolean isValid = true;
534         if (addLine instanceof AppointmentWindowWrapper) {
535             AppointmentWindowWrapper apptWindow = (AppointmentWindowWrapper) addLine;
536             isValid = validateApptWidnow(apptWindow);
537             if (isValid) {
538                 try {
539                     //need to persist the window that has passed the validation to DB
540                     saveApptWindow((AppointmentWindowWrapper) addLine);
541                     //Add a success message
542                     GlobalVariables.getMessageMap().addGrowlMessage("", AppointmentConstants.APPOINTMENT_MSG_INFO_SAVED);
543                 } catch (Exception e) {
544                     LOG.error("Fail to create a window.", e);
545                     GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_WINDOW_SAVE_FAIL);
546                     isValid = false;
547                 }
548             }
549 
550         } else {
551             super.performAddLineValidation(view, collectionGroup, model, addLine);
552         }
553         return isValid;
554     }
555 
556     public AcademicCalendarService getAcalService() {
557         if (academicCalendarService == null) {
558             academicCalendarService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE, AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
559         }
560         return this.academicCalendarService;
561     }
562 
563 
564     public AppointmentService getAppointmentService() {
565         if (appointmentService == null) {
566             appointmentService = (AppointmentService) GlobalResourceLoader.getService(new QName(AppointmentServiceConstants.NAMESPACE, AppointmentServiceConstants.SERVICE_NAME_LOCAL_PART));
567         }
568         return appointmentService;
569     }
570 
571 
572     public TypeService getTypeService() {
573         if (typeService == null) {
574             typeService = (TypeService) GlobalResourceLoader.getService(new QName(TypeServiceConstants.NAMESPACE, TypeServiceConstants.SERVICE_NAME_LOCAL_PART));
575         }
576         return this.typeService;
577     }
578 
579 
580     private PopulationService getPopulationService() {
581         if (populationService == null) {
582             populationService = (PopulationService) GlobalResourceLoader.getService(new QName(PopulationServiceConstants.NAMESPACE, "PopulationService"));
583         }
584         return populationService;
585     }
586 
587     public ContextInfo getContextInfo() {
588         ContextInfo contextInfo = new ContextInfo();
589         contextInfo.setAuthenticatedPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
590         contextInfo.setPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
591         LocaleInfo localeInfo = new LocaleInfo();
592         localeInfo.setLocaleLanguage(Locale.getDefault().getLanguage());
593         localeInfo.setLocaleRegion(Locale.getDefault().getCountry());
594         contextInfo.setLocale(localeInfo);
595         return contextInfo;
596     }
597 
598 
599 }