package net.hamnaberg.json.extension;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javaslang.Tuple;
import javaslang.control.Option;
import net.hamnaberg.json.Error;
import net.hamnaberg.json.InternalObjectFactory;
import net.hamnaberg.json.Json;
public class Errors {
private final Map<String, List<Error>> errors = new LinkedHashMap<String, List<Error>>();
public Errors(Map<String, List<Error>> errors) {
this.errors.putAll(errors);
}
public List<Error> getErrors(String name) {
List<Error> v = errors.get(name);
if (v != null) {
return Collections.unmodifiableList(v);
}
return Collections.emptyList();
}
private Json.JObject asJson() {
return Json.jObject(
errors.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> toArrayNode(entry.getValue())))
);
}
private static Json.JArray toArrayNode(List<Error> errors) {
return Json.jArray(errors.stream()
.map(Extended::asJson)
.collect(Collectors.toList()));
}
public static class Builder {
private Map<String, List<Error>> m = new LinkedHashMap<String, List<Error>>();
public Builder put(String name, List<Error> errors) {
m.put(name, errors);
return this;
}
public Builder add(String name, List<Error> errors) {
List<Error> list = m.get(name);
if (list == null) {
return put(name, errors);
}
list.addAll(errors);
return this;
}
public Errors build() {
return new Errors(m);
}
}
public static class Ext extends Extension<Option<Errors>> {
private InternalObjectFactory factory = new InternalObjectFactory() {};
@Override
public Option<Errors> extract(Json.JObject node) {
Function<Json.JArray, List<Error>> toErrors = arr -> arr.
getListAsObjects().
map(factory::createError).
toJavaList();
Option<Json.JObject> errors = node.getAsObject("errors");
return errors.map(
j -> j.value.map((k, v) -> Tuple.of(k, toErrors.apply(v.asJsonArrayOrEmpty()))).toJavaMap()
).map(Errors::new);
}
@Override
public Json.JObject apply(Option<Errors> value) {
return Json.jObject(value.map(Stream::of)
.getOrElse(Stream.<Errors>empty())
.collect(Collectors.toMap(errors -> "errors", Errors::asJson)));
}
}
}