org.opentestsystem.authoring.testauth.service.impl.AssessmentServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.authoring.testauth.service.impl.AssessmentServiceImpl.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System
 * Copyright (c) 2013 American Institutes for Research
 * 
 * Distributed under the AIR Open Source License, Version 1.0
 * See accompanying file AIR-License-1_0.txt or at
 * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/
package org.opentestsystem.authoring.testauth.service.impl;

import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.paramArray;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.opentestsystem.authoring.testauth.domain.Assessment;
import org.opentestsystem.authoring.testauth.domain.AssessmentType;
import org.opentestsystem.authoring.testauth.domain.PublishingRecord;
import org.opentestsystem.authoring.testauth.domain.PublishingStatus;
import org.opentestsystem.authoring.testauth.domain.SimulationRecord;
import org.opentestsystem.authoring.testauth.domain.search.AssessmentSearchRequest;
import org.opentestsystem.authoring.testauth.persistence.AssessmentCounterRepository;
import org.opentestsystem.authoring.testauth.persistence.AssessmentRepository;
import org.opentestsystem.authoring.testauth.service.AssessmentChildCopier;
import org.opentestsystem.authoring.testauth.service.AssessmentChildDeleter;
import org.opentestsystem.authoring.testauth.service.AssessmentService;
import org.opentestsystem.authoring.testauth.service.FileGroupService;
import org.opentestsystem.authoring.testauth.service.PublicationService;
import org.opentestsystem.authoring.testauth.service.PublishingRecordService;
import org.opentestsystem.authoring.testauth.service.SubjectService;
import org.opentestsystem.shared.exception.LocalizedException;
import org.opentestsystem.shared.exception.RestException;
import org.opentestsystem.shared.search.domain.SearchResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service
public class AssessmentServiceImpl implements AssessmentService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AssessmentServiceImpl.class);
    private static final String TYPE_KEY = "type";

    @Autowired
    private transient AssessmentRepository assessmentRepository;

    @Autowired
    private transient AssessmentCounterRepository assessmentCounterRepository;

    @Autowired
    private SubjectService subjectService;

    @Autowired
    private PublicationService publicationService;

    @Autowired
    private PublishingRecordService publishingRecordService;

    @Autowired
    private FileGroupService fileGroupService;

    @Autowired
    private AssessmentChildCopier assessmentChildCopier;

    @Autowired
    private AssessmentChildDeleter assessmentChildDeleter;

    @Override
    public Assessment saveAssessment(final Assessment assessment) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Saving assessment");
        }

        if (assessment == null || StringUtils.isNotBlank(assessment.getId())) {
            throw new LocalizedException("assessment.invalid.id");
        }
        assessment.setStatus(PublishingStatus.INPROGRESS);
        assessment.setVersion("1.0");
        final Assessment savedAssessment = save(assessment);
        final PublishingRecord publishingRecord = new PublishingRecord();
        publishingRecord.setAssessmentId(savedAssessment.getId());
        this.publishingRecordService.savePublishingRecord(publishingRecord, false);

        final SimulationRecord simulationRecord = new SimulationRecord();
        simulationRecord.setAssessmentId(savedAssessment.getId());
        simulationRecord.setVersion("1.0");
        this.fileGroupService.saveSimulationRecord(simulationRecord);

        return savedAssessment;
    }

    @Override
    public Assessment updateAssessment(final Assessment assessment) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Saving assessment");
        }

        if (assessment == null || StringUtils.isBlank(assessment.getId())) {
            throw new LocalizedException("assessment.invalid.id");
        }
        final Assessment existingAssessment = getAssessment(assessment.getId());
        if (existingAssessment != null && existingAssessment.isLocked()) {
            throw new LocalizedException("assessment.published.cannot.be.altered");
        }
        if (!assessment.getSubjectId().equals(existingAssessment.getSubjectId())
                || !assessment.getPublicationId().equals(existingAssessment.getPublicationId())
                || !assessment.getTenantId().equals(existingAssessment.getTenantId())
                || !arraysOrderAgnosticEqual(existingAssessment.getGrade(), assessment.getGrade())
                || !assessment.getVersion().equals(existingAssessment.getVersion()) || assessment.isLocked()) {
            throw new LocalizedException("assessment.restricted.field.cannot.be.altered");
        }

        return save(assessment);
    }

    private boolean arraysOrderAgnosticEqual(final String[] leftArray, final String[] rightArray) {
        if (leftArray == null || rightArray == null || leftArray.length == 0 || rightArray.length == 0) {
            return false;
        }
        final List<String> leftList = Lists.newArrayList(leftArray);
        final List<String> rightList = Lists.newArrayList(rightArray);
        return leftList.containsAll(rightList) && rightList.containsAll(leftList);
    }

    private Assessment save(final Assessment assessment) {
        try {
            loadReferenceData(assessment);
            loadAssessmentName(assessment);
            return this.assessmentRepository.save(assessment);
        } catch (final DuplicateKeyException dke) {
            throw new LocalizedException("assessment.already.exists", paramArray(assessment.getName()), dke);
        }
    }

    @Override
    public Assessment getAssessment(final String assessmentId) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Finding assessment for Id: " + assessmentId);
        }
        final Assessment assessment = this.assessmentRepository.findOne(assessmentId);
        loadReferenceData(assessment);
        return assessment;
    }

    @Override
    public void removeAssessment(final String assessmentId) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Removing assessment with Id:" + assessmentId);
        }

        final Map<String, String[]> parameterMap = ImmutableMap.of("assessmentId", paramArray(assessmentId),
                "publishingStatus", paramArray("PUBLISHED"));
        final SearchResponse<PublishingRecord> searchResponse = this.publishingRecordService
                .searchPublishingRecords(parameterMap);
        if (searchResponse.getSearchResults().size() > 0) {
            throw new LocalizedException("assessment.published.cannot.be.removed");
        }

        this.assessmentChildDeleter.deleteAssessmentChildren(assessmentId);
        this.assessmentRepository.delete(assessmentId);
    }

    @Override
    public List<Assessment> getAssessments() {
        final List<Assessment> assessments = this.assessmentRepository.findAll();
        for (final Assessment assessment : assessments) {
            loadReferenceData(assessment);
        }
        return assessments;
    }

    @Override
    public SearchResponse<Assessment> searchAssessments(final Map<String, String[]> parameterMap) {
        final Map<String, String[]> paramMap = reviseMapParams(parameterMap);
        final AssessmentSearchRequest searchRequest = new AssessmentSearchRequest(paramMap);
        if (searchRequest.isValid()) {
            final SearchResponse<Assessment> searchResponse = this.assessmentRepository.search(searchRequest);
            for (final Assessment assessment : searchResponse.getSearchResults()) {
                loadReferenceData(assessment);
            }
            return searchResponse;
        } else {
            throw new RestException("assessment.search.invalidSearchCriteria");
        }
    }

    // compensate for opting to use @JsonValue in enum for pretty dropdown choices
    private Map<String, String[]> reviseMapParams(final Map<String, String[]> parameterMap) {
        final Map<String, String[]> paramMap = Maps.newHashMap(parameterMap);
        if (paramMap.containsKey(TYPE_KEY) && paramMap.get(TYPE_KEY)[0] != null) {
            final AssessmentType assessmentType = AssessmentType.fromTitle(paramMap.get(TYPE_KEY)[0]);
            if (assessmentType != null) {
                paramMap.put(TYPE_KEY, paramArray(assessmentType.name()));
            } else {
                paramMap.remove(TYPE_KEY);
            }
        }
        return paramMap;
    }

    private void loadReferenceData(final Assessment assessment) {
        if (assessment != null) {
            if (!StringUtils.isEmpty(assessment.getSubjectId())) {
                assessment.setSubject(this.subjectService.getSubject(assessment.getSubjectId()));
            }
            if (!StringUtils.isEmpty(assessment.getPublicationId())) {
                assessment.setPublication(this.publicationService.getPublication(assessment.getPublicationId()));
            }
        }
    }

    private void loadAssessmentName(final Assessment newAssessment) {
        final Assessment existingAssessment = newAssessment.getId() != null
                ? this.assessmentRepository.findOne(newAssessment.getId())
                : null;
        if (existingAssessment != null) {
            if (existingAssessment.isBlueprintSynced()
                    && !existingAssessment.getPublicationId().equals(newAssessment.getPublicationId())) {
                throw new LocalizedException("assessment.publication.cannot.be.altered");
            }
            existingAssessment
                    .setPublication(this.publicationService.getPublication(existingAssessment.getPublicationId()));
            existingAssessment.setSubject(this.subjectService.getSubject(existingAssessment.getSubjectId()));
        }

        final boolean isNameOutOfDate = existingAssessment == null
                || ComparisonChain.start().compare(existingAssessment.getTenantId(), newAssessment.getTenantId()) // shouldn't differ
                        .compare(existingAssessment.getPublication().getCoreStandardsPublisherKey(),
                                newAssessment.getPublication().getCoreStandardsPublisherKey())
                        .compare(existingAssessment.getSubject().getAbbreviation(),
                                newAssessment.getSubject().getAbbreviation())
                        .result() != 0;

        long sequenceNumber = 0;
        if (isNameOutOfDate) {
            sequenceNumber = this.assessmentCounterRepository
                    .findAndUpdateNextAssessmentNameSequence(newAssessment);
        } else {
            final String[] nameComponents = existingAssessment.getName().split("-");
            sequenceNumber = Long.parseLong(nameComponents[nameComponents.length - 1]);
        }

        final String[] sortedGrades = newAssessment.getGrade();
        Arrays.sort(sortedGrades);
        newAssessment.setGrade(sortedGrades);

        final StringBuilder name = new StringBuilder();
        name.append(newAssessment.getPublication().getCoreStandardsPublisherKey()).append("-");
        name.append(newAssessment.getSubject().getAbbreviation()).append("-");
        name.append(StringUtils.join(newAssessment.getGrade(), "_")).append("-");
        name.append(StringUtils.replace(newAssessment.getAdministration(), " ", "_").toUpperCase()).append("-");
        name.append(newAssessment.getType().getCode()).append("-");
        name.append(sequenceNumber);
        newAssessment.setName(name.toString());
    }

    @Override
    public Assessment copyAssessment(final String assessmentId) {

        final Assessment originalAssessment = this.assessmentRepository.findOne(assessmentId);
        final Assessment assessmentToSave = new Assessment();
        assessmentToSave.setSubjectId(originalAssessment.getSubjectId());
        assessmentToSave.setPublicationId(originalAssessment.getPublicationId());
        assessmentToSave.setGrade(originalAssessment.getGrade());
        assessmentToSave.setType(originalAssessment.getType());
        assessmentToSave.setAdministration(originalAssessment.getAdministration());
        assessmentToSave.setLabel(StringUtils.isEmpty(originalAssessment.getLabel()) ? "COPY"
                : originalAssessment.getLabel() + "-COPY");
        assessmentToSave.setCategory(originalAssessment.getCategory());
        assessmentToSave.setComment(originalAssessment.getComment());
        assessmentToSave.setDescription(originalAssessment.getDescription());
        assessmentToSave.setTenantId(originalAssessment.getTenantId());
        assessmentToSave.setTestFamily(originalAssessment.getTestFamily());
        assessmentToSave.setItemBank(originalAssessment.getItemBank());
        assessmentToSave.setClient(originalAssessment.getClient());
        final Assessment newAssessment = saveAssessment(assessmentToSave);

        this.assessmentChildCopier.copyAssessmentChildren(assessmentId, newAssessment.getId());
        return newAssessment;
    }
}