org.eclipse.ditto.wot.api.resolver.DefaultWotThingModelResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ditto-wot-api Show documentation
Show all versions of ditto-wot-api Show documentation
Eclipse Ditto is a framework for creating and managing digital twins in the IoT.
The newest version!
/*
* Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.wot.api.resolver;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.eclipse.ditto.base.model.headers.DittoHeaders;
import org.eclipse.ditto.internal.utils.cache.Cache;
import org.eclipse.ditto.internal.utils.cache.CacheFactory;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.wot.api.config.WotConfig;
import org.eclipse.ditto.wot.api.generator.WotThingModelExtensionResolver;
import org.eclipse.ditto.wot.api.provider.WotThingModelFetcher;
import org.eclipse.ditto.wot.model.IRI;
import org.eclipse.ditto.wot.model.ThingDefinitionInvalidException;
import org.eclipse.ditto.wot.model.ThingModel;
import org.eclipse.ditto.wot.model.WotThingModelInvalidException;
import org.eclipse.ditto.wot.model.WotThingModelNotAccessibleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.benmanes.caffeine.cache.AsyncCacheLoader;
/**
* Default implementation of {@link WotThingModelResolver} which should be not Ditto specific.
*/
final class DefaultWotThingModelResolver implements WotThingModelResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultWotThingModelResolver.class);
private static final String TM_SUBMODEL = "tm:submodel";
private static final String TM_SUBMODEL_INSTANCE_NAME = "instanceName";
private static final Duration MAX_RESOLVE_MODEL_DURATION = Duration.ofSeconds(12);
private final WotThingModelFetcher thingModelFetcher;
private final WotThingModelExtensionResolver thingModelExtensionResolver;
private final Cache fullyResolvedThingModelCache;
DefaultWotThingModelResolver(final WotConfig wotConfig,
final WotThingModelFetcher thingModelFetcher,
final WotThingModelExtensionResolver thingModelExtensionResolver,
final Executor cacheLoaderExecutor) {
this.thingModelFetcher = thingModelFetcher;
this.thingModelExtensionResolver = thingModelExtensionResolver;
final AsyncCacheLoader loader = this::loadThingModelViaHttp;
fullyResolvedThingModelCache = CacheFactory.createCache(loader,
wotConfig.getCacheConfig(),
"ditto_wot_fully_resolved_thing_model_cache",
cacheLoaderExecutor);
}
@Override
public CompletableFuture resolveThingModel(final IRI iri, final DittoHeaders dittoHeaders) {
try {
return resolveThingModel(new URL(iri.toString()), dittoHeaders);
} catch (final MalformedURLException e) {
throw ThingDefinitionInvalidException.newBuilder(iri)
.dittoHeaders(dittoHeaders)
.build();
}
}
@Override
public CompletableFuture resolveThingModel(final URL url, final DittoHeaders dittoHeaders) {
LOGGER.debug("Resolving ThingModel (from cache or downloading as fallback) from URL: <{}>", url);
return fullyResolvedThingModelCache.get(url)
.thenApply(optTm -> resolveThingModel(optTm.orElse(null), url, dittoHeaders))
.orTimeout(MAX_RESOLVE_MODEL_DURATION.toSeconds(), TimeUnit.SECONDS);
}
@Override
public CompletionStage