com.envimate.mapmate.validation.ExceptionTracker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapmate Show documentation
Show all versions of mapmate Show documentation
MapMate is a modern mapping framework in the scope of mapping data in
Json, XML, or YAML format into DTOs composed and vice versa.
/*
* Copyright (C) 2017 [Richard Hauswald, Nune Isabekyan] (envimate GmbH - https://envimate.com/)
*/
package com.envimate.mapmate.validation;
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 ExceptionMapping exceptionMapping = this.exceptionMapping.get(e.getClass());
if (exceptionMapping != null) {
final ValidationException mapped = exceptionMapping.map(e);
this.exceptions.add(new ExceptionEntry(this.position, resolveBlamed(mapped), e));
} else {
this.exceptions.add(new ExceptionEntry(this.position, new String[]{this.position}, e));
}
}
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 +
'}';
}
}
}