Java tutorial
/******************************************************************************* * 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; } }