001/*
002 * Copyright 2014 The Kuali Foundation Licensed under the
003 * Educational Community License, Version 2.0 (the "License"); you may
004 * not use this file except in compliance with the License. You may
005 * obtain a copy of the License at
006 *
007 * http://www.osedu.org/licenses/ECL-2.0
008 *
009 * Unless required by applicable law or agreed to in writing,
010 * software distributed under the License is distributed on an "AS IS"
011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012 * or implied. See the License for the specific language governing
013 * permissions and limitations under the License.
014 */
015
016package org.kuali.student.ap.planner.service.impl;
017
018import org.kuali.rice.krad.web.form.UifFormBase;
019import org.kuali.student.ap.academicplan.constants.AcademicPlanServiceConstants;
020import org.kuali.student.ap.academicplan.dto.TypedObjectReferenceInfo;
021import org.kuali.student.ap.academicplan.infc.LearningPlan;
022import org.kuali.student.ap.academicplan.infc.PlanItem;
023import org.kuali.student.ap.academicplan.infc.TypedObjectReference;
024import org.kuali.student.ap.coursesearch.CreditsFormatter;
025import org.kuali.student.ap.coursesearch.util.CourseDetailsUtil;
026import org.kuali.student.ap.framework.config.KsapFrameworkServiceLocator;
027import org.kuali.student.ap.framework.context.PlanConstants;
028import org.kuali.student.ap.planner.PlannerForm;
029import org.kuali.student.ap.planner.dataobject.CourseSummaryPopoverDetailsWrapper;
030import org.kuali.student.ap.planner.form.AddCourseToPlanForm;
031import org.kuali.student.ap.planner.form.CourseNoteForm;
032import org.kuali.student.ap.planner.form.CourseSummaryForm;
033import org.kuali.student.ap.planner.form.DeletePlanItemForm;
034import org.kuali.student.ap.planner.form.MovePlanItemForm;
035import org.kuali.student.ap.planner.form.PlanItemEditForm;
036import org.kuali.student.ap.planner.form.PlannerFormImpl;
037import org.kuali.student.ap.planner.form.QuickAddCourseToPlanForm;
038import org.kuali.student.ap.planner.form.TermNoteForm;
039import org.kuali.student.ap.planner.service.PlannerViewHelperService;
040import org.kuali.student.common.collection.KSCollectionUtils;
041import org.kuali.student.r2.common.dto.AttributeInfo;
042import org.kuali.student.r2.common.dto.RichTextInfo;
043import org.kuali.student.r2.common.exceptions.AlreadyExistsException;
044import org.kuali.student.r2.common.exceptions.DoesNotExistException;
045import org.kuali.student.r2.common.exceptions.InvalidParameterException;
046import org.kuali.student.r2.common.exceptions.MissingParameterException;
047import org.kuali.student.r2.common.exceptions.OperationFailedException;
048import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
049import org.kuali.student.r2.core.acal.infc.Term;
050import org.kuali.student.r2.core.comment.dto.CommentInfo;
051import org.kuali.student.r2.core.comment.service.CommentService;
052import org.kuali.student.r2.lum.course.infc.Course;
053import org.slf4j.Logger;
054import org.slf4j.LoggerFactory;
055
056import javax.json.Json;
057import javax.json.JsonObjectBuilder;
058import javax.servlet.ServletException;
059import javax.servlet.http.HttpServletRequest;
060import javax.servlet.http.HttpServletResponse;
061import java.io.IOException;
062import java.util.ArrayList;
063import java.util.List;
064import java.util.UUID;
065
066public class PlannerViewHelperServiceImpl extends PlanEventViewHelperServiceImpl implements PlannerViewHelperService {
067
068    private static final Logger LOG = LoggerFactory.getLogger(PlannerViewHelperServiceImpl.class);
069
070    /**
071     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadAddToPlanDialogForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.AddCourseToPlanForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
072     */
073    @Override
074    public UifFormBase loadAddToPlanDialogForm(UifFormBase submittedForm, AddCourseToPlanForm dialogForm, HttpServletRequest request, HttpServletResponse response){
075        String courseId = request.getParameter("courseId");
076
077        Course course = KsapFrameworkServiceLocator.getCourseHelper().getCurrentVersionOfCourse(courseId);
078
079        dialogForm.setCourseId(courseId);
080        dialogForm.setCourseCode(course.getCode());
081        dialogForm.setCourseTitle(course.getCourseTitle());
082        String uniqueId = ((PlannerFormImpl)submittedForm).getUniqueId();
083        if(uniqueId==null){
084            dialogForm.setUniqueId(UUID.randomUUID().toString());
085        }else{
086            dialogForm.setUniqueId(uniqueId);
087        }
088
089        // Set Credits to display for course
090        String creditString = KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().formatCredits(course);
091        dialogForm.setCreditsDisplay(creditString);
092
093        // Set if course is variable credits
094        boolean isVariableCredits = false;
095        CreditsFormatter.Range range = KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().getRange(course);
096        if(range.getMultiple()!=null && !range.getMultiple().isEmpty()) isVariableCredits = true;
097        isVariableCredits = !range.getMax().equals(range.getMin());
098        dialogForm.setVariableCredit(isVariableCredits);
099
100        dialogForm.setCourseSummaryDetails(getCourseSummaryPopoverDetails(course));
101
102        //Find terms that already contain this planned course
103        List<PlanItem> planItems = KsapFrameworkServiceLocator.getPlanHelper().loadStudentsPlanItemsForCourse(course);
104        List<String> plannedTermIds = KsapFrameworkServiceLocator.getPlanHelper().getTermIdsForPlanItems(planItems);
105        dialogForm.setPlannedTermIds(plannedTermIds);
106
107        return dialogForm;
108    }
109
110    /**
111     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadQuickAddToPlanDialogForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.QuickAddCourseToPlanForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
112     */
113    @Override
114    public UifFormBase loadQuickAddToPlanDialogForm(UifFormBase submittedForm, QuickAddCourseToPlanForm dialogForm, HttpServletRequest request, HttpServletResponse response){
115        String termId = request.getParameter("termId");
116        boolean backup = Boolean.parseBoolean(request.getParameter("backup"));
117
118        dialogForm.setTermId(termId);
119        dialogForm.setBackup(backup);
120        dialogForm.setTermName(KsapFrameworkServiceLocator.getTermHelper().getYearTerm(termId).getLongName());
121
122        return dialogForm;
123    }
124
125    /**
126     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadTermNoteDialogForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.TermNoteForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
127     */
128    @Override
129    public UifFormBase loadTermNoteDialogForm(UifFormBase submittedForm, TermNoteForm dialogForm, HttpServletRequest request, HttpServletResponse response){
130        String termId = request.getParameter("termId");
131        String uniqueId = request.getParameter("uniqueId");
132        String planId = dialogForm.getPlanId();
133
134        dialogForm.setTermId(termId);
135        dialogForm.setTermName(KsapFrameworkServiceLocator.getTermHelper().getYearTerm(termId).getLongName());
136        dialogForm.setUniqueId(uniqueId);
137
138        String termNote = "";
139        CommentService commentService = KsapFrameworkServiceLocator.getCommentService();
140        List<CommentInfo> commentInfos;
141        try {
142            commentInfos = commentService.getCommentsByRefObject(planId,PlanConstants.TERM_NOTE_COMMENT_TYPE,
143                    KsapFrameworkServiceLocator.getContext().getContextInfo());
144        } catch (DoesNotExistException e) {
145            throw new IllegalArgumentException("Comment lookup failure", e);
146        } catch (InvalidParameterException e) {
147            throw new IllegalArgumentException("Comment lookup failure", e);
148        } catch (MissingParameterException e) {
149            throw new IllegalArgumentException("Comment lookup failure", e);
150        } catch (OperationFailedException e) {
151            throw new IllegalStateException("Comment lookup failure", e);
152        } catch (PermissionDeniedException e) {
153            throw new IllegalStateException("Comment lookup failure", e);
154        }
155
156        for (CommentInfo comment : commentInfos) {
157            String commentAtpId = comment.getAttributeValue(PlanConstants.TERM_NOTE_COMMENT_ATTRIBUTE_ATPID);
158            if (termId.equals(commentAtpId)) {
159                RichTextInfo text = comment.getCommentText();
160                if (text != null)
161                    termNote = text.getPlain();
162            }
163        }
164
165        dialogForm.setTermNote(termNote);
166
167        return dialogForm;
168    }
169
170    /**
171     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadPlanItemEditForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.PlanItemEditForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
172     */
173    @Override
174    public UifFormBase loadPlanItemEditForm(UifFormBase submittedForm, PlanItemEditForm dialogForm, HttpServletRequest request, HttpServletResponse response){
175
176        String planItemId = request.getParameter("planItemId");
177        String termId = request.getParameter("termId");
178        String uniqueId = request.getParameter("uniqueId");
179
180
181        PlanItem planItem = KsapFrameworkServiceLocator.getPlanHelper().getPlanItem(planItemId);
182        Course course = KsapFrameworkServiceLocator.getCourseHelper()
183                .getCurrentVersionOfCourseByVersionIndependentId(planItem.getRefObjectId());
184
185        dialogForm.setUniqueId(uniqueId);
186        dialogForm.setPlanItemId(planItem.getId());
187        dialogForm.setPlanId(planItem.getLearningPlanId());
188        dialogForm.setCourseId(planItem.getRefObjectId());
189        String courseNote ="";
190        if(planItem.getDescr()!=null){
191            courseNote = planItem.getDescr().getFormatted();
192        }
193        dialogForm.setCourseNote(courseNote);
194        dialogForm.setCourseCd(course.getCode());
195        dialogForm.setTermId(termId);
196
197        return dialogForm;
198    }
199
200    /**
201     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#finishAddCourse(org.kuali.student.ap.academicplan.infc.LearningPlan, org.kuali.student.ap.planner.PlannerForm, org.kuali.student.r2.lum.course.infc.Course, String, javax.servlet.http.HttpServletResponse)
202     */
203    @Override
204    public void finishAddCourse(LearningPlan plan, PlannerForm form, Course course, String termId,
205                                 HttpServletResponse response) throws IOException, ServletException {
206        AcademicPlanServiceConstants.ItemCategory category = form.isBackup() ? AcademicPlanServiceConstants.ItemCategory.BACKUP
207                : AcademicPlanServiceConstants.ItemCategory.PLANNED;
208        Term term = KsapFrameworkServiceLocator.getTermHelper().getTerm(termId);
209        JsonObjectBuilder eventList = Json.createObjectBuilder();
210
211        PlanItem planItemInfo=null;
212        List<String> planTermIds = new ArrayList<String>(1);
213        planTermIds.add(termId);
214        TypedObjectReference planItemRef = new TypedObjectReferenceInfo(PlanConstants.COURSE_TYPE, course.getVersion().getVersionIndId());
215        List<AttributeInfo> attributes = new ArrayList<AttributeInfo>();
216
217        // Check for existing bookmark items for
218        PlanItem wishlistPlanItem = null;
219        List<PlanItem> existingPlanItems =  KsapFrameworkServiceLocator.getPlanHelper().getPlanItems(plan.getId());
220        if (existingPlanItems != null && planItemRef != null){
221            for (PlanItem existingPlanItem : existingPlanItems) {
222                if (!KsapFrameworkServiceLocator.getPlanHelper().isSame(existingPlanItem, planItemRef) || wishlistPlanItem != null){
223                    continue;
224                }
225
226                // If item has no term then record it
227                if (AcademicPlanServiceConstants.ItemCategory.WISHLIST.equals(existingPlanItem.getCategory())){
228                    wishlistPlanItem = existingPlanItem;
229                }
230            }
231        }
232
233
234        try {
235            planItemInfo = KsapFrameworkServiceLocator.getPlanHelper().addPlanItem(plan.getId(), category,
236                    form.getCourseNote(),form.getCreditsForPlanItem(course),planTermIds,planItemRef,attributes);
237        } catch (AlreadyExistsException e) {
238            LOG.warn(String.format("%s is already planned for %s", course.getCode(), term.getName()), ".", e);
239            sendJsonEvents(false,
240                    KsapFrameworkServiceLocator.getTextHelper().getFormattedMessage(
241                            PlanConstants.COURSE_ALREADY_PLANNED,course.getCode(),term.getName()), response, eventList);
242            return;
243        }
244
245        // Create json strings for displaying action's response and updating the planner screen.
246        eventList = makeAddEvent(planItemInfo, eventList);
247        eventList = updateTotalCreditsEvent(true, termId, eventList);
248        eventList = makeUpdateBookmarkTotalEvent(planItemInfo, eventList);
249        if(wishlistPlanItem != null){
250            eventList = makeRemoveEvent(form.getUniqueId(), wishlistPlanItem, eventList);
251        }
252
253        List<PlanItem> planItems = KsapFrameworkServiceLocator.getPlanHelper().loadStudentsPlanItemsForCourse(course);
254        eventList = makeUpdatePlanItemStatusMessage(planItems, eventList);
255        sendJsonEvents(true, course.getCode() + " was successfully added to your plan.",
256                response, eventList);
257    }
258    /**
259     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadCourseNotePlanForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.CourseNoteForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
260     */
261    @Override
262    public UifFormBase loadCourseNotePlanForm(UifFormBase submittedForm, CourseNoteForm dialogForm,
263            HttpServletRequest request, HttpServletResponse response){
264        String planItemId = request.getParameter("planItemId");
265
266        PlanItem planItem = KsapFrameworkServiceLocator.getPlanHelper().getPlanItem(planItemId);
267        dialogForm.setPlanItemId(planItem.getId());
268        dialogForm.setPlanId(planItem.getLearningPlanId());
269        dialogForm.setCourseId(planItem.getRefObjectId());
270        String courseNote ="";
271        if(planItem.getDescr()!=null){
272            courseNote = planItem.getDescr().getFormatted();
273        }
274        dialogForm.setCourseNote(courseNote);
275        try {
276            dialogForm.setTermId(KSCollectionUtils.getRequiredZeroElement(planItem.getPlanTermIds()));
277        } catch (OperationFailedException e) {
278            String errMsg = String.format("unexpected error retrieving single termId for plannedItem (id=%s): %s",
279                    planItemId, e.getMessage());
280            LOG.warn(errMsg, e);
281            throw new IllegalStateException(errMsg, e);
282        }
283
284        Course course = KsapFrameworkServiceLocator.getCourseHelper().getCurrentVersionOfCourseByVersionIndependentId(
285                planItem.getRefObjectId());
286        dialogForm.setCourseCode(course.getCode());
287        dialogForm.setCourseTitle(course.getCourseTitle());
288        dialogForm.setCourseCredits(KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().formatCreditsShortVersion(course));
289
290        String uniqueId= request.getParameter("uniqueId");
291        if(uniqueId==null){
292            dialogForm.setUniqueId(UUID.randomUUID().toString());
293        }else{
294            dialogForm.setUniqueId(uniqueId);
295        }
296        dialogForm.setUniqueId(uniqueId);
297
298        return dialogForm;
299    }
300
301    /**
302     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadCourseSummaryForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.CourseSummaryForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
303     */
304    @Override
305    public UifFormBase loadCourseSummaryForm(UifFormBase submittedForm, CourseSummaryForm dialogForm,
306                                              HttpServletRequest request, HttpServletResponse response){
307
308        String courseId = request.getParameter("courseId");
309
310        Course course = KsapFrameworkServiceLocator.getCourseHelper().getCurrentVersionOfCourse(courseId);
311
312        dialogForm.setCourseId(courseId);
313        dialogForm.setCourseCode(course.getCode());
314        dialogForm.setCourseTitle(course.getCourseTitle());
315        dialogForm.setCourseSummaryDetails(getCourseSummaryPopoverDetails(course));
316
317        // Set Credits to display for course
318        String creditString = KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().formatCredits(course);
319        dialogForm.setCreditsDisplay(creditString);
320
321        List<PlanItem> planItems = KsapFrameworkServiceLocator.getPlanHelper().loadStudentsPlanItemsForCourse(course);
322        dialogForm.setPlannedMessage(KsapFrameworkServiceLocator.getPlanHelper().createPlanningStatusMessages(planItems));
323        dialogForm.setBookmarkMessage(KsapFrameworkServiceLocator.getPlanHelper().createBookmarkStatusMessages(planItems));
324
325        return dialogForm;
326    }
327
328    /**
329     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadDeletePlanItemForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.DeletePlanItemForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
330     */
331    @Override
332    public UifFormBase loadDeletePlanItemForm(UifFormBase submittedForm, DeletePlanItemForm dialogForm,
333                                             HttpServletRequest request, HttpServletResponse response){
334
335        String courseId = request.getParameter("courseId");
336        String planItemId = request.getParameter("planItemId");
337        String uniqueId = request.getParameter("uniqueId");
338        String termId = request.getParameter("termId");
339
340        Course course = KsapFrameworkServiceLocator.getCourseHelper().getCurrentVersionOfCourse(courseId);
341
342        dialogForm.setCourseId(courseId);
343        dialogForm.setCourseCode(course.getCode());
344        dialogForm.setCourseTitle(course.getCourseTitle());
345
346        // Set Credits to display for course
347        String creditString = KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().formatCredits(course);
348        dialogForm.setCreditsDisplay(creditString);
349
350        dialogForm.setUniqueId(uniqueId);
351        dialogForm.setPlanItemId(planItemId);
352        dialogForm.setTermId(termId);
353        dialogForm.setTermName(KsapFrameworkServiceLocator.getTermHelper().getYearTerm(termId).getLongName());
354
355
356        return dialogForm;
357    }
358
359    /**
360     * @see org.kuali.student.ap.planner.service.PlannerViewHelperService#loadMovePlanItemForm(org.kuali.rice.krad.web.form.UifFormBase, org.kuali.student.ap.planner.form.MovePlanItemForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
361     */
362    @Override
363    public UifFormBase loadMovePlanItemForm(UifFormBase submittedForm, MovePlanItemForm dialogForm,
364                                              HttpServletRequest request, HttpServletResponse response){
365
366        String courseId = request.getParameter("courseId");
367        String planItemId = request.getParameter("planItemId");
368        String uniqueId = request.getParameter("uniqueId");
369        String termId = request.getParameter("termId");
370
371        Course course = KsapFrameworkServiceLocator.getCourseHelper().getCurrentVersionOfCourse(courseId);
372
373        dialogForm.setCourseId(courseId);
374        dialogForm.setCourseCode(course.getCode());
375        dialogForm.setCourseTitle(course.getCourseTitle());
376
377        CourseSummaryPopoverDetailsWrapper courseDetails = new CourseSummaryPopoverDetailsWrapper();
378        courseDetails.setScheduledTerms(KsapFrameworkServiceLocator.getCourseHelper().getScheduledTermsForCourse(course));
379        dialogForm.setCourseSummaryDetails(courseDetails);
380
381        // Set Credits to display for course
382        String creditString = KsapFrameworkServiceLocator.getCourseHelper().getCreditsFormatter().formatCredits(course);
383        dialogForm.setCreditsDisplay(creditString);
384
385        //Find terms that already contain this planned course
386        List<PlanItem> planItems = KsapFrameworkServiceLocator.getPlanHelper().loadStudentsPlanItemsForCourse(course);
387        List<String> plannedTermIds = KsapFrameworkServiceLocator.getPlanHelper().getTermIdsForPlanItems(planItems);
388        dialogForm.setPlannedTermIds(plannedTermIds);
389
390        dialogForm.setUniqueId(uniqueId);
391        dialogForm.setPlanItemId(planItemId);
392        dialogForm.setTermId(termId);
393
394
395        return dialogForm;
396    }
397
398    private CourseSummaryPopoverDetailsWrapper getCourseSummaryPopoverDetails(Course course){
399        CourseSummaryPopoverDetailsWrapper courseDetails = new CourseSummaryPopoverDetailsWrapper();
400
401        // courseDetails.setCourseRequisites(CourseDetailsUtil.getCourseRequisites(course));
402        courseDetails.setCourseRequisitesMap(CourseDetailsUtil.getCourseRequisitesMap(course));
403
404        // Load Term information
405        courseDetails.setScheduledTerms(KsapFrameworkServiceLocator.getCourseHelper()
406                .getScheduledTermsForCourse(course));
407        courseDetails.setProjectedTerms(KsapFrameworkServiceLocator.getCourseHelper().getProjectedTermsForCourse(course));
408
409        // Load Last Offered Term information if course is not scheduled
410        if(courseDetails.getScheduledTerms().isEmpty()){
411            Term lastOfferedTerm = KsapFrameworkServiceLocator.getCourseHelper().getLastOfferedTermForCourse(course);
412            if (lastOfferedTerm != null){
413                courseDetails.setLastOffered(lastOfferedTerm.getName());
414            }
415            else {
416                // If no last offered is found set as null
417                courseDetails.setLastOffered(null);
418            }
419        }else{
420            courseDetails.setLastOffered(null);
421        }
422
423        return courseDetails;
424    }
425}