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

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