package net.hamnaberg.json;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import javaslang.control.Option;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import com.damnhandy.uri.template.MalformedUriTemplateException;
import com.damnhandy.uri.template.UriTemplate;
public final class URITemplateTarget implements Target {
private String href;
public URITemplateTarget(String href) {
try {
UriTemplate.fromTemplate(href);
this.href = href;
} catch (MalformedUriTemplateException e) {
throw new IllegalStateException(e);
}
}
@Override
public boolean isURITemplate() {
return true;
}
public URI toURI() {
try {
return URI.create(UriTemplate.fromTemplate(href).expand());
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public URI expand(Iterable<Property> properties) {
Map<String, Object> map = new HashMap<>();
for (Property property : properties) {
if (property.hasArray()) {
map.put(property.getName(), property.getArray().stream().filter(NOT_NULL_PRED).map(AS_STRING).collect(Collectors.toList()));
}
else if (property.hasObject()) {
map.put(property.getName(),
property.getObject()
.entrySet()
.stream()
.filter(VALUE_NOT_NULL_PRED)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().asString())));
}
else {
Option<Object> value = property.getValue().filter(NOT_NULL_PRED).map(AS_STRING);
value.forEach(val -> map.put(property.getName(), val));
}
}
try {
return URI.create(UriTemplate.fromTemplate(href).expand(map));
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
URITemplateTarget uriTarget = (URITemplateTarget) o;
if (href != null ? !href.equals(uriTarget.href) : uriTarget.href != null) return false;
return true;
}
@Override
public int hashCode() {
return href != null ? href.hashCode() : 0;
}
@Override
public String toString() {
return href;
}
private final Predicate<Map.Entry<String,Value>> VALUE_NOT_NULL_PRED = input -> input.getValue() != Value.NULL;
private Predicate<Value> NOT_NULL_PRED = input -> input != Value.NULL;
private Function<Value,Object> AS_STRING = Value::asString;
}