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 static org.opentestsystem.authoring.testauth.publish.PublisherUtil.validateConversionListFile; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.opentestsystem.authoring.testauth.domain.AffinityGroup; import org.opentestsystem.authoring.testauth.domain.Assessment; import org.opentestsystem.authoring.testauth.domain.BlueprintDenotationType; import org.opentestsystem.authoring.testauth.domain.BlueprintElement; import org.opentestsystem.authoring.testauth.domain.BlueprintReference; import org.opentestsystem.authoring.testauth.domain.BlueprintReferenceType; import org.opentestsystem.authoring.testauth.domain.ReportingMeasure; import org.opentestsystem.authoring.testauth.domain.ScoringRule; import org.opentestsystem.authoring.testauth.domain.Segment; import org.opentestsystem.authoring.testauth.domain.search.ScoringRuleSearchRequest; import org.opentestsystem.authoring.testauth.persistence.GridFsRepository; import org.opentestsystem.authoring.testauth.persistence.ScoringRuleRepository; import org.opentestsystem.authoring.testauth.service.AffinityGroupService; import org.opentestsystem.authoring.testauth.service.AssessmentService; import org.opentestsystem.authoring.testauth.service.BlueprintElementService; import org.opentestsystem.authoring.testauth.service.ReportingMeasureService; import org.opentestsystem.authoring.testauth.service.ScoringRuleService; import org.opentestsystem.authoring.testauth.service.SegmentService; 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 org.springframework.util.CollectionUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mongodb.DBObject; import com.mongodb.gridfs.GridFSDBFile; import com.mongodb.gridfs.GridFSFile; @Service public class ScoringRuleServiceImpl extends AssessmentChildHelper implements ScoringRuleService { private static final Logger LOGGER = LoggerFactory.getLogger(ScoringRuleServiceImpl.class); private static final BlueprintDenotationType[] NON_STANDARD_DENOTATIONS = new BlueprintDenotationType[] { BlueprintDenotationType.LEVEL, BlueprintDenotationType.LEAF_NODES }; private static final String BLUEPRINT_REFERENCE_TYPE_KEY = "blueprintReferenceType"; @Autowired private transient ScoringRuleHelper scoringRuleHelper; @Autowired private transient ScoringRuleRepository scoringRuleRepository; @Autowired private transient ReportingMeasureService reportingMeasureService; @Autowired private transient AssessmentService assessmentService; @Autowired private transient SegmentService segmentService; @Autowired private transient AffinityGroupService affinityGroupService; @Autowired private transient BlueprintElementService blueprintElementService; @Autowired private transient GridFsRepository gridFsRepository; @Override public ScoringRule saveScoringRule(final String scoringRuleId, final ScoringRule scoringRule) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Saving scoringRule"); } if (scoringRuleId != null && (scoringRule == null || StringUtils.isEmpty(scoringRule.getId()) || !scoringRuleId.equals(scoringRule.getId()))) { throw new LocalizedException("scoringRule.invalid.id"); } checkForLockedAssessment(scoringRule.getAssessmentId()); this.scoringRuleHelper.validateScoringRule(scoringRule); ScoringRule existingScoringRule = null; if (StringUtils.isNotBlank(scoringRule.getId())) { existingScoringRule = getScoringRule(scoringRule.getId()); } ScoringRule savedScoringRule = null; try { savedScoringRule = this.scoringRuleRepository.save(scoringRule); // check if this scoring rule is associated with reporting measure if (existingScoringRule != null) { if (existingScoringRule.getBlueprintReferenceType() != scoringRule.getBlueprintReferenceType() || existingScoringRule.getBlueprintDenotationType() != scoringRule .getBlueprintDenotationType()) { removeScoringRulesFromReportingMeasures(scoringRule); } else if (!StringUtils.equals(existingScoringRule.getBlueprintReferenceId(), scoringRule.getBlueprintReferenceId())) { updateRelatedReportingMeasures(existingScoringRule.getBlueprintReferenceId(), scoringRule.getBlueprintReferenceId()); } } } catch (final DuplicateKeyException dke) { if (StringUtils.contains(dke.getMessage(), ScoringRule.ORDER_INDEX_NAME)) { throw new LocalizedException("scoringRule.already.exists.order", paramArray(scoringRule.getAssessmentId(), String.valueOf(scoringRule.getOrder())), dke); } else { throw new LocalizedException("scoringRule.already.exists.label", paramArray(scoringRule.getAssessmentId(), scoringRule.getLabel()), dke); } } return savedScoringRule; } private void updateRelatedReportingMeasures(final String oldBpReferenceId, final String newBpReferenceId) { final List<ReportingMeasure> rmeasures = this.reportingMeasureService .getReportingMeasuresByReferenceId(oldBpReferenceId); for (final ReportingMeasure rmeasure : rmeasures) { rmeasure.setBlueprintReferenceId(newBpReferenceId); this.reportingMeasureService.saveReportingMeasure(rmeasure.getId(), rmeasure); } } @Override public List<ScoringRule> saveScoringRuleList(final List<ScoringRule> scoringRuleList, final boolean clearPrevious) { if (clearPrevious) { for (final ScoringRule scoringRule : scoringRuleList) { checkForLockedAssessment(scoringRule.getAssessmentId()); this.scoringRuleHelper.validateScoringRule(scoringRule); } this.scoringRuleRepository.delete(scoringRuleList); } return this.scoringRuleRepository.save(scoringRuleList); } @Override public ScoringRule getScoringRule(final String scoringRuleId) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Finding scoringRule for Id: " + scoringRuleId); } final ScoringRule scoringRule = this.scoringRuleRepository.findOne(scoringRuleId); populateConversionTableFilenames(scoringRule); this.scoringRuleHelper.populateComputationRule(scoringRule); this.scoringRuleHelper.populateBlueprintReferenceName(scoringRule); return scoringRule; } private void populateConversionTableFilenames(final ScoringRule scoringRule) { if (scoringRule != null && scoringRule.getValueConversionTableGridFsId() != null) { final GridFSFile gridFsFile = this.gridFsRepository .getById(scoringRule.getValueConversionTableGridFsId()); if (gridFsFile == null) { throw new LocalizedException("scoringRule.valueConversionTableGridFsId.file.not.found"); } scoringRule.setValueConversionTableFilename(gridFsFile.getFilename()); } if (scoringRule != null && scoringRule.getStandardErrorConversionTableGridFsId() != null) { final GridFSFile gridFsFile = this.gridFsRepository .getById(scoringRule.getStandardErrorConversionTableGridFsId()); if (gridFsFile == null) { throw new LocalizedException("scoringRule.standardErrorConversionTableGridFsId.file.not.found"); } scoringRule.setStandardErrorConversionTableFilename(gridFsFile.getFilename()); } } @Override public List<ScoringRule> getScoringRulesByAssessmentId(final String assessmentId) { return this.scoringRuleRepository.findAllByAssessmentId(assessmentId); } @Override public List<ScoringRule> getScoringRulesByComputationRuleId(final String computationRuleId) { return this.scoringRuleRepository.findAllByComputationRuleId(computationRuleId); } @Override public void removeScoringRule(final String scoringRuleId) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Removing scoringRule with Id:" + scoringRuleId); } final ScoringRule scoringRuleToDelete = this.scoringRuleRepository.findOne(scoringRuleId); if (scoringRuleToDelete == null) { throw new LocalizedException("scoringRule.invalid.id", paramArray(scoringRuleId)); } removeScoringRules(Lists.newArrayList(scoringRuleToDelete)); } @Override public void removeByAssessmentId(final String assessmentId) { final List<ScoringRule> scoringRuleList = getScoringRulesByAssessmentId(assessmentId); if (!CollectionUtils.isEmpty(scoringRuleList)) { removeScoringRules(scoringRuleList); } } @Override public void removeByBlueprintReferenceId(final String assessmentId, final String... blueprintReferenceIdList) { final List<ScoringRule> scoringRuleList = blueprintReferenceIdList == null || CollectionUtils.isEmpty(Arrays.asList(blueprintReferenceIdList)) ? this.scoringRuleRepository.findAllByAssessmentIdAndBlueprintDenotationTypeIn(assessmentId, NON_STANDARD_DENOTATIONS) : this.scoringRuleRepository.findAllByAssessmentIdAndBlueprintReferenceIdIn(assessmentId, blueprintReferenceIdList); if (!CollectionUtils.isEmpty(scoringRuleList)) { removeScoringRules(scoringRuleList); } } private void removeScoringRules(final List<ScoringRule> scoringRuleList) { final String assessmentId = scoringRuleList.get(0).getAssessmentId(); checkForLockedAssessment(assessmentId); for (final ScoringRule scoringRule : scoringRuleList) { if (scoringRule.getValueConversionTableGridFsId() != null) { this.gridFsRepository.delete(scoringRule.getValueConversionTableGridFsId()); } if (scoringRule.getStandardErrorConversionTableGridFsId() != null) { this.gridFsRepository.delete(scoringRule.getStandardErrorConversionTableGridFsId()); } removeScoringRulesFromReportingMeasures(scoringRule); } this.scoringRuleRepository.delete(scoringRuleList); final List<ScoringRule> scoringRuleListToUpdate = getScoringRulesByAssessmentId(assessmentId); if (!CollectionUtils.isEmpty(scoringRuleListToUpdate)) { int i = 1; for (final ScoringRule scoringRule : scoringRuleListToUpdate) { scoringRule.setOrder(i++); } saveScoringRuleList(scoringRuleListToUpdate, true); } } @Override public SearchResponse<ScoringRule> searchScoringRules(final Map<String, String[]> parameterMap) { final Map<String, String[]> paramMap = reviseMapParams(parameterMap); final ScoringRuleSearchRequest searchRequest = new ScoringRuleSearchRequest(paramMap); if (searchRequest.isValid()) { final SearchResponse<ScoringRule> searchResponse = this.scoringRuleRepository.search(searchRequest); for (final ScoringRule scoringRule : searchResponse.getSearchResults()) { this.scoringRuleHelper.populateComputationRule(scoringRule); this.scoringRuleHelper.populateBlueprintReferenceName(scoringRule); } return searchResponse; } throw new RestException("scoringRule.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(BLUEPRINT_REFERENCE_TYPE_KEY) && paramMap.get(BLUEPRINT_REFERENCE_TYPE_KEY)[0] != null) { final BlueprintReferenceType blueprintReferenceType = BlueprintReferenceType .fromTitle(paramMap.get(BLUEPRINT_REFERENCE_TYPE_KEY)[0]); if (blueprintReferenceType != null) { paramMap.put(BLUEPRINT_REFERENCE_TYPE_KEY, paramArray(blueprintReferenceType.name())); } else { paramMap.remove(BLUEPRINT_REFERENCE_TYPE_KEY); } } return paramMap; } @Override public GridFSDBFile getConversionTableFile(final String inGridFSId) { return this.gridFsRepository.getById(inGridFSId); } @Override public GridFSFile saveConversionTableFile(final String type, final String fileName, final byte[] inBytes, final String contentType) { if (type == null) { throw new LocalizedException("scoringRule.conversionTableFile.type.invalid"); } validateConversionListFile(inBytes, fileName, type, false); final DBObject metadata = null; final GridFSFile gridFsFile = this.gridFsRepository.save(inBytes, fileName, contentType, metadata); return gridFsFile; } @Override public void deleteConversionTableFile(final String fileGridId) { this.gridFsRepository.delete(fileGridId); } @Override public void removeScoringRulesFromReportingMeasures(final ScoringRule scoringRule) { final List<ReportingMeasure> rmeasures = this.reportingMeasureService .getReportingMeasuresByScoringRuleId(scoringRule.getId()); for (final ReportingMeasure rmeasure : rmeasures) { if (rmeasure.getScoringRuleIdList().size() == 1) { this.reportingMeasureService.removeReportingMeasure(rmeasure.getId()); } else if (rmeasure.getScoringRuleIdList().size() > 1) { rmeasure.getScoringRuleIdList().remove(scoringRule.getId()); this.reportingMeasureService.saveReportingMeasure(rmeasure.getId(), rmeasure); } } } @Override public Map<String, String> findDistinctActiveBlueprintLevelsByAssessmentId(final String assessmentId) { return this.scoringRuleHelper.findDistinctActiveBlueprintLevelsByAssessmentId(assessmentId); } @Override public List<BlueprintElement> findBlueprintElementsMissingScoringRule(final String assessmentId) { return this.scoringRuleHelper.findBlueprintElementsMissingScoringRule(assessmentId); } @Override public List<BlueprintReference> getBlueprintReferences(final Map<String, String[]> parameterMap) { final List<BlueprintReference> bpReferenceList = new ArrayList<BlueprintReference>(); final Map<String, String[]> aMap = new HashMap<String, String[]>(); aMap.put("pageSize", new String[] { "1000" }); aMap.put("assessmentId", parameterMap.get("assessmentId")); final SearchResponse<ScoringRule> scoringRules = searchScoringRules(aMap); for (final ScoringRule scoringRule : scoringRules.getSearchResults()) { switch (scoringRule.getBlueprintReferenceType()) { case AFFINITY_GROUP: final AffinityGroup affinityGroup = this.affinityGroupService .getAffinityGroup(scoringRule.getBlueprintReferenceId()); bpReferenceList.add(new BlueprintReference(affinityGroup.getId(), affinityGroup.getGroupName(), BlueprintReferenceType.AFFINITY_GROUP)); break; case SEGMENT: final Segment segment = this.segmentService.getSegment(scoringRule.getBlueprintReferenceId()); bpReferenceList.add(new BlueprintReference(segment.getId(), segment.getPosition() + " - " + segment.getLabel(), BlueprintReferenceType.SEGMENT)); break; case STANDARD: if (scoringRule.getBlueprintDenotationType().equals(BlueprintDenotationType.STANDARD_KEY)) { final BlueprintElement blueprintElement = this.blueprintElementService .getBlueprintElement(scoringRule.getBlueprintReferenceId()); bpReferenceList.add(new BlueprintReference(blueprintElement.getId(), blueprintElement.getStandardKey(), BlueprintReferenceType.STANDARD)); } break; case TEST: final Assessment assessment = this.assessmentService .getAssessment(scoringRule.getBlueprintReferenceId()); bpReferenceList.add(new BlueprintReference(assessment.getId(), assessment.getName(), BlueprintReferenceType.TEST)); break; default: break; } } Collections.sort(bpReferenceList); return bpReferenceList; } }