sdmxdl.web.SdmxWebManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdmx-dl-api Show documentation
Show all versions of sdmx-dl-api Show documentation
Easily download official statistics - API
/*
* Copyright 2015 National Bank of Belgium
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
package sdmxdl.web;
import internal.util.*;
import lombok.AccessLevel;
import lombok.NonNull;
import nbbrd.design.StaticFactoryMethod;
import org.checkerframework.checker.nullness.qual.Nullable;
import sdmxdl.EventListener;
import sdmxdl.*;
import sdmxdl.web.spi.*;
import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
/**
* @author Philippe Charles
*/
@lombok.Value
@lombok.Builder(toBuilder = true)
@lombok.EqualsAndHashCode(callSuper = false)
public class SdmxWebManager extends SdmxManager {
@StaticFactoryMethod
public static @NonNull SdmxWebManager ofServiceLoader() {
return SdmxWebManager
.builder()
.drivers(DriverLoader.load())
.monitors(MonitorLoader.load())
.networking(NetworkingLoader.load())
.caching(WebCachingLoader.load())
.authenticators(AuthenticatorLoader.load())
.build();
}
@StaticFactoryMethod
public static @NonNull SdmxWebManager noOp() {
return SdmxWebManager.builder().build();
}
@lombok.Singular
@NonNull List drivers;
@lombok.Singular
@NonNull List monitors;
@lombok.Builder.Default
@NonNull Networking networking = Networking.getDefault();
@lombok.Builder.Default
@NonNull WebCaching caching = WebCaching.noOp();
@Nullable EventListener super WebSource> onEvent;
@Nullable ErrorListener super WebSource> onError;
@lombok.Singular
@NonNull List authenticators;
@lombok.Singular
@NonNull List customSources;
@lombok.Getter(lazy = true)
@NonNull List defaultSources = initLazyDefaultSources(getDrivers());
@lombok.Getter(lazy = true)
@NonNull SortedMap sources = initLazySourceMap(getCustomSources(), getDefaultSources());
@lombok.Getter(lazy = true, value = AccessLevel.PRIVATE)
@NonNull WebContext context = initLazyContext();
public @NonNull Connection getConnection(@NonNull String name, @NonNull Languages languages) throws IOException {
WebSource source = lookupSource(name)
.orElseThrow(() -> newMissingSource(name));
return getConnection(source, languages);
}
@Override
public @NonNull Connection getConnection(@NonNull WebSource source, @NonNull Languages languages) throws IOException {
Driver driver = lookupDriverById(source.getDriver())
.orElseThrow(() -> new IOException("Failed to find a suitable driver for '" + source + "'"));
checkSourceProperties(source, driver);
return driver.connect(source, languages, getContext());
}
public @NonNull MonitorReport getMonitorReport(@NonNull String name) throws IOException {
WebSource source = lookupSource(name)
.orElseThrow(() -> newMissingSource(name));
return getMonitorReport(source);
}
public @NonNull MonitorReport getMonitorReport(@NonNull WebSource source) throws IOException {
URI monitorURI = source.getMonitor();
if (monitorURI == null) {
throw new IOException("Missing monitor URI for '" + source + "'");
}
Monitor monitor = lookupMonitor(monitorURI.getScheme())
.orElseThrow(() -> new IOException("Failed to find a suitable monitoring for '" + source + "'"));
return monitor.getReport(source, getContext());
}
private void checkSourceProperties(WebSource source, Driver driver) {
if (onEvent != null) {
Collection expected = new ArrayList<>();
expected.addAll(driver.getDriverProperties());
expected.addAll(networking.getNetworkingProperties());
expected.addAll(caching.getWebCachingProperties());
Collection found = source.getProperties().keySet();
String diff = found.stream().filter(item -> !expected.contains(item)).sorted().collect(Collectors.joining(","));
if (!diff.isEmpty()) {
onEvent.accept(source, "WEB_MANAGER", "Unexpected properties [" + diff + "]");
}
}
}
private Optional lookupSource(String name) {
return Optional.ofNullable(getSources().get(name));
}
private Optional lookupDriverById(String id) {
return drivers
.stream()
.filter(driver -> id.equals(driver.getDriverId()))
.findFirst();
}
private Optional lookupMonitor(String uriScheme) {
return monitors
.stream()
.filter(monitor -> uriScheme.equals(monitor.getMonitorUriScheme()))
.findFirst();
}
private WebContext initLazyContext() {
return WebContext
.builder()
.caching(caching)
.networking(networking)
.onEvent(onEvent)
.onError(onError)
.authenticators(authenticators)
.build();
}
private static List initLazyDefaultSources(List drivers) {
return drivers
.stream()
.flatMap(driver -> driver.getDefaultSources().stream())
.filter(distinctByKey(WebSource::getId))
.collect(toList());
}
private static SortedMap initLazySourceMap(List customSources, List defaultSources) {
return Stream.concat(customSources.stream(), defaultSources.stream())
.flatMap(SdmxWebManager::expandAliases)
.collect(groupingBy(WebSource::getId, TreeMap::new, reducingByFirst()));
}
private static Stream expandAliases(WebSource source) {
Stream first = Stream.of(source);
return !source.getAliases().isEmpty()
? Stream.concat(first, source.getAliases().stream().map(source::alias))
: first;
}
private static IOException newMissingSource(String name) {
return new IOException("Missing source '" + name + "'");
}
private static Collector reducingByFirst() {
return Collectors.reducing(null, (first, last) -> first == null ? last : first);
}
private static Predicate distinctByKey(Function super T, ?> keyExtractor) {
Set