org.opentestsystem.authoring.testauth.publish.BasePublisherHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.authoring.testauth.publish.BasePublisherHelper.java

Source

/*******************************************************************************
 * 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());
    }
}