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

com.crabshue.commons.properties.validation.PropertiesValidator Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
package com.crabshue.commons.properties.validation;

import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.crabshue.commons.exceptions.ValidationException;
import com.crabshue.commons.file.nio.FileIOUtils;
import com.crabshue.commons.properties.exceptions.PropertiesErrorContext;
import com.crabshue.commons.properties.exceptions.PropertiesErrorType;
import lombok.NonNull;

/**
 * Validator for properties files.
 *
 */
public class PropertiesValidator {

    private static final String REGEX = "^[a-zA-Z0-9._-]+$";

    /**
     * Validate a properties file.
     *
     * @param propertiesFile the properties file
     * @see #validateProperties(Path, boolean)
     */
    public void validateProperties(@NonNull final Path propertiesFile) {

        validateProperties(propertiesFile, false);
    }

    /**
     * Validate a properties file with option to accept empty values.
     *
     * @param propertiesFile    the properties file.
     * @param acceptEmptyValues the option to accept empty values.
     * @see #validatePropertiesFormat(Path, boolean)
     * @see #validateNoDuplicatedKeys(Path)
     */
    public void validateProperties(@NonNull final Path propertiesFile,
                                   @NonNull final boolean acceptEmptyValues) {

        validatePropertiesFormat(propertiesFile, acceptEmptyValues);
        validateNoDuplicatedKeys(propertiesFile);
    }

    /**
     * Validate the properties file containing non empty key and value separated by
     * '=' and where each keys matches the regex {@link PropertiesValidator#REGEX}.
     *
     * @param propertiesFile Properties file to be validated
     * @see #validatePropertiesLine(Path, String, boolean)
     */
    private void validatePropertiesFormat(@NonNull final Path propertiesFile,
                                          @NonNull final boolean acceptEmptyValues) {

        final Collection lines = FileIOUtils.readLines(propertiesFile);

        for (String line : lines) {
            final String trimmedLine = StringUtils.trim(line);
            validatePropertiesLine(propertiesFile, trimmedLine, acceptEmptyValues);
        }
    }


    private void validatePropertiesLine(@NonNull final Path propertiesFile,
                                        @NonNull final String line,
                                        @NonNull final boolean acceptEmptyValues) {

        if (StringUtils.isEmpty(line)) {
            return;
        }

        final boolean isCommentedLine = StringUtils.startsWithAny(line, new String[]{"#", "!"});
        if (isCommentedLine) {
            return;
        }

        final boolean containsEqual = StringUtils.contains(line, "=");
        if (!containsEqual) {
            throw new ValidationException(PropertiesErrorType.PROPERTIES_FILE_MISSING_EQUAL, "Error in properties file")
                .addContextValue(PropertiesErrorContext.PROPERTIES, propertiesFile)
                .addContextValue(PropertiesErrorContext.LINE, line);
        }

        final String key = StringUtils.substringBefore(line, "=");
        final String trimmedKey = StringUtils.trim(key);
        final String value = StringUtils.substringAfter(line, "=");

        // Validate empty value
        if (!acceptEmptyValues && StringUtils.isEmpty(value)) {
            throw new ValidationException(PropertiesErrorType.PROPERTIES_FILE_MISSING_VALUE, "Error in properties file")
                .addContextValue(PropertiesErrorContext.PROPERTIES, propertiesFile)
                .addContextValue(PropertiesErrorContext.LINE, line);
        }

        validateKey(propertiesFile, trimmedKey);

    }

    private void validateKey(@NonNull final Path propertiesFile,
                             @NonNull final String key) {

        if (!key.matches(REGEX)) {
            throw new ValidationException(PropertiesErrorType.PROPERTIES_WRONGLY_FORMATTED_KEY, "Error in properties file")
                .addContextValue(PropertiesErrorContext.PROPERTIES, propertiesFile)
                .addContextValue(PropertiesErrorContext.KEY, key)
                .addContextValue(PropertiesErrorContext.REGEX, REGEX);
        }
    }

    private void validateNoDuplicatedKeys(@NonNull final Path propertiesFile) {

        final Collection lines = FileIOUtils.readLines(propertiesFile);

        final Set setOfKeys = new HashSet<>();

        for (String line : lines) {
            if (StringUtils.isEmpty(line)) {
                continue;
            }

            final boolean isCommentedLine = StringUtils.startsWithAny(line, new String[]{"#", "!"});
            if (isCommentedLine) {
                continue;
            }

            final String key = line.split("=")[0];
            if (setOfKeys.contains(key)) {
                throw new ValidationException(PropertiesErrorType.PROPERTIES_FILE_DUPLICATE_KEY, "Error in properties validation")
                    .addContextValue(PropertiesErrorContext.PROPERTIES, propertiesFile)
                    .addContextValue(PropertiesErrorContext.KEY, key)
                    ;
            }
            setOfKeys.add(key);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy