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.paramArray; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.opentestsystem.authoring.testauth.domain.AdaptiveItemLocation; import org.opentestsystem.authoring.testauth.domain.AffinityGroup; import org.opentestsystem.authoring.testauth.domain.AffinityGroupItemLocation; import org.opentestsystem.authoring.testauth.domain.Assessment; import org.opentestsystem.authoring.testauth.domain.BlueprintDenotationType; import org.opentestsystem.authoring.testauth.domain.BlueprintElement; import org.opentestsystem.authoring.testauth.domain.BlueprintReferenceType; import org.opentestsystem.authoring.testauth.domain.ComputationRule; import org.opentestsystem.authoring.testauth.domain.ComputationRuleParameter; import org.opentestsystem.authoring.testauth.domain.ConversionTableType; import org.opentestsystem.authoring.testauth.domain.Enemy; import org.opentestsystem.authoring.testauth.domain.FixedFormItemLocation; 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.ItemGroup; import org.opentestsystem.authoring.testauth.domain.ItemGroupLocationType; import org.opentestsystem.authoring.testauth.domain.ItemLocation; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmType; import org.opentestsystem.authoring.testauth.domain.PerformanceLevel; import org.opentestsystem.authoring.testauth.domain.PerformanceLevelValue; import org.opentestsystem.authoring.testauth.domain.ReportingMeasure; import org.opentestsystem.authoring.testauth.domain.ScoringRule; import org.opentestsystem.authoring.testauth.domain.ScoringRuleDictionaryElement; import org.opentestsystem.authoring.testauth.domain.ScoringRuleParameter; import org.opentestsystem.authoring.testauth.domain.Segment; import org.opentestsystem.authoring.testauth.persistence.GridFsRepository; import org.opentestsystem.authoring.testauth.publish.domain.ConversionTable; import org.opentestsystem.authoring.testauth.publish.domain.ConversionTuple; import org.opentestsystem.authoring.testauth.publish.domain.Identifier; import org.opentestsystem.authoring.testauth.publish.domain.ItemReference; import org.opentestsystem.authoring.testauth.publish.domain.ItemReferenceGroup; import org.opentestsystem.authoring.testauth.publish.domain.ItemScoreDimension; import org.opentestsystem.authoring.testauth.publish.domain.ItemScoreParameter; 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.ScoreType; import org.opentestsystem.authoring.testauth.publish.domain.TestComputationRule; import org.opentestsystem.authoring.testauth.publish.domain.TestComputationRuleParameter; import org.opentestsystem.authoring.testauth.publish.domain.TestComputationRuleParameterValue; import org.opentestsystem.authoring.testauth.publish.domain.TestEnemy; 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.shared.exception.LocalizedException; import org.springframework.util.CollectionUtils; import au.com.bytecode.opencsv.CSVReader; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.mongodb.gridfs.GridFSDBFile; public final class PublisherUtil { protected static final String EMPTY_PROPERTY = ""; private PublisherUtil() { // singleton } // ======================================================================================================================================================================== // general protected static Identifier buildIdentifier(final String name, final String label, final String version) { String xmlLabel = StringEscapeUtils.escapeXml(label); final List<String> fields = Lists .newArrayList(Iterables.filter(Lists.newArrayList(StringUtils.trimToNull(name), StringUtils.trimToNull(xmlLabel), StringUtils.trimToNull(version)), Predicates.notNull())); return new Identifier(StringUtils.join(fields.toArray(), "-"), name, xmlLabel, version); } protected static Identifier buildIdentifierPrim(final String name, final String label, final String version) { String xmlLabel = StringEscapeUtils.escapeXml(label); final List<String> fields = Lists .newArrayList(Iterables.filter(Lists.newArrayList(StringUtils.trimToNull(name), StringUtils.trimToNull(xmlLabel), StringUtils.trimToNull(version)), Predicates.notNull())); if (StringUtils.countMatches(name, "-") == 2) { String id = StringUtils.substringAfter(name, "-"); return new Identifier(id, name, xmlLabel, version); } return new Identifier(StringUtils.join(fields.toArray(), "-"), name, xmlLabel, version); } public static String replaceLanguage(final String value) { String val = StringUtils.trim(value); if (val.equalsIgnoreCase("eng")) { return "ENU"; } else if (val.equalsIgnoreCase("spa")) { return "ESN"; } else return val; } protected static final class POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER implements Function<PoolProperty, String> { private final List<String> configuredItemMetadataConfigValues; public static POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER getInstance( final List<String> configuredItemMetadataConfigValues) { return new POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER(configuredItemMetadataConfigValues); } private POOLPROPERTY_TO_POOLPROPERTY_TYPE_TRANSFORMER( final List<String> configuredItemMetadataConfigValues) { this.configuredItemMetadataConfigValues = configuredItemMetadataConfigValues; } @Override public String apply(final PoolProperty poolProperty) { return StringUtils.isBlank(poolProperty.getProperty()) || !this.configuredItemMetadataConfigValues.contains(poolProperty.getProperty()) ? EMPTY_PROPERTY : poolProperty.getProperty(); } }; protected static final Function<PoolProperty, String> POOLPROPERTY_TO_POOLPROPERTY_VALUE_TRANSFORMER = new Function<PoolProperty, String>() { @Override public String apply(final PoolProperty poolProperty) { return StringUtils.isBlank(poolProperty.getValue()) ? EMPTY_PROPERTY : poolProperty.getValue(); } }; protected static final Ordering<PoolProperty> POOL_PROPERTY_ORDER = Ordering.natural() .onResultOf(new Function<PoolProperty, String>() { @Override public String apply(final PoolProperty poolProperty) { return poolProperty.getProperty() + poolProperty.getValue(); } }); // ======================================================================================================================================================================== // item pool construction protected static final Function<ItemGroup, String> ITEMGROUP_MAPKEY_TRANSFORMER = new Function<ItemGroup, String>() { @Override public String apply(final ItemGroup itemGroup) { return itemGroup.getId(); } }; protected static final class ITEM_TESTITEM_TRANSFORMER implements Function<Item, TestItem> { private final Map<String, ItemGroup> itemGroupMap; private final Map<String, Segment> segmentMap; private final Map<String, AffinityGroup> affinityGroupMap; private final String assessmentUniqueId; private final String client; public static ITEM_TESTITEM_TRANSFORMER getInstance(final Map<String, ItemGroup> itemGroupMap, final Map<String, Segment> segmentMap, final Map<String, AffinityGroup> affinityGroupMap, final String assessmentUniqueId, final String client) { return new ITEM_TESTITEM_TRANSFORMER(itemGroupMap, segmentMap, affinityGroupMap, assessmentUniqueId, client); } private ITEM_TESTITEM_TRANSFORMER(final Map<String, ItemGroup> itemGroupMap, final Map<String, Segment> segmentMap, final Map<String, AffinityGroup> affinityGroupMap, final String assessmentUniqueId, final String client) { this.itemGroupMap = itemGroupMap; this.segmentMap = segmentMap; this.affinityGroupMap = affinityGroupMap; this.assessmentUniqueId = assessmentUniqueId; this.client = client; } @Override public TestItem apply(final Item item) { if (item != null && StringUtils.isNotBlank(item.getInteractionType()) && item.getInteractionType().equalsIgnoreCase("Stimulus")) return null; //EF: notice call to buildIdentifierPrim final TestItem testItem = new TestItem(null, item.getInteractionType(), buildIdentifierPrim(item.getTibIdentifier(), item.getTibIdentifier(), item.getVersion())); testItem.setBluprintReferenceList(Lists.newArrayList(Iterables.concat( //EF: this is bpref to segmentid nullsafeListTransform(item.getItemLocation(), ITEM_LOCATION_SEGMENT_ID_TRANSFORMER.getInstance(this.segmentMap, assessmentUniqueId)), //EF: this is bpref to publication levels //Lists.newArrayList(item.getPrimaryStandard()), Lists.newArrayList(buildStandardsList(item.getPrimaryStandard(), this.client)), //this is bpref to affinity groups nullsafeListTransform(item.getItemLocation(), ITEM_LOCATION_AFFINITY_GROUP_ID_TRANSFORMER.getInstance(this.affinityGroupMap))))); testItem.setItemType(item.getInteractionType()); //EF: added setting filename testItem.setFileName(item.getTibIdentifier().concat(".xml")); testItem.setPassageReferenceList(nullsafeListTransform(item.getItemLocation(), ITEMLOCATION_GROUP_PASSAGE_ID_TRANSFORMER.getInstance(this.itemGroupMap))); testItem.setPoolPropertyList(buildPoolPropertyForItem(item)); testItem.setItemScoreDimensionList( nullsafeListTransform(item.getItemScoreDimensionList(), ITEM_SCORE_DIMENSION_TRANSFORMER)); testItem.setDatabaseId(item.getId()); return testItem; } private List<String> buildStandardsList(String primaryStandard, final String client) { List<String> standards = Lists.newArrayList(); String[] arr = StringUtils.split(primaryStandard, "|"); String standardLevel = ""; for (String a : arr) { if (standardLevel.isEmpty()) { // a is root if (a != null) { int pubEndPos = StringUtils.indexOf(a, ":"); if (pubEndPos > 0) a = StringUtils.substring(a, pubEndPos + 1); } standardLevel = standardLevel.concat(client).concat("-").concat(a); } else standardLevel = standardLevel.concat("|").concat(a); standards.add(standardLevel); } return standards; } @SuppressWarnings("unchecked") private List<PoolProperty> buildPoolPropertyForItem(final Item item) { final List<PoolProperty> metadataPoolPropertyList = Lists.newArrayList(); if (item.getAllIncludedMetadata() != null) { for (final Entry<String, Object> metadataEntry : item.getAllIncludedMetadata().entrySet()) { String value = StringEscapeUtils.escapeXml(metadataEntry.getValue().toString()); // previous fix String vl = null; String ky = null; Object obj = metadataEntry.getValue(); if (obj instanceof String) { vl = obj.toString(); value = StringEscapeUtils.escapeXml(vl); metadataPoolPropertyList.add(new PoolProperty(metadataEntry.getKey(), value, value)); } else if (obj instanceof List) { List<Object> objectList = (List<Object>) obj; for (Object o : objectList) { if (o instanceof String) { vl = o.toString(); value = StringEscapeUtils.escapeXml(vl); metadataPoolPropertyList .add(new PoolProperty(metadataEntry.getKey(), value, value)); } else if (o instanceof Map) { Map<Object, Object> valueMap = (Map<Object, Object>) o; for (Entry<Object, Object> entry : valueMap.entrySet()) { vl = entry.getValue().toString(); value = StringEscapeUtils.escapeXml(vl); ky = entry.getKey().toString(); metadataPoolPropertyList.add(new PoolProperty(ky, value, value)); } } } } else if (obj instanceof Map) { Map<Object, Object> valueMap = (Map<Object, Object>) obj; for (Entry<Object, Object> entry : valueMap.entrySet()) { vl = entry.getValue().toString(); value = StringEscapeUtils.escapeXml(vl); ky = entry.getKey().toString(); metadataPoolPropertyList.add(new PoolProperty(ky, value, value)); } } // if (StringUtils.startsWith (value, "[")) { // value = StringUtils.substringAfter (value, "["); // value = StringUtils.substringBeforeLast (value, "]"); // String[] vls = StringUtils.split (value, ","); // for (int i = 0; i < vls.length; i++) // { // String val = vls[i]; // if (metadataEntry.getKey ().equalsIgnoreCase ("Language")) // { // val = replaceLanguage (val); // } // metadataPoolPropertyList.add (new PoolProperty (metadataEntry.getKey (), val, val)); // } // // } else { // // if (metadataEntry.getKey ().equalsIgnoreCase ("Language")) { // value = replaceLanguage (value); // } // metadataPoolPropertyList.add (new PoolProperty (metadataEntry.getKey (), value, value)); // } } } return metadataPoolPropertyList; } }; private static final Function<org.opentestsystem.authoring.testauth.domain.ItemScoreDimension, ItemScoreDimension> ITEM_SCORE_DIMENSION_TRANSFORMER = new Function<org.opentestsystem.authoring.testauth.domain.ItemScoreDimension, ItemScoreDimension>() { @Override public ItemScoreDimension apply( final org.opentestsystem.authoring.testauth.domain.ItemScoreDimension itemScoreDimension) { final ItemScoreDimension isd = new ItemScoreDimension(); isd.setMeasurementModel(itemScoreDimension.getMeasurementModel()); isd.setDimension(itemScoreDimension.getDimension()); isd.setScorePoints(itemScoreDimension.getScorePoints()); isd.setWeight(itemScoreDimension.getWeight()); isd.setItemScoreParameterList(nullsafeListTransform(itemScoreDimension.getItemScoreParameterList(), ITEM_SCORE_PARAMETER_TRANSFORMER)); isd.setStatDomain(itemScoreDimension.getStatDomain()); return isd; }; }; private static final Function<org.opentestsystem.authoring.testauth.domain.ItemScoreParameter, ItemScoreParameter> ITEM_SCORE_PARAMETER_TRANSFORMER = new Function<org.opentestsystem.authoring.testauth.domain.ItemScoreParameter, ItemScoreParameter>() { @Override public ItemScoreParameter apply( final org.opentestsystem.authoring.testauth.domain.ItemScoreParameter itemScoreParameter) { final ItemScoreParameter isp = new ItemScoreParameter(); isp.setMeasurementParameter(itemScoreParameter.getMeasurementParameter()); isp.setValue(itemScoreParameter.getValue()); return isp; }; }; protected static final Function<TestItem, String> TESTITEM_ID_TRANSFORMER = new Function<TestItem, String>() { @Override public String apply(final TestItem testItem) { return testItem.getDatabaseId(); } }; private static final class ITEMLOCATION_FILTER implements Predicate<ItemLocation> { private final String locationId; private final ItemGroupLocationType itemGroupLocationType; public static ITEMLOCATION_FILTER getInstance(final String locationId, final ItemGroupLocationType itemGroupLocationType) { return new ITEMLOCATION_FILTER(locationId, itemGroupLocationType); } private ITEMLOCATION_FILTER(final String aLocationId, final ItemGroupLocationType aItemGroupLocationType) { this.locationId = aLocationId; this.itemGroupLocationType = aItemGroupLocationType; } @Override public boolean apply(final ItemLocation itemLocation) { if (itemLocation instanceof FixedFormItemLocation && this.itemGroupLocationType == ItemGroupLocationType.FORM_PARTITION) { return StringUtils.equals(this.locationId, itemLocation.getFormPartitionId()); } else if (itemLocation instanceof AdaptiveItemLocation && this.itemGroupLocationType == ItemGroupLocationType.SEGMENT) { return StringUtils.equals(this.locationId, itemLocation.getSegmentId()); } return false; }; } protected static final class ITEM_ITEMLOCATION_FILTER implements Function<Item, Item> { private final String locationId; private final ItemGroupLocationType itemGroupLocationType; public static ITEM_ITEMLOCATION_FILTER getInstance(final String locationId, final ItemGroupLocationType itemGroupLocationType) { return new ITEM_ITEMLOCATION_FILTER(locationId, itemGroupLocationType); } private ITEM_ITEMLOCATION_FILTER(final String aLocationId, final ItemGroupLocationType aItemGroupLocationType) { this.locationId = aLocationId; this.itemGroupLocationType = aItemGroupLocationType; } @Override public Item apply(final Item item) { Item returnItem = null; if (item != null && item.getItemLocation() != null && Iterables.any(item.getItemLocation(), ITEMLOCATION_FILTER.getInstance(this.locationId, this.itemGroupLocationType))) { returnItem = item; } return returnItem; } }; protected static final Function<Segment, String> SEGMENT_KEYID_TRANSFORMER = new Function<Segment, String>() { @Override public String apply(final Segment segment) { return segment.getId(); } }; protected static final Function<AffinityGroup, String> AFFINITY_GROUP_KEYID_TRANSFORMER = new Function<AffinityGroup, String>() { @Override public String apply(final AffinityGroup affinityGroup) { return affinityGroup.getId(); } }; protected static final Function<Item, Passage> ITEM_PASSAGE_TRANSFORMER = new Function<Item, Passage>() { @Override public Passage apply(final Item item) { if (item != null && StringUtils.isNotBlank(item.getInteractionType()) && item.getInteractionType().equalsIgnoreCase("Stimulus")) { Passage pass = new Passage(null, buildIdentifierPrim(item.getTibIdentifier(), item.getTibIdentifier(), item.getVersion())); pass.setFileName(item.getTibIdentifier().concat(".xml")); return pass; } else return null; }; }; protected final static Function<Enemy, String> ENEMY_TO_ENEMYID1_TRANSFORMER = new Function<Enemy, String>() { @Override public String apply(final Enemy enemy) { return StringUtils.isBlank(enemy.getObjectId1()) ? EMPTY_PROPERTY : enemy.getObjectId1(); } }; protected static final Function<Enemy, String> ENEMY_TO_ENEMYID2_TRANSFORMER = new Function<Enemy, String>() { @Override public String apply(final Enemy enemy) { return StringUtils.isBlank(enemy.getObjectId2()) ? EMPTY_PROPERTY : enemy.getObjectId2(); } }; // protected static final Function<Enemy, TestEnemy> ENEMY1_TRANSFORMER = new Function<Enemy, TestEnemy>() { // @Override // public TestEnemy apply(final Enemy enemy) { // return new TestEnemy(buildIdentifierPrim(enemy.getObjectId2(), enemy.getObjectId2(), DEFAULT_VERSION).getUniqueId(), enemy.getObjectType2().getXmlValue()); // }; // }; protected static final class ENEMY1_TRANSFORMER implements Function<Enemy, TestEnemy> { private final String itemBank; public static ENEMY1_TRANSFORMER getInstance(final String itembank) { return new ENEMY1_TRANSFORMER(itembank); } private ENEMY1_TRANSFORMER(final String itembank) { this.itemBank = itembank; } @Override public TestEnemy apply(Enemy enemy) { return new TestEnemy( buildEnemyIdentifier(enemy.getObject2(), enemy.getObjectId2(), enemy.getObjectType2().getXmlValue(), this.itemBank).getUniqueId(), enemy.getObjectType2().getXmlValue()); } } protected static final class ENEMY2_TRANSFORMER implements Function<Enemy, TestEnemy> { private final String itemBank; public static ENEMY2_TRANSFORMER getInstance(final String itembank) { return new ENEMY2_TRANSFORMER(itembank); } private ENEMY2_TRANSFORMER(final String itembank) { this.itemBank = itembank; } @Override public TestEnemy apply(Enemy enemy) { return new TestEnemy( buildEnemyIdentifier(enemy.getObject1(), enemy.getObjectId1(), enemy.getObjectType1().getXmlValue(), this.itemBank).getUniqueId(), enemy.getObjectType1().getXmlValue()); } } private static final Identifier buildEnemyIdentifier(Object enemy, final String objId, final String objType, final String itembank) { Identifier identifier = null; if (enemy instanceof Item) { final Item item = (Item) enemy; identifier = PublisherUtil.buildIdentifierPrim(item.getTibIdentifier(), item.getTibIdentifier(), item.getVersion()); } else if (enemy instanceof ItemGroup) { final ItemGroup itemGroup = (ItemGroup) enemy; identifier = new Identifier(itemGroup.getPassageId(), itemGroup.getGroupName(), itemGroup.getGroupName(), DEFAULT_VERSION); identifier.setUniqueId(itembank + '-' + identifier.getUniqueId()); } else if (enemy instanceof Passage) { final Passage pass = (Passage) enemy; identifier = pass.getIdentifier(); } return identifier; } private static final class ITEMLOCATION_GROUP_PASSAGE_ID_TRANSFORMER implements Function<ItemLocation, String> { private final Map<String, ItemGroup> itemGroupMap; public static ITEMLOCATION_GROUP_PASSAGE_ID_TRANSFORMER getInstance( final Map<String, ItemGroup> itemGroupMap) { return new ITEMLOCATION_GROUP_PASSAGE_ID_TRANSFORMER(itemGroupMap); } private ITEMLOCATION_GROUP_PASSAGE_ID_TRANSFORMER(final Map<String, ItemGroup> itemGroupMap) { this.itemGroupMap = itemGroupMap; } @Override public String apply(final ItemLocation itemLocation) { //EF: here we need to add bank number and dash before passage number String bankNumber = ""; if (itemLocation != null && StringUtils.isNotBlank(itemLocation.getItemIdentifier())) { bankNumber = parseBankNumberFromIdentifier(itemLocation.getItemIdentifier()); } if (itemLocation != null && StringUtils.isNotBlank(itemLocation.getItemGroupId()) && !StringUtils.equals(itemLocation.getItemGroupId(), Item.NO_GROUP_KEY) && this.itemGroupMap.get(itemLocation.getItemGroupId()) != null) { if (StringUtils.isNotBlank(bankNumber)) return bankNumber.concat("-") .concat(this.itemGroupMap.get(itemLocation.getItemGroupId()).getPassageId()); else return this.itemGroupMap.get(itemLocation.getItemGroupId()).getPassageId(); } else return null; }; private String parseBankNumberFromIdentifier(String itemIdentifier) { String bankNumber = null; String tmpArr[] = StringUtils.split(itemIdentifier, "-"); if (tmpArr.length == 3) bankNumber = tmpArr[1]; return bankNumber; } }; private static final class ITEM_LOCATION_SEGMENT_ID_TRANSFORMER implements Function<ItemLocation, String> { private final Map<String, Segment> segmentMap; private final String assessmentUniqueId; public static ITEM_LOCATION_SEGMENT_ID_TRANSFORMER getInstance(final Map<String, Segment> segmentMap, String assessmentUniqueId) { return new ITEM_LOCATION_SEGMENT_ID_TRANSFORMER(segmentMap, assessmentUniqueId); } private ITEM_LOCATION_SEGMENT_ID_TRANSFORMER(final Map<String, Segment> segmentMap, String assessmentUniqueId) { this.segmentMap = segmentMap; this.assessmentUniqueId = assessmentUniqueId; } @Override //AK: if there is only one segment segment uniqueid must be equal test(assessment) uniqueid public String apply(final ItemLocation itemLocation) { return (this.segmentMap.size() == 1 && StringUtils.isNotBlank(this.assessmentUniqueId) && !(itemLocation instanceof AffinityGroupItemLocation)) ? this.assessmentUniqueId : itemLocation != null && StringUtils.isNotBlank(itemLocation.getSegmentId()) && !(itemLocation instanceof AffinityGroupItemLocation) ? itemLocation.getSegmentId() : null; }; }; private static final class ITEM_LOCATION_AFFINITY_GROUP_ID_TRANSFORMER implements Function<ItemLocation, String> { private final Map<String, AffinityGroup> affinityGroupMap; public static ITEM_LOCATION_AFFINITY_GROUP_ID_TRANSFORMER getInstance( final Map<String, AffinityGroup> affinityGroupMap) { return new ITEM_LOCATION_AFFINITY_GROUP_ID_TRANSFORMER(affinityGroupMap); } private ITEM_LOCATION_AFFINITY_GROUP_ID_TRANSFORMER(final Map<String, AffinityGroup> affinityGroupMap) { this.affinityGroupMap = affinityGroupMap; } @Override public String apply(final ItemLocation itemLocation) { return itemLocation != null && StringUtils.isNotBlank(itemLocation.getAffinityGroupId()) ? buildIdentifier(this.affinityGroupMap.get(itemLocation.getAffinityGroupId()).getGroupName(), null, DEFAULT_VERSION).getUniqueId() : null; }; }; // ======================================================================================================================================================================== // blueprint construction protected static final class ITEM_COUNT_FILTER implements Predicate<Item> { private final String standardKey; private final String statusKey; private String opItemStatuses; private List<String> opItemStatusList = null; public static ITEM_COUNT_FILTER getInstance(final String standardKey, final String statusKey, final String opItemStatuses) { return new ITEM_COUNT_FILTER(standardKey, statusKey, opItemStatuses); } private ITEM_COUNT_FILTER(final String standardKey, final String statusKey, final String opItemStatuses) { this.standardKey = standardKey; this.statusKey = statusKey; this.opItemStatuses = opItemStatuses; } private boolean isOperationalStatus(final String itemStatus) { if (this.opItemStatusList == null) { if (StringUtils.isEmpty(this.opItemStatuses)) { throw new LocalizedException("item.op.statuses.empty"); } this.opItemStatusList = Arrays.asList(this.opItemStatuses.split(",")); } return this.opItemStatusList.contains(itemStatus); } /* * return true if item status is the "same" as StatusKey */ private boolean isItemStatus(final String status) { if ("OP".equalsIgnoreCase(statusKey)) { return isOperationalStatus(status); } else return !isOperationalStatus(status); } @Override public boolean apply(final Item item) { return item != null && item.getPrimaryStandard() != null && item.getPrimaryStandard().contains(this.standardKey) && item.getStatus() != null && isItemStatus(item.getStatus()); } }; // ======================================================================================================================================================================== // segment construction public static final Predicate<Segment> FIXEDFORM_SEGMENT_FILTER = new Predicate<Segment>() { @Override public boolean apply(final Segment segment) { return segment != null && segment.getItemSelectionAlgorithm() != null && segment.getItemSelectionAlgorithm().getItemSelectionAlgorithmType() != null && segment.getItemSelectionAlgorithm().getItemSelectionAlgorithmType() .equals(ItemSelectionAlgorithmType.FIXEDFORM); } }; protected static final class FORMPARTITION_REFERENCE_TRANSFORMER implements Function<FormPartition, String> { private final String bankKey; private final int serverUniqueNumber; private final String version; public static FORMPARTITION_REFERENCE_TRANSFORMER getInstance(final String bankKey, final int serverUniqueNumber, final String version) { return new FORMPARTITION_REFERENCE_TRANSFORMER(bankKey, serverUniqueNumber, version); } private FORMPARTITION_REFERENCE_TRANSFORMER(final String bankKey, final int serverUniqueNumber, final String version) { this.bankKey = bankKey; this.serverUniqueNumber = serverUniqueNumber; this.version = version; } @Override public String apply(final FormPartition formPartition) { if (formPartition != null && formPartition.getId() != null && formPartition.getId().length() == 24) { return this.bankKey.concat("-") .concat(buildTdsCompatibleId(formPartition.getId(), this.serverUniqueNumber, this.version)); } else return ""; // return formPartition != null && formPartition.getName () != null ? // buildIdentifier(formPartition.getName (), null, DEFAULT_VERSION).getUniqueId () : null; } }; protected static final class ISP_LIST_TRANSFORMER implements Function<Entry<String, Map<String, String>>, ItemSelectionParameter> { private final Map<String, Segment> segmentMap; private final Assessment assessment; public static ISP_LIST_TRANSFORMER getInstance(final Map<String, Segment> segmentMap, Assessment assessment) { return new ISP_LIST_TRANSFORMER(segmentMap, assessment); } private ISP_LIST_TRANSFORMER(final Map<String, Segment> segmentMap, Assessment assessment) { this.segmentMap = segmentMap; this.assessment = assessment; } @Override public ItemSelectionParameter apply(final Entry<String, Map<String, String>> itemSelectionParameterUsage) { final ItemSelectionParameter isp = new ItemSelectionParameter(); String bpElementId; if (this.segmentMap.get(itemSelectionParameterUsage.getKey()) != null) { if (this.segmentMap.size() == 1) bpElementId = buildIdentifier(assessment.getName(), assessment.getLabel(), assessment.getVersion()).getUniqueId(); else bpElementId = itemSelectionParameterUsage.getKey(); } else bpElementId = itemSelectionParameterUsage.getKey(); isp.setBlueprintElementId(bpElementId); if (!itemSelectionParameterUsage.getValue().entrySet().isEmpty()) { final List<Property> propertyList = Lists.newArrayList(); for (final Entry<String, String> mapEntryValue : itemSelectionParameterUsage.getValue() .entrySet()) { propertyList.add(new Property(mapEntryValue.getKey(), mapEntryValue.getValue(), mapEntryValue.getKey(), null)); } isp.setPropertyList(propertyList); } return isp; } }; // ======================================================================================================================================================================== // segment/partition item reference group/item reference (itemgroup/groupitem) protected static final Function<ItemGroup, String> ITEMGROUPID_KEY_TRANSFORMER = new Function<ItemGroup, String>() { @Override public String apply(final ItemGroup itemGroup) { return itemGroup.getId(); } }; protected static final Function<Item, List<String>> ITEM_ITEMGROUPIDLIST_TRANSFORMER = new Function<Item, List<String>>() { @Override public List<String> apply(final Item item) { return Lists.transform(item.getAdaptiveAndFixedItemLocations(), ITEMLOCATION_ITEMGROUP_TRANSFORMER); } }; private static final Function<ItemLocation, String> ITEMLOCATION_ITEMGROUP_TRANSFORMER = new Function<ItemLocation, String>() { @Override public String apply(final ItemLocation itemLocation) { return itemLocation != null ? itemLocation.getItemGroupId() : null; } }; protected static final class ITEM_ITEMGROUP_TRANSFORMER implements Function<Item, ItemReferenceGroup> { private final boolean isSegmentLevel; private final String locationId; private final String bank; private final int serverUniqueNumber; private final String version; public static ITEM_ITEMGROUP_TRANSFORMER getInstance(final boolean isSegmentLevel, final String locationId, final String bank, final int serverUniqueNumber, final String version) { return new ITEM_ITEMGROUP_TRANSFORMER(isSegmentLevel, locationId, bank, serverUniqueNumber, version); } private ITEM_ITEMGROUP_TRANSFORMER(final boolean isSegmentLevel, final String locationId, final String bank, final int serverUniqueNumber, final String version) { this.isSegmentLevel = isSegmentLevel; this.locationId = locationId; this.bank = bank; this.serverUniqueNumber = serverUniqueNumber; this.version = version; } @Override public ItemReferenceGroup apply(final Item item) { final ItemReferenceGroup itemReferenceGroup = new ItemReferenceGroup(); ItemLocation itemLocationToUse = null; for (final ItemLocation itemLocation : item.getAdaptiveAndFixedItemLocations()) { if (this.isSegmentLevel && StringUtils.equals(this.locationId, itemLocation.getSegmentId()) || !this.isSegmentLevel && StringUtils.equals(this.locationId, itemLocation.getFormPartitionId())) { itemLocationToUse = itemLocation; } } itemReferenceGroup.setMaxResponses(this.isSegmentLevel ? null : "1"); itemReferenceGroup.setFormPosition( itemLocationToUse != null ? String.valueOf(itemLocationToUse.getLevel1SortIndex()) : "1"); itemReferenceGroup.setMaxItems(this.isSegmentLevel ? null : "1"); String itemReferenceGroupUniqueIdentifier = "I-".concat(this.bank).concat("-") .concat(item.getAllIncludedMetadata().get("Identifier").toString()); if (this.isSegmentLevel == false) { itemReferenceGroupUniqueIdentifier = this.bank.concat("-") .concat(itemLocationToUse == null ? "" : buildTdsCompatibleId(itemLocationToUse.getFormPartitionId(), this.serverUniqueNumber, this.version)) .concat(":").concat(itemReferenceGroupUniqueIdentifier); } itemReferenceGroup.setIdentifier(new Identifier(itemReferenceGroupUniqueIdentifier, itemReferenceGroupUniqueIdentifier, "", item.getVersion())); //itemReferenceGroup.setIdentifier(buildIdentifier(item.getTibIdentifier(), item.getTibIdentifier(), item.getVersion())); if (StringUtils.isNotBlank(item.getAssociatedStimulus())) { itemReferenceGroup.setPassageReferenceList( Lists.newArrayList(this.bank.concat("-").concat(item.getAssociatedStimulus()))); } itemReferenceGroup.setItemReferenceList(Lists.newArrayList( ITEM_ITEMREFERENCE_TRANSFORMER.getInstance(Item.NO_GROUP_KEY, this.bank).apply(item))); // itemReferenceGroup.setProperty(null); return itemReferenceGroup; } }; // construct group w/ item children protected static final class ITEMLIST_ITEMGROUP_TRANSFORMER implements Function<Entry<ItemGroup, List<Item>>, ItemReferenceGroup> { private final String bank; private final Map<String, Segment> segmentMap; private final int serverUniqueNumber; private final String version; public static ITEMLIST_ITEMGROUP_TRANSFORMER getInstance(final String bank, final Map<String, Segment> segmentMap, final int serverUniqueNumber, final String version) { return new ITEMLIST_ITEMGROUP_TRANSFORMER(bank, segmentMap, serverUniqueNumber, version); } private ITEMLIST_ITEMGROUP_TRANSFORMER(final String bank, final Map<String, Segment> segmentMap, final int serverUniqueNumber, final String version) { this.bank = bank; this.segmentMap = segmentMap; this.serverUniqueNumber = serverUniqueNumber; this.version = version; } @Override public ItemReferenceGroup apply(final Entry<ItemGroup, List<Item>> itemGroupMapEntry) { final ItemReferenceGroup itemReferenceGroup = new ItemReferenceGroup(); final ItemGroup itemGroup = itemGroupMapEntry.getKey(); itemReferenceGroup.setMaxResponses(itemGroup.getMaxResponses().toString()); // all items passed in SHOULD have the same ItemLocation attribute to find ItemLocation itemLocationToUse = null; for (final ItemLocation itemLocation : itemGroupMapEntry.getValue().get(0).getItemLocation()) { if (StringUtils.equals(itemGroup.getId(), itemLocation.getItemGroupId())) { itemLocationToUse = itemLocation; } } itemReferenceGroup.setFormPosition(String.valueOf(itemLocationToUse.getLevel1SortIndex())); itemReferenceGroup.setMaxItems(itemGroup.getMaxitems().toString()); if (StringUtils.isNotBlank(itemGroup.getPassageId())) { itemReferenceGroup.setPassageReferenceList( Lists.newArrayList(this.bank.concat("-").concat(itemGroup.getPassageId()))); } itemReferenceGroup.setItemReferenceList(Lists.transform(itemGroupMapEntry.getValue(), ITEM_ITEMREFERENCE_TRANSFORMER.getInstance(itemGroup.getId(), this.bank))); final String itemReferenceGroupUniqueId = buildItemReferenceGroupUniqueId(itemGroup, itemReferenceGroup.getItemReferenceList(), version); itemReferenceGroup.setIdentifier( new Identifier(itemReferenceGroupUniqueId, itemReferenceGroupUniqueId, "", DEFAULT_VERSION)); //itemReferenceGroup.setIdentifier(buildIdentifier( // StringUtils.isNotBlank(itemGroup.getPassageId()) ? itemGroup.getPassageId() : itemGroup.getGroupName(), // itemGroup.getPassageName(), DEFAULT_VERSION)); return itemReferenceGroup; } String buildItemReferenceGroupUniqueId(ItemGroup itemGroup, List<ItemReference> itemReferenceList, String version) { //suffix format :G-200-1930-1 where 1930 is passageid or :I-200-133 where 133 is an item id int pos = 0; if (itemGroup.getLocationType() == ItemGroupLocationType.FORM_PARTITION && segmentMap != null) { String segmentId = itemGroup.getFormPartition().getSegmentId(); pos = this.segmentMap.get(segmentId).getPosition(); } else if (itemGroup.getLocationType() == ItemGroupLocationType.SEGMENT) pos = itemGroup.getSegment().getPosition(); String theSuffix = (StringUtils.isNotBlank(itemGroup.getPassageId()) ? ":G-".concat(this.bank) .concat("-").concat(itemGroup.getPassageId()).concat("-").concat(Integer.toString(pos)) : ":I-".concat(itemReferenceList.get(0).getItemId())); String uniqueId = this.bank.concat("-") .concat(buildTdsCompatibleId(itemGroup.getLocationId(), this.serverUniqueNumber, this.version)) .concat(theSuffix); return uniqueId; } }; // private static final Function<ItemGroup, String> ITEMGROUP_LOCATIONID_TRANSFORMER = new Function<ItemGroup, String>() { // @Override // public String apply(final ItemGroup itemGroup) { // // return (buildTdsCompatibleId(itemGroup.getLocationId ())); // } // }; public static final class FORM_FORMID_TRANSFORMER implements Function<Form, String> { private int serverUniqueNumber; private final String version; public static FORM_FORMID_TRANSFORMER getInstance(final int serverUniqueNumber, final String version) { return new FORM_FORMID_TRANSFORMER(serverUniqueNumber, version); } private FORM_FORMID_TRANSFORMER(final int serverUniqueNumber, final String version) { this.serverUniqueNumber = serverUniqueNumber; this.version = version; } @Override public String apply(final Form form) { String formId = buildTdsCompatibleId(form.getId(), this.serverUniqueNumber, this.version); if (StringUtils.isEmpty(formId)) formId = form.getName(); return formId; } }; private static final class ITEM_ITEMREFERENCE_TRANSFORMER implements Function<Item, ItemReference> { private final String itemGroupId; private final String bank; public static ITEM_ITEMREFERENCE_TRANSFORMER getInstance(final String itemGroupId, final String bank) { return new ITEM_ITEMREFERENCE_TRANSFORMER(itemGroupId, bank); } private ITEM_ITEMREFERENCE_TRANSFORMER(final String itemGroupId, final String bank) { this.itemGroupId = itemGroupId; this.bank = bank; } @Override public ItemReference apply(final Item item) { ItemLocation itemLocationToUse = null; for (final ItemLocation itemLocation : item.getItemLocation()) { if (StringUtils.equals(this.itemGroupId, itemLocation.getItemGroupId())) { itemLocationToUse = itemLocation; } } return itemLocationToUse != null ? new ItemReference(bank.concat("-").concat(getItemMetadataIdentifier(item)), itemLocationToUse.getLevel2SortIndex(), itemLocationToUse.isAdminRequired(), itemLocationToUse.isResponseRequired(), itemLocationToUse.isFieldTestItem(), itemLocationToUse.isActive(), itemLocationToUse.getBlockId()) : new ItemReference(bank.concat("-").concat(getItemMetadataIdentifier(item)), 1, true, true, false, false, ""); // latter should never actually happen } }; protected static String getItemMetadataIdentifier(final Item item) { return item.getAllIncludedMetadata().get("Identifier").toString(); } protected static final Ordering<ItemReferenceGroup> ITEM_REF_GROUP_ORDER = Ordering.natural() .onResultOf(new Function<ItemReferenceGroup, Integer>() { @Override public Integer apply(final ItemReferenceGroup itemReferenceGroup) { return Integer.valueOf(itemReferenceGroup.getFormPosition()); } }); protected static final class ITEM_LOCATION_MATCHER implements Predicate<ItemLocation> { private final String itemGroupId; private final String locationId; private final ItemGroupLocationType itemGroupLocationType; public static ITEM_LOCATION_MATCHER getInstance(final String itemGroupId, final String locationId, final ItemGroupLocationType itemGroupLocationType) { return new ITEM_LOCATION_MATCHER(itemGroupId, locationId, itemGroupLocationType); } private ITEM_LOCATION_MATCHER(final String itemGroupId, final String locationId, final ItemGroupLocationType itemGroupLocationType) { this.itemGroupId = itemGroupId; this.locationId = locationId; this.itemGroupLocationType = itemGroupLocationType; } @Override public boolean apply(final ItemLocation itemLocation) { return StringUtils.equals(itemLocation.getItemGroupId(), this.itemGroupId) && ITEMLOCATION_FILTER .getInstance(this.locationId, this.itemGroupLocationType).apply(itemLocation); }; } // ======================================================================================================================================================================== // performance level construction protected static final class PERFORMANCE_LEVEL_TRANSFORMER implements Function<PerformanceLevel, List<TestPerformanceLevel>> { private final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap; public static PERFORMANCE_LEVEL_TRANSFORMER getInstance( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap) { return new PERFORMANCE_LEVEL_TRANSFORMER(blueprintReferenceMap); } private PERFORMANCE_LEVEL_TRANSFORMER( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap) { this.blueprintReferenceMap = blueprintReferenceMap; } @Override public List<TestPerformanceLevel> apply(final PerformanceLevel performanceLevel) { if (this.blueprintReferenceMap.get(performanceLevel.getBlueprintReferenceType()) != null && this.blueprintReferenceMap.get(performanceLevel.getBlueprintReferenceType()) .get(performanceLevel.getBlueprintReferenceId()) != null) { final String currentBlueprintReferenceName = this.blueprintReferenceMap .get(performanceLevel.getBlueprintReferenceType()) .get(performanceLevel.getBlueprintReferenceId()); return Lists.transform(performanceLevel.getPerformanceLevelValues(), PERFORMANCE_LEVEL_VALUE_TRANSFORMER.getInstance(currentBlueprintReferenceName)); } return Lists.newArrayList(); } }; private static final class PERFORMANCE_LEVEL_VALUE_TRANSFORMER implements Function<PerformanceLevelValue, TestPerformanceLevel> { private final String bpElementId; public static PERFORMANCE_LEVEL_VALUE_TRANSFORMER getInstance(final String bpElementId) { return new PERFORMANCE_LEVEL_VALUE_TRANSFORMER(bpElementId); } private PERFORMANCE_LEVEL_VALUE_TRANSFORMER(final String bpElementId) { this.bpElementId = bpElementId; } @Override public TestPerformanceLevel apply(final PerformanceLevelValue performanceLevelValue) { return new TestPerformanceLevel(this.bpElementId, performanceLevelValue.getLevel().toString(), performanceLevelValue.getScaledLo(), performanceLevelValue.getScaledHi()); } }; // ======================================================================================================================================================================== // scoring rule construction protected static final class SCORING_RULE_TRANSFORMER implements Function<ScoringRule, TestComputationRule> { private final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap; public static SCORING_RULE_TRANSFORMER getInstance( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap) { return new SCORING_RULE_TRANSFORMER(blueprintReferenceMap); } private SCORING_RULE_TRANSFORMER( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap) { this.blueprintReferenceMap = blueprintReferenceMap; } @Override public TestComputationRule apply(final ScoringRule scoringRule) { if (!(scoringRule.getBlueprintReferenceType().equals(BlueprintReferenceType.STANDARD) && !scoringRule.getBlueprintDenotationType().equals(BlueprintDenotationType.STANDARD_KEY)) && this.blueprintReferenceMap.get(scoringRule.getBlueprintReferenceType()) != null && this.blueprintReferenceMap.get(scoringRule.getBlueprintReferenceType()) .get(scoringRule.getBlueprintReferenceId()) != null) { final String currentBlueprintReferenceName = this.blueprintReferenceMap .get(scoringRule.getBlueprintReferenceType()).get(scoringRule.getBlueprintReferenceId()); final TestComputationRule testComputationRule = new TestComputationRule(); testComputationRule.setScoringRuleId(scoringRule.getId()); testComputationRule.setBpElementId(currentBlueprintReferenceName); testComputationRule.setComputationOrder(scoringRule.getOrder().toString()); final ComputationRule computationRule = scoringRule.getComputationRule(); if (!CollectionUtils.isEmpty(computationRule.getParameters())) { final Map<String, ComputationRuleParameter> computationRuleParameterMap = Maps .uniqueIndex(computationRule.getParameters(), COMPUTATION_RULE_PARAM_NAME_TRANSFORMER); testComputationRule.setComputationRuleParameterList( Lists.transform(scoringRule.getParameters(), SCORING_RULE_PARAMETER_TRANSFORMER .getInstance(scoringRule.getLabel(), computationRuleParameterMap))); } //EF: changed places for name and label. Confirm it! testComputationRule.setIdentifier(buildIdentifier(computationRule.getName(), scoringRule.getLabel(), computationRule.getVersion())); //testComputationRule.setIdentifier(buildIdentifier(scoringRule.getLabel(), computationRule.getName(), computationRule.getVersion())); //EF: substituted identifier with UUID to match legacy system testComputationRule.getIdentifier().setUniqueId(UUID.randomUUID().toString()); return testComputationRule; } return null; } }; private static final Function<ComputationRuleParameter, String> COMPUTATION_RULE_PARAM_NAME_TRANSFORMER = new Function<ComputationRuleParameter, String>() { @Override public String apply(final ComputationRuleParameter computationRuleParameter) { return StringUtils.isBlank(computationRuleParameter.getParameterName()) ? EMPTY_PROPERTY : computationRuleParameter.getParameterName(); } }; private static final class SCORING_RULE_PARAMETER_TRANSFORMER implements Function<ScoringRuleParameter, TestComputationRuleParameter> { private final String scoringRuleName; private final Map<String, ComputationRuleParameter> computationRuleParameterMap; public static SCORING_RULE_PARAMETER_TRANSFORMER getInstance(final String scoringRuleName, final Map<String, ComputationRuleParameter> computationRuleParameterMap) { return new SCORING_RULE_PARAMETER_TRANSFORMER(scoringRuleName, computationRuleParameterMap); } private SCORING_RULE_PARAMETER_TRANSFORMER(final String scoringRuleName, final Map<String, ComputationRuleParameter> computationRuleParameterMap) { this.scoringRuleName = scoringRuleName; this.computationRuleParameterMap = computationRuleParameterMap; } @Override public TestComputationRuleParameter apply(final ScoringRuleParameter scoringRuleParameter) { final TestComputationRuleParameter testComputationRuleParameter = new TestComputationRuleParameter(); final ComputationRuleParameter computationRuleParameter = this.computationRuleParameterMap .get(scoringRuleParameter.getComputationRuleParameterName()); testComputationRuleParameter.setPosition(String.valueOf(computationRuleParameter.getPosition())); testComputationRuleParameter .setParameterType(computationRuleParameter.getComputationRuleType().name().toLowerCase()); final String paramName = scoringRuleParameter.getComputationRuleParameterName(); //EF: changed places for name and label. Dropped label. Confirm it! testComputationRuleParameter.setIdentifier(buildIdentifier(paramName, null, DEFAULT_VERSION)); //testComputationRuleParameter.setIdentifier(buildIdentifier(this.scoringRuleName, paramName, DEFAULT_VERSION)); //EF: substituted identifier with UUID to match legacy system testComputationRuleParameter.getIdentifier().setUniqueId(UUID.randomUUID().toString()); if (computationRuleParameter.getDictionaryIndexType() != null) { final List<Property> propertyList = Lists.newArrayList(new Property("indextype", computationRuleParameter.getDictionaryIndexType().getTitle().toLowerCase(), null)); testComputationRuleParameter.setPropertyList(propertyList); } if (StringUtils.isNotBlank(scoringRuleParameter.getScalarValue())) { testComputationRuleParameter.setComputationRuleParameterValueList(Lists.newArrayList( new TestComputationRuleParameterValue(scoringRuleParameter.getScalarValue(), null))); } else { testComputationRuleParameter.setComputationRuleParameterValueList(Lists.transform( scoringRuleParameter.getDictionaryValue(), this.SCORING_RULE_DICTIONARY_TRANSFORMER)); } return testComputationRuleParameter; } private final Function<ScoringRuleDictionaryElement, TestComputationRuleParameterValue> SCORING_RULE_DICTIONARY_TRANSFORMER = new Function<ScoringRuleDictionaryElement, TestComputationRuleParameterValue>() { @Override public TestComputationRuleParameterValue apply(final ScoringRuleDictionaryElement dictionary) { return new TestComputationRuleParameterValue(dictionary.getValue(), dictionary.getKey()); } }; }; protected static final class CONVERSION_TABLE_TRANSFORMER implements Function<ScoringRule, List<ConversionTable>> { private final GridFsRepository gridFsRepository; public static CONVERSION_TABLE_TRANSFORMER getInstance(final GridFsRepository gridFsRepository) { return new CONVERSION_TABLE_TRANSFORMER(gridFsRepository); } private CONVERSION_TABLE_TRANSFORMER(final GridFsRepository gridFsRepository) { this.gridFsRepository = gridFsRepository; } @Override public List<ConversionTable> apply(final ScoringRule scoringRule) { if (scoringRule.getComputationRule().getConversionTableType().equals(ConversionTableType.NONE)) { return null; } final List<ConversionTable> conversionTableList = Lists.newArrayList(); if (StringUtils.isNotEmpty(scoringRule.getValueConversionTableGridFsId())) { final ConversionTable conversionTable = new ConversionTable(scoringRule.getBlueprintReferenceName(), null, "score", null, buildIdentifier(scoringRule.getValueConversionTableFilename(), null, DEFAULT_VERSION), buildConversionTupleForScoringRule(scoringRule.getValueConversionTableGridFsId(), scoringRule.getLabel(), "VALUE")); conversionTableList.add(conversionTable); } if (StringUtils.isNotEmpty(scoringRule.getStandardErrorConversionTableGridFsId())) { final ConversionTable conversionTable = new ConversionTable(scoringRule.getBlueprintReferenceName(), null, "standarderror", null, buildIdentifier(scoringRule.getStandardErrorConversionTableFilename(), null, DEFAULT_VERSION), buildConversionTupleForScoringRule(scoringRule.getStandardErrorConversionTableGridFsId(), scoringRule.getLabel(), "STANDARD_ERROR")); conversionTableList.add(conversionTable); } return conversionTableList; } private List<ConversionTuple> buildConversionTupleForScoringRule(final String gridFsId, final String scoringRuleName, final String conversionTableType) { final GridFSDBFile file = this.gridFsRepository.getById(gridFsId); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { file.writeTo(baos); } catch (final IOException e) { throw new LocalizedException("publishingRecord.conversionTableFile.ioexception", paramArray(scoringRuleName, conversionTableType)); } final List<ConversionTuple> conversionTupleList = validateConversionListFile(baos.toByteArray(), scoringRuleName, conversionTableType, true); // do not return header row as that should not make it into outbound XML return conversionTupleList.subList(1, conversionTupleList.size()); } }; public static List<ConversionTuple> validateConversionListFile(final byte[] file, final String name, final String fileType, final boolean publishMode) { final List<ConversionTuple> conversionTupleList = Lists.newArrayList(); final String messagePrefix = publishMode ? "publishingRecord" : "scoringRule"; CSVReader reader = null; try { reader = new CSVReader(new InputStreamReader(new ByteArrayInputStream(file), Charset.forName("UTF-8"))); String[] csvContent; int i = 0; while ((csvContent = reader.readNext()) != null) { if (csvContent != null && csvContent.length > 1) { if (i == 0) { // first record, validate headers if (!StringUtils.equalsIgnoreCase("invalue", csvContent[0])) { throw new LocalizedException(messagePrefix + ".conversionTableFile.header.invalue", paramArray(name, fileType)); } else if (!StringUtils.equalsIgnoreCase("outvalue", csvContent[1])) { throw new LocalizedException(messagePrefix + ".conversionTableFile.header.outvalue", paramArray(name, fileType)); } } if (StringUtils.isBlank(csvContent[0])) { throw new LocalizedException(messagePrefix + ".conversionTableFile.blank.invalue", paramArray(name, fileType)); } if (StringUtils.isBlank(csvContent[1])) { throw new LocalizedException(messagePrefix + ".conversionTableFile.blank.outvalue", paramArray(name, fileType)); } conversionTupleList.add(new ConversionTuple(csvContent[0], csvContent[1])); } else { throw new LocalizedException(messagePrefix + ".conversionTableFile.unparseable", paramArray(name, fileType)); } i++; } } catch (final IOException e) { throw new LocalizedException(messagePrefix + ".conversionTableFile.ioexception", paramArray(name, fileType)); } finally { if (reader != null) { try { reader.close(); } catch (final IOException e) { throw new LocalizedException(messagePrefix + ".conversionTableFile.closeexception", paramArray(name, fileType)); } } } return conversionTupleList; } protected static final class LEAF_NODE_LEVEL_SCORING_RULE_TRANSFORMER implements Function<BlueprintElement, TestComputationRule> { private final ScoringRule scoringRule; private int orderIncr; public static LEAF_NODE_LEVEL_SCORING_RULE_TRANSFORMER getInstance(final ScoringRule scoringRule, final int orderIncr) { return new LEAF_NODE_LEVEL_SCORING_RULE_TRANSFORMER(scoringRule, orderIncr); } private LEAF_NODE_LEVEL_SCORING_RULE_TRANSFORMER(final ScoringRule scoringRule, final int orderIncr) { this.scoringRule = scoringRule; this.orderIncr = orderIncr; } @Override public TestComputationRule apply(final BlueprintElement blueprintElement) { final TestComputationRule testComputationRule = new TestComputationRule(); testComputationRule.setScoringRuleId(this.scoringRule.getId()); testComputationRule.setBpElementId(blueprintElement.getStandardKey()); testComputationRule.setComputationOrder(this.scoringRule.getOrder().toString() + "." + StringUtils.leftPad(String.valueOf(this.orderIncr++), 5, '0')); final ComputationRule computationRule = this.scoringRule.getComputationRule(); if (!CollectionUtils.isEmpty(computationRule.getParameters())) { final Map<String, ComputationRuleParameter> computationRuleParameterMap = Maps .uniqueIndex(computationRule.getParameters(), COMPUTATION_RULE_PARAM_NAME_TRANSFORMER); testComputationRule.setComputationRuleParameterList( Lists.transform(this.scoringRule.getParameters(), SCORING_RULE_PARAMETER_TRANSFORMER .getInstance(this.scoringRule.getLabel(), computationRuleParameterMap))); } //EF: changed places for name and label. Confirm it! testComputationRule.setIdentifier(buildIdentifier(computationRule.getName(), this.scoringRule.getLabel() + testComputationRule.getComputationOrder(), computationRule.getVersion())); //testComputationRule.setIdentifier(buildIdentifier(this.scoringRule.getLabel() + testComputationRule.getComputationOrder(), computationRule.getName(), computationRule.getVersion())); //EF: substituted identifier with UUID to match legacy system testComputationRule.getIdentifier().setUniqueId(UUID.randomUUID().toString()); return testComputationRule; } }; protected static final Predicate<ScoringRule> LEAF_NODE_TYPE_FILTER = new Predicate<ScoringRule>() { @Override public boolean apply(final ScoringRule scoringRule) { return scoringRule != null && BlueprintDenotationType.LEAF_NODES == scoringRule.getBlueprintDenotationType(); } }; protected static final Predicate<BlueprintElement> PARENT_KEY_FILTER = new Predicate<BlueprintElement>() { @Override public boolean apply(final BlueprintElement bpElement) { return StringUtils.isBlank(bpElement.getParentKey()); } }; protected static final Function<BlueprintElement, String> BP_PARENT_KEY_TRANSFORMER = new Function<BlueprintElement, String>() { @Override public String apply(final BlueprintElement bpElement) { return bpElement.getParentKey(); } }; protected static final class NON_LEAF_NODE_FILTER implements Predicate<BlueprintElement> { private final Set<String> parentKeys; public static NON_LEAF_NODE_FILTER getInstance(final Set<String> parentKeys) { return new NON_LEAF_NODE_FILTER(parentKeys); } private NON_LEAF_NODE_FILTER(final Set<String> parentKeys) { this.parentKeys = parentKeys; } @Override public boolean apply(final BlueprintElement bpElement) { return this.parentKeys.contains(bpElement.getStandardKey()); } } protected static final Predicate<ScoringRule> LEVEL_TYPE_FILTER = new Predicate<ScoringRule>() { @Override public boolean apply(final ScoringRule scoringRule) { return scoringRule != null && BlueprintDenotationType.LEVEL == scoringRule.getBlueprintDenotationType(); } }; protected static final class LEVEL_FILTER implements Predicate<BlueprintElement> { private final String level; public static LEVEL_FILTER getInstance(final String level) { return new LEVEL_FILTER(level); } private LEVEL_FILTER(final String level) { this.level = level; } @Override public boolean apply(final BlueprintElement bpElement) { return StringUtils.equals(this.level, bpElement.getLevel()); } } protected static final Ordering<TestComputationRule> COMPUTATION_RULE_ORDER = Ordering.natural() .onResultOf(new Function<TestComputationRule, BigDecimal>() { @Override public BigDecimal apply(final TestComputationRule testComputationRule) { return new BigDecimal(testComputationRule.getComputationOrder()); } }); protected static final class COMP_RULE_REORDER_TRANSFORMER implements Function<TestComputationRule, TestComputationRule> { private int orderIncr; public static COMP_RULE_REORDER_TRANSFORMER getInstance(final int orderIncr) { return new COMP_RULE_REORDER_TRANSFORMER(orderIncr); } private COMP_RULE_REORDER_TRANSFORMER(final int orderIncr) { this.orderIncr = orderIncr; } @Override public TestComputationRule apply(final TestComputationRule testComputationRule) { testComputationRule.setComputationOrder(String.valueOf(this.orderIncr++)); return testComputationRule; } }; protected static final Function<TestComputationRule, String> COMPRULE_MULTIMAP_TRANSFORMER = new Function<TestComputationRule, String>() { @Override public String apply(final TestComputationRule testComputationRule) { return testComputationRule.getScoringRuleId(); } }; // ======================================================================================================================================================================== // reporting measure construction protected static final class REPORTING_MEASURE_TRANSFORMER implements Function<ReportingMeasure, List<TestReportingMeasure>> { private final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap; private final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap; public static REPORTING_MEASURE_TRANSFORMER getInstance( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap, final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap) { return new REPORTING_MEASURE_TRANSFORMER(blueprintReferenceMap, scoringRuleReferenceMap); } private REPORTING_MEASURE_TRANSFORMER( final Map<BlueprintReferenceType, Map<String, String>> blueprintReferenceMap, final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap) { this.blueprintReferenceMap = blueprintReferenceMap; this.scoringRuleReferenceMap = scoringRuleReferenceMap; } @Override public List<TestReportingMeasure> apply(final ReportingMeasure reportingMeasure) { if (this.blueprintReferenceMap.get(reportingMeasure.getBlueprintReferenceType()) != null) { final Map<String, Collection<TestComputationRule>> rulesNeedingMeasureMap = Maps.filterEntries( this.scoringRuleReferenceMap, RULES_MATCHING_MEASURE_FILTER.getInstance(reportingMeasure.getScoringRuleIdList())); final List<TestReportingMeasure> testReportingMeasureList = Lists.newArrayList(); if (reportingMeasure.getBlueprintReferenceType() == BlueprintReferenceType.STANDARD && (reportingMeasure.getBlueprintDenotationType() == BlueprintDenotationType.LEVEL || reportingMeasure .getBlueprintDenotationType() == BlueprintDenotationType.LEAF_NODES)) { for (final Collection<TestComputationRule> levelCompRuleList : rulesNeedingMeasureMap .values()) { for (final TestComputationRule testComputationRule : levelCompRuleList) { testReportingMeasureList .add(new TestReportingMeasure(testComputationRule.getBpElementId(), Lists.newArrayList( new ScoreType(testComputationRule.getIdentifier().getName(), testComputationRule.getIdentifier().getLabel())))); } } } else if (this.blueprintReferenceMap.get(reportingMeasure.getBlueprintReferenceType()) .get(reportingMeasure.getBlueprintReferenceId()) != null) { final String currentBlueprintReferenceName = this.blueprintReferenceMap .get(reportingMeasure.getBlueprintReferenceType()) .get(reportingMeasure.getBlueprintReferenceId()); testReportingMeasureList.add(new TestReportingMeasure(currentBlueprintReferenceName, Lists.newArrayList( Iterables.concat(nullsafeListTransform(reportingMeasure.getScoringRuleIdList(), REPORTINGMEASURE_SCORINGREFERENCE_TRANSFORMER .getInstance(rulesNeedingMeasureMap)))))); } return testReportingMeasureList; } return null; } }; private static final class RULES_MATCHING_MEASURE_FILTER implements Predicate<Entry<String, Collection<TestComputationRule>>> { private final List<String> scoringRuleIdList; public static RULES_MATCHING_MEASURE_FILTER getInstance(final List<String> scoringRuleIdList) { return new RULES_MATCHING_MEASURE_FILTER(scoringRuleIdList); } private RULES_MATCHING_MEASURE_FILTER(final List<String> scoringRuleIdList) { this.scoringRuleIdList = scoringRuleIdList; } @Override public boolean apply(final Entry<String, Collection<TestComputationRule>> testComputationRuleEntry) { return this.scoringRuleIdList != null && testComputationRuleEntry != null && this.scoringRuleIdList.contains(testComputationRuleEntry.getKey()); } }; private static final class REPORTINGMEASURE_SCORINGREFERENCE_TRANSFORMER implements Function<String, List<ScoreType>> { private final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap; public static REPORTINGMEASURE_SCORINGREFERENCE_TRANSFORMER getInstance( final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap) { return new REPORTINGMEASURE_SCORINGREFERENCE_TRANSFORMER(scoringRuleReferenceMap); } private REPORTINGMEASURE_SCORINGREFERENCE_TRANSFORMER( final Map<String, Collection<TestComputationRule>> scoringRuleReferenceMap) { this.scoringRuleReferenceMap = scoringRuleReferenceMap; } @Override public List<ScoreType> apply(final String scoringRuleId) { if (this.scoringRuleReferenceMap.containsKey(scoringRuleId)) { final List<ScoreType> scoreTypeList = Lists.newArrayList(); for (final TestComputationRule compRule : this.scoringRuleReferenceMap.get(scoringRuleId)) { scoreTypeList.add( new ScoreType(compRule.getIdentifier().getName(), compRule.getIdentifier().getLabel())); } return scoreTypeList; } return null; } }; // This method converts objectId from MongoDB collections records into // bigint value suitable for storing into Mysql db bigint(20) columns // Mongodb ObjectId is a 12-byte BSON type, constructed using: // -- a 4-byte value representing the seconds since the Unix epoch, // -- a 3-byte machine identifier, // -- a 2-byte process id, and // -- a 3-byte counter, starting with a random value. // (see http://docs.mongodb.org/manual/reference/object-id/) // Max value for Mysql bigint column is 18446744073709551615 or // 0x1999999999999999, i.e. 8 bytes with the highest byte value below 0x19 // (see https://dev.mysql.com/doc/refman/5.6/en/integer-types.html) // To build unique mysql id suitable for bigint(20) column // we build 8 bytes hex string using: // -- a short int (two bytes) serverUniqueNumber which is configured thru Progman // Min value 1, max value 0x0FFF // -- The last three bytes from 4-bytes value representing the seconds // since the Unix epoch from Mongodb ObjectId // -- The 3-byte counter from Mongodb ObjectId // Example: // Mongodb objectId as hex string, displayed split in parts per description above: // 55e9cc46 62e9d4 65e5 2c1256 // Assume that serverUniqueNumber was configured in program as 4010, i.e. 0x0FAA // Mysql compatible id will be build as follow: // 0x0FAA E9CC46 2C1256 or converted into decimal: 1128971720169624150 protected static final int MONGOFBOBJECTLENGTH = 12; // remember that counts start from 0, not 1 protected static final int MONGODBOBJECTSECONDSBYTESSTART = 0; protected static final int MONGODBOBJECTRANDOMBYTESSTART = 9; protected static final int MAXIMUMMINORVERSIONS = 1000; protected static final String DECIMALSEPARATOR = "."; protected static final String buildTdsCompatibleId(String id, int serverUniqueNumber, String version) { // Remember that id parameter is a hex string representation of 12 bytes hex value if (id == null || id.length() != 2 * MONGOFBOBJECTLENGTH) return ""; String tmp = Integer.toHexString(serverUniqueNumber). // second, third and fourth bytes from the 4-bytes representing seconds from epoch concat(id.substring(2 * (MONGODBOBJECTSECONDSBYTESSTART + 1), 2 * (MONGODBOBJECTSECONDSBYTESSTART + 4))) . // the last three bytes of mongodb objectid, they represent 3-bytes counter concat(id.substring(2 * MONGODBOBJECTRANDOMBYTESSTART)); String compatibleId = ((new BigInteger(tmp, 16)) .add(new BigInteger(versionTransformer(version).toString()))).toString(); return compatibleId; } // parse version and return version amendment to compatibleid protected static final Integer versionTransformer(final String version) { try { int decimalSeparatorPosition = StringUtils.indexOf(version, DECIMALSEPARATOR); String fraction = StringUtils.substring(version, decimalSeparatorPosition + 1); String integerPart = version.substring(0, decimalSeparatorPosition); Integer fracPart = Integer.valueOf(fraction); Integer intPart = Integer.valueOf(integerPart); return intPart * MAXIMUMMINORVERSIONS + fracPart; } catch (Exception e) { return 0; } } }