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.publish; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.DEFAULT_VERSION; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.nullsafeListTransform; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.safeParseInt; import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.searchParamsByAssessmentIdLarge; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.AFFINITY_GROUP_KEYID_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.COMPRULE_MULTIMAP_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ENEMY1_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ENEMY2_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ENEMY_TO_ENEMYID1_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ENEMY_TO_ENEMYID2_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.FORMPARTITION_REFERENCE_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEMGROUPID_KEY_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEMGROUP_MAPKEY_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEMLIST_ITEMGROUP_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_ITEMGROUPIDLIST_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_PASSAGE_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_REF_GROUP_ORDER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.POOLPROPERTY_TO_POOLPROPERTY_VALUE_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.POOL_PROPERTY_ORDER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.SEGMENT_KEYID_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.TESTITEM_ID_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.FORM_FORMID_TRANSFORMER; import static org.opentestsystem.authoring.testauth.publish.PublisherUtil.buildIdentifier; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.opentestsystem.authoring.testauth.config.TestAuthUtil; import org.opentestsystem.authoring.testauth.domain.AffinityGroup; import org.opentestsystem.authoring.testauth.domain.AffinityGroupValue; import org.opentestsystem.authoring.testauth.domain.Assessment; import org.opentestsystem.authoring.testauth.domain.BlueprintElement; import org.opentestsystem.authoring.testauth.domain.BlueprintElementValue; import org.opentestsystem.authoring.testauth.domain.BlueprintReferenceType; import org.opentestsystem.authoring.testauth.domain.Enemy; import org.opentestsystem.authoring.testauth.domain.Form; import org.opentestsystem.authoring.testauth.domain.FormPartition; import org.opentestsystem.authoring.testauth.domain.Item; import org.opentestsystem.authoring.testauth.domain.ItemCountSummary; import org.opentestsystem.authoring.testauth.domain.ItemGroup; import org.opentestsystem.authoring.testauth.domain.ItemGroupLocationType; import org.opentestsystem.authoring.testauth.domain.ItemMetadataConfig; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithm; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmParameter; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmType; import org.opentestsystem.authoring.testauth.domain.PerformanceLevel; import org.opentestsystem.authoring.testauth.domain.ReportingMeasure; import org.opentestsystem.authoring.testauth.domain.Segment; import org.opentestsystem.authoring.testauth.persistence.GridFsRepository; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.ISP_LIST_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_COUNT_FILTER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_ITEMGROUP_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_ITEMLOCATION_FILTER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.ITEM_TESTITEM_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.PERFORMANCE_LEVEL_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.PublisherUtil.REPORTING_MEASURE_TRANSFORMER; import org.opentestsystem.authoring.testauth.publish.domain.AdministrationSegment; import org.opentestsystem.authoring.testauth.publish.domain.Identifier; import org.opentestsystem.authoring.testauth.publish.domain.ItemPool; import org.opentestsystem.authoring.testauth.publish.domain.ItemReferenceGroup; import org.opentestsystem.authoring.testauth.publish.domain.ItemSelectionParameter; import org.opentestsystem.authoring.testauth.publish.domain.Passage; import org.opentestsystem.authoring.testauth.publish.domain.PoolProperty; import org.opentestsystem.authoring.testauth.publish.domain.Property; import org.opentestsystem.authoring.testauth.publish.domain.Purpose; import org.opentestsystem.authoring.testauth.publish.domain.PurposeBaseContent; import org.opentestsystem.authoring.testauth.publish.domain.PurposeBaseForm; import org.opentestsystem.authoring.testauth.publish.domain.PurposeBaseSegment; import org.opentestsystem.authoring.testauth.publish.domain.SegmentBlueprintElement; import org.opentestsystem.authoring.testauth.publish.domain.TestBlueprintElement; import org.opentestsystem.authoring.testauth.publish.domain.TestComputationRule; import org.opentestsystem.authoring.testauth.publish.domain.TestEnemyGroup; import org.opentestsystem.authoring.testauth.publish.domain.TestForm; import org.opentestsystem.authoring.testauth.publish.domain.TestFormPartition; import org.opentestsystem.authoring.testauth.publish.domain.TestItem; import org.opentestsystem.authoring.testauth.publish.domain.TestPerformanceLevel; import org.opentestsystem.authoring.testauth.publish.domain.TestReportingMeasure; import org.opentestsystem.authoring.testauth.publish.domain.TestSpecification; import org.opentestsystem.authoring.testauth.service.AffinityGroupService; import org.opentestsystem.authoring.testauth.service.BlueprintElementService; import org.opentestsystem.authoring.testauth.service.ComputationRuleService; import org.opentestsystem.authoring.testauth.service.EnemyService; import org.opentestsystem.authoring.testauth.service.FormPartitionService; import org.opentestsystem.authoring.testauth.service.FormService; import org.opentestsystem.authoring.testauth.service.ItemGroupService; import org.opentestsystem.authoring.testauth.service.ItemMetadataConfigService; 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.shared.exception.LocalizedException; import org.opentestsystem.shared.search.domain.SearchResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; @Component public abstract class BasePublisherHelper extends SharedPublisherHelper { @Autowired private transient SegmentService segmentService; @Autowired private transient FormService formService; @Autowired private transient FormPartitionService formPartitionService; @Autowired private transient BlueprintElementService blueprintElementService; @Autowired private transient AffinityGroupService affinityGroupService; @Autowired private transient ItemService itemService; @Autowired private transient ItemGroupService itemGroupService; @Autowired private transient EnemyService enemyService; @Autowired private transient PerformanceLevelService performanceLevelService; @Autowired private transient ScoringRuleService scoringRuleService; @Autowired private transient ComputationRuleService computationRuleService; @Autowired private transient GridFsRepository gridFsRepository; @Autowired private transient ReportingMeasureService reportingMeasureService; @Autowired private transient ItemMetadataConfigService itemMetadataConfigService; @Resource(name = "languageMap") private Map<String, String> languageMap; @Value("${testauth.serveruniquenumber}") private int serverUniqueNumber; @Value("${testauth.item.op.statuses}") private String opItemStatuses; protected static final String SELECTION_ALGORITHM = "selectionalgorithm"; protected static final String STRAND = "strand"; // ======================================================================================================================================================================== // general protected <T extends PurposeBaseContent> TestSpecification<T> doGeneralTestSpecificationSetup( final Assessment assessment, final DateTime publishDate, final String version, final Purpose purpose, final Class<T> clazz) { final TestSpecification<T> testSpec = new TestSpecification<T>(); testSpec.setTenantId(assessment.getClient()); testSpec.setPublishDate(publishDate); testSpec.setPurpose(purpose.toString()); testSpec.setIdentifier(buildIdentifier(assessment.getName(), assessment.getLabel(), version)); testSpec.getIdentifier().setName(assessment.getName() + '-' + version); testSpec.setComment(assessment.getComment()); testSpec.setDescription(assessment.getDescription()); final List<Property> propertyList = Lists.newArrayList( new Property("subject", assessment.getSubject().getAbbreviation(), assessment.getSubject().getName()), new Property("type", assessment.getType().toString().toLowerCase(), assessment.getType().toString().toLowerCase()), new Property("label", assessment.getLabel(), assessment.getLabel()), new Property("category", assessment.getCategory(), assessment.getCategory()), new Property("comment", assessment.getComment(), assessment.getComment()), new Property("description", assessment.getDescription(), assessment.getDescription()), new Property("testfamily", assessment.getTestFamily(), assessment.getTestFamily()), new Property("itembank", assessment.getItemBank(), "itembank" + assessment.getItemBank()), new Property("tenantid", assessment.getTenantId(), assessment.getTenantId())); for (final String grade : assessment.getGrade()) { propertyList.add(new Property("grade", grade, "grade " + grade)); } testSpec.setPropertyList(propertyList); return testSpec; } protected Map<String, List<Item>> retrieveScopedItems(final String assessmentId, final List<Item> itemList, final String segmentId, final boolean isFixedForm) { final Map<String, List<Item>> itemsListMap = Maps.newHashMap(); if (isFixedForm) { final SearchResponse<Form> formSearchResponse = this.formService .searchForms(searchParamsByAssessmentIdLarge(assessmentId)); this.formService.populateReferenceData(formSearchResponse.getSearchResults()); for (final Form form : formSearchResponse.getSearchResults()) { for (final FormPartition formPartition : form.getPartitions()) { // if segmentId is passed, scope by that segmentId, otherwise just return everything for the form if (StringUtils.isEmpty(segmentId) || formPartition.getSegmentId().equals(segmentId)) { final List<Item> filteredItemList = nullsafeListTransform(itemList, ITEM_ITEMLOCATION_FILTER .getInstance(formPartition.getId(), ItemGroupLocationType.FORM_PARTITION)); itemsListMap.put(formPartition.getId(), filteredItemList); } } } } else { final List<Item> filteredItemList = nullsafeListTransform(itemList, ITEM_ITEMLOCATION_FILTER.getInstance(segmentId, ItemGroupLocationType.SEGMENT)); itemsListMap.put(segmentId, filteredItemList); } return itemsListMap; } protected List<PoolProperty> buildTopLevelPoolPropertyList(final String assessmentId, final List<Item> itemList, final List<Segment> segmentList, final Map<String, TestItem> testItemMap) { final List<List<PoolProperty>> poolPropertyLists = Lists.newArrayList(); for (final Segment segment : segmentList) { final boolean isFixedFormSegment = segment.getItemSelectionAlgorithm().getItemSelectionAlgorithmType() .equals(ItemSelectionAlgorithmType.FIXEDFORM); final List<Item> filteredItemList = Lists.newArrayList(Iterables.concat( retrieveScopedItems(assessmentId, itemList, segment.getId(), isFixedFormSegment).values())); poolPropertyLists.add(buildPoolPropertyListFromItemList(testItemMap, filteredItemList)); } return sumPoolPropertyLists(Lists.newArrayList(Iterables.concat(poolPropertyLists))); } protected List<PoolProperty> sumPoolPropertyLists(final List<PoolProperty> poolPropertySumList) { final Map<String, PoolProperty> summedPoolPropertyMap = Maps.newHashMap(); for (final PoolProperty poolProperty : poolPropertySumList) { final String mapKey = poolProperty.getProperty() + "|" + poolProperty.getValue(); if (summedPoolPropertyMap.get(mapKey) == null) { summedPoolPropertyMap.put(mapKey, new PoolProperty(poolProperty.getProperty(), poolProperty.getValue(), poolProperty.getLabel(), poolProperty.getItemcount())); } else { summedPoolPropertyMap.get(mapKey) .setItemcount(String.valueOf(safeParseInt(summedPoolPropertyMap.get(mapKey).getItemcount()) + safeParseInt(poolProperty.getItemcount()))); } } return POOL_PROPERTY_ORDER.sortedCopy(summedPoolPropertyMap.values()); } protected Map<String, TestItem> buildTestItemMap(final List<TestItem> testItemList) { return Maps.uniqueIndex(testItemList, TESTITEM_ID_TRANSFORMER); } protected List<PoolProperty> buildPoolPropertyListFromItemList(final Map<String, TestItem> testItemMap, final List<Item> itemList) { final List<PoolProperty> combinedPoolPropertyList = Lists.newArrayList(); final List<PoolProperty> metadataPoolPropertyList = Lists.newArrayList(); String assessmentId = null; for (final Item item : itemList) { assessmentId = item.getAssessmentId(); if (testItemMap.get(item.getId()) != null) { metadataPoolPropertyList.addAll(testItemMap.get(item.getId()).getPoolPropertyList()); } } ItemMetadataConfig itemMetadataConfig = null; if (StringUtils.isNotBlank(assessmentId)) { itemMetadataConfig = this.itemMetadataConfigService.getItemMetadataConfigByAssessment(assessmentId); } if (itemMetadataConfig != null) { final Map<String, Collection<PoolProperty>> poolPropertyMultiMap = Maps .newHashMap( Multimaps .index(metadataPoolPropertyList, POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER.getInstance(Lists .newArrayList(itemMetadataConfig.getItemMetadataReckonSet()))) .asMap()); poolPropertyMultiMap.remove(PublisherUtil.EMPTY_PROPERTY); for (final Entry<String, Collection<PoolProperty>> poolPropertyEntry : poolPropertyMultiMap .entrySet()) { final Map<String, Collection<PoolProperty>> poolPropertyValueMultiMap = Multimaps .index(poolPropertyEntry.getValue(), POOLPROPERTY_TO_POOLPROPERTY_VALUE_TRANSFORMER) .asMap(); for (final Entry<String, Collection<PoolProperty>> poolPropertyValueEntry : poolPropertyValueMultiMap .entrySet()) { combinedPoolPropertyList.add(new PoolProperty(poolPropertyEntry.getKey(), poolPropertyValueEntry.getKey(), poolPropertyValueEntry.getKey(), String.valueOf(poolPropertyValueEntry.getValue().size()))); } } } return combinedPoolPropertyList; } protected List<Item> retrieveItemsForAssessment(final String assessmentId) { return this.itemService.getItemsByAssessmentId(assessmentId); } // ======================================================================================================================================================================== // item pool construction protected ItemPool setupItemPoolData(final Assessment assessment, final List<Item> itemList, final List<Segment> segmentList, final List<AffinityGroup> affinityGroupList, final String version) { final String assessmentId = assessment.getAssessmentId(); final String assessmentUniqueId = buildIdentifier(assessment.getName(), assessment.getLabel(), version) .getUniqueId(); final ItemPool itemPool = new ItemPool(); final List<ItemGroup> itemGroupList = this.itemGroupService.getItemGroupsByAssessment(assessmentId); final Map<String, ItemGroup> itemGroupMap = Maps.newHashMap(); if (!CollectionUtils.isEmpty(itemGroupList)) { itemGroupMap.putAll(Maps.uniqueIndex(itemGroupList, ITEMGROUP_MAPKEY_TRANSFORMER)); } itemPool.setTestItemList(nullsafeListTransform(itemList, ITEM_TESTITEM_TRANSFORMER.getInstance(itemGroupMap, Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER), Maps.uniqueIndex(affinityGroupList, AFFINITY_GROUP_KEYID_TRANSFORMER), assessmentUniqueId, assessment.getClient()))); // build up all the passages and use Set to pare down to unique instances // itemPool.setPassageList(Lists.newArrayList(Sets.newHashSet(nullsafeListTransform(itemList, ITEM_PASSAGE_TRANSFORMER)))); // unique by uniqueId itemPool.setPassageList( buildUniquePassegesByUniqueId(nullsafeListTransform(itemList, ITEM_PASSAGE_TRANSFORMER))); final List<Enemy> enemyList = this.enemyService.getEnemiesByAssessmentId(assessmentId); if (!CollectionUtils.isEmpty(enemyList)) { final List<TestEnemyGroup> testEnemyGroupList = Lists.newArrayList(); final Map<String, Collection<Enemy>> enemy1MultiMap = Multimaps .index(enemyList, ENEMY_TO_ENEMYID1_TRANSFORMER).asMap(); for (final String enemy1Id : enemy1MultiMap.keySet()) { final List<Enemy> enemy1List = this.enemyService.getEnemiesByAssessmentIdAndObjectId1(assessmentId, enemy1Id); testEnemyGroupList.add(new TestEnemyGroup( buildTestEnemyGroupIdentifier(enemy1List.get(0).getObject1(), assessment.getItemBank()), nullsafeListTransform(enemy1List, ENEMY1_TRANSFORMER.getInstance(assessment.getItemBank())))); } final Map<String, Collection<Enemy>> enemy2MultiMap = Multimaps .index(enemyList, ENEMY_TO_ENEMYID2_TRANSFORMER).asMap(); for (final String enemy2Id : enemy2MultiMap.keySet()) { final List<Enemy> enemy2List = this.enemyService.getEnemiesByAssessmentIdAndObjectId2(assessmentId, enemy2Id); testEnemyGroupList.add(new TestEnemyGroup( buildTestEnemyGroupIdentifier(enemy2List.get(0).getObject2(), assessment.getItemBank()), nullsafeListTransform(enemy2List, ENEMY2_TRANSFORMER.getInstance(assessment.getItemBank())))); } itemPool.setTestEnemyGroupList(testEnemyGroupList); } return itemPool; } private final Identifier buildTestEnemyGroupIdentifier(final Object enemyProtagonist, final String itembank) { Identifier enemyProtagonistIdentifier = null; if (enemyProtagonist instanceof Item) { final Item item = (Item) enemyProtagonist; enemyProtagonistIdentifier = PublisherUtil.buildIdentifierPrim(item.getTibIdentifier(), item.getTibIdentifier(), item.getVersion()); } else if (enemyProtagonist instanceof ItemGroup) { final ItemGroup itemGroup = (ItemGroup) enemyProtagonist; enemyProtagonistIdentifier = new Identifier(itemGroup.getPassageId(), itemGroup.getGroupName(), itemGroup.getGroupName(), DEFAULT_VERSION); enemyProtagonistIdentifier.setUniqueId(itembank + '-' + enemyProtagonistIdentifier.getUniqueId()); } else if (enemyProtagonist instanceof Passage) { final Passage passage = (Passage) enemyProtagonist; enemyProtagonistIdentifier = passage.getIdentifier(); } return enemyProtagonistIdentifier; } // ===============================================================================================================================================.===== // blueprint construction protected List<TestBlueprintElement> setupBlueprintData(final Assessment assessment, final List<Item> itemList, final List<Segment> segmentList, final List<BlueprintElement> blueprintElementList, final List<AffinityGroup> affinityGroupList) { final List<TestBlueprintElement> blueprintList = Lists.newArrayList(); int testLevelOpMin = 0, testLevelOpMax = 0, testLevelFtMin = 0, testLevelFtMax = 0, testLevelOpItemCount = 0, testLevelFtItemCount = 0; // roll up all totals per segment final Map<String, ItemCountSummary> masterItemCounts = new HashMap<String, ItemCountSummary>(); final List<TestBlueprintElement> segmentBlueprintList = Lists.newArrayList(); for (final Segment segment : segmentList) { final boolean isFixedFormSegment = segment.getItemSelectionAlgorithm().getItemSelectionAlgorithmType() .equals(ItemSelectionAlgorithmType.FIXEDFORM); final Map<String, ItemCountSummary> blueprintItemCountsBySegment = getBlueprintItemCounts(assessment, itemList, segment.getId(), blueprintElementList, isFixedFormSegment); // in order to avoid multiple adding int segmentLevelOpItemCount = 0, segmentLevelFtItemCount = 0; final Map<String, ItemCountSummary> blueprintItemCountsBySegmentByStrands = getBlueprintItemCountsByStrands( assessment, itemList, segment.getId(), blueprintElementList, isFixedFormSegment); for (final Entry<String, ItemCountSummary> blueprintElementCount : blueprintItemCountsBySegmentByStrands .entrySet()) { segmentLevelOpItemCount = segmentLevelOpItemCount + blueprintElementCount.getValue().getOpCount(); segmentLevelFtItemCount = segmentLevelFtItemCount + blueprintElementCount.getValue().getFtCount(); } for (final Entry<String, ItemCountSummary> blueprintElementCount : blueprintItemCountsBySegment .entrySet()) { // roll up totals by blueprint standard for master level ItemCountSummary masterBpElementItemCounts = masterItemCounts.get(blueprintElementCount.getKey()); if (masterBpElementItemCounts == null) { masterBpElementItemCounts = new ItemCountSummary(); masterItemCounts.put(blueprintElementCount.getKey(), masterBpElementItemCounts); } final int newOpCount = TestAuthUtil.safeParseInt(masterBpElementItemCounts.getOpCount()) + blueprintElementCount.getValue().getOpCount(); masterBpElementItemCounts.setOpCount(newOpCount); final int newFtCount = TestAuthUtil.safeParseInt(masterBpElementItemCounts.getFtCount()) + blueprintElementCount.getValue().getFtCount(); masterBpElementItemCounts.setFtCount(newFtCount); } // segment level // AK: if there is only one segment segment uniqueid must be equal test(assessment) uniqueid segmentBlueprintList.add(new TestBlueprintElement( new Identifier( (segmentList.size() == 1) ? buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()).getUniqueId() : segment.getId(), segment.getLabel(), segment.getLabel(), DEFAULT_VERSION), "segment", buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()) .getUniqueId(), segment.getMinOpItems(), segment.getMaxOpItems(), segment.getMinFtItems(), segment.getMaxFtItems(), segmentLevelOpItemCount, segmentLevelFtItemCount)); testLevelOpMin = testLevelOpMin + segment.getMinOpItems(); testLevelOpMax = testLevelOpMax + segment.getMaxOpItems(); testLevelFtMin = testLevelFtMin + segment.getMinFtItems(); testLevelFtMax = testLevelFtMax + segment.getMaxFtItems(); testLevelOpItemCount = testLevelOpItemCount + segmentLevelOpItemCount; testLevelFtItemCount = testLevelFtItemCount + segmentLevelFtItemCount; } // master bp elemenets String name = null; final List<TestBlueprintElement> masterBlueprintList = Lists.newArrayList(); for (final BlueprintElement blueprintElement : blueprintElementList) { // StandardKey at this point has 'client' as prefix; 'name' element does not need this prefix int pubEndPos = StringUtils.indexOf(blueprintElement.getStandardKey(), "-"); if (pubEndPos > 0) name = StringUtils.substring(blueprintElement.getStandardKey(), pubEndPos + 1); masterBlueprintList.add(new TestBlueprintElement( new Identifier(blueprintElement.getStandardKey(), name, null, DEFAULT_VERSION), blueprintElement.getElementTypeName(), blueprintElement.getParentKey(), blueprintElement.getMasterValue().getOperationalItemMinValue(), blueprintElement.getMasterValue().getOperationalItemMaxValue(), blueprintElement.getMasterValue().getFieldTestItemMinValue(), blueprintElement.getMasterValue().getFieldTestItemMaxValue(), masterItemCounts.get(blueprintElement.getStandardKey()).getOpCount(), masterItemCounts.get(blueprintElement.getStandardKey()).getFtCount())); } // top/test level final List<TestBlueprintElement> testBlueprintList = Lists.newArrayList(); // this change has to fix null -> uniqueid for bpelement with type = 'test' // this uniqueid must be the same as testspecificationUniqueid TestBlueprintElement tbp = new TestBlueprintElement( buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()), "test", null, testLevelOpMin, testLevelOpMax, testLevelFtMin, testLevelFtMax, testLevelOpItemCount, testLevelFtItemCount); tbp.getIdentifier().setName(assessment.getName() + '-' + assessment.getVersion()); testBlueprintList.add(tbp); final List<TestBlueprintElement> affinityGroupBlueprintList = Lists.newArrayList(); for (final AffinityGroup affinityGroup : affinityGroupList) { affinityGroupBlueprintList.add(new TestBlueprintElement( buildIdentifier(affinityGroup.getGroupName(), null, DEFAULT_VERSION), "affinitygroup", buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()) .getUniqueId())); } blueprintList.addAll(testBlueprintList); blueprintList.addAll(segmentBlueprintList); blueprintList.addAll(masterBlueprintList); blueprintList.addAll(affinityGroupBlueprintList); return blueprintList; } private Map<String, ItemCountSummary> getBlueprintItemCounts(final Assessment assessment, final List<Item> itemList, final String segmentId, final List<BlueprintElement> blueprintElementList, final boolean isFixedFormSegment) { final Map<String, ItemCountSummary> itemCountsMap = Maps.newHashMap(); final Map<String, List<Item>> itemsMap = retrieveScopedItems(assessment.getId(), itemList, segmentId, isFixedFormSegment); for (final BlueprintElement blueprintElement : blueprintElementList) { final BlueprintElementValue bpElementValue = blueprintElement.getBlueprintElementValueMap() .get(segmentId); final ItemCountSummary itemCount = new ItemCountSummary(); itemCount.setOpMin(bpElementValue != null ? bpElementValue.getOperationalItemMinValue() : 0); itemCount.setOpMax(bpElementValue != null ? bpElementValue.getOperationalItemMaxValue() : 0); itemCount.setFtMin(bpElementValue != null ? bpElementValue.getFieldTestItemMinValue() : 0); itemCount.setFtMax(bpElementValue != null ? bpElementValue.getFieldTestItemMaxValue() : 0); int opCount = 0; int ftCount = 0; for (final Entry<String, List<Item>> itemListEntry : itemsMap.entrySet()) { opCount = opCount + Lists.newArrayList(Iterables.filter(itemListEntry.getValue(), ITEM_COUNT_FILTER.getInstance( cutClientName(assessment.getClient(), blueprintElement.getStandardKey()), "OP", opItemStatuses))) .size(); ftCount = ftCount + Lists.newArrayList(Iterables.filter(itemListEntry.getValue(), ITEM_COUNT_FILTER.getInstance( cutClientName(assessment.getClient(), blueprintElement.getStandardKey()), "FT", opItemStatuses))) .size(); } itemCount.setOpCount(opCount); itemCount.setFtCount(ftCount); itemCountsMap.put(blueprintElement.getStandardKey(), itemCount); } return itemCountsMap; } private Map<String, ItemCountSummary> getBlueprintItemCountsByStrands(final Assessment assessment, final List<Item> itemList, final String segmentId, final List<BlueprintElement> blueprintElementList, final boolean isFixedFormSegment) { final Map<String, ItemCountSummary> itemCountsMap = Maps.newHashMap(); final Map<String, List<Item>> itemsMap = retrieveScopedItems(assessment.getId(), itemList, segmentId, isFixedFormSegment); for (final BlueprintElement blueprintElement : blueprintElementList) { if (blueprintElement.getElementTypeName().equalsIgnoreCase(STRAND)) { final BlueprintElementValue bpElementValue = blueprintElement.getBlueprintElementValueMap() .get(segmentId); final ItemCountSummary itemCount = new ItemCountSummary(); itemCount.setOpMin(bpElementValue != null ? bpElementValue.getOperationalItemMinValue() : 0); itemCount.setOpMax(bpElementValue != null ? bpElementValue.getOperationalItemMaxValue() : 0); itemCount.setFtMin(bpElementValue != null ? bpElementValue.getFieldTestItemMinValue() : 0); itemCount.setFtMax(bpElementValue != null ? bpElementValue.getFieldTestItemMaxValue() : 0); int opCount = 0; int ftCount = 0; for (final Entry<String, List<Item>> itemListEntry : itemsMap.entrySet()) { opCount = opCount + Lists.newArrayList(Iterables.filter(itemListEntry.getValue(), ITEM_COUNT_FILTER.getInstance( cutClientName(assessment.getClient(), blueprintElement.getStandardKey()), "OP", opItemStatuses))) .size(); ftCount = ftCount + Lists.newArrayList(Iterables.filter(itemListEntry.getValue(), ITEM_COUNT_FILTER.getInstance( cutClientName(assessment.getClient(), blueprintElement.getStandardKey()), "FT", opItemStatuses))) .size(); } itemCount.setOpCount(opCount); itemCount.setFtCount(ftCount); itemCountsMap.put(blueprintElement.getStandardKey(), itemCount); } } return itemCountsMap; } private String cutClientName(final String clientName, String standardKey) { int index = standardKey.indexOf(clientName.concat("-")); if (index > -1) return standardKey.substring(clientName.length() + 1); else return standardKey; } // ======================================================================================================================================================================== // segment construction protected List<AdministrationSegment> setupAdminSegmentData(final Assessment assessment, final List<Item> itemList, final List<Segment> segmentList, final List<TestBlueprintElement> testBlueprintElementList, final List<BlueprintElement> blueprintElementList, final List<AffinityGroup> affinityGroupList) { final List<AdministrationSegment> adminSegmentList = Lists.newArrayList(); for (final Segment segment : segmentList) { final ItemSelectionAlgorithmType segmentType = segment.getItemSelectionAlgorithm() .getItemSelectionAlgorithmType(); // AdministrationSegment.id must be equal to segment.id! final String itemSelection = (segment.getItemSelectionParameters() != null && segment.getItemSelectionParameters().get(SELECTION_ALGORITHM) != null ? segment.getItemSelectionParameters().get(SELECTION_ALGORITHM).toLowerCase() : segmentType.toString().toLowerCase()); // AK: if there is only one segment segment uniqueid must be equal test(assessment) uniqueid final AdministrationSegment adminSegment = new AdministrationSegment((segmentList.size() == 1) ? buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()) .getUniqueId() : segment.getId(), segment.getPosition(), itemSelection); if (segmentType.equals(ItemSelectionAlgorithmType.FIXEDFORM)) { final List<FormPartition> formPartitionList = this.formPartitionService .getFormPartitionsBySegmentId(segment.getId()); adminSegment.setFormPartitionReferenceList( nullsafeListTransform(formPartitionList, FORMPARTITION_REFERENCE_TRANSFORMER.getInstance( assessment.getItemBank(), this.serverUniqueNumber, assessment.getVersion()))); } else { adminSegment.setItemReferenceGroupList(buildItemReferenceGroups(assessment.getItemBank(), null, assessment, itemList, segment.getId(), true)); } // itemselector's itemselectionparameter list populated from all usages of item selection algorithm in the segment/blueprint // (scalar/blueprint; e.g. 200 standards x 3 bp isa params + 5 sc isa params = 605 itemselectionparameter entries) final ItemSelectionAlgorithm isa = segment.getItemSelectionAlgorithm(); adminSegment.setItemSelectorIdentifier(buildIdentifier(isa.getName(), null, isa.getVersion())); final List<ItemSelectionParameter> itemSelectionParameterList = Lists.newArrayList(); final List<ItemSelectionAlgorithmParameter> scalarParams = segment.getItemSelectionAlgorithm() .getScalarParameters(); final List<ItemSelectionAlgorithmParameter> blueprintParams = segment.getItemSelectionAlgorithm() .getBlueprintParameters(); if (!CollectionUtils.isEmpty(scalarParams)) { final Map<String, Map<String, String>> segmentItemSelectionParameters = ImmutableMap .of(segment.getId(), segment.getItemSelectionParameters()); itemSelectionParameterList.addAll(nullsafeListTransform(segmentItemSelectionParameters.entrySet(), ISP_LIST_TRANSFORMER.getInstance(Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER), assessment))); } if (!CollectionUtils.isEmpty(blueprintParams)) { final Map<String, Map<String, String>> blueprintElementItemSelectionParameters = findBlueprintElementItemSelectionParameters( segment.getAssessmentId(), segment.getId(), blueprintElementList); itemSelectionParameterList.addAll(nullsafeListTransform( blueprintElementItemSelectionParameters.entrySet(), ISP_LIST_TRANSFORMER.getInstance( Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER), assessment))); final Map<String, Map<String, String>> affinityGroupItemSelectionParameters = findAffinityGroupItemSelectionParameters( segment.getAssessmentId(), segment.getId(), affinityGroupList); itemSelectionParameterList.addAll(nullsafeListTransform( affinityGroupItemSelectionParameters.entrySet(), ISP_LIST_TRANSFORMER.getInstance( Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER), assessment))); } adminSegment.setItemSelectionParameterList(itemSelectionParameterList); final Map<String, ItemCountSummary> blueprintItemCountsBySegment = getBlueprintItemCounts(assessment, itemList, segment.getId(), blueprintElementList, segmentType.equals(ItemSelectionAlgorithmType.FIXEDFORM)); final List<SegmentBlueprintElement> segmentBlueprintElementList = Lists.newArrayList(); for (final Entry<String, ItemCountSummary> blueprintElementCount : blueprintItemCountsBySegment .entrySet()) { segmentBlueprintElementList.add(new SegmentBlueprintElement(blueprintElementCount.getKey(), blueprintElementCount.getValue().getOpMin(), blueprintElementCount.getValue().getOpMax(), blueprintElementCount.getValue().getFtMin(), blueprintElementCount.getValue().getFtMax(), blueprintElementCount.getValue().getOpCount(), blueprintElementCount.getValue().getFtCount())); } for (final AffinityGroup affinityGroup : affinityGroupList) { // segment bp elements final Map<String, ItemCountSummary> affinityGroupItemCounts = this.itemService .getAffinityGroupItemCounts(affinityGroup.getId()); final ItemCountSummary segmentItemCounts = affinityGroupItemCounts.get(segment.getId()); segmentBlueprintElementList.add(new SegmentBlueprintElement( buildIdentifier(affinityGroup.getGroupName(), null, DEFAULT_VERSION).getUniqueId(), //affinityGroup.getGroupName(), segmentItemCounts.getOpMin(), segmentItemCounts.getOpMax(), segmentItemCounts.getFtMin(), segmentItemCounts.getFtMax(), segmentItemCounts.getOpCount(), segmentItemCounts.getOpMax())); } adminSegment.setSegmentBlueprintElementList(segmentBlueprintElementList); adminSegmentList.add(adminSegment); } return adminSegmentList; } private Map<String, Map<String, String>> findBlueprintElementItemSelectionParameters(final String assessmentId, final String segmentId, final List<BlueprintElement> blueprintElementList) { final Map<String, Map<String, String>> blueprintElementItemSelectionParameterMapList = Maps.newHashMap(); for (final BlueprintElement blueprintElement : blueprintElementList) { final BlueprintElementValue bpElementValue = blueprintElement.getBlueprintElementValueMap() .get(segmentId); if (bpElementValue != null && bpElementValue.getItemSelectionParameters() != null) { blueprintElementItemSelectionParameterMapList.put(blueprintElement.getStandardKey(), bpElementValue.getItemSelectionParameters()); } } return blueprintElementItemSelectionParameterMapList; } private Map<String, Map<String, String>> findAffinityGroupItemSelectionParameters(final String assessmentId, final String segmentId, final List<AffinityGroup> affinityGroupList) { final Map<String, Map<String, String>> affinityGroupItemSelectionParameterMapList = Maps.newHashMap(); for (final AffinityGroup affinityGroup : affinityGroupList) { final AffinityGroupValue affinityGroupValue = affinityGroup.getAffinityGroupValueMap().get(segmentId); if (affinityGroupValue != null && affinityGroupValue.getItemSelectionParameters() != null) { affinityGroupItemSelectionParameterMapList.put( buildIdentifier(affinityGroup.getGroupName(), null, DEFAULT_VERSION).getUniqueId(), affinityGroupValue.getItemSelectionParameters()); } } return affinityGroupItemSelectionParameterMapList; } // ======================================================================================================================================================================== // form/partition construction protected List<TestForm> setupTestFormData(final Assessment assessment, final List<Segment> segmentList, final List<Item> itemList, final Map<String, TestItem> testItemMap) { final List<TestForm> formList = Lists.newArrayList(); final SearchResponse<Form> formSearchResponse = this.formService .searchForms(searchParamsByAssessmentIdLarge(assessment.getAssessmentId())); for (final Form form : formSearchResponse.getSearchResults()) { // final List<Item> filteredItemList = Lists.newArrayList(Iterables.concat(retrieveScopedItems(assessmentId, itemList, null, true).values())); //EF: different forms can have the same item, we want here list of unique items, // changed from Lists to Sets; final Set<Item> filteredItemSet = Sets.newHashSet(Iterables .concat(retrieveScopedItems(assessment.getAssessmentId(), itemList, null, true).values())); final List<Item> filteredItemList = new ArrayList<Item>(filteredItemSet); final TestForm testForm = doGeneralFormSetup(TestForm.class, form, filteredItemList, testItemMap, assessment.getVersion()); final List<TestFormPartition> testFormPartitionList = Lists.newArrayList(); testForm.setTestFormPartitionList(testFormPartitionList); final List<FormPartition> formPartitionList = this.formPartitionService .getFormPartitionsByFormId(form.getId()); for (final FormPartition formPartition : formPartitionList) { //Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER) // Segment seg = segmentMap.get (formPartition.getSegmentId ()); final List<ItemReferenceGroup> itemReferenceGroupList = buildItemReferenceGroups( assessment.getItemBank(), Maps.uniqueIndex(segmentList, SEGMENT_KEYID_TRANSFORMER), assessment, filteredItemList, formPartition.getId(), false); final TestFormPartition testFormPartition = new TestFormPartition( new Identifier( FORMPARTITION_REFERENCE_TRANSFORMER.getInstance(assessment.getItemBank(), this.serverUniqueNumber, assessment.getVersion()).apply(formPartition), formPartition.getName(), formPartition.getName(), DEFAULT_VERSION), ITEM_REF_GROUP_ORDER.sortedCopy(itemReferenceGroupList)); testForm.getTestFormPartitionList().add(testFormPartition); } formList.add(testForm); } return formList; } protected <F extends PurposeBaseForm, S extends PurposeBaseSegment> F doGeneralFormSetup(final Class<F> clazz, final Form form, final List<Item> filteredItemList, final Map<String, TestItem> testItemMap, final String version) { F newForm = null; try { newForm = clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new LocalizedException("publishingRecord.testspec.form.invalid", new String[] { e.getMessage() }, e); } newForm.setIdentifier( new Identifier(FORM_FORMID_TRANSFORMER.getInstance(this.serverUniqueNumber, version).apply(form), form.getName(), null, DEFAULT_VERSION)); //newForm.setIdentifier(buildIdentifier(form.getName(), null, DEFAULT_VERSION)); newForm.setPropertyList(Lists.newArrayList( new Property("language", PublisherUtil.replaceLanguage(form.getLanguage().toUpperCase()), this.languageMap.get(form.getLanguage())))); newForm.setPoolPropertyList( sumPoolPropertyLists(buildPoolPropertyListFromItemList(testItemMap, filteredItemList))); return newForm; } // ======================================================================================================================================================================== // segment/partition item reference group/item reference (itemgroup/groupitem) private List<ItemReferenceGroup> buildItemReferenceGroups(final String bankKey, final Map<String, Segment> segmentMap, final Assessment assessment, final List<Item> itemList, final String locationId, final boolean processSegmentLevel) { // find any/all existing itemGroups by segmentId/formPartitionId, build into multimap keyed by itemGroupId final List<ItemGroup> itemGroupList = processSegmentLevel ? this.itemGroupService.getItemGroupsBySegment(locationId) : this.itemGroupService.getItemGroupsFormPartition(locationId); final ListMultimap<String, ItemGroup> existingItemGroupMap = Multimaps.index(itemGroupList, ITEMGROUPID_KEY_TRANSFORMER); // returns map w/ key of segmentId/formPartitionId and value of item list final Map<String, List<Item>> itemsMap = processSegmentLevel ? retrieveScopedItems(assessment.getId(), itemList, locationId, false) : retrieveScopedItems(assessment.getId(), itemList, null, true); // scope by just location Id (instead of summed partitions per segment) final List<Item> flattenedItemList = processSegmentLevel ? Lists.newArrayList(Iterables.concat(itemsMap.values())) : itemsMap.get(locationId); // item can belong to more than one group or 'NO_GROUP'; attempt to invert the relationship to construct // a) map w/ key of item group & value of list of items // b) list of lone-wolf 'NO_GROUP' items for which an ItemReferenceGroup will be later fabricated final Multimap<List<String>, Item> groupedMultiMap = Multimaps.index(flattenedItemList, ITEM_ITEMGROUPIDLIST_TRANSFORMER); final Map<ItemGroup, List<Item>> groupedItemMap = Maps.newHashMap(); final Set<Item> ungroupedItemSet = Sets.newHashSet(); for (final Entry<List<String>, Item> itemGrouping : groupedMultiMap.entries()) { for (final String itemGroupingKey : itemGrouping.getKey()) { if (StringUtils.equals(itemGroupingKey, Item.SKIP_GROUP_KEY)) { } else if (!StringUtils.equals(itemGroupingKey, Item.NO_GROUP_KEY)) { ItemGroup itemGroup = null; if (!CollectionUtils.isEmpty(existingItemGroupMap.get(itemGroupingKey))) { itemGroup = existingItemGroupMap.get(itemGroupingKey).get(0); } if (itemGroup != null) { if (CollectionUtils.isEmpty(groupedItemMap.get(itemGroup))) { final List<Item> itemsPerItemGroupList = Lists.newArrayList(); groupedItemMap.put(itemGroup, itemsPerItemGroupList); } groupedItemMap.get(itemGroup).add(itemGrouping.getValue()); } } else if (Iterables.any(itemGrouping.getValue().getAdaptiveAndFixedItemLocations(), PublisherUtil.ITEM_LOCATION_MATCHER.getInstance(Item.NO_GROUP_KEY, locationId, processSegmentLevel ? ItemGroupLocationType.SEGMENT : ItemGroupLocationType.FORM_PARTITION))) { ungroupedItemSet.add(itemGrouping.getValue()); } } } // transform grouped // note that segmentMap parameter is null in case processSegmentLevel parameter was true final List<ItemReferenceGroup> groupedItems = nullsafeListTransform(groupedItemMap.entrySet(), ITEMLIST_ITEMGROUP_TRANSFORMER.getInstance(bankKey, segmentMap, this.serverUniqueNumber, assessment.getVersion())); // transform ungrouped final List<ItemReferenceGroup> ungroupedItems = nullsafeListTransform(ungroupedItemSet, ITEM_ITEMGROUP_TRANSFORMER.getInstance(processSegmentLevel, locationId, bankKey, this.serverUniqueNumber, assessment.getVersion())); return Lists.newArrayList(Iterables.concat(ungroupedItems, groupedItems)); } // ======================================================================================================================================================================== // performance level construction protected List<TestPerformanceLevel> setupPerformanceLevelData(final String assessmentId, final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap) { final List<PerformanceLevel> performanceLevelList = this.performanceLevelService .getPerformanceLevelsByAssessmentId(assessmentId); final List<List<TestPerformanceLevel>> listOfTestPerformanceLevelLists = nullsafeListTransform( performanceLevelList, PERFORMANCE_LEVEL_TRANSFORMER.getInstance(blueprintReferenceMap)); return Lists.newArrayList(Iterables.concat(listOfTestPerformanceLevelLists)); } // ======================================================================================================================================================================== // reporting measure construction protected List<TestReportingMeasure> setupReportingMeasureData(final String assessmentId, final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap, final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap) { final List<ReportingMeasure> reportingMeasureList = this.reportingMeasureService .getReportingMeasuresByAssessmentId(assessmentId); return Lists.newArrayList(Iterables.concat(nullsafeListTransform(reportingMeasureList, REPORTING_MEASURE_TRANSFORMER.getInstance(blueprintReferenceMap, scoringRuleReferenceMap)))); } // ======================================================================================================================================================================== // general protected Map<String, Collection<TestComputationRule>> buildScoringRuleReferenceMap( final List<TestComputationRule> testComputationRuleList) { return Multimaps.index(testComputationRuleList, COMPRULE_MULTIMAP_TRANSFORMER).asMap(); } // ======================================================================================================================================================================== // general protected List<Passage> buildUniquePassegesByUniqueId(final List<Passage> passageList) { Map<String, Passage> uniquePassages = new HashMap<String, Passage>(); for (Passage p : passageList) { uniquePassages.put(p.getIdentifier().getUniqueId(), p); } return Lists.newArrayList(uniquePassages.values()); } }