alfio.util.Validator.java Source code

Java tutorial

Introduction

Here is the source code for alfio.util.Validator.java

Source

/**
 * This file is part of alf.io.
 *
 * alf.io is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * alf.io is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with alf.io.  If not, see <http://www.gnu.org/licenses/>.
 */
package alfio.util;

import alfio.controller.form.UpdateTicketOwnerForm;
import alfio.controller.form.WaitingQueueSubscriptionForm;
import alfio.model.ContentLanguage;
import alfio.model.Event;
import alfio.model.TicketFieldConfiguration;
import alfio.model.modification.DateTimeModification;
import alfio.model.modification.EventModification;
import alfio.model.modification.TicketCategoryModification;
import alfio.model.result.ErrorCode;
import alfio.model.result.ValidationResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public final class Validator {

    private static final Pattern SIMPLE_E_MAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9]+.*?@.+?\\..+$");

    private Validator() {
    }

    public static ValidationResult validateEventHeader(Optional<Event> event, EventModification ev, Errors errors) {

        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "shortName", "error.shortname");
        if (ev.getOrganizationId() < 0) {
            errors.rejectValue("organizationId", "error.organizationId");
        }
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "location", "error.location");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "websiteUrl", "error.websiteurl");

        if (isInternal(event, ev)) {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "description", "error.description");
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "termsAndConditionsUrl",
                    "error.termsandconditionsurl");
        } else {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "externalUrl", "error.externalurl");
        }

        if (ev.getFileBlobId() == null) {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "imageUrl", "error.imageurl");
            if (!StringUtils.startsWith(ev.getImageUrl(), "https://")) {
                errors.rejectValue("imageUrl", "error.imageurl");
            }
        }
        return evaluateValidationResult(errors);
    }

    private static boolean isInternal(Optional<Event> event, EventModification ev) {
        return event.map(Event::getType).orElse(ev.getEventType()) == Event.EventType.INTERNAL;
    }

    public static ValidationResult validateEventPrices(Optional<Event> event, EventModification ev, Errors errors) {

        if (!isInternal(event, ev)) {
            return ValidationResult.success();
        }

        if (!ev.isFreeOfCharge()) {
            if (isCollectionEmpty(ev.getAllowedPaymentProxies())) {
                errors.rejectValue("allowedPaymentProxies", "error.allowedpaymentproxies");
            }
            if (ev.getRegularPrice() == null || BigDecimal.ZERO.compareTo(ev.getRegularPrice()) >= 0) {
                errors.rejectValue("regularPrice", "error.regularprice");
            }
            if (ev.getVatPercentage() == null || BigDecimal.ZERO.compareTo(ev.getVatPercentage()) > 0) {
                errors.rejectValue("vat", "error.vat");
            }
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "currency", "error.currency");
        }
        if (ev.getAvailableSeats() < 1) {
            errors.rejectValue("availableSeats", "error.availableseats");
        }
        return evaluateValidationResult(errors);
    }

    public static ValidationResult validateCategory(TicketCategoryModification category, Errors errors,
            String prefix) {
        if (StringUtils.isBlank(category.getName())) {
            errors.rejectValue(prefix + "name", "error.category.name");
        }
        if (category.isBounded() && category.getMaxTickets() < 1) {
            errors.rejectValue(prefix + "maxTickets", "error.category.maxtickets");
        }
        if (!category.getInception().isBefore(category.getExpiration())) {
            errors.rejectValue(prefix + "dateString", "error.date");
        }
        return evaluateValidationResult(errors);
    }

    public static ValidationResult validateCategory(TicketCategoryModification category, Errors errors) {
        return validateCategory(category, errors, "");
    }

    private static boolean isCollectionEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    public static ValidationResult evaluateValidationResult(Errors errors) {
        if (errors.hasFieldErrors()) {
            return ValidationResult.failed(errors.getFieldErrors().stream()
                    .map(ValidationResult.ErrorDescriptor::fromFieldError).collect(Collectors.toList()));
        }
        return ValidationResult.success();
    }

    public static ValidationResult validateTicketAssignment(UpdateTicketOwnerForm form,
            List<TicketFieldConfiguration> additionalFieldsForEvent, Optional<Errors> errorsOptional, Event event) {
        if (!errorsOptional.isPresent()) {
            return ValidationResult.success();//already validated
        }
        Errors errors = errorsOptional.get();
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "error.email");
        String email = form.getEmail();
        if (!isEmailValid(email)) {
            errors.rejectValue("email", "error.email");
        }

        if (event.mustUseFirstAndLastName()) {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", ErrorsCode.STEP_2_EMPTY_FIRSTNAME);
            validateMaxLength(form.getFirstName(), "firstName", ErrorsCode.STEP_2_MAX_LENGTH_FIRSTNAME, 255,
                    errors);

            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", ErrorsCode.STEP_2_EMPTY_LASTNAME);
            validateMaxLength(form.getLastName(), "lastName", ErrorsCode.STEP_2_MAX_LENGTH_LASTNAME, 255, errors);
        } else {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "fullName", ErrorsCode.STEP_2_EMPTY_FULLNAME);
            validateMaxLength(form.getFullName(), "fullName", ErrorsCode.STEP_2_MAX_LENGTH_FULLNAME, 255, errors);
        }

        //
        for (TicketFieldConfiguration fieldConf : additionalFieldsForEvent) {

            boolean isField = form.getAdditional() != null && form.getAdditional().containsKey(fieldConf.getName());

            if (!isField) {
                continue;
            }

            form.getAdditional().get(fieldConf.getName()).forEach(formValue -> {
                if (fieldConf.isMaxLengthDefined()) {
                    validateMaxLength(formValue, "additional['" + fieldConf.getName() + "']",
                            "error." + fieldConf.getName(), fieldConf.getMaxLength(), errors);
                }

                if (!fieldConf.getRestrictedValues().isEmpty()) {
                    validateRestrictedValue(formValue, "additional['" + fieldConf.getName() + "']",
                            "error." + fieldConf.getName(), fieldConf.getRestrictedValues(), errors);
                }

                if (fieldConf.isRequired() && StringUtils.isBlank(formValue)) {
                    errors.rejectValue("additional['" + fieldConf.getName() + "']", "error." + fieldConf.getName());
                }
            });

            //TODO: complete checks: min length
        }

        return evaluateValidationResult(errors);
    }

    private static void validateRestrictedValue(String value, String fieldName, String errorCode,
            List<String> restrictedValues, Errors errors) {
        if (StringUtils.isNotBlank(value) && !restrictedValues.contains(value)) {
            errors.rejectValue(fieldName, errorCode);
        }
    }

    private static boolean isEmailValid(String email) {
        return StringUtils.isNotEmpty(email) && SIMPLE_E_MAIL_PATTERN.matcher(email).matches();
    }

    public static void validateMaxLength(String value, String fieldName, String errorCode, int maxLength,
            Errors errors) {
        if (StringUtils.isNotBlank(value) && StringUtils.length(value) > maxLength) {
            errors.rejectValue(fieldName, errorCode);
        }
    }

    public static ValidationResult validateWaitingQueueSubscription(WaitingQueueSubscriptionForm form,
            Errors errors, Event event) {
        if (!form.isTermAndConditionsAccepted()) {
            errors.rejectValue("termAndConditionsAccepted", "error.termAndConditionsAccepted");
        }

        if (event.mustUseFirstAndLastName()) {
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "error.firstname");
            validateMaxLength(form.getFirstName(), "firstName", "error.firstname", 255, errors);

            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "lastname.fullname");
            validateMaxLength(form.getLastName(), "lastName", "error.lastname", 255, errors);
        } else {
            validateMaxLength(form.getFullName(), "fullName", "error.fullname", 255, errors);
            ValidationUtils.rejectIfEmptyOrWhitespace(errors, "fullName", "error.fullname");
        }

        if (!isEmailValid(form.getEmail())) {
            errors.rejectValue("email", "error.email");
        }
        if (form.getUserLanguage() == null) {
            errors.rejectValue("userLanguage", "error.userLanguage");
        }
        return evaluateValidationResult(errors);
    }

    public static ValidationResult validateAdditionalService(EventModification.AdditionalService additionalService,
            Errors errors) {
        return validateAdditionalService(additionalService, null, errors);
    }

    public static ValidationResult validateAdditionalService(EventModification.AdditionalService additionalService,
            EventModification eventModification, Errors errors) {
        if (additionalService.isFixPrice() && !Optional.ofNullable(additionalService.getPrice())
                .filter(p -> p.compareTo(BigDecimal.ZERO) >= 0).isPresent()) {
            errors.rejectValue("additionalServices", "error.price");
        }

        List<EventModification.AdditionalServiceText> descriptions = additionalService.getDescription();
        List<EventModification.AdditionalServiceText> titles = additionalService.getTitle();
        if (descriptions == null || titles == null || titles.size() != descriptions.size()) {
            errors.rejectValue("additionalServices", "error.title");
            errors.rejectValue("additionalServices", "error.description");
        } else {
            if (!validateDescriptionList(titles) || !containsAllRequiredTranslations(eventModification, titles)) {
                errors.rejectValue("additionalServices", "error.title");
            }
            if (!validateDescriptionList(descriptions)
                    || !containsAllRequiredTranslations(eventModification, descriptions)) {
                errors.rejectValue("additionalServices", "error.description");
            }
        }

        DateTimeModification inception = additionalService.getInception();
        DateTimeModification expiration = additionalService.getExpiration();
        if (inception == null || expiration == null || expiration.isBefore(inception)) {
            errors.rejectValue("additionalServices", "error.inception");
            errors.rejectValue("additionalServices", "error.expiration");
        } else if (eventModification != null && expiration.isAfter(eventModification.getEnd())) {
            errors.rejectValue("additionalServices", "error.expiration");
        }

        return evaluateValidationResult(errors);

    }

    private static boolean containsAllRequiredTranslations(EventModification eventModification,
            List<EventModification.AdditionalServiceText> descriptions) {
        Optional<EventModification> optional = Optional.ofNullable(eventModification);
        return !optional.isPresent() || optional.map(e -> ContentLanguage.findAllFor(e.getLocales()))
                .filter(l -> l.stream().allMatch(
                        l1 -> descriptions.stream().anyMatch(d -> d.getLocale().equals(l1.getLanguage()))))
                .isPresent();
    }

    private static boolean validateDescriptionList(List<EventModification.AdditionalServiceText> descriptions) {
        return descriptions.stream().allMatch(t -> StringUtils.isNotBlank(t.getValue()));
    }

    public static ValidationResult validateAdditionalFields(List<TicketFieldConfiguration> fieldConf,
            EventModification.AdditionalField field, Errors errors) {
        String duplicateName = fieldConf.stream().filter(f -> f.getName().equalsIgnoreCase(field.getName()))
                .map(TicketFieldConfiguration::getName).findAny().orElse("");
        if (StringUtils.isNotBlank(duplicateName)) {
            errors.rejectValue("name", ErrorCode.DUPLICATE);
        }
        return evaluateValidationResult(errors);
    }
}