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.validation; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithm; import org.opentestsystem.authoring.testauth.domain.ItemSelectionAlgorithmParameter; import org.opentestsystem.authoring.testauth.domain.ItemSelectionPurpose; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Maps; import com.google.common.collect.Multimaps; @Component public class ItemSelectionAlgorithmValidator extends AbstractDomainValidator { private static final String ERROR_MSG_ROOT = "itemSelectionAlgorithm."; private static final String PARAMETERS_FIELD = "parameters"; private static final String PARAMETERS_NAME_FIELD = PARAMETERS_FIELD + ".parameterName"; private static final String PARAMETERS_POSITION_FIELD = PARAMETERS_FIELD + ".position"; private static final String EMPTY_ALGORITHM_PARAMETER_NAME = ""; private static final Function<ItemSelectionAlgorithmParameter, String> ITEM_SELECTION_ALGORITHM_PARAMETER_TO_NAME_TRANSFORMER = new Function<ItemSelectionAlgorithmParameter, String>() { @Override public String apply(final ItemSelectionAlgorithmParameter itemSelectionAlgorithmParameter) { return StringUtils.isEmpty(itemSelectionAlgorithmParameter.getParameterName()) ? EMPTY_ALGORITHM_PARAMETER_NAME : itemSelectionAlgorithmParameter.getParameterName(); } }; private static final Function<ItemSelectionAlgorithmParameter, String> ITEM_SELECTION_ALGORITHM_PARAMETER_TO_POSITION_TRANSFORMER = new Function<ItemSelectionAlgorithmParameter, String>() { @Override public String apply(final ItemSelectionAlgorithmParameter itemSelectionAlgorithmParameter) { return String.valueOf(itemSelectionAlgorithmParameter.getPosition()); } }; private static final Predicate<Entry<String, Collection<ItemSelectionAlgorithmParameter>>> ITEM_SELECTION_ALGORITHM_PARAMETER_DUPLICATE_FILTER = new Predicate<Entry<String, Collection<ItemSelectionAlgorithmParameter>>>() { @Override public boolean apply(final Entry<String, Collection<ItemSelectionAlgorithmParameter>> entry) { if (!EMPTY_ALGORITHM_PARAMETER_NAME.equals(entry.getKey()) && entry.getValue().size() > 2) { return true; } else if (!EMPTY_ALGORITHM_PARAMETER_NAME.equals(entry.getKey()) && entry.getValue().size() == 2) { ItemSelectionAlgorithmParameter[] iSAPs = new ItemSelectionAlgorithmParameter[2]; entry.getValue().toArray(iSAPs); ItemSelectionPurpose first = iSAPs[0].getItemSelectionPurpose(); ItemSelectionPurpose second = iSAPs[1].getItemSelectionPurpose(); if (first != null && second != null && first.compareTo(second) == 0) return true; else return false; } return !EMPTY_ALGORITHM_PARAMETER_NAME.equals(entry.getKey()) && entry.getValue().size() > 1; } }; @Autowired private ItemSelectionAlgorithmParameterValidator itemSelectionAlgorithmParameterValidator; @Autowired @Qualifier("jsr303Validator") private Validator jsrValidator; @Override public boolean supports(final Class<?> clazz) { return ItemSelectionAlgorithm.class.equals(clazz); } @Override public void validate(final Object obj, final Errors errors) { // execute JSR-303 validations (annotations) this.jsrValidator.validate(obj, errors); final ItemSelectionAlgorithm algorithm = (ItemSelectionAlgorithm) obj; if (algorithm.getParameters() != null) { // custom validation for each itemSelectionAlgorithmParameter for (int i = 0; i < algorithm.getParameters().size(); i++) { final ItemSelectionAlgorithmParameter nextParameter = algorithm.getParameters().get(i); try { errors.pushNestedPath(PARAMETERS_FIELD + "[" + i + "]"); ValidationUtils.invokeValidator(this.itemSelectionAlgorithmParameterValidator, nextParameter, errors); if (nextParameter.getPosition() > algorithm.getParameters().size()) { rejectValue(errors, "position", getErrorMessageRoot() + PARAMETERS_POSITION_FIELD + MSG_INVALID, nextParameter.getPosition()); } } finally { errors.popNestedPath(); } } // check if parameters have duplicate names final Map<String, Collection<ItemSelectionAlgorithmParameter>> duplicates = Maps.filterEntries( Multimaps.index(algorithm.getParameters(), ITEM_SELECTION_ALGORITHM_PARAMETER_TO_NAME_TRANSFORMER).asMap(), ITEM_SELECTION_ALGORITHM_PARAMETER_DUPLICATE_FILTER); if (!duplicates.isEmpty()) { rejectValue(errors, PARAMETERS_FIELD, getErrorMessageRoot() + PARAMETERS_NAME_FIELD + MSG_DUPLICATES, duplicates.keySet().toString()); } // check if parameters have duplicate position final Map<String, Collection<ItemSelectionAlgorithmParameter>> duplicatePositions = Maps.filterEntries( Multimaps.index(algorithm.getParameters(), ITEM_SELECTION_ALGORITHM_PARAMETER_TO_POSITION_TRANSFORMER).asMap(), ITEM_SELECTION_ALGORITHM_PARAMETER_DUPLICATE_FILTER); if (!duplicatePositions.isEmpty()) { rejectValue(errors, PARAMETERS_FIELD, getErrorMessageRoot() + PARAMETERS_POSITION_FIELD + MSG_DUPLICATES, duplicatePositions.keySet().toString()); } } if (StringUtils.trimToNull(algorithm.getVersion()) != null) { String[] parts = algorithm.getVersion().split("\\."); if (parts.length != 2) { //not the right number version parts //should be 2 parts like "1.0" rejectValue(errors, "version", "version.format", new Object() { }); return; } if (NumberUtils.toInt(parts[0], -1) < 1 || parts[1].length() > 1 || (NumberUtils.toInt(parts[1], -1) < 0 || NumberUtils.toInt(parts[1], -1) > 9)) { //major is a negative number or some other character rejectValue(errors, "version", "version.majorminor.format", new Object() { }); } } if (!errors.hasErrors()) { algorithm.trimParameterValues(); } } @Override protected String getErrorMessageRoot() { return ERROR_MSG_ROOT; } }