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.DEFAULT_VERSION; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.paramArray; import static org.opentestsystem.shared.search.domain.AbstractSearchRequest.SORT_DIR; import java.math.BigDecimal; import java.util.AbstractMap; import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.opentestsystem.authoring.testauth.domain.Assessment; import org.opentestsystem.authoring.testauth.domain.PsychometricRecord; import org.opentestsystem.authoring.testauth.domain.PublishingRecord; import org.opentestsystem.authoring.testauth.domain.PublishingStatus; import org.opentestsystem.authoring.testauth.domain.search.PublishingRecordSearchRequest; import org.opentestsystem.authoring.testauth.persistence.AssessmentRepository; import org.opentestsystem.authoring.testauth.persistence.PsychometricRecordRepository; import org.opentestsystem.authoring.testauth.persistence.PublishingRecordRepository; import org.opentestsystem.authoring.testauth.publish.PublisherRunner; import org.opentestsystem.authoring.testauth.publish.domain.Purpose; import org.opentestsystem.authoring.testauth.publish.domain.PurposeBaseContent; import org.opentestsystem.authoring.testauth.publish.domain.TestSpecification; import org.opentestsystem.authoring.testauth.service.ApprovalService; import org.opentestsystem.authoring.testauth.service.AssessmentService; import org.opentestsystem.authoring.testauth.service.PublishingRecordService; import org.opentestsystem.authoring.testauth.validation.PublishingRecordValidationHelper; import org.opentestsystem.shared.exception.LocalizedException; import org.opentestsystem.shared.exception.RestException; import org.opentestsystem.shared.search.domain.SearchResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; @Service public class PublishingRecordServiceImpl implements PublishingRecordService { @Autowired private transient AssessmentRepository assessmentRepository; @Autowired private transient AssessmentService assessmentService; @Autowired private transient ApprovalService approvalService; @Autowired private transient PublishingRecordRepository publishingRecordRepository; @Autowired private transient PsychometricRecordRepository psychometricRecordRepository; @Autowired private PublishingRecordValidationHelper publishingRecordValidationHelper; @Autowired private MessageSource messageSource; @Autowired private PublisherRunner publishRunner; // used for publishing display @Override public PublishingRecord retrievePublishingRecordWithAllowablePurposes(final String assessmentId) { final PublishingRecord publishingRecord = retrieveCurrentPublishingRecord(assessmentId); if (publishingRecord != null) { publishingRecord.setPurpose(Iterables.toArray( this.publishingRecordValidationHelper.determineAvailableSpecTypesForAssessment(assessmentId), Purpose.class)); try { this.publishingRecordValidationHelper.verifyCanPublish(publishingRecord, false); } catch (final LocalizedException e) { publishingRecord.setErrorMessageText( this.messageSource.getMessage(e.getMessageCode(), e.getMessageArgs(), Locale.US)); } finally { this.publishingRecordRepository.save(publishingRecord); } } return publishingRecord; } // used for assessment display @Override public PublishingRecord retrieveCurrentPublishingRecord(final String assessmentId) { if (assessmentId == null) { return null; } final Map<String, String[]> parameterMap = ImmutableMap.of("assessmentId", paramArray(assessmentId), "sortKey", paramArray("lastUpdatedDate"), SORT_DIR, paramArray("DESC")); final SearchResponse<PublishingRecord> searchResponse = searchPublishingRecords(parameterMap); PublishingRecord publishingRecord = null; if (searchResponse.getSearchResults().size() > 0) { publishingRecord = searchResponse.getSearchResults().get(0); } return publishingRecord; } @Override public PublishingRecord getPublishingRecord(final String publishingRecordId) { return this.publishingRecordRepository.findOne(publishingRecordId); } // used for publishing record display @Override public SearchResponse<PublishingRecord> searchPublishingRecords(final Map<String, String[]> parameterMap) { final PublishingRecordSearchRequest searchRequest = new PublishingRecordSearchRequest(parameterMap); if (searchRequest.isValid()) { return this.publishingRecordRepository.search(searchRequest); } throw new RestException("publishingRecord.search.invalidSearchCriteria"); } @Override public PublishingRecord savePublishingRecord(final PublishingRecord publishingRecord, final boolean incrementNextMajor) { final PublishingRecord latestPublishingRecord = retrievePublishingRecordWithAllowablePurposes( publishingRecord.getAssessmentId()); if (latestPublishingRecord != null && publishingRecord.getPublishingStatus() == null) { throw new LocalizedException("publishingRecord.publishingStatus.required", paramArray(latestPublishingRecord.getPublishingStatus().toString())); } boolean createPsychometricRecord = false; if (publishingRecord.getPublishingStatus() != null) { // cannot spoof publishing status, only deviation from existing is to reject if (!latestPublishingRecord.getPublishingStatus().equals(publishingRecord.getPublishingStatus())) { if (latestPublishingRecord.getPublishingStatus().equals(PublishingStatus.AWAITING_APPROVAL) && !publishingRecord.getPublishingStatus().equals(PublishingStatus.REJECT)) { throw new LocalizedException("publishingRecord.publishingStatus.mismatch", paramArray(publishingRecord.getPublishingStatus().toString(), latestPublishingRecord.getPublishingStatus().toString())); } } // cannot spoof version if (!latestPublishingRecord.getVersion().equals(publishingRecord.getVersion())) { throw new LocalizedException("publishingRecord.version.mismatch", paramArray(publishingRecord.getVersion(), latestPublishingRecord.getVersion())); } final Assessment assessment = this.assessmentService.getAssessment(publishingRecord.getAssessmentId()); switch (publishingRecord.getPublishingStatus()) { case PUBLISHED: processNextVersion(assessment, publishingRecord, incrementNextMajor); createPsychometricRecord = true; break; case AWAITING_APPROVAL: approveAndPublish(assessment, publishingRecord); break; case INPROGRESS: setupForApproval(assessment, publishingRecord); break; case REJECT: processRejection(assessment, publishingRecord); break; default: break; } } else { processInitial(publishingRecord); createPsychometricRecord = true; } publishingRecord.setLastUpdatedDate(new DateTime()); final PublishingRecord savedPublishingRecord = this.publishingRecordRepository.save(publishingRecord); if (createPsychometricRecord) { final PsychometricRecord psychometricRecord = new PsychometricRecord(); psychometricRecord.setPublishingRecordId(savedPublishingRecord.getId()); psychometricRecord.setVersion(savedPublishingRecord.getVersion()); this.psychometricRecordRepository.save(psychometricRecord); } return savedPublishingRecord; } /** * save new INPROGRESS status row w/ same assessment ID and w/ incremented version # of PUBLISHED row */ private void processNextVersion(final Assessment assessment, final PublishingRecord publishingRecord, final boolean incrementNextMajor) { if (!this.approvalService.isAdminUser()) { throw new LocalizedException("publishingRecord.invalid.user"); } publishingRecord.setId(null); publishingRecord.setPublishingStatus(PublishingStatus.INPROGRESS); assessment.setStatus(PublishingStatus.INPROGRESS); if (incrementNextMajor) { final BigDecimal major = new BigDecimal( StringUtils.substringBefore(publishingRecord.getVersion(), ".")); publishingRecord.setVersion(major.add(BigDecimal.ONE).toString() + ".0"); } else { publishingRecord.setVersion( new BigDecimal(publishingRecord.getVersion()).add(new BigDecimal("0.1")).toString()); } assessment.setVersion(publishingRecord.getVersion()); assessment.setLocked(false); this.assessmentRepository.save(assessment); } /** * run validation to ensure assessment is complete enough for selected Purpose */ private void setupForApproval(final Assessment assessment, final PublishingRecord publishingRecord) { this.publishingRecordValidationHelper.verifyCanPublish(publishingRecord, false); if (CollectionUtils.isEmpty(publishingRecord.getValidationResultList()) || !CollectionUtils.isEmpty(Arrays.asList(publishingRecord.getPurpose()))) { publishingRecord.setPublishingStatus(PublishingStatus.AWAITING_APPROVAL); assessment.setStatus(PublishingStatus.AWAITING_APPROVAL); this.approvalService.createInitialApprovals(publishingRecord.getId()); assessment.setLocked(true); this.assessmentRepository.save(assessment); } } private void processRejection(final Assessment assessment, final PublishingRecord publishingRecord) { publishingRecord.setPublishingStatus(PublishingStatus.INPROGRESS); assessment.setStatus(PublishingStatus.INPROGRESS); assessment.setLocked(false); this.assessmentRepository.save(assessment); } private void approveAndPublish(final Assessment assessment, final PublishingRecord publishingRecord) { if (this.approvalService.canPublishToSpecBank(publishingRecord.getId())) { publishingRecord.setPublishingStatus(PublishingStatus.PUBLISHING); publishingRecord.setLastUpdatedDate(new DateTime()); this.publishingRecordRepository.save(publishingRecord); assessment.setStatus(PublishingStatus.PUBLISHING); this.assessmentRepository.save(assessment); this.publishRunner.publishAndSend(assessment, publishingRecord); } } private void processInitial(final PublishingRecord publishingRecord) { publishingRecord.setPurpose(new Purpose[] { Purpose.REGISTRATION }); publishingRecord.setPublishingStatus(PublishingStatus.INPROGRESS); publishingRecord.setVersion(DEFAULT_VERSION); } @Override public void removeByAssessmentId(final String assessmentId) { this.publishingRecordRepository.delete(this.publishingRecordRepository.findAllByAssessmentId(assessmentId)); } @Override public Entry<String, byte[]> simulate(final String publishingRecordId, final String purposeString) { final PublishingRecord publishingRecord = getPublishingRecord(publishingRecordId); final Purpose purpose = Purpose.valueOf(purposeString); publishingRecord.setPurpose(new Purpose[] { purpose }); this.publishingRecordValidationHelper.verifyCanPublish(publishingRecord, true); if (CollectionUtils.isEmpty(publishingRecord.getValidationResultList()) || !CollectionUtils.isEmpty(Arrays.asList(publishingRecord.getPurpose()))) { } final Assessment assessment = this.assessmentService.getAssessment(publishingRecord.getAssessmentId()); final TestSpecification<? extends PurposeBaseContent> testSpec = this.publishRunner .createTestSpec(assessment, publishingRecord, purpose, true, null); return new AbstractMap.SimpleEntry<String, byte[]>(simulationFilename(testSpec, purposeString), this.publishRunner.generateAndValidateXml(testSpec)); } private String simulationFilename(final TestSpecification<? extends PurposeBaseContent> testSpec, final String purposeString) { final StringBuilder sb = new StringBuilder(); sb.append(testSpec.getIdentifier().getName()); sb.append("_"); sb.append(purposeString); sb.append("_"); sb.append(testSpec.getPurpose()); sb.append("_"); sb.append(testSpec.getPublishDate()); sb.append(".xml"); return sb.toString(); } }