org.zalando.riptide.DefaultRoutingTree Maven / Gradle / Ivy
package org.zalando.riptide;
/*
*
* Riptide
*
* Copyright (C) 2015 - 2016 Zalando SE
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.toMap;
final class DefaultRoutingTree implements RoutingTree {
private final Navigator navigator;
private final Map routes;
private final Optional wildcard;
DefaultRoutingTree(final Navigator navigator, final List> bindings) {
this(navigator, map(bindings));
}
private DefaultRoutingTree(final Navigator navigator, final Map routes) {
this(navigator, unmodifiableMap(routes), Optional.ofNullable(routes.remove(null)));
}
private DefaultRoutingTree(final Navigator navigator, final Map routes, final Optional wildcard) {
this.navigator = navigator;
this.routes = routes;
this.wildcard = wildcard;
}
@Override
public Set keySet() {
return routes.keySet();
}
@Override
public Optional get(final A attribute) {
return Optional.ofNullable(routes.get(attribute));
}
@Override
public Optional getWildcard() {
return wildcard;
}
@Override
public RoutingTree merge(final List> bindings) {
final List> present = new ArrayList<>(routes.size() + 1);
routes.forEach((attribute, route) -> present.add(Binding.create(attribute, route)));
wildcard.ifPresent(route -> present.add(Binding.create(null, route)));
return RoutingTree.dispatch(navigator, navigator.merge(present, bindings));
}
private static Map map(final List> bindings) {
return bindings.stream()
.collect(toMap(Binding::getAttribute, Binding::getRoute, (u, v) -> {
throw new IllegalArgumentException(String.format("Duplicate key %s", u));
}, LinkedHashMap::new));
}
@Override
public void execute(final ClientHttpResponse response, final MessageReader reader) throws Exception {
final Optional route = navigator.navigate(response, this);
if (route.isPresent()) {
try {
route.get().execute(response, reader);
} catch (final NoRouteException e) {
executeWildcardOrThrow(response, reader, always(e));
}
} else {
executeWildcardOrThrow(response, reader, () -> new NoRouteException(response));
}
}
private void executeWildcardOrThrow(final ClientHttpResponse response,
final MessageReader reader, final ThrowingSupplier e) throws Exception {
if (wildcard.isPresent()) {
wildcard.get().execute(response, reader);
} else {
throw e.get();
}
}
@FunctionalInterface
private interface ThrowingSupplier {
T get() throws IOException;
}
private static ThrowingSupplier always(final T t) {
return () -> t;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy