org.opentestsystem.authoring.testauth.service.impl.BlueprintHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.authoring.testauth.service.impl.BlueprintHelper.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.service.impl;

import static org.opentestsystem.authoring.testauth.config.TestAuthUtil.safeParseInt;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.opentestsystem.authoring.testauth.domain.BlueprintElement;
import org.opentestsystem.authoring.testauth.domain.BlueprintElementValue;
import org.opentestsystem.authoring.testauth.domain.CoreStandardPublicationPayloadElement;
import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithm;
import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmHelper;
import org.opentestsystem.authoring.testauth.domain.Segment;

import com.google.common.base.Equivalence;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables;
import com.google.common.collect.MapDifference.ValueDifference;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

public final class BlueprintHelper {

    private BlueprintHelper() {
        // do not instantiate
    }

    // define equivalence of Blueprint Elements to Core Standards
    protected static final Equivalence<BlueprintElement> BLUEPRINT_ELEMENT_EQUIVALENCE = new Equivalence<BlueprintElement>() {
        @Override
        protected boolean doEquivalent(final BlueprintElement left, final BlueprintElement right) {
            return ComparisonChain.start().compare(left.getStandardKey(), right.getStandardKey())
                    .compare(left.getLevel(), right.getLevel()).compare(left.getGrade(), right.getGrade())
                    .compare(left.getTextDescription(), right.getTextDescription()).result() == 0;
        }

        @Override
        protected int doHash(final BlueprintElement blueprintElement) {
            return blueprintElement.hashCode();
        }
    };

    protected static final Function<ValueDifference<BlueprintElement>, BlueprintElement> BLUEPRINT_ELEMENT_VALUE_DIFF_TRANS = new Function<ValueDifference<BlueprintElement>, BlueprintElement>() {
        @Override
        public BlueprintElement apply(final ValueDifference<BlueprintElement> valueDifference) {
            final BlueprintElement modifiedBlueprintElement = valueDifference.leftValue();
            modifiedBlueprintElement.setStandardKey(valueDifference.rightValue().getStandardKey()); // should already be equal
            modifiedBlueprintElement.setSortData(valueDifference.rightValue().getSortData()); // should already be equal
            modifiedBlueprintElement.setLevel(valueDifference.rightValue().getLevel());
            modifiedBlueprintElement.setGrade(valueDifference.rightValue().getGrade());
            modifiedBlueprintElement.setTextDescription(valueDifference.rightValue().getTextDescription());
            return modifiedBlueprintElement;
        }
    };

    protected static final Function<BlueprintElement, String> BLUEPRINT_ELEMENT_UNIQUE_KEY_FUNCTION = new Function<BlueprintElement, String>() {
        @Override
        public String apply(final BlueprintElement blueprintElement) {
            return blueprintElement.getStandardKey() + ">" + blueprintElement.getGrade();
        }
    };

    protected static final Function<BlueprintElement, String> BLUEPRINT_ELEMENT_PARENT_KEY_FUNCTION = new Function<BlueprintElement, String>() {
        @Override
        public String apply(final BlueprintElement blueprintElement) {
            return StringUtils.isEmpty(blueprintElement.getParentKey()) ? null
                    : blueprintElement.getParentKey() + ">" + blueprintElement.getGrade();
        }
    };

    protected static final class BPE_BPEV_TRANSFORMER implements Function<BlueprintElement, BlueprintElementValue> {
        private final String valueKey;

        public static BPE_BPEV_TRANSFORMER getInstance(final String valueKey) {
            return new BPE_BPEV_TRANSFORMER(valueKey);
        }

        public BPE_BPEV_TRANSFORMER(final String aValueKey) {
            this.valueKey = aValueKey;
        }

        @Override
        public BlueprintElementValue apply(final BlueprintElement blueprintElement) {
            return blueprintElement.getBlueprintElementValueMap().get(this.valueKey);
        }
    };

    protected static final Function<BlueprintElement, String> BLUEPRINT_ELEMENT_GRADE_FUNCTION = new Function<BlueprintElement, String>() {
        @Override
        public String apply(final BlueprintElement blueprintElement) {
            return blueprintElement.getGrade();
        }
    };

    protected static final class CORE_STANDARD_BLUEPRINT_ELEMENT_TRANSFORMER
            implements Function<CoreStandardPublicationPayloadElement, BlueprintElement> {
        private final String client;

        public static CORE_STANDARD_BLUEPRINT_ELEMENT_TRANSFORMER getInstance(final String client) {
            return new CORE_STANDARD_BLUEPRINT_ELEMENT_TRANSFORMER(client);
        }

        private CORE_STANDARD_BLUEPRINT_ELEMENT_TRANSFORMER(final String client) {
            this.client = client;
        }

        @Override
        public BlueprintElement apply(final CoreStandardPublicationPayloadElement csElement) {
            final BlueprintElement be = new BlueprintElement();
            // AK: We have blueprint as "SBAC-ELA-v1:2-W" and need to transform to "SBAC-2-W"
            // check for presence of publication separated by ':'
            int pubEndPos = StringUtils.indexOf(csElement.getKey(), ":");
            if (pubEndPos > 0)
                be.setStandardKey(
                        client.concat("-").concat(StringUtils.substring(csElement.getKey(), pubEndPos + 1)));
            else
                be.setStandardKey(client.concat("-").concat(csElement.getKey()));
            //be.setSortData(StringUtils.replace(csElement.getKey(), "|", " "));
            be.setSortData(StringUtils.replace(be.getStandardKey(), "|", " "));

            // seems that CoreStandards sets parent same as the key,
            // rather than to one level of standard up
            // temp solution is to check for such case and fix it here TODO
            String parent = csElement.getFkParent();
            if (parent != null && csElement.getKey().equalsIgnoreCase(parent)) {

                int lastPipePos = StringUtils.lastIndexOf(parent, "|");
                if (lastPipePos > 0)
                    parent = StringUtils.substring(parent, 0, lastPipePos);
            }
            if (parent != null) {
                pubEndPos = StringUtils.indexOf(parent, ":");
                if (pubEndPos > 0)
                    parent = client.concat("-").concat(StringUtils.substring(parent, pubEndPos + 1));
            }
            be.setParentKey(parent);

            be.setLevel(csElement.getTreeLevel());
            org.springframework.util.StringUtils.trimAllWhitespace(csElement.getFkGradeLevel());
            be.setGrade(csElement.getFkGradeLevel());
            be.setTextDescription(csElement.getDescription());
            be.setActive(true);
            return be;
        }
    };

    protected static final Predicate<BlueprintElement> CORE_STANDARDS_INVALID_BLUEPRINT_FILTER = new Predicate<BlueprintElement>() {
        @Override
        public boolean apply(final BlueprintElement blueprintElement) {
            return !StringUtils.isEmpty(blueprintElement.getGrade());
        }
    };

    protected static final class BLUEPRINT_ELEMENT_CLEAR_SEGMENT_VALUE_TRANSFORMER
            implements Function<BlueprintElement, BlueprintElement> {
        private final String segmentId;

        public static BLUEPRINT_ELEMENT_CLEAR_SEGMENT_VALUE_TRANSFORMER getInstance(final String segmentId) {
            return new BLUEPRINT_ELEMENT_CLEAR_SEGMENT_VALUE_TRANSFORMER(segmentId);
        }

        private BLUEPRINT_ELEMENT_CLEAR_SEGMENT_VALUE_TRANSFORMER(final String segmentId) {
            this.segmentId = segmentId;
        }

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            if (blueprintElement != null && blueprintElement.getBlueprintElementValueMap() != null
                    && blueprintElement.getBlueprintElementValueMap().get(this.segmentId) != null) {
                blueprintElement.getBlueprintElementValueMap().get(this.segmentId).setOperationalItemMinValue(0);
                blueprintElement.getBlueprintElementValueMap().get(this.segmentId).setOperationalItemMaxValue(0);
                blueprintElement.getBlueprintElementValueMap().get(this.segmentId).setFieldTestItemMinValue(0);
                blueprintElement.getBlueprintElementValueMap().get(this.segmentId).setFieldTestItemMaxValue(0);
            }
            return blueprintElement;
        }
    };

    protected static final class BLUEPRINT_ELEMENT_INJECT_DEFAULT_VALUES_TRANSFORMER
            implements Function<BlueprintElement, BlueprintElement> {
        private final String assessmentId;
        private final String[] grades;
        private final Map<String, Segment> segmentIdKeyMap;

        public static BLUEPRINT_ELEMENT_INJECT_DEFAULT_VALUES_TRANSFORMER getInstance(final String assessmentId,
                final String[] grades, final Map<String, Segment> segmentIdKeyMap) {
            return new BLUEPRINT_ELEMENT_INJECT_DEFAULT_VALUES_TRANSFORMER(assessmentId, grades, segmentIdKeyMap);
        }

        private BLUEPRINT_ELEMENT_INJECT_DEFAULT_VALUES_TRANSFORMER(final String assessmentId,
                final String[] grades, final Map<String, Segment> segmentIdKeyMap) {
            this.assessmentId = assessmentId;
            this.grades = grades;
            this.segmentIdKeyMap = segmentIdKeyMap;
        }

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            blueprintElement.setAssessmentId(this.assessmentId);
            blueprintElement.setActive(Iterables.any(Arrays.asList(blueprintElement.getGrade()),
                    BLUEPRINT_ELEMENT_GRADE_FILTER.getInstance(this.grades)));
            if (blueprintElement.getBlueprintElementValueMap() == null) {
                blueprintElement.setBlueprintElementValueMap(new HashMap<String, BlueprintElementValue>());
            }
            // add any missing segment IDs
            for (final String segmentId : this.segmentIdKeyMap.keySet()) {
                if (blueprintElement.getBlueprintElementValueMap().get(segmentId) == null) {
                    blueprintElement.getBlueprintElementValueMap().put(segmentId,
                            new BlueprintElementValue(0, 0, 0, 0));
                    populateDefaultItemSelectionParameters(blueprintElement, segmentId,
                            this.segmentIdKeyMap.get(segmentId).getItemSelectionAlgorithm());
                }
            }

            final Set<String> keysToRemove = Sets.newHashSet();
            // remove anything not in the current set of segment IDs
            for (final String blueprintElementMapKey : blueprintElement.getBlueprintElementValueMap().keySet()) {
                if (!this.segmentIdKeyMap.keySet().contains(blueprintElementMapKey)) {
                    keysToRemove.add(blueprintElementMapKey);
                }
            }
            for (final String keyToRemove : keysToRemove) {
                blueprintElement.getBlueprintElementValueMap().remove(keyToRemove);
            }

            return blueprintElement;
        }
    };

    protected static final class BLUEPRINT_ELEMENT_UPDATE_ISA_PARAMETERS_TRANSFORMER
            implements Function<BlueprintElement, BlueprintElement> {
        private final String segmentId;
        private final ItemSelectionAlgorithm itemSelectionAlgorithm;

        public static BLUEPRINT_ELEMENT_UPDATE_ISA_PARAMETERS_TRANSFORMER getInstance(final String segmentId,
                final ItemSelectionAlgorithm itemSelectionAlgorithm) {
            return new BLUEPRINT_ELEMENT_UPDATE_ISA_PARAMETERS_TRANSFORMER(segmentId, itemSelectionAlgorithm);
        }

        private BLUEPRINT_ELEMENT_UPDATE_ISA_PARAMETERS_TRANSFORMER(final String aSegmentId,
                final ItemSelectionAlgorithm aItemSelectionAlgorithm) {
            this.segmentId = aSegmentId;
            this.itemSelectionAlgorithm = aItemSelectionAlgorithm;
        }

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            if (blueprintElement != null && blueprintElement.getBlueprintElementValueMap() != null
                    && blueprintElement.getBlueprintElementValueMap().get(this.segmentId) != null) {
                populateDefaultItemSelectionParameters(blueprintElement, this.segmentId,
                        this.itemSelectionAlgorithm);
            }
            return blueprintElement;
        }
    };

    private static class BLUEPRINT_ELEMENT_GRADE_FILTER implements Predicate<String> {
        private final String[] grades;

        private BLUEPRINT_ELEMENT_GRADE_FILTER(final String[] grades) {
            this.grades = grades;
        }

        public static BLUEPRINT_ELEMENT_GRADE_FILTER getInstance(final String[] grades) {
            return new BLUEPRINT_ELEMENT_GRADE_FILTER(grades);
        }

        @Override
        public boolean apply(final String blueprintElementGrade) {
            return this.grades != null && blueprintElementGrade != null
                    && Iterables.contains(Arrays.asList(this.grades), blueprintElementGrade);
        }
    };

    protected static class BLUEPRINT_ELEMENT_FILTER_BY_CHOSEN_GRADES implements Predicate<BlueprintElement> {
        private final String[] grades;

        private BLUEPRINT_ELEMENT_FILTER_BY_CHOSEN_GRADES(final String[] grades) {
            this.grades = grades;
        }

        public static BLUEPRINT_ELEMENT_FILTER_BY_CHOSEN_GRADES getInstance(final String[] grades) {
            return new BLUEPRINT_ELEMENT_FILTER_BY_CHOSEN_GRADES(grades);
        }

        @Override
        public boolean apply(final BlueprintElement blueprintElement) {
            return Iterables.any(Arrays.asList(blueprintElement.getGrade()),
                    BLUEPRINT_ELEMENT_GRADE_FILTER.getInstance(this.grades));
        }
    };

    protected static final Predicate<BlueprintElement> BLUEPRINT_ELEMENT_FILTER_REMOVE = new Predicate<BlueprintElement>() {
        @Override
        public boolean apply(final BlueprintElement blueprintElement) {
            return blueprintElement != null && blueprintElement.getId() != null
                    && blueprintElement.getLevel() == null;
        }
    };

    protected static final Function<BlueprintElement, BlueprintElement> BLUEPRINT_ELEMENT_REMOVE_TRANSFORMER = new Function<BlueprintElement, BlueprintElement>() {

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            blueprintElement.setLevel(null);
            return blueprintElement;
        }
    };

    protected static final class BLUEPRINT_ELEMENT_ADD_DEFAULT_SEGMENT_VALUE_TRANSFORMER
            implements Function<BlueprintElement, BlueprintElement> {
        private final String segmentId;
        private final String segmentIdToClone;
        private final ItemSelectionAlgorithm itemSelectionAlgorithm;

        public static BLUEPRINT_ELEMENT_ADD_DEFAULT_SEGMENT_VALUE_TRANSFORMER getInstance(final String segmentId,
                final String segmentIdToClone, final ItemSelectionAlgorithm itemSelectionAlgorithm) {
            return new BLUEPRINT_ELEMENT_ADD_DEFAULT_SEGMENT_VALUE_TRANSFORMER(segmentId, segmentIdToClone,
                    itemSelectionAlgorithm);
        }

        private BLUEPRINT_ELEMENT_ADD_DEFAULT_SEGMENT_VALUE_TRANSFORMER(final String segmentId,
                final String segmentIdToClone, final ItemSelectionAlgorithm itemSelectionAlgorithm) {
            this.segmentId = segmentId;
            this.segmentIdToClone = segmentIdToClone;
            this.itemSelectionAlgorithm = itemSelectionAlgorithm;
        }

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            if (blueprintElement != null && blueprintElement.getBlueprintElementValueMap() != null) {
                // set min/max values
                if (this.segmentIdToClone != null) {
                    final BlueprintElementValue blueprintElementValue = blueprintElement
                            .getBlueprintElementValueMap().get(this.segmentIdToClone);
                    if (blueprintElementValue != null) {
                        blueprintElement.getBlueprintElementValueMap().get(this.segmentId)
                                .copyMinMaxValuesToElement(blueprintElementValue);
                    }
                } else {
                    blueprintElement.getBlueprintElementValueMap().put(this.segmentId,
                            new BlueprintElementValue(0, 0, 0, 0));
                    populateDefaultItemSelectionParameters(blueprintElement, this.segmentId,
                            this.itemSelectionAlgorithm);
                }
            }
            return blueprintElement;
        }
    };

    protected static final class BLUEPRINT_ELEMENT_REMOVE_SEGMENT_VALUE_TRANSFORMER
            implements Function<BlueprintElement, BlueprintElement> {
        private final String segmentId;

        public static BLUEPRINT_ELEMENT_REMOVE_SEGMENT_VALUE_TRANSFORMER getInstance(final String segmentId) {
            return new BLUEPRINT_ELEMENT_REMOVE_SEGMENT_VALUE_TRANSFORMER(segmentId);
        }

        private BLUEPRINT_ELEMENT_REMOVE_SEGMENT_VALUE_TRANSFORMER(final String segmentId) {
            this.segmentId = segmentId;
        }

        @Override
        public BlueprintElement apply(final BlueprintElement blueprintElement) {
            blueprintElement.getBlueprintElementValueMap().remove(this.segmentId);
            return blueprintElement;
        }
    };

    protected static final BlueprintElementValue getListSum(final Collection<BlueprintElementValue> bpValueList) {
        final BlueprintElementValue sumValue = new BlueprintElementValue(0, 0, 0, 0);
        for (final BlueprintElementValue nextValue : bpValueList) {
            sumValue.setOperationalItemMinValue(Math.min(
                    sumValue.getOperationalItemMinValue() + safeParseInt(nextValue.getOperationalItemMinValue()),
                    BlueprintElementValue.MAX_VALUE));
            sumValue.setOperationalItemMaxValue(Math.min(
                    sumValue.getOperationalItemMaxValue() + safeParseInt(nextValue.getOperationalItemMaxValue()),
                    BlueprintElementValue.MAX_VALUE));
            sumValue.setFieldTestItemMinValue(Math.min(
                    sumValue.getFieldTestItemMinValue() + safeParseInt(nextValue.getFieldTestItemMinValue()),
                    BlueprintElementValue.MAX_VALUE));
            sumValue.setFieldTestItemMaxValue(Math.min(
                    sumValue.getFieldTestItemMaxValue() + safeParseInt(nextValue.getFieldTestItemMaxValue()),
                    BlueprintElementValue.MAX_VALUE));
        }
        return sumValue;
    }

    protected static final BlueprintElementValue calculateDifference(final BlueprintElementValue left,
            final BlueprintElementValue right) {
        final BlueprintElementValue calculatedValue = new BlueprintElementValue();
        calculatedValue.setOperationalItemMinValue(
                Math.max(left.getOperationalItemMinValue() - right.getOperationalItemMinValue(), 0));
        calculatedValue.setOperationalItemMaxValue(
                Math.max(left.getOperationalItemMaxValue() - right.getOperationalItemMaxValue(), 0));
        calculatedValue.setFieldTestItemMinValue(
                Math.max(left.getFieldTestItemMinValue() - right.getFieldTestItemMinValue(), 0));
        calculatedValue.setFieldTestItemMaxValue(
                Math.max(left.getFieldTestItemMaxValue() - right.getFieldTestItemMaxValue(), 0));
        return calculatedValue;
    }

    private static final void populateDefaultItemSelectionParameters(final BlueprintElement blueprintElement,
            final String segmentId, final ItemSelectionAlgorithm itemSelectionAlgorithm) {
        if (itemSelectionAlgorithm != null && itemSelectionAlgorithm.getBlueprintParameters() != null) {
            blueprintElement.getBlueprintElementValueMap().get(segmentId)
                    .setItemSelectionParameters(Maps.transformValues(
                            Maps.uniqueIndex(itemSelectionAlgorithm.getBlueprintParameters(),
                                    ItemSelectionAlgorithmHelper.ISA_PARAMETER_NAME_TRANSFORMER),
                            ItemSelectionAlgorithmHelper.ISA_PARAMETER_DEFAULT_VALUE_TRANSFORMER));
        } else {
            blueprintElement.getBlueprintElementValueMap().get(segmentId).setItemSelectionParameters(null);
        }
    }

    protected static final Function<BlueprintElement, String> BP_ELEMENT_ID_TRANSFORMER = new Function<BlueprintElement, String>() {
        @Override
        public String apply(final BlueprintElement blueprintElement) {
            return blueprintElement.getId();
        }
    };

    protected static final Predicate<BlueprintElement> BP_ELEMENT_ID_INACTIVE_FILTER = new Predicate<BlueprintElement>() {
        @Override
        public boolean apply(final BlueprintElement blueprintElement) {
            return !blueprintElement.isActive();
        }
    };
}