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.buildValidationFieldError; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.paramArray; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.opentestsystem.authoring.testauth.domain.FormPartition; import org.opentestsystem.authoring.testauth.domain.ItemGroup; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithm; import org.opentestsystem.authoring.testauth.domain.Segment; import org.opentestsystem.authoring.testauth.domain.search.SegmentSearchRequest; import org.opentestsystem.authoring.testauth.persistence.SegmentRepository; import org.opentestsystem.authoring.testauth.service.AffinityGroupService; import org.opentestsystem.authoring.testauth.service.BlueprintElementService; import org.opentestsystem.authoring.testauth.service.FormPartitionService; import org.opentestsystem.authoring.testauth.service.ItemGroupService; import org.opentestsystem.authoring.testauth.service.ItemSelectionAlgorithmService; import org.opentestsystem.authoring.testauth.service.ItemService; import org.opentestsystem.authoring.testauth.service.PerformanceLevelService; import org.opentestsystem.authoring.testauth.service.ReportingMeasureService; import org.opentestsystem.authoring.testauth.service.ScoringRuleService; import org.opentestsystem.authoring.testauth.service.SegmentService; import org.opentestsystem.authoring.testauth.service.impl.SegmentHelper.SEGMENT_POSITION_TRANSFORMER; import org.opentestsystem.authoring.testauth.validation.SegmentValidator; import org.opentestsystem.authoring.testauth.validation.ValidationHelper; 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.validation.BeanPropertyBindingResult; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @Service public class SegmentServiceImpl extends AssessmentChildHelper implements SegmentService { private static final Logger LOGGER = LoggerFactory.getLogger(SegmentServiceImpl.class); private static final int SEGMENT_MAX_POSITION = 1000; private static final int SEGMENT_MIN_POSITION = 1; @Autowired private transient SegmentRepository segmentRepository; @Autowired private transient BlueprintElementService blueprintElementService; @Autowired private transient AffinityGroupService affinityGroupService; @Autowired private transient ItemGroupService itemGroupService; @Autowired private transient ItemService itemService; @Autowired private transient ScoringRuleService scoringRuleService; @Autowired private transient FormPartitionService formPartitionService; @Autowired private transient PerformanceLevelService performanceLevelService; @Autowired private transient ReportingMeasureService reportingMeasureService; @Autowired private transient ItemSelectionAlgorithmService itemSelectionAlgorithmService; @Autowired private transient SegmentValidator segmentValidator; @Override public Segment createSegment(final Segment segment) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Saving segment"); } checkForLockedAssessment(segment.getAssessmentId()); if (segment == null || StringUtils.isNotBlank(segment.getId())) { throw new LocalizedException("segment.invalid.id"); } final BindingResult bindingResult = new BeanPropertyBindingResult(segment, "segment"); if (findSegmentListByAssessmentId(segment.getAssessmentId()).size() + 1 != segment.getPosition() || segment.getPosition() > SEGMENT_MAX_POSITION || segment.getPosition() < SEGMENT_MIN_POSITION) { bindingResult.addError( new FieldError("segment", "position", null, false, paramArray("segment.invalid.position"), paramArray(String.valueOf(segment.getPosition())), "segment.invalid.position")); } Segment savedSegment = null; validateSegment(bindingResult, segment); try { savedSegment = this.segmentRepository.save(segment); loadReferenceData(savedSegment); } catch (final DuplicateKeyException dke) { throw new LocalizedException("segment.already.exists", paramArray(segment.getLabel()), dke); } this.blueprintElementService.addBlueprintElementValueGroup(savedSegment.getAssessmentId(), savedSegment.getId(), null); this.affinityGroupService.addAffinityGroupValueGroup(savedSegment.getAssessmentId(), savedSegment.getId()); return savedSegment; } @Override public Segment updateSegment(final Segment segment) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Updating segment"); } checkForLockedAssessment(segment.getAssessmentId()); if (segment == null || StringUtils.isBlank(segment.getId())) { throw new LocalizedException("segment.invalid.id"); } final BindingResult bindingResult = new BeanPropertyBindingResult(segment, "segment"); if (findSegmentListByAssessmentId(segment.getAssessmentId()).size() < segment.getPosition() || segment.getPosition() > SEGMENT_MAX_POSITION || segment.getPosition() < SEGMENT_MIN_POSITION) { bindingResult.addError( new FieldError("segment", "position", null, false, paramArray("segment.invalid.position"), paramArray(String.valueOf(segment.getPosition())), "segment.invalid.position")); } final String existingSegmentItemSelectionAlgorithmId = this.segmentRepository.findOne(segment.getId()) .getItemSelectionAlgorithmId(); final boolean isNewItemSelectionAlgorithm = !StringUtils.equals(existingSegmentItemSelectionAlgorithmId, segment.getItemSelectionAlgorithmId()); if (isNewItemSelectionAlgorithm) { final ItemSelectionAlgorithm existingItemSelectionAlgorithm = this.itemSelectionAlgorithmService .getItemSelectionAlgorithm(existingSegmentItemSelectionAlgorithmId); final ItemSelectionAlgorithm newItemSelectionAlgorithm = this.itemSelectionAlgorithmService .getItemSelectionAlgorithm(segment.getItemSelectionAlgorithmId()); if (existingItemSelectionAlgorithm.getItemSelectionAlgorithmType() != newItemSelectionAlgorithm .getItemSelectionAlgorithmType()) { bindingResult.addError(buildValidationFieldError("segment", "itemSelectionAlgorithmId", "segment.cannot.alter.itemSelectionAlgorithm.type", paramArray(existingItemSelectionAlgorithm.getItemSelectionAlgorithmType().name()))); } } validateSegment(bindingResult, segment); segmentPositionResequencing(segment, true); Segment savedSegment = null; try { savedSegment = this.segmentRepository.save(segment); // if ISA has changed, update blueprint values if (isNewItemSelectionAlgorithm) { this.blueprintElementService.updateBlueprintElementItemSelectionParameters( savedSegment.getAssessmentId(), savedSegment.getId()); this.affinityGroupService.updateAffinityGroupItemSelectionParameters(savedSegment.getAssessmentId(), savedSegment.getId()); } loadReferenceData(savedSegment); } catch (final DuplicateKeyException dke) { throw new LocalizedException("segment.already.exists", paramArray(segment.getLabel()), dke); } return savedSegment; } private void segmentPositionResequencing(final Segment modifiedSegment, final boolean updateIsTrueDeleteIsFalse) { final List<Segment> segmentList = findSegmentListByAssessmentId(modifiedSegment.getAssessmentId()); if (segmentList.size() > 1) { final Map<String, Segment> segmentMap = Maps .newHashMap(SegmentHelper.createSegmentIdKeyMap(segmentList)); // only re-sequence if deleting or if the position value has changed for the segment being updated if (segmentMap.containsKey(modifiedSegment.getId()) && (!updateIsTrueDeleteIsFalse || segmentMap.get(modifiedSegment.getId()).getPosition() != modifiedSegment.getPosition())) { final int previousPosition = segmentMap.get(modifiedSegment.getId()).getPosition(); final int newPosition = updateIsTrueDeleteIsFalse ? modifiedSegment.getPosition() : segmentList.size(); // if deleting...move to end of list final List<Segment> updatedSegmentList = Lists .newArrayList(Iterables.filter( Iterables.transform(segmentMap.values(), SEGMENT_POSITION_TRANSFORMER.getInstance(modifiedSegment.getId(), newPosition, previousPosition)), SegmentHelper.SEGMENT_NOTNULL_FILTER)); this.segmentRepository.delete(updatedSegmentList); this.segmentRepository.save(updatedSegmentList); } } } @Override public Segment getSegment(final String segmentId) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Finding segment for Id: " + segmentId); } final Segment segment = this.segmentRepository.findOne(segmentId); loadReferenceData(segment); return segment; } @Override public void removeSegment(final String segmentId) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Removing segment with Id:" + segmentId); } final Segment segment = this.segmentRepository.findOne(segmentId); checkForLockedAssessment(segment.getAssessmentId()); segmentPositionResequencing(segment, false); this.itemService.removeBySegmentId(segmentId); removeItemGroupsBySegment(segmentId); removeFormPartitionsBySegment(segmentId); this.scoringRuleService.removeByBlueprintReferenceId(segment.getAssessmentId(), segmentId); this.performanceLevelService.removeByReferenceId(segmentId); this.reportingMeasureService.removeByReferenceId(segmentId); this.blueprintElementService.removeBlueprintElementValueGroup(segment.getAssessmentId(), segmentId); this.affinityGroupService.removeAffinityGroupValueGroup(segment.getAssessmentId(), segmentId); this.segmentRepository.delete(segmentId); } @Override public void removeByAssessmentId(final String parentId) { this.segmentRepository.delete(this.segmentRepository.findAllByAssessmentId(parentId)); } @Override public SearchResponse<Segment> searchSegments(final Map<String, String[]> requestMap) { final SegmentSearchRequest searchRequest = new SegmentSearchRequest(requestMap); if (searchRequest.isValid()) { return this.segmentRepository.search(searchRequest); } else { throw new RestException("segment.search.invalidSearchCriteria"); } } @Override public void loadReferenceData(final List<Segment> segmentList) { for (final Segment segment : segmentList) { loadReferenceData(segment); } } private void loadReferenceData(final Segment segment) { if (segment != null && StringUtils.isNotEmpty(segment.getItemSelectionAlgorithmId())) { segment.setItemSelectionAlgorithm(this.itemSelectionAlgorithmService .getItemSelectionAlgorithm(segment.getItemSelectionAlgorithmId())); } } private void validateSegment(final BindingResult bindingResult, final Segment segment) { this.segmentValidator.validate(segment, bindingResult); if (bindingResult.hasErrors()) { throw ValidationHelper.convertErrorsToConstraintException(segment, bindingResult); } } private void removeItemGroupsBySegment(final String segmentId) { final List<ItemGroup> itemGroups = this.itemGroupService.getItemGroupsBySegment(segmentId); for (final ItemGroup itemGroup : itemGroups) { this.itemGroupService.removeItemGroup(itemGroup.getId()); } } private void removeFormPartitionsBySegment(final String segmentId) { final List<FormPartition> partitions = this.formPartitionService.getFormPartitionsBySegmentId(segmentId); for (final FormPartition partition : partitions) { this.formPartitionService.removeFormPartition(partition.getId()); } } @Override public List<Segment> findSegmentListByAssessmentId(final String assessmentId) { return this.segmentRepository.findAllByAssessmentId(assessmentId); } @Override public List<Segment> saveSegmentList(final List<Segment> segmentList, final boolean clearPrevious) { if (clearPrevious) { for (final Segment segment : segmentList) { checkForLockedAssessment(segment.getAssessmentId()); } this.segmentRepository.delete(segmentList); } return this.segmentRepository.save(segmentList); } }