001/* 
002 * Copyright 2018 Leibniz-Institut für Analytische Wissenschaften – ISAS – e.V..
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.isas.mztab2.validation;
017
018import de.isas.lipidomics.mztab2.validation.Validator;
019import de.isas.mztab2.model.MzTab;
020import de.isas.mztab2.model.ValidationMessage;
021import java.lang.annotation.Annotation;
022import java.util.LinkedList;
023import java.util.List;
024import java.util.Set;
025import javax.validation.ConstraintValidator;
026import javax.validation.ConstraintViolation;
027import javax.validation.Validation;
028import org.hibernate.validator.HibernateValidator;
029import org.hibernate.validator.HibernateValidatorConfiguration;
030import org.hibernate.validator.cfg.ConstraintMapping;
031
032/**
033 * <p>
034 * This validator used the HibernateValidator bean validation reference
035 * implementation. It understands the standard annotations that are placed on
036 * the domain objects generated from Swagger Codegen.</p>
037 *
038 * @author nilshoffmann
039 *
040 */
041public class MzTabBeanValidator implements Validator<MzTab> {
042
043    private final HibernateValidatorConfiguration configuration;
044    private final ConstraintMapping constraintMapping;
045
046    /**
047     * Default constructor. Fail fast validation is disabled.
048     */
049    public MzTabBeanValidator() {
050        this(false);
051    }
052
053    /**
054     * Constructor setting up the validator configuration and default constraint
055     * mapping.
056     *
057     * @param failFast if true, first validation error will terminate any
058     * further validation. If false, validation will continue and report all
059     * validation errors.
060     */
061    public MzTabBeanValidator(boolean failFast) {
062        this.configuration = Validation
063            .byProvider(HibernateValidator.class).
064            configure();
065
066        this.configuration.failFast(failFast);
067        this.constraintMapping = configuration.
068            createConstraintMapping();
069
070    }
071
072    /**
073     * Allows registration of custom constraint / validator pairs on the
074     * validation configuration. This requires that the objects to be validated
075     * are annotated with the corresponding constraint definition.
076     *
077     * @param <A> The annotation marking elements that should be validated.
078     * @param <T> The Object type on which the validation should be performed.
079     * @param <V> The validator to use for the validation.
080     * @param constraintDefinition The annotation marking elements that should
081     * be validated.
082     * @param validator The validator to use for the validation.
083     * @param includeExistingValidators If true, existing validators for the
084     * same type will be applied, too. If false, only the registered validator
085     * will be retained for that type.
086     */
087    public <A extends Annotation, T extends Object, V extends ConstraintValidator<A, T>> void addConstraintAndValidator(
088        Class<A> constraintDefinition, Class<V> validator,
089        boolean includeExistingValidators) {
090        constraintMapping.constraintDefinition(constraintDefinition).
091            includeExistingValidators(includeExistingValidators).
092            validatedBy(validator);
093    }
094
095    /**
096     * Allows registration of custom constraint / validator pairs on the
097     * validation configuration for a specific (unannotated) type.
098     *
099     * @param <A> The annotation marking elements that should be validated.
100     * @param <T> The Object type on which the validation should be performed.
101     * @param <V> The validator to use for the validation.
102     * @param typeToValidate The class/type that should be validated.
103     * @param constraintDefinition The annotation marking elements that should
104     * be validated.
105     * @param validator The validator to use for the validation.
106     * @param includeExistingValidators If true, existing validators for the
107     * same type will be applied, too. If false, only the registered validator
108     * will be retained for that type.
109     */
110    public <A extends Annotation, T extends Object, V extends ConstraintValidator<A, T>> void addConstraintAndValidator(
111        Class<T> typeToValidate,
112        Class<A> constraintDefinition, Class<V> validator,
113        boolean includeExistingValidators) {
114        constraintMapping.type(typeToValidate).
115            constraintDefinition(constraintDefinition).
116            includeExistingValidators(includeExistingValidators).
117            validatedBy(validator);
118    }
119
120    /**
121     * {@inheritDoc}
122     */
123    @Override
124    public List<ValidationMessage> validate(MzTab mzTab) {
125        List<ValidationMessage> list = new LinkedList<>();
126
127        javax.validation.Validator validator = configuration.addMapping(
128            constraintMapping).
129            buildValidatorFactory().
130            getValidator();
131
132        Set<ConstraintViolation<MzTab>> violations = validator.validate(mzTab);
133        for (ConstraintViolation<MzTab> violation : violations) {
134            list.add(new ValidationMessage().message(getPathLocatorString(
135                violation) + ": " + violation.getMessage()).
136                messageType(ValidationMessage.MessageTypeEnum.ERROR));
137        }
138        return list;
139    }
140
141    /**
142     * <p>
143     * getPathLocatorString.</p>
144     *
145     * @param cv a {@link javax.validation.ConstraintViolation} object.
146     * @return a {@link java.lang.String} object.
147     */
148    protected String getPathLocatorString(ConstraintViolation<?> cv) {
149        return cv.getPropertyPath().
150            toString();
151    }
152}