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                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().before(apptWindow.getStartDate())) {
243                     GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].endDate",
244                             AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_IS_BEFORE_START_DATE);
245                     isValid = false;
246                 }
247                 if (period.getStartDate().after(apptWindow.getStartDate()) || period.getEndDate().before(apptWindow.getStartDate())) {
248                     GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].startDate",
249                             AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_OUT_OF_RANGE);
250                     isValid = false;
251                 }
252                 if (apptWindow.getEndDate() != null && !apptWindow.getEndDate().toString().isEmpty()) {
253                     if (period.getStartDate().after(apptWindow.getEndDate()) || period.getEndDate().before(apptWindow.getEndDate())) {
254                         GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endDate",
255                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_OUT_OF_RANGE);
256                         isValid = false;
257                     }
258                 }
259 
260                 // 5) when end date is not null, end time cannot be before the start time
261                 //if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm())) {
262                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && ((apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm()) || (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) ))) {
263                     Date start = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getStartTime());
264                     Date end = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getEndTime());
265                     if (end.before(start)) {
266                         GlobalVariables.getMessageMap().putError("appointmentWindows['appointmentWindows'].endTime",
267                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_BEFORE_START_TIME);
268                         isValid = false;
269                     }
270 
271                     // 6) when end date is not null, end time AM-PM cannot be before the start time
272                     if (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) {
273                         GlobalVariables.getMessageMap().putError("newCollectionLines['appointmentWindows'].endTimeAmPm",
274                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_AM_PM_BEFORE_START_TIME_AM_PM);
275                         isValid = false;
276                     }
277                 }
278             } catch (Exception e) {
279                 LOG.error("Fail to find periods for a selected term.", e);
280                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
281                 isValid = false;
282             }
283         }
284 
285         try {
286             Map<String, String> fieldValues = new HashMap<String, String>();
287             fieldValues.put("name", apptWindow.getAssignedPopulationName());
288             QueryByCriteria qbc = buildQueryByCriteria(fieldValues);
289             List<PopulationInfo> populationInfoList = getPopulationService().searchForPopulations(qbc, getContextInfo());
290 
291             if (populationInfoList == null || populationInfoList.isEmpty()) {
292                 GlobalVariables.getMessageMap().putErrorForSectionId("addRegistrationWindowCollection", PopulationConstants.POPULATION_MSG_ERROR_POPULATION_NOT_FOUND, apptWindow.getAssignedPopulationName());
293                 isValid = false;
294             } else {
295                 apptWindow.setAssignedPopulationName(populationInfoList.get(0).getName());
296                 apptWindow.getAppointmentWindowInfo().setAssignedPopulationId(populationInfoList.get(0).getId());
297             }
298 
299         } catch (Exception e) {
300             throw new RuntimeException(e);
301         }
302 
303         return isValid;
304     }
305 
306     public boolean validateApptWidnow(AppointmentWindowWrapper apptWindow, int windowIndex) {
307         boolean isValid = true;
308         //  1) a window end date is not required for a One-Slot or Max Number Slot Allocation Method/Window Type
309         //  2) a window end date is required for uniform
310         String windowTypeKey = apptWindow.getWindowTypeKey();
311 
312         if (AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_SLOTTED_UNIFORM_KEY.equals(windowTypeKey)) {
313             if (apptWindow.getEndDate() == null) {
314                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
315                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_REQUIRED_FOR_UNIFORM);
316                 isValid = false;
317             }
318             if (apptWindow.getEndTime() == null) {
319                 GlobalVariables.getMessageMap().putError("appointmentWindows[windowIndex].endTime",
320                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
321                 isValid = false;
322             }
323             if (apptWindow.getEndTime().isEmpty()) {
324                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTimeAmPm",
325                         AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_REQUIRED_FOR_UNIFORM);
326                 isValid = false;
327             }
328         }
329 
330         // 3) start date, time and AmPm are a required field
331         if (apptWindow.getStartDate() == null || StringUtils.isEmpty(apptWindow.getStartTime()) || StringUtils.isEmpty(apptWindow.getStartTimeAmPm())) {
332             if (apptWindow.getStartDate() == null) {
333                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startDate",
334                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_REQUIRED_FIELD);
335             } else if (apptWindow.getStartDate() == null) {
336                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startTime",
337                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_REQUIRED_FIELD);
338             } else {
339                 GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startTimeAmPm",
340                         AppointmentConstants.APPOINTMENT_MSG_ERROR_START_TIME_AM_PM_REQUIRED_FIELD);
341             }
342             isValid = false;
343         } else {
344             // 4) when end date is not null, start/end date should be in the date range of the selected period
345             // Aslo check to make sure the end date is not before the start date
346             String periodId = apptWindow.getPeriodKey();
347             try {
348                 KeyDateInfo period = getAcalService().getKeyDate(periodId, getContextInfo());
349                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().before(apptWindow.getStartDate())) {
350                     GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
351                             AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_IS_BEFORE_START_DATE);
352                     isValid = false;
353                 }
354                 if (period.getStartDate().after(apptWindow.getStartDate()) || period.getEndDate().before(apptWindow.getStartDate())) {
355                     GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].startDate",
356                             AppointmentConstants.APPOINTMENT_MSG_ERROR_START_DATE_OUT_OF_RANGE);
357                     isValid = false;
358                 }
359                 if (apptWindow.getEndDate() != null && !apptWindow.getEndDate().toString().isEmpty()) {
360                     if (period.getStartDate().after(apptWindow.getEndDate()) || period.getEndDate().before(apptWindow.getEndDate())) {
361                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endDate",
362                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_DATE_OUT_OF_RANGE);
363                         isValid = false;
364                     }
365                 }
366 
367                 // 5) when end date is not null, end time cannot be before the start time
368                 //if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm())) {
369                 if (apptWindow.getEndDate() != null && apptWindow.getEndDate().equals(apptWindow.getStartDate()) && ((apptWindow.getStartTimeAmPm().equals(apptWindow.getEndTimeAmPm()) || (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) ))) {
370                     Date start = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getStartTime());
371                     Date end = DateFormatters.HOUR_MINUTE_TIME_FORMATTER.parse(apptWindow.getEndTime());
372                     if (end.before(start)) {
373                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTime",
374                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_BEFORE_START_TIME);
375                         isValid = false;
376                     }
377 
378                     // 6) when end date is not null, end time AM-PM cannot be before the start time
379                     if (apptWindow.getEndTimeAmPm().equalsIgnoreCase("am") && apptWindow.getStartTimeAmPm().equalsIgnoreCase("pm")) {
380                         GlobalVariables.getMessageMap().putError("appointmentWindows[" + windowIndex + "].endTimeAmPm",
381                                 AppointmentConstants.APPOINTMENT_MSG_ERROR_END_TIME_AM_PM_BEFORE_START_TIME_AM_PM);
382                         isValid = false;
383                     }
384                 }
385 
386             } catch (Exception e) {
387                 LOG.error("Fail to find periods for a selected term.", e);
388                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_NO_REG_PERIODS_FOR_TERM);
389                 isValid = false;
390             }
391         }
392 
393         try {
394             Map<String, String> fieldValues = new HashMap<String, String>();
395             fieldValues.put("name", apptWindow.getAssignedPopulationName());
396             QueryByCriteria qbc = buildQueryByCriteria(fieldValues);
397             List<PopulationInfo> populationInfoList = getPopulationService().searchForPopulations(qbc, getContextInfo());
398 
399             if (populationInfoList == null || populationInfoList.isEmpty()) {
400                 GlobalVariables.getMessageMap().putErrorForSectionId("addRegistrationWindowCollection", PopulationConstants.POPULATION_MSG_ERROR_POPULATION_NOT_FOUND, apptWindow.getAssignedPopulationName());
401                 isValid = false;
402             } else {
403                 apptWindow.setAssignedPopulationName(populationInfoList.get(0).getName());
404                 apptWindow.getAppointmentWindowInfo().setAssignedPopulationId(populationInfoList.get(0).getId());
405             }
406 
407         } catch (Exception e) {
408             throw new RuntimeException(e);
409         }
410 
411         return isValid;
412     }
413 
414     private QueryByCriteria buildQueryByCriteria(Map<String, String> fieldValues) {
415         String populationName = fieldValues.get("name");
416 
417         List<Predicate> predicates = new ArrayList<Predicate>();
418         if (StringUtils.isNotBlank(populationName)) {
419             predicates.add(PredicateFactory.equalIgnoreCase("name", populationName));
420             predicates.add(PredicateFactory.and(PredicateFactory.equal("populationState", PopulationServiceConstants.POPULATION_ACTIVE_STATE_KEY)));
421         }
422 
423         QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
424         qbcBuilder.setPredicates(predicates.toArray(new Predicate[predicates.size()]));
425         QueryByCriteria qbc = qbcBuilder.build();
426 
427         return qbc;
428     }
429 
430     protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
431         if (addLine instanceof AppointmentWindowWrapper) {
432             //in the AddLine (/inputLine) when the periodId is not all, need to set the selected periodId and periodName
433             // in the addLine
434             RegistrationWindowsManagementForm form = (RegistrationWindowsManagementForm) model;
435             AppointmentWindowWrapper newCollectionLine = (AppointmentWindowWrapper) form.getNewCollectionLines().get("appointmentWindows");
436             String periodId = form.getPeriodId();
437             if (periodId != "all" && !periodId.isEmpty()) {
438                 newCollectionLine.setPeriodName(form.getPeriodName());
439                 newCollectionLine.setPeriodKey(form.getPeriodId());
440             }
441         }
442     }
443 
444     public boolean saveApptWindow(AppointmentWindowWrapper appointmentWindowWrapper) throws InvalidParameterException, DataValidationErrorException, MissingParameterException, DoesNotExistException, ReadOnlyException, PermissionDeniedException, OperationFailedException, VersionMismatchException {
445         boolean isSave = true;
446         //Copy the form data from the wrapper to the bean.
447         AppointmentWindowInfo appointmentWindowInfo = appointmentWindowWrapper.getAppointmentWindowInfo();
448         appointmentWindowInfo.setTypeKey(appointmentWindowWrapper.getWindowTypeKey());
449         appointmentWindowInfo.setPeriodMilestoneId(appointmentWindowWrapper.getPeriodKey());
450         appointmentWindowInfo.setStartDate(CommonUtils.getDateWithTime(appointmentWindowWrapper.getStartDate(), appointmentWindowWrapper.getStartTime(), appointmentWindowWrapper.getStartTimeAmPm()));
451         appointmentWindowInfo.setEndDate(CommonUtils.getDateWithTime(appointmentWindowWrapper.getEndDate(), appointmentWindowWrapper.getEndTime(), appointmentWindowWrapper.getEndTimeAmPm()));
452 
453         //TODO Default to some value if nothing is entered(Service team needs to make up some real types or make not nullable)
454         if (appointmentWindowInfo.getAssignedOrderTypeKey() == null || appointmentWindowInfo.getAssignedOrderTypeKey().isEmpty()) {
455             appointmentWindowInfo.setAssignedOrderTypeKey("DUMMY_ID");
456         }
457 
458         //Default to single slot type if nothing is entered
459         if (appointmentWindowInfo.getTypeKey() == null || appointmentWindowInfo.getTypeKey().isEmpty()) {
460             appointmentWindowInfo.setTypeKey(AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY);
461         }
462 
463         if (appointmentWindowInfo.getId() == null || appointmentWindowInfo.getId().isEmpty()) {
464             //Default the state to active
465             appointmentWindowInfo.setStateKey(AppointmentServiceConstants.APPOINTMENT_WINDOW_STATE_DRAFT_KEY);
466 
467             //Converting appointment rule type code to AppointmentSlotRuleInfo object when apptWindowInfo..getTypeKey != AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY
468             if (!AppointmentServiceConstants.APPOINTMENT_WINDOW_TYPE_ONE_SLOT_KEY.equals(appointmentWindowInfo.getTypeKey())) {
469                 appointmentWindowInfo.setSlotRule(AppointmentSlotRuleTypeConversion.convToAppointmentSlotRuleInfo(appointmentWindowWrapper.getSlotRuleEnumType()));
470             }
471             //appointmentWindowInfo.getSlotRule().setWeekdays(new ArrayList<Integer>());
472             //appointmentWindowInfo.getSlotRule().getWeekdays().add(1);
473             appointmentWindowInfo = getAppointmentService().createAppointmentWindow(appointmentWindowInfo.getTypeKey(), appointmentWindowInfo, new ContextInfo());
474         } else {
475             appointmentWindowInfo = getAppointmentService().updateAppointmentWindow(appointmentWindowInfo.getId(), appointmentWindowInfo, new ContextInfo());
476         }
477 
478         //Reset the windowInfo from the service's returned value
479         appointmentWindowWrapper.setAppointmentWindowInfo(appointmentWindowInfo);
480         appointmentWindowWrapper.setId(appointmentWindowInfo.getId());
481         appointmentWindowWrapper.setWindowName(appointmentWindowInfo.getName());
482 
483         return isSave;
484 
485     }
486 
487     public boolean saveWindows(RegistrationWindowsManagementForm form) throws InvalidParameterException, DataValidationErrorException, MissingParameterException, DoesNotExistException, ReadOnlyException, PermissionDeniedException, OperationFailedException, VersionMismatchException {
488         boolean isApptWindowSaved = true;
489         boolean allWindowsSaved = true;
490         if (form.getAppointmentWindows() != null) {
491             int windowIndex = 0;
492             for (AppointmentWindowWrapper appointmentWindowWrapper : form.getAppointmentWindows()) {
493                 boolean isValid = validateApptWidnow(appointmentWindowWrapper, windowIndex);
494                 if (isValid) {
495                     isApptWindowSaved = saveApptWindow(appointmentWindowWrapper);
496                     if (!isApptWindowSaved)
497                         allWindowsSaved = isApptWindowSaved;
498                 }
499                 windowIndex++;
500             }
501             //Add a success message
502             if (isApptWindowSaved)
503                 GlobalVariables.getMessageMap().addGrowlMessage("", AppointmentConstants.APPOINTMENT_MSG_INFO_SAVED);
504         }
505         return allWindowsSaved;
506     }
507 
508     protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
509         if (addLine instanceof AppointmentWindowWrapper) {
510             RegistrationWindowsManagementForm form = (RegistrationWindowsManagementForm) model;
511             List<KeyDateInfo> periodMilestones = form.getPeriodMilestones();
512             String periodKey = ((AppointmentWindowWrapper) addLine).getPeriodKey();
513             for (KeyDateInfo period : periodMilestones) {
514                 if (periodKey.equals(period.getId())) {
515                     if (period.getName() != null && !period.getName().isEmpty()) {
516                         ((AppointmentWindowWrapper) addLine).setPeriodName(period.getName());
517                     } else {
518                         ((AppointmentWindowWrapper) addLine).setPeriodName(periodKey);
519                     }
520                     break;
521                 }
522             }
523             String windowName = ((AppointmentWindowWrapper) addLine).getAppointmentWindowInfo().getName();
524             ((AppointmentWindowWrapper) addLine).setWindowName(windowName);
525         }
526     }
527 
528     protected boolean performAddLineValidation(View view, CollectionGroup collectionGroup, Object model,
529                                                Object addLine) {
530         boolean isValid = true;
531         if (addLine instanceof AppointmentWindowWrapper) {
532             AppointmentWindowWrapper apptWindow = (AppointmentWindowWrapper) addLine;
533             isValid = validateApptWidnow(apptWindow);
534             if (isValid) {
535                 try {
536                     //need to persist the window that has passed the validation to DB
537                     saveApptWindow((AppointmentWindowWrapper) addLine);
538                     //Add a success message
539                     GlobalVariables.getMessageMap().addGrowlMessage("", AppointmentConstants.APPOINTMENT_MSG_INFO_SAVED);
540                 } catch (Exception e) {
541                     LOG.error("Fail to create a window.", e);
542                     GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, AppointmentConstants.APPOINTMENT_MSG_ERROR_WINDOW_SAVE_FAIL);
543                     isValid = false;
544                 }
545             }
546 
547         } else {
548             super.performAddLineValidation(view, collectionGroup, model, addLine);
549         }
550         return isValid;
551     }
552 
553     public AcademicCalendarService getAcalService() {
554         if (academicCalendarService == null) {
555             academicCalendarService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE, AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
556         }
557         return this.academicCalendarService;
558     }
559 
560 
561     public AppointmentService getAppointmentService() {
562         if (appointmentService == null) {
563             appointmentService = (AppointmentService) GlobalResourceLoader.getService(new QName(AppointmentServiceConstants.NAMESPACE, AppointmentServiceConstants.SERVICE_NAME_LOCAL_PART));
564         }
565         return appointmentService;
566     }
567 
568 
569     public TypeService getTypeService() {
570         if (typeService == null) {
571             typeService = (TypeService) GlobalResourceLoader.getService(new QName(TypeServiceConstants.NAMESPACE, TypeServiceConstants.SERVICE_NAME_LOCAL_PART));
572         }
573         return this.typeService;
574     }
575 
576 
577     private PopulationService getPopulationService() {
578         if (populationService == null) {
579             populationService = (PopulationService) GlobalResourceLoader.getService(new QName(PopulationServiceConstants.NAMESPACE, "PopulationService"));
580         }
581         return populationService;
582     }
583 
584     public ContextInfo getContextInfo() {
585         ContextInfo contextInfo = new ContextInfo();
586         contextInfo.setAuthenticatedPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
587         contextInfo.setPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
588         LocaleInfo localeInfo = new LocaleInfo();
589         localeInfo.setLocaleLanguage(Locale.getDefault().getLanguage());
590         localeInfo.setLocaleRegion(Locale.getDefault().getCountry());
591         contextInfo.setLocale(localeInfo);
592         return contextInfo;
593     }
594 
595 
596 }