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

com.exasol.errorcodecrawlermavenplugin.validation.DuplicatesValidator Maven / Gradle / Ivy

package com.exasol.errorcodecrawlermavenplugin.validation;

import static java.util.stream.Collectors.joining;

import java.util.*;

import com.exasol.errorcodecrawlermavenplugin.Finding;
import com.exasol.errorcodecrawlermavenplugin.config.ErrorCodeConfig;
import com.exasol.errorreporting.ExaError;
import com.exsol.errorcodemodel.ErrorIdentifier;
import com.exsol.errorcodemodel.ErrorIdentifier.SyntaxException;
import com.exsol.errorcodemodel.ErrorMessageDeclaration;

/**
 * This {@link ErrorMessageDeclarationValidator} validates that no error code is declared twice.
 */
// [impl->dsn~duplication-validator~1]
class DuplicatesValidator implements ErrorMessageDeclarationValidator {

    private final ErrorCodeConfig config;

    DuplicatesValidator(final ErrorCodeConfig config) {
        this.config = config;
    }

    @Override
    public List validate(final Collection errorMessageDeclarations) {
        final Map> declarationsPerCode = groupDeclarationsByErrorCode(
                errorMessageDeclarations);
        return generateFindingsForDuplicates(declarationsPerCode);
    }

    private Map> groupDeclarationsByErrorCode(
            final Collection errorMessageDeclarations) {
        final Map> declarationsPerCode = new HashMap<>();
        for (final ErrorMessageDeclaration errorMessageDeclaration : errorMessageDeclarations) {
            try {
                final var errorCode = ErrorIdentifier.parse(errorMessageDeclaration.getIdentifier());
                final String errorId = errorCode.getTag() + "-" + errorCode.getIndex();
                if (declarationsPerCode.containsKey(errorId)) {
                    declarationsPerCode.get(errorId).add(errorMessageDeclaration);
                } else {
                    declarationsPerCode.put(errorId, new LinkedList<>(List.of(errorMessageDeclaration)));
                }
            } catch (final ErrorIdentifier.SyntaxException exception) {
                // ignore. Will be reported by another validator
            }
        }
        return declarationsPerCode;
    }

    private List generateFindingsForDuplicates(
            final Map> positionsPerCode) {
        final List findings = new ArrayList<>();
        for (final Map.Entry> declaration : positionsPerCode.entrySet()) {
            if (declaration.getValue().size() > 1) {
                final String locations = declaration.getValue().stream() //
                        .map(PositionFormatter::getFormattedPosition) //
                        .collect(joining(", "));
                final Optional identifier = parseIdentifier(declaration.getValue().get(0));
                if (identifier.isEmpty()) {
                    // Ignore. Will be reported by another validator
                    continue;
                }
                final String errorTag = identifier.get().getTag();
                final int nextAvailableIndex = this.config.getHighestIndexForErrorTag(errorTag) + 1;
                findings.add(new Finding(ExaError.messageBuilder("E-ECM-4").message(
                        "Found duplicate error code: {{errorCode}} was declared multiple times: {{declarations|uq}}.")
                        .parameter("errorCode", declaration.getKey()) //
                        .parameter("declarations", locations) //
                        .mitigation("Next available index for error tag {{error tag}} is {{next available index}}.")
                        .parameter("error tag", errorTag) //
                        .parameter("next available index", nextAvailableIndex) //
                        .toString()));
            }
        }
        return findings;
    }

    private Optional parseIdentifier(final ErrorMessageDeclaration errorMessageDeclaration) {
        try {
            return Optional.of(ErrorIdentifier.parse(errorMessageDeclaration.getIdentifier()));
        } catch (final SyntaxException exception) {
            return Optional.empty();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy