org.opentestsystem.authoring.testauth.validation.ItemSelectionAlgorithmParameterValidator.java Source code

Java tutorial

Introduction

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

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmParameter;
import org.opentestsystem.authoring.testauth.domain.ItemSelectionParameterElement;
import org.opentestsystem.authoring.testauth.domain.ItemSelectionType;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;

@Component
public class ItemSelectionAlgorithmParameterValidator extends AbstractDomainValidator {
    private static final String ITEM_SELECTION_ROOT = "itemSelectionAlgorithm.parameters.";
    private static final String DEFAULT_FIELD = "defaultValue";
    private static final String MINIMUM_FIELD = "minimumValue";
    private static final String MAXIMUM_FIELD = "maximumValue";
    private static final String ITEM_TYPE_FIELD = "itemSelectionType";
    private static final String ITEM_LIST_FIELD = "itemSelectionList";
    private static final String ITEM_LIST_NAME_FIELD = ITEM_LIST_FIELD + ".name";
    private static final String ITEM_LIST_POSITION_FIELD = ITEM_LIST_FIELD + ".position";
    private static final Integer MAXIMUM_DEFAULT_STRING_LENGTH = 60;

    private static final String EMPTY_PARAMETER_ELEMENT_NAME = "";
    private static final Function<ItemSelectionParameterElement, String> ITEM_SELECTION_PARAMETER_ELEMENT_TO_NAME_TRANSFORMER = new Function<ItemSelectionParameterElement, String>() {
        @Override
        public String apply(final ItemSelectionParameterElement itemSelectionParameterElement) {
            return StringUtils.isBlank(itemSelectionParameterElement.getName()) ? EMPTY_PARAMETER_ELEMENT_NAME
                    : itemSelectionParameterElement.getName();
        }
    };

    private static final Function<ItemSelectionParameterElement, String> ITEM_SELECTION_PARAMETER_ELEMENT_TO_POSITION_TRANSFORMER = new Function<ItemSelectionParameterElement, String>() {
        @Override
        public String apply(final ItemSelectionParameterElement itemSelectionParameterElement) {
            return String.valueOf(itemSelectionParameterElement.getPosition());
        }
    };

    private static final Predicate<Entry<String, Collection<ItemSelectionParameterElement>>> ITEM_SELECTION_PARAMETER_ELEMENT_DUPLICATE_FILTER = new Predicate<Entry<String, Collection<ItemSelectionParameterElement>>>() {
        @Override
        public boolean apply(final Entry<String, Collection<ItemSelectionParameterElement>> entry) {
            return !EMPTY_PARAMETER_ELEMENT_NAME.equals(entry.getKey()) && entry.getValue().size() > 1;
        }
    };

    private static final Predicate<ItemSelectionParameterElement> ITEM_SELECTION_PARAMETER_ELEMENT_BLANK = new Predicate<ItemSelectionParameterElement>() {
        @Override
        public boolean apply(final ItemSelectionParameterElement ispe) {
            return ispe != null && StringUtils.isBlank(ispe.getName());
        }
    };

    private static final class PARAMETER_POSITION_OUT_OF_RANGE_FILTER
            implements Predicate<ItemSelectionParameterElement> {
        private final int parameterListSize;

        private PARAMETER_POSITION_OUT_OF_RANGE_FILTER(final int parameterListSize) {
            this.parameterListSize = parameterListSize;
        }

        public static PARAMETER_POSITION_OUT_OF_RANGE_FILTER getInstance(final int parameterListSize) {
            return new PARAMETER_POSITION_OUT_OF_RANGE_FILTER(parameterListSize);
        }

        @Override
        public boolean apply(final ItemSelectionParameterElement input) {
            return input == null || input.getPosition() < 1 || input.getPosition() > this.parameterListSize;
        }
    };

    @Override
    public boolean supports(final Class<?> clazz) {
        return ItemSelectionAlgorithmParameter.class.equals(clazz);
    }

    @Override
    public void validate(final Object obj, final Errors e) {
        final ItemSelectionAlgorithmParameter parameter = (ItemSelectionAlgorithmParameter) obj;

        if (parameter.getItemSelectionType() != null) {
            final Object[] errorArgs = new String[] { parameter.getItemSelectionType().name(),
                    parameter.getParameterName() };

            switch (parameter.getItemSelectionType()) {
            case FLOAT:
            case INTEGER:
                // defaultValue validated via jsr-303
                rejectIfTooLong(e, DEFAULT_FIELD, MAX_PARSEABLE_LENGTH, errorArgs);

                final boolean isFloat = parameter.getItemSelectionType() == ItemSelectionType.FLOAT;
                rejectIfNotFloatOrIntegerParseable(e, DEFAULT_FIELD, isFloat, errorArgs);
                rejectIfNotFloatOrIntegerParseable(e, MINIMUM_FIELD, isFloat, errorArgs);
                rejectIfNotFloatOrIntegerParseable(e, MAXIMUM_FIELD, isFloat, errorArgs);
                if (!e.hasErrors()) {
                    boolean compareDefaultToMinMax = true;
                    if (StringUtils.isNotBlank(parameter.getMinimumValue())
                            && StringUtils.isNotBlank(parameter.getMaximumValue())) {
                        final BigDecimal minimumBigDecimal = new BigDecimal(parameter.getMinimumValue());
                        final BigDecimal maximumBigDecimal = new BigDecimal(parameter.getMaximumValue());
                        if (minimumBigDecimal.compareTo(maximumBigDecimal) > -1) {
                            rejectValue(e, MINIMUM_FIELD, getErrorMessageRoot() + MINIMUM_FIELD + MSG_LESS_THAN_MAX,
                                    errorArgs);
                            compareDefaultToMinMax = false;
                        }
                    }
                    if (StringUtils.isNotBlank(parameter.getDefaultValue())) {
                        final BigDecimal defaultBigDecimal = new BigDecimal(parameter.getDefaultValue());
                        if (StringUtils.isNotBlank(parameter.getMinimumValue())) {
                            final BigDecimal minimumBigDecimal = new BigDecimal(parameter.getMinimumValue());
                            if (compareDefaultToMinMax && defaultBigDecimal.compareTo(minimumBigDecimal) < 0) {
                                rejectValue(e, DEFAULT_FIELD,
                                        getErrorMessageRoot() + DEFAULT_FIELD + MSG_WITHIN_MIN_MAX, errorArgs);
                            }
                        }
                        if (StringUtils.isNotBlank(parameter.getMaximumValue())) {
                            final BigDecimal maximumBigDecimal = new BigDecimal(parameter.getMaximumValue());
                            if (compareDefaultToMinMax && defaultBigDecimal.compareTo(maximumBigDecimal) > 0) {
                                rejectValue(e, DEFAULT_FIELD,
                                        getErrorMessageRoot() + DEFAULT_FIELD + MSG_WITHIN_MIN_MAX, errorArgs);
                            }
                        }
                    }
                }
                rejectIfCollectionNotEmpty(e, ITEM_LIST_FIELD, errorArgs);
                break;
            case BOOLEAN:
                rejectIfNotEmpty(e, MINIMUM_FIELD, errorArgs);
                rejectIfNotEmpty(e, MAXIMUM_FIELD, errorArgs);
                rejectIfNotBooleanParseable(e, DEFAULT_FIELD, errorArgs);
                rejectIfCollectionNotEmpty(e, ITEM_LIST_FIELD, errorArgs);
                break;
            case LIST:
                rejectIfNotEmpty(e, MINIMUM_FIELD, errorArgs);
                rejectIfNotEmpty(e, MAXIMUM_FIELD, errorArgs);
                rejectIfCollectionEmpty(e, ITEM_LIST_FIELD, errorArgs);

                if (parameter.getItemSelectionList() != null) {
                    if (Iterables.any(parameter.getItemSelectionList(), ITEM_SELECTION_PARAMETER_ELEMENT_BLANK)) {
                        rejectValue(e, ITEM_LIST_FIELD, getErrorMessageRoot() + ITEM_LIST_NAME_FIELD + MSG_REQUIRED,
                                errorArgs);
                    }
                    // check if defaultValue is one of values in selection list
                    rejectIfNotInCollection(e, DEFAULT_FIELD, Lists.transform(parameter.getItemSelectionList(),
                            ITEM_SELECTION_PARAMETER_ELEMENT_TO_NAME_TRANSFORMER), errorArgs);

                    // check if list has duplicate names and duplicate or out-of-range positions
                    final Map<String, Collection<ItemSelectionParameterElement>> duplicates = Maps.filterEntries(
                            Multimaps.index(parameter.getItemSelectionList(),
                                    ITEM_SELECTION_PARAMETER_ELEMENT_TO_NAME_TRANSFORMER).asMap(),
                            ITEM_SELECTION_PARAMETER_ELEMENT_DUPLICATE_FILTER);
                    if (!duplicates.isEmpty()) {
                        rejectValue(e, ITEM_LIST_FIELD,
                                getErrorMessageRoot() + ITEM_LIST_NAME_FIELD + MSG_DUPLICATES,
                                duplicates.keySet().toString());
                    }
                    final Map<String, Collection<ItemSelectionParameterElement>> duplicatePositions = Maps
                            .filterEntries(
                                    Multimaps
                                            .index(parameter.getItemSelectionList(),
                                                    ITEM_SELECTION_PARAMETER_ELEMENT_TO_POSITION_TRANSFORMER)
                                            .asMap(),
                                    ITEM_SELECTION_PARAMETER_ELEMENT_DUPLICATE_FILTER);
                    if (!duplicatePositions.isEmpty()) {
                        rejectValue(e, ITEM_LIST_FIELD,
                                getErrorMessageRoot() + ITEM_LIST_POSITION_FIELD + MSG_DUPLICATES,
                                duplicatePositions.keySet().toString());
                    }
                    final List<String> outOfRange = Lists.newArrayList(Iterables.transform(
                            Iterables.filter(parameter.getItemSelectionList(),
                                    PARAMETER_POSITION_OUT_OF_RANGE_FILTER
                                            .getInstance(parameter.getItemSelectionList().size())),
                            ITEM_SELECTION_PARAMETER_ELEMENT_TO_POSITION_TRANSFORMER));
                    if (outOfRange.size() > 0) {
                        rejectValue(e, ITEM_LIST_FIELD,
                                getErrorMessageRoot() + ITEM_LIST_POSITION_FIELD + MSG_INVALID,
                                outOfRange.toString());
                    }
                }
                break;
            case STRING:
                rejectIfNotEmpty(e, MINIMUM_FIELD, errorArgs);
                rejectIfNotEmpty(e, MAXIMUM_FIELD, errorArgs);
                rejectIfCollectionNotEmpty(e, ITEM_LIST_FIELD, errorArgs);
                rejectIfTooLong(e, DEFAULT_FIELD, MAXIMUM_DEFAULT_STRING_LENGTH, errorArgs);
                break;
            default:
                rejectValue(e, ITEM_TYPE_FIELD, getErrorMessageRoot() + ITEM_TYPE_FIELD + MSG_INVALID, errorArgs);
                break;
            }
        }
    }

    @Override
    protected String getErrorMessageRoot() {
        return ITEM_SELECTION_ROOT;
    }

}