All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jarbframework.constraint.validation.ViolationMessageBuilder Maven / Gradle / Ivy

The newest version!
package org.jarbframework.constraint.validation;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableMap;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintTarget;
import javax.validation.ConstraintValidator;
import javax.validation.MessageInterpolator;
import javax.validation.Payload;
import javax.validation.metadata.ConstraintDescriptor;

/**
 * Constructs constraint violation messages with enhanced flexibility. Message variables
 * can be defined manually, rather than extracting them from a constraint annotation. This
 * allows us to generate violation messages for property violations with no corresponding
 * constraint annotation.
 * 
 * @author Jeroen van Schagen
 * @since 24-05-2011
 */
class ViolationMessageBuilder {
	
    private final MessageInterpolator messageInterpolator;

    /**
     * Construct a new {@link ViolationMessageBuilder}, using a custom message interpoulator.
     * @param messageInterpolator interpolator used to build violation messages
     */
    public ViolationMessageBuilder(MessageInterpolator messageInterpolator) {
        this.messageInterpolator = messageInterpolator;
    }

    /**
     * Builds a new message according to some template.
     * @param templateName name of the template
     * @return new message based on a template
     */
    public ViolationMessageTemplate template(String templateName) {
        return new ViolationMessageTemplate(templateName);
    }

    /**
     * Represents a message in a specific template. Variables can be defined as attributes,
     * and also the rejected property value can be configured. After all values have been
     * defined, the actual string message is retrieved by calling {@link #message()}.
     */
    public class ViolationMessageTemplate {

        private final Map attributes;

        private final String templateName;

        private Object value;

        /**
         * Construct a new {@link ViolationMessageTemplate}.
         * @param templateName name of the template
         */
        private ViolationMessageTemplate(String templateName) {
            this.templateName = templateName;
            attributes = new HashMap();
        }

        /**
         * Configure a new attribute value, which can be referenced inside the template.
         * @param attribute name of the attribute
         * @param value value that the attribute should have
         * @return same template instance, allowing method chaining
         */
        public ViolationMessageTemplate attribute(String attribute, Object value) {
            attributes.put(attribute, value);
            return this;
        }

        /**
         * Configure the value that was validated, which can be referenced inside the template.
         * @param value the rejected value
         * @return same template instance, allowing method chaining
         */
        public ViolationMessageTemplate value(Object value) {
            this.value = value;
            return this;
        }

        /**
         * Retrieve the actual violation message.
         * @return violation message
         */
        public String message() {
            AttributeConstraintDescriptor descriptor = new AttributeConstraintDescriptor(attributes);
            return messageInterpolator.interpolate(templateName, new SimpleInterpolatorContext(descriptor, value));
        }
    }

    /**
     * Simple interpolator context implementation that returns the configured values.
     */
    private static class SimpleInterpolatorContext implements MessageInterpolator.Context {

        private final ConstraintDescriptor constraintDescriptor;

        private final Object value;

        public SimpleInterpolatorContext(ConstraintDescriptor constraintDescriptor, Object value) {
            this.constraintDescriptor = constraintDescriptor;
            this.value = value;
        }

        @Override
        public ConstraintDescriptor getConstraintDescriptor() {
            return constraintDescriptor;
        }

        @Override
        public Object getValidatedValue() {
            return value;
        }
        
        @Override
        public  T unwrap(Class type) {
            if (type.isAssignableFrom(SimpleInterpolatorContext.class)) {
                return type.cast(this);
            }
            throw new UnsupportedOperationException();
        }

    }

    /**
     * Constraint descriptor implementation that only provides the configured attributes.
     * This adapter class is needed to enable usage of the message interpolator.
     */
    private static class AttributeConstraintDescriptor implements ConstraintDescriptor {

        private final Map attributes;

        public AttributeConstraintDescriptor(Map attributes) {
            this.attributes = unmodifiableMap(attributes);
        }

        @Override
        public Annotation getAnnotation() {
            return null;
        }

        @Override
        public Map getAttributes() {
            return attributes;
        }

        @Override
        public Set> getComposingConstraints() {
            return emptySet();
        }

        @Override
        public List>> getConstraintValidatorClasses() {
            return emptyList();
        }

        @Override
        public Set> getGroups() {
            return emptySet();
        }

        @Override
        public Set> getPayload() {
            return emptySet();
        }

        @Override
        public boolean isReportAsSingleViolation() {
            return false;
        }

        @Override
        public String getMessageTemplate() {
            return "";
        }
        
        @Override
        public ConstraintTarget getValidationAppliesTo() {
            return null;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy