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

com.envimate.mapmate.validation.ExceptionTracker Maven / Gradle / Ivy

Go to download

MapMate is a modern mapping framework in the scope of mapping data in Json, XML, or YAML format into DTOs composed and vice versa.

There is a newer version: 1.6.8
Show newest version
/*
 * Copyright (C) 2017 [Richard Hauswald, Nune Isabekyan] (envimate GmbH - https://envimate.com/)
 */

package com.envimate.mapmate.validation;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

public final class ExceptionTracker {

    private final Set exceptions;
    private final String position;
    private final Map, ExceptionMapping> exceptionMapping;

    private final List children;

    public ExceptionTracker(final Map, ExceptionMapping> exceptionMapping) {
        this.exceptionMapping = exceptionMapping;
        this.exceptions = new HashSet<>(0);
        this.position = "";
        this.children = new ArrayList<>(0);
    }

    private ExceptionTracker(final String position, final Map, ExceptionMapping> exceptionMapping) {
        this.exceptionMapping = exceptionMapping;
        this.exceptions = new HashSet<>(0);
        this.position = position;
        this.children = new ArrayList<>(0);
    }

    @SuppressWarnings({"CastToConcreteClass", "ThrowableNotThrown"})
    public void track(final Throwable e) {
        final Throwable resolvedThrowable;
        if(e instanceof InvocationTargetException) {
            resolvedThrowable = ((InvocationTargetException) e).getTargetException();
        } else {
            resolvedThrowable = e;
        }
        final ExceptionMapping exceptionMapping = this.exceptionMapping.get(resolvedThrowable.getClass());
        if (exceptionMapping != null) {
            final ValidationException mapped = exceptionMapping.map(resolvedThrowable);
            this.exceptions.add(new ExceptionEntry(this.position, resolveBlamed(mapped), resolvedThrowable));
        } else {
            this.exceptions.add(new ExceptionEntry(this.position, new String[]{this.position}, resolvedThrowable));
        }
    }

    private String[] resolveBlamed(final ValidationException e) {
        final String[] fields = e.getBlamedFields();
        final String[] blamed = new String[fields.length];

        for (int key = 0; key < fields.length; key++) {
            final String value = fields[key];
            if (this.position.equals("")) {
                blamed[key] = value;
            } else {
                blamed[key] = this.position + "." + value;
            }
        }

        return blamed;
    }

    public ExceptionTracker stepInto(final String position) {
        final ExceptionTracker exceptionTracker;
        if (this.position.equals("")) {
            exceptionTracker = new ExceptionTracker(position, this.exceptionMapping);
        } else {
            exceptionTracker = new ExceptionTracker(this.position + "." + position, this.exceptionMapping);
        }
        this.children.add(exceptionTracker);
        return exceptionTracker;
    }

    public Set resolve() {
        final Set flattened = this.flatten();
        //noinspection Annotator
        final Collection markedForRemoval = new ArrayList<>(0);
        for (final ExceptionEntry entry : flattened) {
            final List blaming = Arrays.asList(entry.getBlamed());

            final long count = flattened.stream()
                    .filter(value -> {
                        return blaming.contains(value.getFrom()) && entry != value;
                    }).count();

            if (count > 0) {
                markedForRemoval.add(entry);
            }
        }

        markedForRemoval.forEach(flattened::remove);

        return flattened;
    }

    @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
    private Set flatten() {
        this.children.forEach(child -> {
            this.exceptions.addAll(child.flatten());
        });

        return this.exceptions;
    }

    public static final class ExceptionEntry {
        private final String from;
        private final String[] blamed;
        private final Throwable exception;

        ExceptionEntry(final String from, final String[] blamed, final Throwable e) {
            this.from = from;
            this.blamed = blamed.clone();
            this.exception = e;
        }

        public ExceptionEntry(final String from, final String blamed, final Throwable e) {
            this.from = from;
            this.blamed = new String[]{blamed};
            this.exception = e;
        }

        public String getFrom() {
            return this.from;
        }

        public String[] getBlamed() {
            return this.blamed.clone();
        }

        public Throwable getException() {
            return this.exception;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final ExceptionEntry that = (ExceptionEntry) obj;
            return Objects.equals(this.from, that.from) &&
                    Objects.equals(this.exception, that.exception);
        }

        @Override
        public int hashCode() {

            return Objects.hash(this.from, this.exception);
        }

        @Override
        public String toString() {
            return "ExceptionEntry{" +
                    "from='" + this.from + '\'' +
                    ", exception=" + this.exception +
                    '}';
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy