package fi.otavanopisto.muikku.plugins.evaluation; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.logging.Logger; import javax.ejb.Stateful; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import fi.otavanopisto.muikku.i18n.LocaleController; import fi.otavanopisto.muikku.model.base.Tag; import fi.otavanopisto.muikku.model.users.UserEntity; import fi.otavanopisto.muikku.model.workspace.WorkspaceEntity; import fi.otavanopisto.muikku.model.workspace.WorkspaceRoleArchetype; import fi.otavanopisto.muikku.model.workspace.WorkspaceUserEntity; import fi.otavanopisto.muikku.plugins.communicator.CommunicatorController; import fi.otavanopisto.muikku.plugins.communicator.model.CommunicatorMessageCategory; import fi.otavanopisto.muikku.plugins.evaluation.model.SupplementationRequest; import fi.otavanopisto.muikku.plugins.evaluation.model.WorkspaceMaterialEvaluation; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.RestAssessment; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.RestAssessmentRequest; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.RestAssignment; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.RestSupplementationRequest; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.WorkspaceGrade; import fi.otavanopisto.muikku.plugins.evaluation.rest.model.WorkspaceGradingScale; import fi.otavanopisto.muikku.plugins.workspace.WorkspaceMaterialController; import fi.otavanopisto.muikku.plugins.workspace.WorkspaceMaterialReplyController; import fi.otavanopisto.muikku.plugins.workspace.model.WorkspaceMaterial; import fi.otavanopisto.muikku.plugins.workspace.model.WorkspaceMaterialAssignmentType; import fi.otavanopisto.muikku.plugins.workspace.model.WorkspaceMaterialReply; import fi.otavanopisto.muikku.plugins.workspace.model.WorkspaceMaterialReplyState; import fi.otavanopisto.muikku.schooldata.GradingController; import fi.otavanopisto.muikku.schooldata.RestCatchSchoolDataExceptions; import fi.otavanopisto.muikku.schooldata.SchoolDataIdentifier; import fi.otavanopisto.muikku.schooldata.WorkspaceController; import fi.otavanopisto.muikku.schooldata.WorkspaceEntityController; import fi.otavanopisto.muikku.schooldata.entity.CompositeAssessmentRequest; import fi.otavanopisto.muikku.schooldata.entity.CompositeGrade; import fi.otavanopisto.muikku.schooldata.entity.CompositeGradingScale; import fi.otavanopisto.muikku.schooldata.entity.GradingScale; import fi.otavanopisto.muikku.schooldata.entity.GradingScaleItem; import fi.otavanopisto.muikku.schooldata.entity.User; import fi.otavanopisto.muikku.schooldata.entity.Workspace; import fi.otavanopisto.muikku.schooldata.entity.WorkspaceAssessment; import fi.otavanopisto.muikku.schooldata.entity.WorkspaceUser; import fi.otavanopisto.muikku.security.MuikkuPermissions; import fi.otavanopisto.muikku.servlet.BaseUrl; import fi.otavanopisto.muikku.session.SessionController; import fi.otavanopisto.muikku.users.UserController; import fi.otavanopisto.muikku.users.UserEntityController; import fi.otavanopisto.muikku.users.WorkspaceUserEntityController; import fi.otavanopisto.security.rest.RESTPermit; import fi.otavanopisto.security.rest.RESTPermit.Handling; @RequestScoped @Stateful @Produces("application/json") @Path("/evaluation") @RestCatchSchoolDataExceptions public class Evaluation2RESTService { @Inject @BaseUrl private String baseUrl; @Inject private Logger logger; @Inject private LocaleController localeController; @Inject private SessionController sessionController; @Inject private CommunicatorController communicatorController; @Inject private GradingController gradingController; @Inject private UserController userController; @Inject private UserEntityController userEntityController; @Inject private WorkspaceController workspaceController; @Inject private EvaluationController evaluationController; @Inject private WorkspaceEntityController workspaceEntityController; @Inject private WorkspaceUserEntityController workspaceUserEntityController; @Inject private WorkspaceMaterialController workspaceMaterialController; @Inject private WorkspaceMaterialReplyController workspaceMaterialReplyController; @DELETE @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/evaluationdata") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response deleteWorkspaceAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // Entities and identifiers WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (workspaceEntity == null || userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); SchoolDataIdentifier userIdentifier = new SchoolDataIdentifier(userEntity.getDefaultIdentifier(), userEntity.getDefaultSchoolDataSource().getIdentifier()); // If the workspace user has been given a graded evaluation, remove that // TODO listWorkspaceAssessments is incorrect; one student in one workspace should have one assessment at most List<WorkspaceAssessment> workspaceAssessments = gradingController.listWorkspaceAssessments(workspaceIdentifier, userIdentifier); WorkspaceAssessment workspaceAssessment = workspaceAssessments.isEmpty() ? null : workspaceAssessments.get(0); if (workspaceAssessment != null) { gradingController.deleteWorkspaceAssessment(workspaceIdentifier, userIdentifier, workspaceAssessment.getIdentifier()); } // If the workspace user has been given a supplementation request, remove that SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspace(userEntityId, workspaceEntityId); if (supplementationRequest != null) { evaluationController.deleteSupplementationRequest(supplementationRequest); } // If student has assessment requests, restore the latest one (issue #2716) gradingController.restoreLatestAssessmentRequest(workspaceIdentifier, userIdentifier); return Response.noContent().build(); } @GET @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/assessment") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response findWorkspaceAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { // Allow students to access their own assessments if (!sessionController.getLoggedUserEntity().getId().equals(userEntityId)) { return Response.status(Status.FORBIDDEN).build(); } return Response.status(Status.FORBIDDEN).build(); } // Entities and identifiers WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (workspaceEntity == null || userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); SchoolDataIdentifier userIdentifier = new SchoolDataIdentifier(userEntity.getDefaultIdentifier(), userEntity.getDefaultSchoolDataSource().getIdentifier()); // TODO listWorkspaceAssessments is incorrect; one student in one workspace should have one assessment at most List<WorkspaceAssessment> workspaceAssessments = gradingController.listWorkspaceAssessments(workspaceIdentifier, userIdentifier); WorkspaceAssessment workspaceAssessment = workspaceAssessments.isEmpty() ? null : workspaceAssessments.get(0); if (workspaceAssessment == null) { return Response.status(Status.NOT_FOUND).build(); } RestAssessment restAssessment = new RestAssessment( workspaceAssessment.getIdentifier().toId(), workspaceAssessment.getAssessingUserIdentifier().toId(), workspaceAssessment.getGradingScaleIdentifier().toId(), workspaceAssessment.getGradeIdentifier().toId(), workspaceAssessment.getVerbalAssessment(), workspaceAssessment.getDate(), workspaceAssessment.getPassing()); return Response.ok(restAssessment).build(); } @GET @Path("/workspace/{WORKSPACEENTITYID}/assignments") @RESTPermit(handling = Handling.INLINE) public Response listWorkspaceAssignments(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @QueryParam("userEntityId") Long userEntityId) { // Workspace entity WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.NOT_FOUND).build(); } // User entity (optional) UserEntity userEntity = null; if (userEntityId != null) { userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.NOT_FOUND).build(); } } // Workspace materials... List<WorkspaceMaterial> workspaceMaterials = workspaceMaterialController.listVisibleWorkspaceMaterialsByAssignmentType(workspaceEntity, WorkspaceMaterialAssignmentType.EVALUATED); workspaceMaterials.addAll(workspaceMaterialController.listVisibleWorkspaceMaterialsByAssignmentType(workspaceEntity, WorkspaceMaterialAssignmentType.EXERCISE)); // ...to RestAssignments List<RestAssignment> assignments = new ArrayList<RestAssignment>(); for (WorkspaceMaterial workspaceMaterial : workspaceMaterials) { Long workspaceMaterialEvaluationId = null; Long workspaceMaterialId = workspaceMaterial.getId(); Long materialId = workspaceMaterial.getMaterialId(); String path = workspaceMaterial.getPath(); String title = workspaceMaterial.getTitle(); Boolean evaluable = workspaceMaterial.getAssignmentType() == WorkspaceMaterialAssignmentType.EVALUATED; Date submitted = null; Date evaluated = null; String grade = null; String literalEvaluation = null; if (userEntity != null) { WorkspaceMaterialReply workspaceMaterialReply = workspaceMaterialReplyController.findWorkspaceMaterialReplyByWorkspaceMaterialAndUserEntity(workspaceMaterial, userEntity); if (workspaceMaterialReply != null) { WorkspaceMaterialReplyState replyState = workspaceMaterialReply.getState(); if (replyState == WorkspaceMaterialReplyState.SUBMITTED || replyState == WorkspaceMaterialReplyState.PASSED || replyState == WorkspaceMaterialReplyState.FAILED || replyState == WorkspaceMaterialReplyState.INCOMPLETE) { submitted = workspaceMaterialReply.getLastModified(); } } WorkspaceMaterialEvaluation workspaceMaterialEvaluation = evaluationController.findWorkspaceMaterialEvaluationByWorkspaceMaterialAndStudent(workspaceMaterial, userEntity); if (workspaceMaterialEvaluation != null) { workspaceMaterialEvaluationId = workspaceMaterialEvaluation.getId(); evaluated = workspaceMaterialEvaluation.getEvaluated(); GradingScale gradingScale = gradingController.findGradingScale( workspaceMaterialEvaluation.getGradingScaleSchoolDataSource(), workspaceMaterialEvaluation.getGradingScaleIdentifier()); if (gradingScale != null) { GradingScaleItem gradingScaleItem = gradingController.findGradingScaleItem( gradingScale, workspaceMaterialEvaluation.getGradeSchoolDataSource(), workspaceMaterialEvaluation.getGradeIdentifier()); if (gradingScaleItem != null) { grade = gradingScaleItem.getName(); } } literalEvaluation = workspaceMaterialEvaluation.getVerbalAssessment(); } else { SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspaceMaterialAndArchived( userEntity.getId(), workspaceMaterial.getId(), Boolean.FALSE); if (supplementationRequest != null) { evaluated = supplementationRequest.getRequestDate(); literalEvaluation = supplementationRequest.getRequestText(); } } } assignments.add(new RestAssignment(workspaceMaterialEvaluationId, workspaceMaterialId, materialId, path, title, evaluable, submitted, evaluated, grade, literalEvaluation)); } return Response.ok(assignments).build(); } @GET @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/workspacematerial/{WORKSPACEMATERIALID}/assessment") @RESTPermit(handling = Handling.INLINE) public Response findWorkspaceMaterialAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, @PathParam("WORKSPACEMATERIALID") Long workspaceMaterialId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material WorkspaceMaterial workspaceMaterial = workspaceMaterialController.findWorkspaceMaterialById(workspaceMaterialId); if (workspaceMaterial == null) { return Response.status(Status.NOT_FOUND).entity("workspaceMaterial not found").build(); } // Workspace material evaluation WorkspaceMaterialEvaluation workspaceMaterialEvaluation = evaluationController.findWorkspaceMaterialEvaluationByWorkspaceMaterialAndStudent(workspaceMaterial, userEntity); if (workspaceMaterialEvaluation == null) { return Response.status(Status.NOT_FOUND).build(); } // WorkspaceMaterialEvaluation to RestAssessment UserEntity assessingUser = userEntityController.findUserEntityById(workspaceMaterialEvaluation.getAssessorEntityId()); String assessmentIdentifier = workspaceMaterialEvaluation.getId().toString(); String assessingUserIdentifier = new SchoolDataIdentifier(assessingUser.getDefaultIdentifier(), assessingUser.getDefaultSchoolDataSource().getIdentifier()).toId(); String gradingScaleIdentifier = new SchoolDataIdentifier(workspaceMaterialEvaluation.getGradingScaleIdentifier(), workspaceMaterialEvaluation.getGradingScaleSchoolDataSource()).toId(); String gradeIdentifier = new SchoolDataIdentifier(workspaceMaterialEvaluation.getGradeIdentifier(), workspaceMaterialEvaluation.getGradeSchoolDataSource()).toId(); RestAssessment restAssessment = new RestAssessment( assessmentIdentifier, assessingUserIdentifier, gradingScaleIdentifier, gradeIdentifier, workspaceMaterialEvaluation.getVerbalAssessment(), workspaceMaterialEvaluation.getEvaluated(), null); // TODO Passing grade return Response.ok(restAssessment).build(); } @GET @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/supplementationrequest") @RESTPermit(handling = Handling.INLINE) public Response findWorkspaceSupplementationRequest(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace entity WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.NOT_FOUND).entity("workspaceEntity not found").build(); } // Workspace supplementation request SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspace(userEntityId, workspaceEntityId); if (supplementationRequest == null) { return Response.status(Status.NOT_FOUND).build(); } // SupplementationRequest to RestSupplementationRequest RestSupplementationRequest restSupplementationRequest = new RestSupplementationRequest( supplementationRequest.getId(), supplementationRequest.getUserEntityId(), supplementationRequest.getStudentEntityId(), supplementationRequest.getWorkspaceEntityId(), supplementationRequest.getWorkspaceMaterialId(), supplementationRequest.getRequestDate(), supplementationRequest.getRequestText()); return Response.ok(restSupplementationRequest).build(); } @GET @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/workspacematerial/{WORKSPACEMATERIALID}/supplementationrequest") @RESTPermit(handling = Handling.INLINE) public Response findWorkspaceMaterialSupplementationRequest(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, @PathParam("WORKSPACEMATERIALID") Long workspaceMaterialId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { // Allow students to access their own supplementation requests if (!sessionController.getLoggedUserEntity().getId().equals(userEntityId)) { return Response.status(Status.FORBIDDEN).build(); } } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material WorkspaceMaterial workspaceMaterial = workspaceMaterialController.findWorkspaceMaterialById(workspaceMaterialId); if (workspaceMaterial == null) { return Response.status(Status.NOT_FOUND).entity("workspaceMaterial not found").build(); } // Supplementation request SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspaceMaterial(userEntityId, workspaceMaterialId); if (supplementationRequest == null) { return Response.status(Status.NOT_FOUND).build(); } // SupplementationRequest to RestSupplementationRequest RestSupplementationRequest restSupplementationRequest = new RestSupplementationRequest( supplementationRequest.getId(), supplementationRequest.getUserEntityId(), supplementationRequest.getStudentEntityId(), supplementationRequest.getWorkspaceEntityId(), supplementationRequest.getWorkspaceMaterialId(), supplementationRequest.getRequestDate(), supplementationRequest.getRequestText()); return Response.ok(restSupplementationRequest).build(); } @PUT @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/workspacematerial/{WORKSPACEMATERIALID}/assessment") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response updateWorkspaceMaterialAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, @PathParam("WORKSPACEMATERIALID") Long workspaceMaterialId, RestAssessment payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material WorkspaceMaterial workspaceMaterial = workspaceMaterialController.findWorkspaceMaterialById(workspaceMaterialId); if (workspaceMaterial == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material evaluation WorkspaceMaterialEvaluation workspaceMaterialEvaluation = evaluationController.findWorkspaceMaterialEvaluationByWorkspaceMaterialAndStudent(workspaceMaterial, userEntity); if (workspaceMaterialEvaluation == null) { return Response.status(Status.BAD_REQUEST).build(); } // Grade SchoolDataIdentifier gradingScaleIdentifier = SchoolDataIdentifier.fromId(payload.getGradingScaleIdentifier()); GradingScale gradingScale = gradingController.findGradingScale(gradingScaleIdentifier); SchoolDataIdentifier gradeIdentifier = SchoolDataIdentifier.fromId(payload.getGradeIdentifier()); GradingScaleItem gradingScaleItem = gradingController.findGradingScaleItem(gradingScale, gradeIdentifier); // Assessor SchoolDataIdentifier assessorIdentifier = SchoolDataIdentifier.fromId(payload.getAssessorIdentifier()); User assessingUser = userController.findUserByIdentifier(assessorIdentifier); UserEntity assessor = userEntityController.findUserEntityByUser(assessingUser); workspaceMaterialEvaluation = evaluationController.updateWorkspaceMaterialEvaluation( workspaceMaterialEvaluation, gradingScale, gradingScaleItem, assessor, payload.getAssessmentDate(), payload.getVerbalAssessment()); // WorkspaceMaterialEvaluation to RestAssessment RestAssessment restAssessment = new RestAssessment( workspaceMaterialEvaluation.getId().toString(), assessorIdentifier.toId(), gradingScaleIdentifier.toId(), gradeIdentifier.toId(), workspaceMaterialEvaluation.getVerbalAssessment(), workspaceMaterialEvaluation.getEvaluated(), gradingScaleItem.isPassingGrade()); return Response.ok(restAssessment).build(); } @PUT @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/assessment") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response updateWorkspaceAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, RestAssessment payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // Entities and identifiers WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); Workspace workspace = workspaceController.findWorkspace(workspaceEntity); if (workspaceEntity == null || userEntity == null || workspace == null) { return Response.status(Status.BAD_REQUEST).build(); } SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); SchoolDataIdentifier userIdentifier = new SchoolDataIdentifier(userEntity.getDefaultIdentifier(), userEntity.getDefaultSchoolDataSource().getIdentifier()); // TODO listWorkspaceAssessments is incorrect; one student in one workspace should have one assessment at most List<WorkspaceAssessment> workspaceAssessments = gradingController.listWorkspaceAssessments(workspaceIdentifier, userIdentifier); WorkspaceAssessment workspaceAssessment = workspaceAssessments.isEmpty() ? null : workspaceAssessments.get(0); if (workspaceAssessment == null) { return Response.status(Status.NOT_FOUND).build(); } // Workspace user WorkspaceUser workspaceUser = workspaceController.findWorkspaceUserByWorkspaceAndUser(workspaceIdentifier, userIdentifier); // Assessor SchoolDataIdentifier assessorIdentifier = SchoolDataIdentifier.fromId(payload.getAssessorIdentifier()); User assessingUser = userController.findUserByIdentifier(assessorIdentifier); UserEntity assessingUserEntity = userEntityController.findUserEntityByUser(assessingUser); // Grade SchoolDataIdentifier gradingScaleIdentifier = SchoolDataIdentifier.fromId(payload.getGradingScaleIdentifier()); GradingScale gradingScale = gradingController.findGradingScale(gradingScaleIdentifier); SchoolDataIdentifier gradeIdentifier = SchoolDataIdentifier.fromId(payload.getGradeIdentifier()); GradingScaleItem gradingScaleItem = gradingController.findGradingScaleItem(gradingScale, gradeIdentifier); // Update workspaceAssessment = gradingController.updateWorkspaceAssessment( workspaceAssessment.getIdentifier(), workspaceUser, assessingUser, gradingScaleItem, payload.getVerbalAssessment(), payload.getAssessmentDate()); // Notification sendAssessmentNotification(workspaceEntity, workspaceAssessment, assessingUserEntity, userEntity, workspace, gradingScaleItem.getName()); // Back to rest RestAssessment restAssessment = new RestAssessment( workspaceAssessment.getIdentifier().toId(), workspaceAssessment.getAssessingUserIdentifier().toId(), workspaceAssessment.getGradingScaleIdentifier().toId(), workspaceAssessment.getGradeIdentifier().toId(), workspaceAssessment.getVerbalAssessment(), workspaceAssessment.getDate(), workspaceAssessment.getPassing()); return Response.ok(restAssessment).build(); } @POST @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/workspacematerial/{WORKSPACEMATERIALID}/assessment") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response createWorkspaceMaterialAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, @PathParam("WORKSPACEMATERIALID") Long workspaceMaterialId, RestAssessment payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material WorkspaceMaterial workspaceMaterial = workspaceMaterialController.findWorkspaceMaterialById(workspaceMaterialId); if (workspaceMaterial == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material evaluation WorkspaceMaterialEvaluation workspaceMaterialEvaluation = evaluationController.findWorkspaceMaterialEvaluationByWorkspaceMaterialAndStudent(workspaceMaterial, userEntity); // Grade SchoolDataIdentifier gradingScaleIdentifier = SchoolDataIdentifier.fromId(payload.getGradingScaleIdentifier()); GradingScale gradingScale = gradingController.findGradingScale(gradingScaleIdentifier); SchoolDataIdentifier gradeIdentifier = SchoolDataIdentifier.fromId(payload.getGradeIdentifier()); GradingScaleItem gradingScaleItem = gradingController.findGradingScaleItem(gradingScale, gradeIdentifier); // Assessor SchoolDataIdentifier assessorIdentifier = SchoolDataIdentifier.fromId(payload.getAssessorIdentifier()); User assessingUser = userController.findUserByIdentifier(assessorIdentifier); UserEntity assessor = userEntityController.findUserEntityByUser(assessingUser); // Create/update material assessment if (workspaceMaterialEvaluation == null) { workspaceMaterialEvaluation = evaluationController.createWorkspaceMaterialEvaluation( userEntity, workspaceMaterial, gradingScale, gradingScaleItem, assessor, payload.getAssessmentDate(), payload.getVerbalAssessment()); } else { workspaceMaterialEvaluation = evaluationController.updateWorkspaceMaterialEvaluation( workspaceMaterialEvaluation, gradingScale, gradingScaleItem, assessor, payload.getAssessmentDate(), payload.getVerbalAssessment()); } // Remove possible workspace assignment supplementation request SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspaceMaterialAndArchived(userEntityId, workspaceMaterialId, Boolean.FALSE); if (supplementationRequest != null) { evaluationController.deleteSupplementationRequest(supplementationRequest); } // WorkspaceMaterialEvaluation to RestAssessment RestAssessment restAssessment = new RestAssessment( workspaceMaterialEvaluation.getId().toString(), assessorIdentifier.toId(), gradingScaleIdentifier.toId(), gradeIdentifier.toId(), workspaceMaterialEvaluation.getVerbalAssessment(), workspaceMaterialEvaluation.getEvaluated(), gradingScaleItem.isPassingGrade()); return Response.ok(restAssessment).build(); } @POST @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/supplementationrequest") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response createWorkspaceSupplementationRequest(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, RestSupplementationRequest payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace entity WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); if (workspaceEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace supplementation request SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspace(userEntityId, workspaceEntityId); // Create/update workspace supplementation request if (supplementationRequest == null) { supplementationRequest = evaluationController.createSupplementationRequest( payload.getUserEntityId(), payload.getStudentEntityId(), payload.getWorkspaceEntityId(), null, payload.getRequestDate(), payload.getRequestText()); } else { supplementationRequest = evaluationController.updateSupplementationRequest( supplementationRequest, payload.getUserEntityId(), payload.getRequestDate(), payload.getRequestText()); } // Delete possible workspace assessment SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); SchoolDataIdentifier userIdentifier = new SchoolDataIdentifier(userEntity.getDefaultIdentifier(), userEntity.getDefaultSchoolDataSource().getIdentifier()); // TODO listWorkspaceAssessments is incorrect; one student in one workspace should have one assessment at most List<WorkspaceAssessment> workspaceAssessments = gradingController.listWorkspaceAssessments(workspaceIdentifier, userIdentifier); WorkspaceAssessment workspaceAssessment = workspaceAssessments.isEmpty() ? null : workspaceAssessments.get(0); if (workspaceAssessment != null) { gradingController.deleteWorkspaceAssessment(workspaceIdentifier, userIdentifier, workspaceAssessment.getIdentifier()); } // SupplementationRequest to RestSupplementationRequest RestSupplementationRequest restSupplementationRequest = new RestSupplementationRequest( supplementationRequest.getId(), supplementationRequest.getUserEntityId(), supplementationRequest.getStudentEntityId(), supplementationRequest.getWorkspaceEntityId(), supplementationRequest.getWorkspaceMaterialId(), supplementationRequest.getRequestDate(), supplementationRequest.getRequestText()); return Response.ok(restSupplementationRequest).build(); } @POST @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/workspacematerial/{WORKSPACEMATERIALID}/supplementationrequest") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response createWorkspaceMaterialSupplementationRequest(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, @PathParam("WORKSPACEMATERIALID") Long workspaceMaterialId, RestSupplementationRequest payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // User entity UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); if (userEntity == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material WorkspaceMaterial workspaceMaterial = workspaceMaterialController.findWorkspaceMaterialById(workspaceMaterialId); if (workspaceMaterial == null) { return Response.status(Status.BAD_REQUEST).build(); } // Workspace material supplementation request SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspaceMaterial(userEntityId, workspaceMaterialId); // Create/update workspace material supplementation request if (supplementationRequest == null) { supplementationRequest = evaluationController.createSupplementationRequest( payload.getUserEntityId(), payload.getStudentEntityId(), null, payload.getWorkspaceMaterialId(), payload.getRequestDate(), payload.getRequestText()); } else { supplementationRequest = evaluationController.updateSupplementationRequest( supplementationRequest, payload.getUserEntityId(), payload.getRequestDate(), payload.getRequestText()); } // Delete possible workspace material assessment WorkspaceMaterialEvaluation workspaceMaterialEvaluation = evaluationController.findWorkspaceMaterialEvaluationByWorkspaceMaterialAndStudent(workspaceMaterial, userEntity); if (workspaceMaterialEvaluation != null) { evaluationController.deleteWorkspaceMaterialEvaluation(workspaceMaterialEvaluation); } // SupplementationRequest to RestSupplementationRequest RestSupplementationRequest restSupplementationRequest = new RestSupplementationRequest( supplementationRequest.getId(), supplementationRequest.getUserEntityId(), supplementationRequest.getStudentEntityId(), supplementationRequest.getWorkspaceEntityId(), supplementationRequest.getWorkspaceMaterialId(), supplementationRequest.getRequestDate(), supplementationRequest.getRequestText()); return Response.ok(restSupplementationRequest).build(); } @POST @Path("/workspace/{WORKSPACEENTITYID}/user/{USERENTITYID}/assessment") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response createWorkspaceAssessment(@PathParam("WORKSPACEENTITYID") Long workspaceEntityId, @PathParam("USERENTITYID") Long userEntityId, RestAssessment payload) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } // Entities and identifiers WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); UserEntity userEntity = userEntityController.findUserEntityById(userEntityId); Workspace workspace = workspaceController.findWorkspace(workspaceEntity); if (workspaceEntity == null || userEntity == null || workspace == null) { return Response.status(Status.BAD_REQUEST).build(); } SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); SchoolDataIdentifier userIdentifier = new SchoolDataIdentifier(userEntity.getDefaultIdentifier(), userEntity.getDefaultSchoolDataSource().getIdentifier()); // TODO listWorkspaceAssessments is incorrect; one student in one workspace should have one assessment at most List<WorkspaceAssessment> workspaceAssessments = gradingController.listWorkspaceAssessments(workspaceIdentifier, userIdentifier); WorkspaceAssessment workspaceAssessment = workspaceAssessments.isEmpty() ? null : workspaceAssessments.get(0); // Workspace user WorkspaceUser workspaceUser = workspaceController.findWorkspaceUserByWorkspaceAndUser(workspaceIdentifier, userIdentifier); // Assessor SchoolDataIdentifier assessorIdentifier = SchoolDataIdentifier.fromId(payload.getAssessorIdentifier()); User assessingUser = userController.findUserByIdentifier(assessorIdentifier); UserEntity assessingUserEntity = userEntityController.findUserEntityByUser(assessingUser); // Grade SchoolDataIdentifier gradingScaleIdentifier = SchoolDataIdentifier.fromId(payload.getGradingScaleIdentifier()); GradingScale gradingScale = gradingController.findGradingScale(gradingScaleIdentifier); SchoolDataIdentifier gradeIdentifier = SchoolDataIdentifier.fromId(payload.getGradeIdentifier()); GradingScaleItem gradingScaleItem = gradingController.findGradingScaleItem(gradingScale, gradeIdentifier); // Create/update workspace assessment if (workspaceAssessment == null) { workspaceAssessment = gradingController.createWorkspaceAssessment( workspaceIdentifier.getDataSource(), workspaceUser, assessingUser, gradingScaleItem, payload.getVerbalAssessment(), payload.getAssessmentDate()); } else { workspaceAssessment = gradingController.updateWorkspaceAssessment( workspaceAssessment.getIdentifier(), workspaceUser, assessingUser, gradingScaleItem, payload.getVerbalAssessment(), payload.getAssessmentDate()); } // Delete workspace supplementation request (if any) SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspace(userEntity.getId(), workspaceEntity.getId()); if (supplementationRequest != null) { evaluationController.deleteSupplementationRequest(supplementationRequest); } // Notification sendAssessmentNotification(workspaceEntity, workspaceAssessment, assessingUserEntity, userEntity, workspace, gradingScaleItem.getName()); // Back to rest RestAssessment restAssessment = new RestAssessment( workspaceAssessment.getIdentifier().toId(), workspaceAssessment.getAssessingUserIdentifier().toId(), workspaceAssessment.getGradingScaleIdentifier().toId(), workspaceAssessment.getGradeIdentifier().toId(), workspaceAssessment.getVerbalAssessment(), workspaceAssessment.getDate(), workspaceAssessment.getPassing()); return Response.ok(restAssessment).build(); } @GET @Path("/compositeGradingScales") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response listGrades() { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } List<WorkspaceGradingScale> restGradingScales = new ArrayList<WorkspaceGradingScale>(); List<CompositeGradingScale> gradingScales = gradingController.listCompositeGradingScales(); for (CompositeGradingScale gradingScale : gradingScales) { List<CompositeGrade> grades = gradingScale.getGrades(); List<WorkspaceGrade> restGrades = new ArrayList<WorkspaceGrade>(); for (CompositeGrade grade : grades) { restGrades.add(new WorkspaceGrade(grade.getGradeName(), grade.getGradeIdentifier(), gradingScale.getSchoolDataSource())); } restGradingScales.add(new WorkspaceGradingScale( gradingScale.getScaleName(), gradingScale.getScaleIdentifier(), gradingScale.getSchoolDataSource(), restGrades)); } return Response.ok(restGradingScales).build(); } @GET @Path("/compositeAssessmentRequests") @RESTPermit (handling = Handling.INLINE, requireLoggedIn = true) public Response listAssessmentRequests(@QueryParam("workspaceEntityId") Long workspaceEntityId) { if (!sessionController.isLoggedIn()) { return Response.status(Status.UNAUTHORIZED).build(); } if (!sessionController.hasEnvironmentPermission(MuikkuPermissions.ACCESS_EVALUATION)) { return Response.status(Status.FORBIDDEN).build(); } List<RestAssessmentRequest> restAssessmentRequests = new ArrayList<RestAssessmentRequest>(); if (workspaceEntityId == null) { // List assessment requests by staff member SchoolDataIdentifier loggedUser = sessionController.getLoggedUser(); List<CompositeAssessmentRequest> assessmentRequests = gradingController.listAssessmentRequestsByStaffMember(loggedUser); for (CompositeAssessmentRequest assessmentRequest : assessmentRequests) { restAssessmentRequests.add(toRestAssessmentRequest(assessmentRequest)); } } else { // List assessment requests by workspace WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceEntityById(workspaceEntityId); SchoolDataIdentifier workspaceIdentifier = new SchoolDataIdentifier(workspaceEntity.getIdentifier(), workspaceEntity.getDataSource().getIdentifier()); List<WorkspaceUserEntity> workspaceUserEntities = workspaceUserEntityController.listWorkspaceUserEntitiesByRoleArchetype(workspaceEntity, WorkspaceRoleArchetype.STUDENT); List<String> workspaceStudentIdentifiers = new ArrayList<String>(); for (WorkspaceUserEntity workspaceUserEntity : workspaceUserEntities) { workspaceStudentIdentifiers.add(workspaceUserEntity.getIdentifier()); } List<CompositeAssessmentRequest> assessmentRequests = gradingController.listAssessmentRequestsByWorkspace(workspaceIdentifier, workspaceStudentIdentifiers); for (CompositeAssessmentRequest assessmentRequest : assessmentRequests) { restAssessmentRequests.add(toRestAssessmentRequest(assessmentRequest)); } } return Response.ok(restAssessmentRequests).build(); } private RestAssessmentRequest toRestAssessmentRequest(CompositeAssessmentRequest compositeAssessmentRequest) { Long assignmentsDone = 0L; Long assignmentsTotal = 0L; // Assignments total WorkspaceEntity workspaceEntity = workspaceEntityController.findWorkspaceByIdentifier(compositeAssessmentRequest.getCourseIdentifier()); if (workspaceEntity == null) { logger.severe(String.format("WorkspaceEntity for course %s not found", compositeAssessmentRequest.getCourseIdentifier())); } else { List<WorkspaceMaterial> evaluatedAssignments = workspaceMaterialController.listVisibleWorkspaceMaterialsByAssignmentType( workspaceEntity, WorkspaceMaterialAssignmentType.EVALUATED); assignmentsTotal = new Long(evaluatedAssignments.size()); // Assignments done by user if (assignmentsTotal > 0) { UserEntity userEntity = userEntityController.findUserEntityByUserIdentifier(compositeAssessmentRequest.getUserIdentifier()); if (userEntity == null) { logger.severe(String.format("UserEntity not found for AssessmentRequest student %s not found", compositeAssessmentRequest.getUserIdentifier())); } else { List<WorkspaceMaterialReplyState> replyStates = new ArrayList<WorkspaceMaterialReplyState>(); replyStates.add(WorkspaceMaterialReplyState.FAILED); replyStates.add(WorkspaceMaterialReplyState.PASSED); replyStates.add(WorkspaceMaterialReplyState.SUBMITTED); replyStates.add(WorkspaceMaterialReplyState.INCOMPLETE); assignmentsDone = workspaceMaterialReplyController.getReplyCountByUserEntityAndReplyStatesAndWorkspaceMaterials(userEntity.getId(), replyStates, evaluatedAssignments); } } } WorkspaceUserEntity workspaceUserEntity = workspaceUserEntityController.findWorkspaceUserEntityByWorkspaceUserIdentifierIncludeArchived(compositeAssessmentRequest.getCourseStudentIdentifier()); UserEntity userEntity = userEntityController.findUserEntityByUserIdentifier(compositeAssessmentRequest.getUserIdentifier()); // An active workspace supplementation request will override graded, passing, and evaluationDate Boolean graded = Boolean.TRUE; Boolean passing = compositeAssessmentRequest.getPassing(); Date evaluationDate = compositeAssessmentRequest.getEvaluationDate(); if (userEntity != null) { SupplementationRequest supplementationRequest = evaluationController.findSupplementationRequestByStudentAndWorkspaceAndArchived( userEntity.getId(), workspaceEntity.getId(), Boolean.FALSE); if (supplementationRequest != null) { graded = Boolean.FALSE; passing = Boolean.FALSE; evaluationDate = supplementationRequest.getRequestDate(); } } RestAssessmentRequest restAssessmentRequest = new RestAssessmentRequest(); restAssessmentRequest.setWorkspaceUserEntityId(workspaceUserEntity == null ? null : workspaceUserEntity.getId()); restAssessmentRequest.setWorkspaceUserIdentifier(compositeAssessmentRequest.getCourseStudentIdentifier().toId()); restAssessmentRequest.setUserEntityId(userEntity == null ? null : userEntity.getId()); restAssessmentRequest.setAssessmentRequestDate(compositeAssessmentRequest.getAssessmentRequestDate()); restAssessmentRequest.setEvaluationDate(evaluationDate); restAssessmentRequest.setPassing(passing); restAssessmentRequest.setGraded(graded); restAssessmentRequest.setAssignmentsDone(assignmentsDone); restAssessmentRequest.setAssignmentsTotal(assignmentsTotal); restAssessmentRequest.setEnrollmentDate(compositeAssessmentRequest.getCourseEnrollmentDate()); restAssessmentRequest.setFirstName(compositeAssessmentRequest.getFirstName()); restAssessmentRequest.setLastName(compositeAssessmentRequest.getLastName()); restAssessmentRequest.setStudyProgramme(compositeAssessmentRequest.getStudyProgramme()); restAssessmentRequest.setWorkspaceEntityId(workspaceEntity == null ? null : workspaceEntity.getId()); restAssessmentRequest.setWorkspaceName(compositeAssessmentRequest.getCourseName()); restAssessmentRequest.setWorkspaceNameExtension(compositeAssessmentRequest.getCourseNameExtension()); restAssessmentRequest.setWorkspaceUrlName(workspaceEntity == null ? null : workspaceEntity.getUrlName()); return restAssessmentRequest; } private void sendAssessmentNotification(WorkspaceEntity workspaceEntity, WorkspaceAssessment workspaceAssessment, UserEntity evaluator, UserEntity student, Workspace workspace, String grade) { String workspaceUrl = String.format("%s/workspace/%s/materials", baseUrl, workspaceEntity.getUrlName()); Locale locale = userEntityController.getLocale(student); CommunicatorMessageCategory category = communicatorController.persistCategory("assessments"); communicatorController.createMessage( communicatorController.createMessageId(), evaluator, Arrays.asList(student), null, null, null, category, localeController.getText( locale, "plugin.workspace.assessment.notificationTitle", new Object[] {workspace.getName(), grade}), localeController.getText( locale, "plugin.workspace.assessment.notificationContent", new Object[] {workspaceUrl, workspace.getName(), grade, workspaceAssessment.getVerbalAssessment()}), Collections.<Tag>emptySet()); } }