org.sakaiproject.gradebookng.tool.actions.GradeUpdateAction.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.gradebookng.tool.actions.GradeUpdateAction.java

Source

/**
 * Copyright (c) 2003-2017 The Apereo Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *             http://opensource.org/licenses/ecl2
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sakaiproject.gradebookng.tool.actions;

import java.io.Serializable;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.sakaiproject.gradebookng.business.GradeSaveResponse;
import org.sakaiproject.gradebookng.business.util.CourseGradeFormatter;
import org.sakaiproject.gradebookng.business.util.FormatHelper;
import org.sakaiproject.gradebookng.tool.model.GradebookUiSettings;
import org.sakaiproject.gradebookng.tool.pages.GradebookPage;
import org.sakaiproject.gradebookng.business.GradebookNgBusinessService;
import org.sakaiproject.service.gradebook.shared.CategoryScoreData;
import org.sakaiproject.service.gradebook.shared.CourseGrade;
import org.sakaiproject.tool.gradebook.Gradebook;
import org.sakaiproject.util.NumberUtil;

public class GradeUpdateAction extends InjectableAction implements Serializable {

    private static final long serialVersionUID = 1L;

    @SpringBean(name = "org.sakaiproject.gradebookng.business.GradebookNgBusinessService")
    private GradebookNgBusinessService businessService;

    public GradeUpdateAction() {
    }

    private class GradeUpdateResponse implements ActionResponse {
        private String courseGrade;
        private String points;
        private String categoryScore;
        private List<Long> droppedItems;
        private boolean isOverride;
        private boolean extraCredit;

        public GradeUpdateResponse(final boolean extraCredit, final String courseGrade, final String points,
                final boolean isOverride, final String categoryScore, List<Long> droppedItems) {
            this.courseGrade = courseGrade;
            this.categoryScore = categoryScore;
            this.droppedItems = droppedItems;
            this.points = points;
            this.isOverride = isOverride;
            this.extraCredit = extraCredit;
        }

        public String getStatus() {
            return "OK";
        }

        public String toJson() {
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode result = mapper.createObjectNode();

            ArrayNode courseGradeArray = mapper.createArrayNode();
            courseGradeArray.add(courseGrade);
            courseGradeArray.add(points);
            courseGradeArray.add(isOverride ? 1 : 0);

            result.put("courseGrade", courseGradeArray);
            result.put("categoryScore", categoryScore);
            result.put("extraCredit", extraCredit);

            ArrayNode catDroppedItemsArray = mapper.createArrayNode();
            droppedItems.stream().forEach(i -> catDroppedItemsArray.add(i));
            result.put("categoryDroppedItems", catDroppedItemsArray);

            return result.toString();
        }
    }

    private class SaveGradeErrorResponse implements ActionResponse {
        private GradeSaveResponse serverResponse;

        public SaveGradeErrorResponse(GradeSaveResponse serverResponse) {
            this.serverResponse = serverResponse;
        }

        public String getStatus() {
            return "error";
        }

        public String toJson() {
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode result = mapper.createObjectNode();

            result.put("msg", serverResponse.toString());

            return result.toString();
        }
    }

    private class SaveGradeNoChangeResponse extends EmptyOkResponse {
        public SaveGradeNoChangeResponse() {
        }

        @Override
        public String getStatus() {
            return "nochange";
        }
    }

    @Override
    public ActionResponse handleEvent(final JsonNode params, final AjaxRequestTarget target) {
        final GradebookPage page = (GradebookPage) target.getPage();

        // clear the feedback message at the top of the page
        target.addChildren(page, FeedbackPanel.class);

        final String rawOldGrade = params.get("oldScore").textValue();
        final String rawNewGrade = params.get("newScore").textValue();

        if (StringUtils.isNotBlank(rawNewGrade)
                && (!NumberUtil.isValidLocaleDouble(rawNewGrade) || FormatHelper.validateDouble(rawNewGrade) < 0)) {
            target.add(page.updateLiveGradingMessage(page.getString("feedback.error")));

            return new ArgumentErrorResponse("Grade not valid");
        }

        final String oldGrade = FormatHelper.formatGradeFromUserLocale(rawOldGrade);
        final String newGrade = FormatHelper.formatGradeFromUserLocale(rawNewGrade);

        final String assignmentId = params.get("assignmentId").asText();
        final String studentUuid = params.get("studentId").asText();
        final String categoryId = params.has("categoryId") ? params.get("categoryId").asText() : null;

        // We don't pass the comment from the use interface,
        // but the service needs it otherwise it will assume 'null'
        // so pull it back from the service and poke it in there!
        final String comment = businessService.getAssignmentGradeComment(Long.valueOf(assignmentId), studentUuid);

        // for concurrency, get the original grade we have in the UI and pass it into the service as a check
        final GradeSaveResponse result = businessService.saveGrade(Long.valueOf(assignmentId), studentUuid,
                oldGrade, newGrade, comment);

        if (result.equals(GradeSaveResponse.NO_CHANGE)) {
            target.add(page.updateLiveGradingMessage(page.getString("feedback.saved")));

            return new SaveGradeNoChangeResponse();
        }

        if (!result.equals(GradeSaveResponse.OK) && !result.equals(GradeSaveResponse.OVER_LIMIT)) {
            target.add(page.updateLiveGradingMessage(page.getString("feedback.error")));

            return new SaveGradeErrorResponse(result);
        }

        final CourseGrade studentCourseGrade = businessService.getCourseGrade(studentUuid);

        boolean isOverride = false;
        String grade = "-";
        String points = "0";

        if (studentCourseGrade != null) {
            final GradebookUiSettings uiSettings = page.getUiSettings();
            final Gradebook gradebook = businessService.getGradebook();
            final CourseGradeFormatter courseGradeFormatter = new CourseGradeFormatter(gradebook,
                    page.getCurrentRole(),
                    businessService.isCourseGradeVisible(businessService.getCurrentUser().getId()),
                    uiSettings.getShowPoints(), true);

            grade = courseGradeFormatter.format(studentCourseGrade);
            if (studentCourseGrade.getPointsEarned() != null) {
                points = FormatHelper.formatDoubleToDecimal(studentCourseGrade.getPointsEarned());
            }
            if (studentCourseGrade.getEnteredGrade() != null) {
                isOverride = true;
            }
        }

        Optional<CategoryScoreData> catData = categoryId == null ? Optional.empty()
                : businessService.getCategoryScoreForStudent(Long.valueOf(categoryId), studentUuid, true);
        String categoryScore = catData.map(c -> String.valueOf(c.score)).orElse("-");
        List<Long> droppedItems = catData.map(c -> c.droppedItems).orElse(Collections.emptyList());

        target.add(page.updateLiveGradingMessage(page.getString("feedback.saved")));

        return new GradeUpdateResponse(result.equals(GradeSaveResponse.OVER_LIMIT), grade, points, isOverride,
                categoryScore, droppedItems);
    }
}