
sdmxdl.web.SdmxWebManager Maven / Gradle / Ivy
/*
* 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.SdmxWebAuthenticatorLoader;
import internal.util.SdmxWebDriverLoader;
import internal.util.SdmxWebMonitoringLoader;
import lombok.AccessLevel;
import org.checkerframework.checker.nullness.qual.NonNull;
import sdmxdl.LanguagePriorityList;
import sdmxdl.SdmxManager;
import sdmxdl.ext.NetworkFactory;
import sdmxdl.ext.SdmxCache;
import sdmxdl.ext.SdmxException;
import sdmxdl.ext.spi.SdmxDialect;
import sdmxdl.ext.spi.SdmxDialectLoader;
import sdmxdl.web.spi.SdmxWebAuthenticator;
import sdmxdl.web.spi.SdmxWebContext;
import sdmxdl.web.spi.SdmxWebDriver;
import sdmxdl.web.spi.SdmxWebMonitoring;
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;
/**
* @author Philippe Charles
*/
@lombok.Value
@lombok.Builder(toBuilder = true)
public class SdmxWebManager implements SdmxManager {
@NonNull
public static SdmxWebManager ofServiceLoader() {
return SdmxWebManager
.builder()
.drivers(SdmxWebDriverLoader.load())
.dialects(SdmxDialectLoader.load())
.monitorings(SdmxWebMonitoringLoader.load())
.authenticators(SdmxWebAuthenticatorLoader.load())
.build();
}
@lombok.NonNull
@lombok.Singular
List drivers;
@lombok.NonNull
@lombok.Singular
List dialects;
@lombok.NonNull
@lombok.Singular
List monitorings;
@lombok.NonNull
@lombok.Builder.Default
LanguagePriorityList languages = LanguagePriorityList.ANY;
@lombok.NonNull
@lombok.Builder.Default
NetworkFactory network = NetworkFactory.getDefault();
@lombok.NonNull
@lombok.Builder.Default
SdmxCache cache = SdmxCache.noOp();
@lombok.NonNull
@lombok.Builder.Default
SdmxWebListener eventListener = SdmxWebListener.getDefault();
@lombok.NonNull
@lombok.Singular
List authenticators;
@lombok.NonNull
@lombok.Singular
List customSources;
@lombok.NonNull
@lombok.Getter(lazy = true)
List defaultSources = initDefaultSources(getDrivers());
@lombok.NonNull
@lombok.Getter(lazy = true)
SortedMap sources = initSourceMap(getCustomSources(), getDefaultSources());
@lombok.NonNull
@lombok.Getter(lazy = true, value = AccessLevel.PRIVATE)
SdmxWebContext context = initContext();
@Override
public SdmxWebConnection getConnection(String name) throws IOException {
Objects.requireNonNull(name);
SdmxWebSource source = lookupSource(name)
.orElseThrow(() -> SdmxException.missingSource(name, SdmxWebSource.class));
return getConnection(source);
}
@NonNull
public SdmxWebConnection getConnection(@NonNull SdmxWebSource source) throws IOException {
Objects.requireNonNull(source);
SdmxWebDriver driver = lookupDriver(source.getDriver())
.orElseThrow(() -> new IOException("Failed to find a suitable driver for '" + source + "'"));
checkSourceProperties(source, driver);
return driver.connect(source, getContext());
}
@NonNull
public SdmxWebMonitorReport getMonitorReport(@NonNull String name) throws IOException {
Objects.requireNonNull(name);
SdmxWebSource source = lookupSource(name)
.orElseThrow(() -> SdmxException.missingSource(name, SdmxWebSource.class));
return getMonitorReport(source);
}
@NonNull
public SdmxWebMonitorReport getMonitorReport(@NonNull SdmxWebSource source) throws IOException {
Objects.requireNonNull(source);
URI monitor = source.getMonitor();
if (monitor == null) {
throw new IOException("Missing monitor for '" + source + "'");
}
SdmxWebMonitoring monitoring = lookupMonitoring(monitor.getScheme())
.orElseThrow(() -> new IOException("Failed to find a suitable monitoring for '" + source + "'"));
return monitoring.getReport(source, getContext());
}
private void checkSourceProperties(SdmxWebSource source, SdmxWebDriver driver) {
if (eventListener.isEnabled()) {
Collection expected = driver.getSupportedProperties();
Collection found = source.getProperties().keySet();
String diff = found.stream().filter(item -> !expected.contains(item)).sorted().collect(Collectors.joining(","));
if (!diff.isEmpty()) {
eventListener.onWebSourceEvent(source, "Unexpected properties [" + diff + "]");
}
}
}
private Optional lookupSource(String name) {
return Optional.ofNullable(getSources().get(name));
}
private Optional lookupDriver(String name) {
return drivers
.stream()
.filter(driver -> name.equals(driver.getName()))
.findFirst();
}
private Optional lookupMonitoring(String uriScheme) {
return monitorings
.stream()
.filter(monitoring -> uriScheme.equals(monitoring.getUriScheme()))
.findFirst();
}
private SdmxWebContext initContext() {
return SdmxWebContext
.builder()
.cache(cache)
.languages(languages)
.network(network)
.dialects(dialects)
.eventListener(eventListener)
.authenticators(authenticators)
.build();
}
private static List initDefaultSources(List drivers) {
return drivers
.stream()
.flatMap(driver -> driver.getDefaultSources().stream())
.filter(distinctByKey(SdmxWebSource::getName))
.collect(Collectors.toList());
}
private static SortedMap initSourceMap(List customSources, List defaultSources) {
return Stream.concat(customSources.stream(), defaultSources.stream())
.flatMap(SdmxWebManager::expandAliases)
.collect(Collectors.groupingBy(SdmxWebSource::getName, TreeMap::new, reducingByFirst()));
}
private static Stream expandAliases(SdmxWebSource source) {
Stream first = Stream.of(source);
return !source.getAliases().isEmpty()
? Stream.concat(first, source.getAliases().stream().map(source::alias))
: first;
}
private static Collector reducingByFirst() {
return Collectors.reducing(null, (first, last) -> first == null ? last : first);
}
private static Predicate distinctByKey(Function super T, ?> keyExtractor) {
Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy