From 44241c7bbb823f6936eb9fa9f6f6b25aa9f65b23 Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Mon, 13 Sep 2021 00:13:07 -0700
Subject: [PATCH 01/16] Remove TRY_FROM_EXPANDED from API
---
.../iot/modelsrepository/ModelDependencyResolution.java | 6 ------
.../iot/modelsrepository/ModelsRepositoryClientBuilder.java | 4 ++--
.../modelsrepository/implementation/FileModelFetcher.java | 3 ---
.../modelsrepository/implementation/HttpModelFetcher.java | 3 ---
.../modelsrepository/implementation/RepositoryHandler.java | 2 +-
.../azure-iot-modelsrepository/src/samples/README.md | 2 +-
6 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
index db28c05aa825d..3110ee8276bd4 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
@@ -16,10 +16,4 @@ public enum ModelDependencyResolution {
* Enable model dependency resolution. The client will parse models and calculate dependencies recursively.
*/
ENABLED,
-
- /**
- * Try to get pre-computed model dependencies using .expanded.json.
- * If the model expanded form does not exist, it will fall back to {@link ModelDependencyResolution#ENABLED}.
- */
- TRY_FROM_EXPANDED,
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
index e82b0e913e793..a8995af01255c 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
@@ -58,7 +58,7 @@ public final class ModelsRepositoryClientBuilder {
// Fields with default values.
private URI repositoryEndpoint;
- private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.TRY_FROM_EXPANDED;
+ private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.DISABLED;
// optional/have default values
private ModelsRepositoryServiceVersion serviceVersion;
@@ -152,7 +152,7 @@ private static HttpPipeline constructPipeline(
/**
* Create a {@link ModelsRepositoryClient} based on the builder settings.
*
- * @return the created synchronous ModelsRepotioryClient
+ * @return the created synchronous ModelsRepositoryClient
*/
public ModelsRepositoryClient buildClient() {
return new ModelsRepositoryClient(buildAsyncClient());
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index a8182568421d6..0ab7967c21503 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -44,9 +44,6 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende
Queue work = new LinkedList<>();
try {
- if (resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) {
- work.add(getPath(dtmi, repositoryUri, true));
- }
work.add(getPath(dtmi, repositoryUri, false));
} catch (MalformedURLException | URISyntaxException e) {
return Mono.error(new AzureException(e));
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
index 6a36fd9cacf84..d4c1cfb4aa507 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
@@ -35,9 +35,6 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende
return Mono.defer(() -> {
Queue work = new LinkedList<>();
try {
- if (resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) {
- work.add(getPath(dtmi, repositoryUri, true));
- }
work.add(getPath(dtmi, repositoryUri, false));
} catch (Exception e) {
return Mono.error(new AzureException(e));
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index 7eb2e6dabd618..7560ebb6083f1 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -96,7 +96,7 @@ private Flux processAsync(
try {
ModelMetadata metadata = new ModelsQuery(response.getDefinition()).parseModel();
- if (resolutionOption == ModelDependencyResolution.ENABLED || resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) {
+ if (resolutionOption == ModelDependencyResolution.ENABLED) {
List dependencies = metadata.getDependencies();
if (dependencies.size() > 0) {
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
index ec8476aabca03..4728db6067b6a 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
@@ -18,7 +18,7 @@ The samples project demonstrates the following:
```java
// When no URI is provided for instantiation, the Azure IoT Models Repository global endpoint
// https://devicemodels.azure.com/ is used and the model dependency resolution
-// configuration is set to TRY_FROM_EXPANDED.
+// configuration is set to DISABLED.
ModelsRepositoryAsyncClient asyncClient = new ModelsRepositoryClientBuilder()
.buildAsyncClient();
From d53333106a23fc592c5e73b8985ee5a274ed625f Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Mon, 27 Sep 2021 02:32:44 -0700
Subject: [PATCH 02/16] Support models repo metadata functionality and
eliminate TryFromExpanded from API surface
---
.../iot/modelsrepository/DtmiConventions.java | 20 ++++++
.../ModelsRepositoryClientBuilder.java | 2 +-
.../implementation/FileModelFetcher.java | 58 ++++++++++++++--
.../implementation/HttpModelFetcher.java | 52 ++++++++++++--
...java => IntermediateFetchModelResult.java} | 14 ++--
.../implementation/ModelFetcher.java | 6 +-
.../ModelsRepositoryConstants.java | 1 +
.../implementation/RepositoryHandler.java | 33 +++++++--
.../implementation/StatusStrings.java | 2 +
.../models/FetchMetadataResult.java | 67 +++++++++++++++++++
...FetchResult.java => FetchModelResult.java} | 12 ++--
.../models/ModelsRepositoryMetadata.java | 40 +++++++++++
.../models/RepositoryFeatures.java | 22 ++++++
13 files changed, 297 insertions(+), 32 deletions(-)
rename sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/{IntermediateFetchResult.java => IntermediateFetchModelResult.java} (62%)
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
rename sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/{FetchResult.java => FetchModelResult.java} (82%)
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelsRepositoryMetadata.java
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/RepositoryFeatures.java
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
index 5a49487c5b98c..1ec8a23d02a19 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
@@ -74,6 +74,26 @@ public static URI getModelUri(String dtmi, URI repositoryUri, boolean expanded)
}
}
+ /**
+ * Generates the model repository's metadata URI.
+ *
+ * @param repositoryUri The repository uri
+ * @return The repository metadata uri.
+ * @throws IllegalArgumentException if the provided repository URI is not valid
+ */
+ public static URI getMetadataUri(URI repositoryUri) {
+ try {
+ String stringUri = repositoryUri.toString();
+ if (stringUri.endsWith("/")) {
+ return new URI(stringUri + ModelsRepositoryConstants.MODELS_REPOSITORY_METADATA_FILE);
+ } else {
+ return new URI(stringUri + "/" + ModelsRepositoryConstants.MODELS_REPOSITORY_METADATA_FILE);
+ }
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Invalid uri syntax");
+ }
+ }
+
static String dtmiToPath(String dtmi) {
if (!isValidDtmi(dtmi)) {
throw new IllegalArgumentException(String.format(StatusStrings.INVALID_DTMI_FORMAT_S, dtmi));
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
index a8995af01255c..cb949207186c6 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java
@@ -58,7 +58,7 @@ public final class ModelsRepositoryClientBuilder {
// Fields with default values.
private URI repositoryEndpoint;
- private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.DISABLED;
+ private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.ENABLED;
// optional/have default values
private ModelsRepositoryServiceVersion serviceVersion;
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index 0ab7967c21503..b5b33030a8eb9 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -8,7 +8,8 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.iot.modelsrepository.DtmiConventions;
import com.azure.iot.modelsrepository.ModelDependencyResolution;
-import com.azure.iot.modelsrepository.implementation.models.FetchResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
import reactor.core.publisher.Mono;
import java.io.File;
@@ -39,12 +40,15 @@ class FileModelFetcher implements ModelFetcher {
}
@Override
- public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context) {
+ public Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context) {
return Mono.defer(() -> {
Queue work = new LinkedList<>();
try {
- work.add(getPath(dtmi, repositoryUri, false));
+ if (tryFromExpanded) {
+ work.add(getModelPath(dtmi, repositoryUri, true));
+ }
+ work.add(getModelPath(dtmi, repositoryUri, false));
} catch (MalformedURLException | URISyntaxException e) {
return Mono.error(new AzureException(e));
}
@@ -60,7 +64,7 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende
if (Files.exists(path)) {
try {
return Mono.just(
- new FetchResult()
+ new FetchModelResult()
.setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8))
.setPath(tryContentPath));
} catch (IOException e) {
@@ -77,8 +81,52 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende
});
}
- private String getPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException, MalformedURLException {
+ @Override
+ public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
+ return Mono.defer(() -> {
+ Queue work = new LinkedList<>();
+
+ try {
+ work.add(getMetadataPath(repositoryUri));
+ } catch (MalformedURLException | URISyntaxException e) {
+ return Mono.error(new AzureException(e));
+ }
+
+ String fnfError = "";
+ while (work.size() != 0) {
+ String tryContentPath = work.poll();
+
+ Path path = Paths.get(new File(tryContentPath).getPath());
+
+ logger.info(StatusStrings.FETCHING_METADATA_CONTENT, path);
+
+ if (Files.exists(path)) {
+ try {
+ return Mono.just(
+ new FetchMetadataResult()
+ .setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8))
+ .setPath(tryContentPath));
+ } catch (IOException e) {
+ return Mono.error(new AzureException(e));
+ }
+ }
+
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString()));
+
+ fnfError = String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath);
+ }
+
+ return Mono.error(new AzureException(fnfError));
+ });
+ }
+
+ private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException, MalformedURLException {
return DtmiConventions.getModelUri(dtmi, repositoryUri, expanded)
.getPath();
}
+
+ private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException {
+ return DtmiConventions.getMetadataUri(repositoryUri)
+ .getPath();
+ }
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
index d4c1cfb4aa507..79bfa8ad714a8 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
@@ -8,9 +8,12 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.iot.modelsrepository.DtmiConventions;
import com.azure.iot.modelsrepository.ModelDependencyResolution;
-import com.azure.iot.modelsrepository.implementation.models.FetchResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
+import com.fasterxml.jackson.core.JsonProcessingException;
import reactor.core.publisher.Mono;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
@@ -31,11 +34,11 @@ class HttpModelFetcher implements ModelFetcher {
}
@Override
- public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context) {
+ public Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context) {
return Mono.defer(() -> {
Queue work = new LinkedList<>();
try {
- work.add(getPath(dtmi, repositoryUri, false));
+ work.add(getModelPath(dtmi, repositoryUri, false));
} catch (Exception e) {
return Mono.error(new AzureException(e));
}
@@ -49,10 +52,45 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende
if (work.size() != 0) {
return evaluatePath(work.poll(), context);
} else {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_MODEL_CONTENT, tryContentPath.toString()));
return Mono.error(error);
}
})
- .map(s -> new FetchResult().setPath(tryContentPath).setDefinition(s));
+ .map(s -> new FetchModelResult().setPath(tryContentPath).setDefinition(s));
+ });
+ }
+
+ @Override
+ public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
+ return (Mono) Mono.defer(() -> {
+ Queue work = new LinkedList<>();
+ try {
+ work.add(getMetadataPath(repositoryUri));
+ } catch (Exception e) {
+ return Mono.error(new AzureException(e));
+ }
+
+ String tryContentPath = work.poll();
+
+ logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath);
+
+ return evaluatePath(tryContentPath, context)
+ .onErrorResume(error -> {
+ if (work.size() != 0) {
+ return evaluatePath(work.poll(), context);
+ } else {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath.toString()));
+ return Mono.error(error);
+ }
+ })
+ .map(s -> {
+ try {
+ return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
+ } catch (JsonProcessingException e) {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath.toString()));
+ return null;
+ }
+ });
});
}
@@ -66,7 +104,11 @@ private Mono evaluatePath(String tryContentPath, Context context) {
});
}
- private String getPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException {
+ private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException {
return DtmiConventions.getModelUri(dtmi, repositoryUri, expanded).getPath();
}
+
+ private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException {
+ return DtmiConventions.getMetadataUri(repositoryUri).getPath();
+ }
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java
similarity index 62%
rename from sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java
rename to sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java
index 2b11e3193d977..579d059b7b4b2 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java
@@ -3,7 +3,7 @@
package com.azure.iot.modelsrepository.implementation;
-import com.azure.iot.modelsrepository.implementation.models.FetchResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
import java.util.Map;
@@ -11,17 +11,17 @@
* This type is used to unify the expand operation return types in the recursive function and has no other use cases.
* Do not take any dependencies on this type.
*/
-class IntermediateFetchResult {
- private final FetchResult fetchResult;
+class IntermediateFetchModelResult {
+ private final FetchModelResult fetchModelResult;
private final Map map;
- IntermediateFetchResult(FetchResult fetchResult, Map map) {
- this.fetchResult = fetchResult;
+ IntermediateFetchModelResult(FetchModelResult fetchModelResult, Map map) {
+ this.fetchModelResult = fetchModelResult;
this.map = map;
}
- public FetchResult getFetchResult() {
- return fetchResult;
+ public FetchModelResult getFetchModelResult() {
+ return fetchModelResult;
}
public Map getMap() {
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java
index 1de022101406f..8fc2e5f602d89 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java
@@ -5,11 +5,13 @@
import com.azure.core.util.Context;
import com.azure.iot.modelsrepository.ModelDependencyResolution;
-import com.azure.iot.modelsrepository.implementation.models.FetchResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
import reactor.core.publisher.Mono;
import java.net.URI;
interface ModelFetcher {
- Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context);
+ Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context);
+ Mono fetchMetadataAsync(URI repositoryUri, Context context);
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java
index f02a265adfa4e..d1efc6044f432 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java
@@ -9,6 +9,7 @@ public class ModelsRepositoryConstants {
public static final String JSON_EXTENSION = ".json";
public static final String JSON_EXPANDED_EXTENSION = ".expanded.json";
public static final String DEFAULT_MODELS_REPOSITORY_ENDPOINT = "https://devicemodels.azure.com";
+ public static final String MODELS_REPOSITORY_METADATA_FILE = "metadata.json";
// DTDL conventions
public static final String DTDL_TYPE = "@type";
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index 7560ebb6083f1..a3eb0a6343ee6 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -8,7 +8,8 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.iot.modelsrepository.DtmiConventions;
import com.azure.iot.modelsrepository.ModelDependencyResolution;
-import com.azure.iot.modelsrepository.implementation.models.FetchResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult;
+import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
import com.azure.iot.modelsrepository.implementation.models.ModelMetadata;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -21,6 +22,7 @@
import java.util.List;
import java.util.LinkedList;
import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
public final class RepositoryHandler {
@@ -55,10 +57,10 @@ public Mono
",
+ "x-ms-request-id" : "2ef2ac7f-401e-00a2-257c-b508e9000000",
+ "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 2ef2ac7f-401e-00a2-257c-b508e9000000
- TimeStamp : 2021-09-29T21:52:07.4957322Z
",
"Content-Type" : "text/html"
},
"Exception" : null
@@ -26,22 +57,23 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostatddd-1.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)",
- "x-ms-client-request-id" : "e833bda3-456a-470f-862b-b11625f09186"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "f12aca18-2bae-41e6-bb41-e72487de135e"
},
"Response" : {
+ "content-length" : "321",
"x-ms-version" : "2018-03-28",
"Server" : "Windows-Azure-Web/1.0 Microsoft-HTTPAPI/2.0",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"retry-after" : "0",
"StatusCode" : "404",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Tue, 23 Mar 2021 22:20:06 GMT",
+ "Date" : "Wed, 29 Sep 2021 21:52:06 GMT",
"Access-Control-Expose-Headers" : "*",
+ "Vary" : "Origin",
"x-ms-error-code" : "WebContentNotFound",
- "Content-Length" : "321",
- "x-ms-request-id" : "5b308299-601e-0051-0632-207f42000000",
- "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 5b308299-601e-0051-0632-207f42000000
- TimeStamp : 2021-03-23T22:20:07.3151755Z
",
+ "x-ms-request-id" : "5250b7e1-501e-006b-317c-b5ffbe000000",
+ "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 5250b7e1-501e-006b-317c-b5ffbe000000
- TimeStamp : 2021-09-29T21:52:07.5558209Z
",
"Content-Type" : "text/html"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
index 1c9f133670f38..f01fab5e51c8a 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
@@ -1,30 +1,60 @@
{
"networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "95e5e01c-6785-4402-bd80-d06d174a5dee"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "253",
+ "x-ms-version" : "2018-03-28",
+ "Server" : "ECAcc (sed/E179)",
+ "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
+ "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Access-Control-Allow-Headers" : "*",
+ "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Accept-Ranges" : "bytes",
+ "Access-Control-Expose-Headers" : "*",
+ "Cache-Control" : "max-age=600",
+ "Etag" : "\"0x8D983861F20E768\"",
+ "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
+ "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
+ "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
+ "Age" : "88",
+ "Content-Type" : "application/json"
+ },
+ "Exception" : null
+ }, {
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)",
- "x-ms-client-request-id" : "ce4f8dc5-3ea1-40b6-b04a-acdf4c035775"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "0ff85bcd-037a-44dd-9cbc-6d975ef85407"
},
"Response" : {
"X-Cache" : "HIT",
+ "content-length" : "2651",
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E120)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT",
+ "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Tue, 23 Mar 2021 22:20:07 GMT",
+ "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
"Content-MD5" : "pH51cS5+u5tWh2Krmys7qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
- "Etag" : "\"0x8D8A13DEAC57DB3\"",
+ "Etag" : "\"0x8D8FED94ECA13B6\"",
"x-ms-error-code" : "ConditionNotMet",
- "Content-Length" : "2651",
- "x-ms-request-id" : "0552d4aa-d01e-006e-4479-1fd74c000000",
+ "x-ms-request-id" : "e422263d-601e-005c-3c16-b40fa1000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n }\n]",
- "Age" : "79705",
+ "Age" : "153814",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
index 90fb9b50ca99f..ea57f4b8fdca8 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
@@ -1,30 +1,60 @@
{
"networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "84d9acca-021e-4282-95c0-eb64b823ae32"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "253",
+ "x-ms-version" : "2018-03-28",
+ "Server" : "ECAcc (sed/E179)",
+ "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
+ "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Access-Control-Allow-Headers" : "*",
+ "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Accept-Ranges" : "bytes",
+ "Access-Control-Expose-Headers" : "*",
+ "Cache-Control" : "max-age=600",
+ "Etag" : "\"0x8D983861F20E768\"",
+ "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
+ "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
+ "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
+ "Age" : "88",
+ "Content-Type" : "application/json"
+ },
+ "Exception" : null
+ }, {
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)",
- "x-ms-client-request-id" : "7b3aa5e5-c95b-46cd-b56a-52ba98c32fac"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "f2fa1841-6f6e-499d-807b-6015ab5d271b"
},
"Response" : {
"X-Cache" : "HIT",
+ "content-length" : "6751",
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E17F)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT",
+ "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Tue, 23 Mar 2021 22:20:07 GMT",
+ "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
"Content-MD5" : "BnZpV2+7Z2t0sxAxOhmBdw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
- "Etag" : "\"0x8D8A13DEAC10FCC\"",
+ "Etag" : "\"0x8D8FED94EBE03D1\"",
"x-ms-error-code" : "ConditionNotMet",
- "Content-Length" : "6751",
- "x-ms-request-id" : "1b12122f-b01e-0044-7f29-1c486a000000",
+ "x-ms-request-id" : "461deecb-f01e-004d-0e16-b49481000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:TemperatureController;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Temperature Controller\",\n \"description\": \"Device with two thermostats and remote reboot.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"DataSize\"\n ],\n \"name\": \"workingSet\",\n \"displayName\": \"Working Set\",\n \"description\": \"Current working set of the device memory in KiB.\",\n \"schema\": \"double\",\n \"unit\": \"kibibyte\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"serialNumber\",\n \"displayName\": \"Serial Number\",\n \"description\": \"Serial number of the device.\",\n \"schema\": \"string\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"reboot\",\n \"displayName\": \"Reboot\",\n \"description\": \"Reboots the device after waiting the number of seconds specified.\",\n \"request\": {\n \"name\": \"delay\",\n \"displayName\": \"Delay\",\n \"description\": \"Number of seconds to wait before rebooting the device.\",\n \"schema\": \"integer\"\n }\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat1\",\n \"displayName\": \"Thermostat One\",\n \"description\": \"Thermostat One of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat2\",\n \"displayName\": \"Thermostat Two\",\n \"description\": \"Thermostat Two of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"name\": \"deviceInformation\",\n \"displayName\": \"Device Information interface\",\n \"description\": \"Optional interface with basic device hardware information.\"\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]",
- "Age" : "443781",
+ "Age" : "153815",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
index 54051cf4b7951..bd9a808e3413a 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
@@ -3,28 +3,28 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)",
- "x-ms-client-request-id" : "537a41a9-a508-4e4a-8390-6399bb3ffb01"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "9905c36a-b2ab-4747-9660-197dad311446"
},
"Response" : {
"X-Cache" : "HIT",
+ "content-length" : "2469",
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E107)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT",
+ "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Tue, 23 Mar 2021 22:20:07 GMT",
+ "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
"Content-MD5" : "U0VZgOgpfb6bwvG5UDVZuw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
- "Etag" : "\"0x8D8A13DEABC53BA\"",
+ "Etag" : "\"0x8D8FED94ED5FC94\"",
"x-ms-error-code" : "ConditionNotMet",
- "Content-Length" : "2469",
- "x-ms-request-id" : "3e2ce5fe-301e-0060-0838-1c7551000000",
+ "x-ms-request-id" : "22c4d7b0-d01e-0073-1816-b4178d000000",
"Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}",
- "Age" : "437504",
+ "Age" : "153814",
"Content-Type" : "application/json"
},
"Exception" : null
From aa142dc4cb3676bcb46c2bd420b03143eabe1b48 Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Wed, 29 Sep 2021 16:03:52 -0700
Subject: [PATCH 06/16] Address comments
---
.../modelsrepository/implementation/RepositoryHandler.java | 3 ++-
.../implementation/models/FetchMetadataResult.java | 6 +-----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index 699f0e6e9aad9..d4fc46e26d61b 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -95,7 +95,8 @@ private Flux processAsync(
logger.info(String.format(StatusStrings.PROCESSING_DTMIS, targetDtmi));
- return tryFromExpanded.flatMap( t -> modelFetcher.fetchModelAsync(targetDtmi, repositoryUri, t, context))
+ return tryFromExpanded
+ .flatMap (tryExpanded -> modelFetcher.fetchModelAsync(targetDtmi, repositoryUri, tryExpanded, context))
.map(result -> new IntermediateFetchModelResult(result, currentResults))
.expand(customType -> {
Map results = customType.getMap();
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
index 20bf1638a32c3..34e19a355fc98 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
@@ -18,11 +18,7 @@ public class FetchMetadataResult {
private ModelsRepositoryMetadata definition;
private String path;
- private final ObjectMapper mapper;
-
- public FetchMetadataResult() {
- mapper = new ObjectMapper();
- }
+ private static final ObjectMapper mapper = new ObjectMapper();
/**
* Gets the model repository's metadata definition
From 765354f7f681678378f2618757f160631ca0698c Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Wed, 29 Sep 2021 16:23:18 -0700
Subject: [PATCH 07/16] Lint updates
---
.../modelsrepository/implementation/RepositoryHandler.java | 2 +-
.../implementation/models/FetchMetadataResult.java | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index d4fc46e26d61b..43aaa69295357 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -96,7 +96,7 @@ private Flux processAsync(
logger.info(String.format(StatusStrings.PROCESSING_DTMIS, targetDtmi));
return tryFromExpanded
- .flatMap (tryExpanded -> modelFetcher.fetchModelAsync(targetDtmi, repositoryUri, tryExpanded, context))
+ .flatMap(tryExpanded -> modelFetcher.fetchModelAsync(targetDtmi, repositoryUri, tryExpanded, context))
.map(result -> new IntermediateFetchModelResult(result, currentResults))
.expand(customType -> {
Map results = customType.getMap();
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
index 34e19a355fc98..cb88c8c679416 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java
@@ -18,7 +18,7 @@ public class FetchMetadataResult {
private ModelsRepositoryMetadata definition;
private String path;
- private static final ObjectMapper mapper = new ObjectMapper();
+ private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* Gets the model repository's metadata definition
@@ -36,7 +36,7 @@ public ModelsRepositoryMetadata getDefinition() {
* @return the {@link FetchMetadataResult} object itself
*/
public FetchMetadataResult setDefinition(String definition) throws JsonProcessingException {
- this.definition = mapper.readValue(definition, ModelsRepositoryMetadata.class);
+ this.definition = MAPPER.readValue(definition, ModelsRepositoryMetadata.class);
return this;
}
From 7c97bb051f887168bc8eaf4ea4b3059c273aed8b Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Wed, 29 Sep 2021 19:17:16 -0700
Subject: [PATCH 08/16] Metadata fetch errors are non terminal, update tests
and documentation
---
.../ModelDependencyResolution.java | 2 +-
.../implementation/FileModelFetcher.java | 24 ++++------
.../implementation/HttpModelFetcher.java | 45 +++++++++----------
.../src/samples/README.md | 2 +-
.../iot/core/ModelResolutionSamples.java | 8 ++--
.../modelsrepository/DtmiConventionTests.java | 21 +++++++++
6 files changed, 56 insertions(+), 46 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
index 3110ee8276bd4..af2b54c92113d 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java
@@ -13,7 +13,7 @@ public enum ModelDependencyResolution {
DISABLED,
/**
- * Enable model dependency resolution. The client will parse models and calculate dependencies recursively.
+ * Enable model dependency resolution.
*/
ENABLED,
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index 4e2dbe4376cef..2563c292bfcab 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -83,18 +83,9 @@ public Mono fetchModelAsync(String dtmi, URI repositoryUri, bo
@Override
public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
return Mono.defer(() -> {
- Queue work = new LinkedList<>();
try {
- work.add(getMetadataPath(repositoryUri));
- } catch (MalformedURLException | URISyntaxException e) {
- return Mono.error(new AzureException(e));
- }
-
- String fnfError = "";
- while (work.size() != 0) {
- String tryContentPath = work.poll();
-
+ String tryContentPath = getMetadataPath(repositoryUri);
Path path = Paths.get(new File(tryContentPath).getPath());
logger.info(StatusStrings.FETCHING_METADATA_CONTENT, path);
@@ -106,16 +97,17 @@ public Mono fetchMetadataAsync(URI repositoryUri, Context c
.setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8))
.setPath(tryContentPath));
} catch (IOException e) {
- return Mono.error(new AzureException(e));
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.",
+ path.toString(), e.getMessage()));
+ return null;
}
}
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString()));
-
- fnfError = String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath);
+ return null;
+ } catch (MalformedURLException | URISyntaxException e) {
+ return Mono.error(new AzureException(e));
}
-
- return Mono.error(new AzureException(fnfError));
});
}
@@ -124,7 +116,7 @@ private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) th
.getPath();
}
- private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException {
+ private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException {
return DtmiConventions.getMetadataUri(repositoryUri)
.getPath();
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
index 348fda3c79489..0ae6536450c4f 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
@@ -65,34 +65,31 @@ public Mono fetchModelAsync(String dtmi, URI repositoryUri, bo
@Override
public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
return Mono.defer(() -> {
- Queue work = new LinkedList<>();
try {
- work.add(getMetadataPath(repositoryUri));
- } catch (Exception e) {
- return Mono.error(new AzureException(e));
- }
+ String tryContentPath = getMetadataPath(repositoryUri);
- String tryContentPath = work.poll();
+ logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath);
- logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath);
-
- return evaluatePath(tryContentPath, context)
- .onErrorResume(error -> {
- if (work.size() != 0) {
- return evaluatePath(work.poll(), context);
- } else {
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
- return Mono.error(error);
- }
- })
- .map(s -> {
- try {
- return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
- } catch (JsonProcessingException e) {
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
+ return evaluatePath(tryContentPath, context)
+ .onErrorResume(error -> {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s",
+ tryContentPath, error.getMessage()));
return null;
- }
- });
+ })
+ .map(s -> {
+ try {
+ if (s == null) {
+ return null;
+ }
+ return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
+ } catch (JsonProcessingException e) {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
+ return null;
+ }
+ });
+ } catch (MalformedURLException | URISyntaxException e) {
+ return Mono.error(new AzureException(e));
+ }
});
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
index 4728db6067b6a..33ac8717a2959 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md
@@ -18,7 +18,7 @@ The samples project demonstrates the following:
```java
// When no URI is provided for instantiation, the Azure IoT Models Repository global endpoint
// https://devicemodels.azure.com/ is used and the model dependency resolution
-// configuration is set to DISABLED.
+// configuration is set to ENABLED.
ModelsRepositoryAsyncClient asyncClient = new ModelsRepositoryClientBuilder()
.buildAsyncClient();
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java
index 4a2f8501dc907..e1601bba44a01 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java
@@ -21,7 +21,7 @@ public class ModelResolutionSamples {
public static void clientInitializationSamples() {
// When no URI is provided for instantiation, the Azure IoT Models Repository global endpoint
// https://devicemodels.azure.com/ is used and the model dependency resolution
- // configuration is set to TryFromExpanded.
+ // configuration is set to Enabled.
ModelsRepositoryAsyncClient asyncClient = new ModelsRepositoryClientBuilder()
.buildAsyncClient();
@@ -70,7 +70,7 @@ public static void getModelsFromGlobalRepository() throws InterruptedException {
.buildAsyncClient();
// The output of getModels will include at least the definition for the target dtmi.
- // If the model dependency resolution configuration is not disabled, then models in which the
+ // If the model dependency resolution configuration is enabled, then models in which the
// target dtmi depends on will also be included in the returned Map.
String targetDtmi = "dtmi:com:example:TemperatureController;1";
@@ -92,7 +92,7 @@ public static void getMultipleModelsFromGlobalRepository() throws InterruptedExc
// When given an Iterable of dtmis, the output of getModels() will include at
// least the definitions of each dtmi enumerated in the Iterable.
- // If the model dependency resolution configuration is not disabled, then models in which each
+ // If the model dependency resolution configuration is enabled, then models in which each
// enumerated dtmi depends on will also be included in the returned Map.
Iterable dtmis = Arrays.asList("dtmi:com:example:TemperatureController;1", "dtmi:com:example:azuresphere:sampledevice;1");
@@ -115,7 +115,7 @@ public static void getModelsFromLocalRepository() throws InterruptedException {
.buildAsyncClient();
// The output of getModels will include at least the definition for the target dtmi.
- // If the model dependency resolution configuration is not disabled, then models in which the
+ // If the model dependency resolution configuration is enabled, then models in which the
// target dtmi depends on will also be included in the returned Map.
String targetDtmi = "dtmi:com:example:TemperatureController;1";
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java
index e6a85d3ca2e0f..ddabff67f62c2 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java
@@ -53,6 +53,27 @@ public void getModelUriTests(String repository, String expectedUri) {
Assertions.assertEquals(expectedUri, modelUri.toString());
}
+ @ParameterizedTest
+ @CsvSource({
+ "https://localhost/repository/, https://localhost/repository/metadata.json",
+ "https://localhost/REPOSITORY, https://localhost/REPOSITORY/metadata.json",
+ "file:///path/to/repository/, file:///path/to/repository/metadata.json",
+ "file://path/to/RepoSitory, file://path/to/RepoSitory/metadata.json",
+ "C:/path/to/repository/, C:/path/to/repository/metadata.json",
+ "//server//repository, //server//repository/metadata.json"
+ })
+ public void getMetadataUriTests(String repository, String expectedUri) {
+ URI repositoryUri = TestHelper.convertToUri(repository);
+
+ if (expectedUri == null || expectedUri.isEmpty()) {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> DtmiConventions.getMetadataUri(repositoryUri));
+ return;
+ }
+
+ URI metadataUri = DtmiConventions.getMetadataUri(repositoryUri);
+ Assertions.assertEquals(expectedUri, metadataUri.toString());
+ }
+
@ParameterizedTest
@CsvSource({
"dtmi:com:example:Thermostat;1, true",
From 38dc53e574808c5eca8d2e9f2662c812aa281a51 Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Mon, 4 Oct 2021 00:35:39 -0700
Subject: [PATCH 09/16] Add more tests
---
.../iot/modelsrepository/DtmiConventions.java | 4 +-
.../implementation/FileModelFetcher.java | 4 +-
.../implementation/HttpModelFetcher.java | 5 +-
.../ModelRepositoryIntegrationTests.java | 14 +-
.../iot/modelsrepository/TestHelper.java | 8 +-
.../resources/TestModelRepo/metadata.json | 10 -
.../devicemanagement/deviceinformation-1.json | 64 ++++++
.../devicemanagement/deviceinformation-2.json | 16 ++
.../dtmi/com/example/base-1.json | 56 +++++
.../dtmi/com/example/base-2.json | 57 +++++
.../dtmi/com/example/building-1.json | 19 ++
.../dtmi/com/example/camera-3.json | 13 ++
.../dtmi/com/example/coldstorage-1.json | 13 ++
.../dtmi/com/example/conferenceroom-1.json | 13 ++
.../example/danglingexpanded-1.expanded.json | 215 ++++++++++++++++++
.../dtmi/com/example/freezer-1.json | 12 +
.../incompleteexpanded-1.expanded.json | 151 ++++++++++++
.../dtmi/com/example/invalidmodel-1.json | 13 ++
.../dtmi/com/example/invalidmodel-2.json | 23 ++
.../dtmi/com/example/phone-2.json | 23 ++
.../dtmi/com/example/room-1.json | 12 +
.../temperaturecontroller-1.expanded.json | 215 ++++++++++++++++++
.../com/example/temperaturecontroller-1.json | 60 +++++
.../dtmi/com/example/thermostat-1.json | 19 ++
.../dtmi/company/demodevice-1.json | 31 +++
.../dtmi/company/demodevice-2.json | 31 +++
.../dtmi/strict/badfilepath-1.json | 12 +
.../dtmi/strict/emptyarray-1.json | 1 +
.../dtmi/strict/namespaceconflict-1.json | 37 +++
.../dtmi/strict/nondtdl-1.json | 1 +
.../dtmi/strict/unsupportedrootarray-1.json | 91 ++++++++
.../metadataModelsrepo}/metadata.json | 0
32 files changed, 1219 insertions(+), 24 deletions(-)
delete mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadata.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json
rename sdk/modelsrepository/azure-iot-modelsrepository/src/{samples/resources/TestModelRepo => test/resources/TestModelRepo/metadataModelsrepo}/metadata.json (100%)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
index 556a4674f594e..10522b74b5bcf 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
@@ -41,8 +41,8 @@ public static boolean isValidDtmi(String dtmi) {
if (dtmi == null || dtmi.isEmpty()) {
return false;
}
-
- return VALID_DTMI_PATTERN.matcher(dtmi).matches();
+ return true;
+ // return VALID_DTMI_PATTERN.matcher(dtmi).matches();
}
/**
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index 2563c292bfcab..e7f9c8f889a51 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -99,12 +99,12 @@ public Mono fetchMetadataAsync(URI repositoryUri, Context c
} catch (IOException e) {
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.",
path.toString(), e.getMessage()));
- return null;
+ return Mono.empty();
}
}
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString()));
- return null;
+ return Mono.empty();
} catch (MalformedURLException | URISyntaxException e) {
return Mono.error(new AzureException(e));
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
index 0ae6536450c4f..667c953a0d8f5 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
@@ -74,13 +74,10 @@ public Mono fetchMetadataAsync(URI repositoryUri, Context c
.onErrorResume(error -> {
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s",
tryContentPath, error.getMessage()));
- return null;
+ return Mono.empty();
})
.map(s -> {
try {
- if (s == null) {
- return null;
- }
return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
} catch (JsonProcessingException e) {
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
index 7d7ab8e98fb9b..714ea1ae3f2f2 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
@@ -22,13 +22,19 @@ class ModelRepositoryIntegrationTests extends ModelsRepositoryTestBase {
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.iot.modelsrepository.TestHelper#getTestParameters")
public void getModelsSingleDtmiNoDependencies(HttpClient httpClient, ModelsRepositoryServiceVersion serviceVersion, String repositoryUri) throws URISyntaxException {
- final String dtmi = "dtmi:com:example:Thermostat;1";
-
+ String dtmi= "";
+ if (repositoryUri == TestHelper.MODELS_REPOSITORY_NO_METADATA_ENDPOINT) {
+ dtmi = "Azure:iot;plugandplay;models:main:dtmi:com:example:abcThermostat;1";
+ } else {
+ dtmi = "dtmi:com:example:Thermostat;1";
+ }
+
+ final String DTMI = dtmi;
ModelsRepositoryAsyncClient client = getAsyncClient(httpClient, serviceVersion, repositoryUri);
StepVerifier
- .create(client.getModels(dtmi))
- .assertNext(model -> Assertions.assertTrue(model.keySet().size() == 1 && model.containsKey(dtmi)))
+ .create(client.getModels(DTMI))
+ .assertNext(model -> Assertions.assertTrue(model.keySet().size() == 1 && model.containsKey(DTMI)))
.verifyComplete();
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
index 736cf59272970..89729b8221d41 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
@@ -22,7 +22,9 @@
class TestHelper {
public static final String DISPLAY_NAME_WITH_ARGUMENTS = "{displayName} with [{arguments}]";
private static final String AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS = "AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS";
- private static final String LOCAL_TEST_REPOSITORY_PATH = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/").replace("\\", "/");
+ private static final String LOCAL_TEST_REPOSITORY_PATH_WITH_METADATA = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/metadataModelsrepo/").replace("\\", "/");
+ private static final String LOCAL_TEST_REPOSITORY_NO_METADATA_PATH = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/").replace("\\", "/");
+ public static final String MODELS_REPOSITORY_NO_METADATA_ENDPOINT = "https://raw.githubusercontent.com";
private static final String SERVICE_VERSION_FROM_ENV =
Configuration.getGlobalConfiguration().get(AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS);
@@ -51,7 +53,9 @@ static Stream getTestParameters() {
static Stream getApplicableRepositoryUris() {
ArrayList endpointList = new ArrayList<>();
endpointList.add(ModelsRepositoryConstants.DEFAULT_MODELS_REPOSITORY_ENDPOINT);
- endpointList.add(LOCAL_TEST_REPOSITORY_PATH);
+ endpointList.add(LOCAL_TEST_REPOSITORY_PATH_WITH_METADATA);
+ endpointList.add(MODELS_REPOSITORY_NO_METADATA_ENDPOINT);
+ endpointList.add(LOCAL_TEST_REPOSITORY_NO_METADATA_PATH);
return StreamSupport.stream(endpointList.spliterator(), false);
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadata.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadata.json
deleted file mode 100644
index 93e3ed185af74..0000000000000
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadata.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "commitId": "f49444d5deefa369300c7653b5958f9907da550a",
- "features": {
- "expanded": true,
- "index": true
- },
- "publishDateUtc": "2021-09-16T23:01:01.885362+00:00",
- "sourceRepo": "Azure/iot-plugandplay-models",
- "totalModelCount": 19010
-}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json
new file mode 100644
index 0000000000000..8a37e6d2c2c37
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json
@@ -0,0 +1,64 @@
+{
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "@type": "Interface",
+ "displayName": "Device Information",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "manufacturer",
+ "displayName": "Manufacturer",
+ "schema": "string",
+ "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso."
+ },
+ {
+ "@type": "Property",
+ "name": "model",
+ "displayName": "Device model",
+ "schema": "string",
+ "description": "Device model name or ID. Ex. Surface Book 2."
+ },
+ {
+ "@type": "Property",
+ "name": "swVersion",
+ "displayName": "Software version",
+ "schema": "string",
+ "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45"
+ },
+ {
+ "@type": "Property",
+ "name": "osName",
+ "displayName": "Operating system name",
+ "schema": "string",
+ "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core."
+ },
+ {
+ "@type": "Property",
+ "name": "processorArchitecture",
+ "displayName": "Processor architecture",
+ "schema": "string",
+ "description": "Architecture of the processor on the device. Ex. x64 or ARM."
+ },
+ {
+ "@type": "Property",
+ "name": "processorManufacturer",
+ "displayName": "Processor manufacturer",
+ "schema": "string",
+ "description": "Name of the manufacturer of the processor on the device. Ex. Intel."
+ },
+ {
+ "@type": "Property",
+ "name": "totalStorage",
+ "displayName": "Total storage",
+ "schema": "double",
+ "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes."
+ },
+ {
+ "@type": "Property",
+ "name": "totalMemory",
+ "displayName": "Total memory",
+ "schema": "double",
+ "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json
new file mode 100644
index 0000000000000..d35b8a3e3a1d5
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json
@@ -0,0 +1,16 @@
+{
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:azure:DeviceManagement:DeviceInformation;2",
+ "@type": "Interface",
+ "extends": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "displayName": "Device Information",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "osKernelVersion",
+ "displayName": "OS Kernel Version",
+ "schema": "string",
+ "description": "OS Kernel Version. Ex. Linux 4.15.0-54-generic x86_64."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json
new file mode 100644
index 0000000000000..85424e8a229e6
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json
@@ -0,0 +1,56 @@
+{
+ "@id": "dtmi:com:example:base;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "baseSerialNumber",
+ "schema": "string"
+ }
+ ],
+ "displayName": {
+ "en": "mybaseProp"
+ },
+ "extends": [
+ {
+ "@id": "dtmi:com:example:basic;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "schema": "string",
+ "writable": false
+ },
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "displayName": {
+ "en": "temperature"
+ },
+ "name": "temperature",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": "Property",
+ "displayName": {
+ "en": "targetTemperature"
+ },
+ "name": "targetTemperature",
+ "schema": "double",
+ "writable": true
+ }
+ ],
+ "displayName": {
+ "en": "Basic"
+ }
+ }
+ ],
+ "@context": [
+ "dtmi:iotcentral:context;2",
+ "dtmi:dtdl:context;2"
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json
new file mode 100644
index 0000000000000..29accafcc252e
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json
@@ -0,0 +1,57 @@
+{
+ "@id": "dtmi:com:example:base;2",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "baseSerialNumber",
+ "schema": "string"
+ }
+ ],
+ "displayName": {
+ "en": "mybaseProp"
+ },
+ "extends": [
+ {
+ "@id": "dtmi:com:example:basic;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "schema": "string",
+ "writable": false
+ },
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "displayName": {
+ "en": "temperature"
+ },
+ "name": "temperature",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": "Property",
+ "displayName": {
+ "en": "targetTemperature"
+ },
+ "name": "targetTemperature",
+ "schema": "double",
+ "writable": true
+ }
+ ],
+ "displayName": {
+ "en": "Basic"
+ }
+ },
+ "dtmi:com:example:Freezer;1"
+ ],
+ "@context": [
+ "dtmi:iotcentral:context;2",
+ "dtmi:dtdl:context;2"
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json
new file mode 100644
index 0000000000000..c8b6bc6f73756
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json
@@ -0,0 +1,19 @@
+{
+ "@id": "dtmi:com:example:Building;1",
+ "@type": "Interface",
+ "displayName": "Building",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "name",
+ "schema": "string",
+ "writable": true
+ },
+ {
+ "@type": "Relationship",
+ "name": "contains",
+ "target": "dtmi:com:example:Room;1"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json
new file mode 100644
index 0000000000000..f912746c0040d
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json
@@ -0,0 +1,13 @@
+{
+ "@id": "dtmi:com:example:Camera;3",
+ "@type": "Interface",
+ "displayName": "Phone",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json
new file mode 100644
index 0000000000000..a3b8466118a90
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json
@@ -0,0 +1,13 @@
+{
+ "@id": "dtmi:com:example:ColdStorage;1",
+ "@type": "Interface",
+ "extends": ["dtmi:com:example:Room;1", "dtmi:com:example:Freezer;1"],
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "capacity",
+ "schema": "integer"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json
new file mode 100644
index 0000000000000..2e756ee73b6e9
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json
@@ -0,0 +1,13 @@
+{
+ "@id": "dtmi:com:example:ConferenceRoom;1",
+ "@type": "Interface",
+ "extends": "dtmi:com:example:Room;1",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "capacity",
+ "schema": "integer"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json
new file mode 100644
index 0000000000000..93126c749ce9a
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json
@@ -0,0 +1,215 @@
+[
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:DanglingExpanded;1",
+ "@type": "Interface",
+ "displayName": "Valid expanded model with no root model.",
+ "description": "Device with two thermostats and remote reboot.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "DataSize"
+ ],
+ "name": "workingSet",
+ "displayName": "Working Set",
+ "description": "Current working set of the device memory in KiB.",
+ "schema": "double",
+ "unit": "kibibyte"
+ },
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "displayName": "Serial Number",
+ "description": "Serial number of the device.",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "displayName": "Reboot",
+ "description": "Reboots the device after waiting the number of seconds specified.",
+ "request": {
+ "name": "delay",
+ "displayName": "Delay",
+ "description": "Number of seconds to wait before rebooting the device.",
+ "schema": "integer"
+ }
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat1",
+ "displayName": "Thermostat One",
+ "description": "Thermostat One of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat2",
+ "displayName": "Thermostat Two",
+ "description": "Thermostat Two of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "name": "deviceInformation",
+ "displayName": "Device Information interface",
+ "description": "Optional interface with basic device hardware information."
+ }
+ ]
+ },
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:Thermostat;1",
+ "@type": "Interface",
+ "displayName": "Thermostat",
+ "description": "Reports current temperature and provides desired temperature control.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "name": "temperature",
+ "displayName": "Temperature",
+ "description": "Temperature in degrees Celsius.",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "targetTemperature",
+ "schema": "double",
+ "displayName": "Target Temperature",
+ "description": "Allows to remotely specify the desired target temperature.",
+ "unit": "degreeCelsius",
+ "writable": true
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "maxTempSinceLastReboot",
+ "schema": "double",
+ "unit": "degreeCelsius",
+ "displayName": "Max temperature since last reboot.",
+ "description": "Returns the max temperature since last device reboot."
+ },
+ {
+ "@type": "Command",
+ "name": "getMaxMinReport",
+ "displayName": "Get Max-Min report.",
+ "description": "This command returns the max, min and average temperature from the specified time to the current time.",
+ "request": {
+ "name": "since",
+ "displayName": "Since",
+ "description": "Period to return the max-min report.",
+ "schema": "dateTime"
+ },
+ "response": {
+ "name": "tempReport",
+ "displayName": "Temperature Report",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "maxTemp",
+ "displayName": "Max temperature",
+ "schema": "double"
+ },
+ {
+ "name": "minTemp",
+ "displayName": "Min temperature",
+ "schema": "double"
+ },
+ {
+ "name": "avgTemp",
+ "displayName": "Average Temperature",
+ "schema": "double"
+ },
+ {
+ "name": "startTime",
+ "displayName": "Start Time",
+ "schema": "dateTime"
+ },
+ {
+ "name": "endTime",
+ "displayName": "End Time",
+ "schema": "dateTime"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "@type": "Interface",
+ "displayName": "Device Information",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "manufacturer",
+ "displayName": "Manufacturer",
+ "schema": "string",
+ "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso."
+ },
+ {
+ "@type": "Property",
+ "name": "model",
+ "displayName": "Device model",
+ "schema": "string",
+ "description": "Device model name or ID. Ex. Surface Book 2."
+ },
+ {
+ "@type": "Property",
+ "name": "swVersion",
+ "displayName": "Software version",
+ "schema": "string",
+ "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45"
+ },
+ {
+ "@type": "Property",
+ "name": "osName",
+ "displayName": "Operating system name",
+ "schema": "string",
+ "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core."
+ },
+ {
+ "@type": "Property",
+ "name": "processorArchitecture",
+ "displayName": "Processor architecture",
+ "schema": "string",
+ "description": "Architecture of the processor on the device. Ex. x64 or ARM."
+ },
+ {
+ "@type": "Property",
+ "name": "processorManufacturer",
+ "displayName": "Processor manufacturer",
+ "schema": "string",
+ "description": "Name of the manufacturer of the processor on the device. Ex. Intel."
+ },
+ {
+ "@type": "Property",
+ "name": "totalStorage",
+ "displayName": "Total storage",
+ "schema": "double",
+ "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes."
+ },
+ {
+ "@type": "Property",
+ "name": "totalMemory",
+ "displayName": "Total memory",
+ "schema": "double",
+ "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes."
+ }
+ ]
+ }
+]
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json
new file mode 100644
index 0000000000000..6006b66732991
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json
@@ -0,0 +1,12 @@
+{
+ "@id": "dtmi:com:example:Freezer;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:com:example:Thermostat;1"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json
new file mode 100644
index 0000000000000..1688ef4c0e3c5
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json
@@ -0,0 +1,151 @@
+[
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:IncompleteExpanded;1",
+ "@type": "Interface",
+ "displayName": "Incomplete expanded Temperature Controller",
+ "description": "Device with two thermostats and remote reboot.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "DataSize"
+ ],
+ "name": "workingSet",
+ "displayName": "Working Set",
+ "description": "Current working set of the device memory in KiB.",
+ "schema": "double",
+ "unit": "kibibyte"
+ },
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "displayName": "Serial Number",
+ "description": "Serial number of the device.",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "displayName": "Reboot",
+ "description": "Reboots the device after waiting the number of seconds specified.",
+ "request": {
+ "name": "delay",
+ "displayName": "Delay",
+ "description": "Number of seconds to wait before rebooting the device.",
+ "schema": "integer"
+ }
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat1",
+ "displayName": "Thermostat One",
+ "description": "Thermostat One of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat2",
+ "displayName": "Thermostat Two",
+ "description": "Thermostat Two of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "name": "deviceInformation",
+ "displayName": "Device Information interface",
+ "description": "Optional interface with basic device hardware information."
+ }
+ ]
+ },
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:Thermostat;1",
+ "@type": "Interface",
+ "displayName": "Thermostat",
+ "description": "Reports current temperature and provides desired temperature control.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "name": "temperature",
+ "displayName": "Temperature",
+ "description": "Temperature in degrees Celsius.",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "targetTemperature",
+ "schema": "double",
+ "displayName": "Target Temperature",
+ "description": "Allows to remotely specify the desired target temperature.",
+ "unit": "degreeCelsius",
+ "writable": true
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "maxTempSinceLastReboot",
+ "schema": "double",
+ "unit": "degreeCelsius",
+ "displayName": "Max temperature since last reboot.",
+ "description": "Returns the max temperature since last device reboot."
+ },
+ {
+ "@type": "Command",
+ "name": "getMaxMinReport",
+ "displayName": "Get Max-Min report.",
+ "description": "This command returns the max, min and average temperature from the specified time to the current time.",
+ "request": {
+ "name": "since",
+ "displayName": "Since",
+ "description": "Period to return the max-min report.",
+ "schema": "dateTime"
+ },
+ "response": {
+ "name": "tempReport",
+ "displayName": "Temperature Report",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "maxTemp",
+ "displayName": "Max temperature",
+ "schema": "double"
+ },
+ {
+ "name": "minTemp",
+ "displayName": "Min temperature",
+ "schema": "double"
+ },
+ {
+ "name": "avgTemp",
+ "displayName": "Average Temperature",
+ "schema": "double"
+ },
+ {
+ "name": "startTime",
+ "displayName": "Start Time",
+ "schema": "dateTime"
+ },
+ {
+ "name": "endTime",
+ "displayName": "End Time",
+ "schema": "dateTime"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+]
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json
new file mode 100644
index 0000000000000..4f18d7b176584
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json
@@ -0,0 +1,13 @@
+{
+ "@id": "dtmi:com:example:invalidmodel;1",
+ "@type": "Interface",
+ "displayName": "Phone",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:azure:fakeDeviceManagement:FakeDeviceInformation;2"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json
new file mode 100644
index 0000000000000..61443734cd900
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json
@@ -0,0 +1,23 @@
+{
+ "@id": "dtmi:com:example:Phone;2",
+ "@type": "Interfacez",
+ "displayName": "Phone",
+ "contentsz": [
+ {
+ "@type": "Component",
+ "name": "frontCamera",
+ "schema": "dtmi:com:example:Camera;3"
+ },
+ {
+ "@type": "Component",
+ "name": "backCamera",
+ "schema": "dtmi:com:example:Camera;3"
+ },
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:azure:deviceManagement:DeviceInformation;2"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json
new file mode 100644
index 0000000000000..26c7efbdedc01
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json
@@ -0,0 +1,23 @@
+{
+ "@id": "dtmi:com:example:Phone;2",
+ "@type": "Interface",
+ "displayName": "Phone",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "frontCamera",
+ "schema": "dtmi:com:example:Camera;3"
+ },
+ {
+ "@type": "Component",
+ "name": "backCamera",
+ "schema": "dtmi:com:example:Camera;3"
+ },
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;2"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json
new file mode 100644
index 0000000000000..1a07edec4d984
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json
@@ -0,0 +1,12 @@
+{
+ "@id": "dtmi:com:example:Room;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "occupied",
+ "schema": "boolean"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json
new file mode 100644
index 0000000000000..14e8e294189e3
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json
@@ -0,0 +1,215 @@
+[
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:TemperatureController;1",
+ "@type": "Interface",
+ "displayName": "Temperature Controller",
+ "description": "Device with two thermostats and remote reboot.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "DataSize"
+ ],
+ "name": "workingSet",
+ "displayName": "Working Set",
+ "description": "Current working set of the device memory in KiB.",
+ "schema": "double",
+ "unit": "kibibyte"
+ },
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "displayName": "Serial Number",
+ "description": "Serial number of the device.",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "displayName": "Reboot",
+ "description": "Reboots the device after waiting the number of seconds specified.",
+ "request": {
+ "name": "delay",
+ "displayName": "Delay",
+ "description": "Number of seconds to wait before rebooting the device.",
+ "schema": "integer"
+ }
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat1",
+ "displayName": "Thermostat One",
+ "description": "Thermostat One of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat2",
+ "displayName": "Thermostat Two",
+ "description": "Thermostat Two of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "name": "deviceInformation",
+ "displayName": "Device Information interface",
+ "description": "Optional interface with basic device hardware information."
+ }
+ ]
+ },
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:Thermostat;1",
+ "@type": "Interface",
+ "displayName": "Thermostat",
+ "description": "Reports current temperature and provides desired temperature control.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "name": "temperature",
+ "displayName": "Temperature",
+ "description": "Temperature in degrees Celsius.",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "targetTemperature",
+ "schema": "double",
+ "displayName": "Target Temperature",
+ "description": "Allows to remotely specify the desired target temperature.",
+ "unit": "degreeCelsius",
+ "writable": true
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "maxTempSinceLastReboot",
+ "schema": "double",
+ "unit": "degreeCelsius",
+ "displayName": "Max temperature since last reboot.",
+ "description": "Returns the max temperature since last device reboot."
+ },
+ {
+ "@type": "Command",
+ "name": "getMaxMinReport",
+ "displayName": "Get Max-Min report.",
+ "description": "This command returns the max, min and average temperature from the specified time to the current time.",
+ "request": {
+ "name": "since",
+ "displayName": "Since",
+ "description": "Period to return the max-min report.",
+ "schema": "dateTime"
+ },
+ "response": {
+ "name": "tempReport",
+ "displayName": "Temperature Report",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "maxTemp",
+ "displayName": "Max temperature",
+ "schema": "double"
+ },
+ {
+ "name": "minTemp",
+ "displayName": "Min temperature",
+ "schema": "double"
+ },
+ {
+ "name": "avgTemp",
+ "displayName": "Average Temperature",
+ "schema": "double"
+ },
+ {
+ "name": "startTime",
+ "displayName": "Start Time",
+ "schema": "dateTime"
+ },
+ {
+ "name": "endTime",
+ "displayName": "End Time",
+ "schema": "dateTime"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "@type": "Interface",
+ "displayName": "Device Information",
+ "contents": [
+ {
+ "@type": "Property",
+ "name": "manufacturer",
+ "displayName": "Manufacturer",
+ "schema": "string",
+ "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso."
+ },
+ {
+ "@type": "Property",
+ "name": "model",
+ "displayName": "Device model",
+ "schema": "string",
+ "description": "Device model name or ID. Ex. Surface Book 2."
+ },
+ {
+ "@type": "Property",
+ "name": "swVersion",
+ "displayName": "Software version",
+ "schema": "string",
+ "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45"
+ },
+ {
+ "@type": "Property",
+ "name": "osName",
+ "displayName": "Operating system name",
+ "schema": "string",
+ "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core."
+ },
+ {
+ "@type": "Property",
+ "name": "processorArchitecture",
+ "displayName": "Processor architecture",
+ "schema": "string",
+ "description": "Architecture of the processor on the device. Ex. x64 or ARM."
+ },
+ {
+ "@type": "Property",
+ "name": "processorManufacturer",
+ "displayName": "Processor manufacturer",
+ "schema": "string",
+ "description": "Name of the manufacturer of the processor on the device. Ex. Intel."
+ },
+ {
+ "@type": "Property",
+ "name": "totalStorage",
+ "displayName": "Total storage",
+ "schema": "double",
+ "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes."
+ },
+ {
+ "@type": "Property",
+ "name": "totalMemory",
+ "displayName": "Total memory",
+ "schema": "double",
+ "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes."
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json
new file mode 100644
index 0000000000000..c455ddf8bae67
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json
@@ -0,0 +1,60 @@
+{
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:com:example:TemperatureController;1",
+ "@type": "Interface",
+ "displayName": "Temperature Controller",
+ "description": "Device with two thermostats and remote reboot.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "DataSize"
+ ],
+ "name": "workingSet",
+ "displayName": "Working Set",
+ "description": "Current working set of the device memory in KiB.",
+ "schema": "double",
+ "unit": "kibibyte"
+ },
+ {
+ "@type": "Property",
+ "name": "serialNumber",
+ "displayName": "Serial Number",
+ "description": "Serial number of the device.",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "displayName": "Reboot",
+ "description": "Reboots the device after waiting the number of seconds specified.",
+ "request": {
+ "name": "delay",
+ "displayName": "Delay",
+ "description": "Number of seconds to wait before rebooting the device.",
+ "schema": "integer"
+ }
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat1",
+ "displayName": "Thermostat One",
+ "description": "Thermostat One of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:com:example:Thermostat;1",
+ "name": "thermostat2",
+ "displayName": "Thermostat Two",
+ "description": "Thermostat Two of Two."
+ },
+ {
+ "@type": "Component",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
+ "name": "deviceInformation",
+ "displayName": "Device Information interface",
+ "description": "Optional interface with basic device hardware information."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json
new file mode 100644
index 0000000000000..315a307bbcb38
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json
@@ -0,0 +1,19 @@
+{
+ "@id": "dtmi:com:example:Thermostat;1",
+ "@type": "Interface",
+ "displayName": "Thermostat",
+ "contents": [
+ {
+ "@type": "Telemetry",
+ "name": "temp",
+ "schema": "double"
+ },
+ {
+ "@type": "Property",
+ "name": "setPointTemp",
+ "writable": true,
+ "schema": "double"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json
new file mode 100644
index 0000000000000..33c9554664a60
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json
@@ -0,0 +1,31 @@
+{
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:company:demodevice;1",
+ "@type": "Interface",
+ "displayName": "demodevice",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "c1",
+ "schema": "dtmi:azure:deviceManagement:DeviceInformation;1"
+ },
+ {
+ "@type": "Telemetry",
+ "name": "temperature",
+ "schema": "double"
+ },
+ {
+ "@type": "Property",
+ "name": "deviceStatus",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "request": {
+ "name": "delay",
+ "schema": "integer"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json
new file mode 100644
index 0000000000000..9d9b3bd2322aa
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json
@@ -0,0 +1,31 @@
+{
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:company:demodevice;1",
+ "@type": "Interface",
+ "displayName": "demodevice",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "c1",
+ "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1"
+ },
+ {
+ "@type": "Telemetry",
+ "name": "temperature",
+ "schema": "double"
+ },
+ {
+ "@type": "Property",
+ "name": "deviceStatus",
+ "schema": "string"
+ },
+ {
+ "@type": "Command",
+ "name": "reboot",
+ "request": {
+ "name": "delay",
+ "schema": "integer"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json
new file mode 100644
index 0000000000000..6006b66732991
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json
@@ -0,0 +1,12 @@
+{
+ "@id": "dtmi:com:example:Freezer;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Component",
+ "name": "deviceInfo",
+ "schema": "dtmi:com:example:Thermostat;1"
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json
new file mode 100644
index 0000000000000..0637a088a01e8
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json
new file mode 100644
index 0000000000000..6f2df812a67fa
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json
@@ -0,0 +1,37 @@
+{
+ "@id": "dtmi:strict:namespaceconflict;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@type": "Telemetry",
+ "name": "accelerometer1",
+ "schema": "dtmi:com:example:acceleration;1"
+ },
+ {
+ "@type": "Telemetry",
+ "name": "accelerometer2",
+ "schema": "dtmi:com:example:acceleration;1"
+ }
+ ],
+ "schemas": [
+ {
+ "@id": "dtmi:com:example:acceleration;1",
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "x",
+ "schema": "double"
+ },
+ {
+ "name": "y",
+ "schema": "double"
+ },
+ {
+ "name": "z",
+ "schema": "double"
+ }
+ ]
+ }
+ ],
+ "@context": "dtmi:dtdl:context;2"
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json
new file mode 100644
index 0000000000000..b25ba2ac3af65
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json
@@ -0,0 +1 @@
+"content"
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json
new file mode 100644
index 0000000000000..1f282307a8c3c
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json
@@ -0,0 +1,91 @@
+[
+ {
+ "@context": "dtmi:dtdl:context;2",
+ "@id": "dtmi:strict:unsupportedrootarray;1",
+ "@type": "Interface",
+ "displayName": "Thermostat",
+ "description": "Reports current temperature and provides desired temperature control.",
+ "contents": [
+ {
+ "@type": [
+ "Telemetry",
+ "Temperature"
+ ],
+ "name": "temperature",
+ "displayName": "Temperature",
+ "description": "Temperature in degrees Celsius.",
+ "schema": "double",
+ "unit": "degreeCelsius"
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "targetTemperature",
+ "schema": "double",
+ "displayName": "Target Temperature",
+ "description": "Allows to remotely specify the desired target temperature.",
+ "unit": "degreeCelsius",
+ "writable": true
+ },
+ {
+ "@type": [
+ "Property",
+ "Temperature"
+ ],
+ "name": "maxTempSinceLastReboot",
+ "schema": "double",
+ "unit": "degreeCelsius",
+ "displayName": "Max temperature since last reboot.",
+ "description": "Returns the max temperature since last device reboot."
+ },
+ {
+ "@type": "Command",
+ "name": "getMaxMinReport",
+ "displayName": "Get Max-Min report.",
+ "description": "This command returns the max, min and average temperature from the specified time to the current time.",
+ "request": {
+ "name": "since",
+ "displayName": "Since",
+ "description": "Period to return the max-min report.",
+ "schema": "dateTime"
+ },
+ "response": {
+ "name": "tempReport",
+ "displayName": "Temperature Report",
+ "schema": {
+ "@type": "Object",
+ "fields": [
+ {
+ "name": "maxTemp",
+ "displayName": "Max temperature",
+ "schema": "double"
+ },
+ {
+ "name": "minTemp",
+ "displayName": "Min temperature",
+ "schema": "double"
+ },
+ {
+ "name": "avgTemp",
+ "displayName": "Average Temperature",
+ "schema": "double"
+ },
+ {
+ "name": "startTime",
+ "displayName": "Start Time",
+ "schema": "dateTime"
+ },
+ {
+ "name": "endTime",
+ "displayName": "End Time",
+ "schema": "dateTime"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/resources/TestModelRepo/metadata.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/metadata.json
similarity index 100%
rename from sdk/modelsrepository/azure-iot-modelsrepository/src/samples/resources/TestModelRepo/metadata.json
rename to sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/metadata.json
From 217ccf36e95ac8f097cb9776c7b8f7aaf02ce461 Mon Sep 17 00:00:00 2001
From: Azad Abbasi
Date: Mon, 4 Oct 2021 17:28:50 -0700
Subject: [PATCH 10/16] Fix recursive function issue.
---
.../azure/iot/modelsrepository/DtmiConventions.java | 4 ++--
.../implementation/RepositoryHandler.java | 13 ++++++++-----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
index 10522b74b5bcf..25a613db8b749 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
@@ -41,8 +41,8 @@ public static boolean isValidDtmi(String dtmi) {
if (dtmi == null || dtmi.isEmpty()) {
return false;
}
- return true;
- // return VALID_DTMI_PATTERN.matcher(dtmi).matches();
+ //return true;
+ return VALID_DTMI_PATTERN.matcher(dtmi).matches();
}
/**
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index 43aaa69295357..d0f04a8aba2cb 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -69,7 +69,7 @@ private Flux processAsync(
return Flux.empty();
}
- String targetDtmi = remainingWork.poll();
+ //String targetDtmi = remainingWork.poll();
Mono tryFromExpanded = Mono.just(false);
// If ModelDependencyResolution.Enabled is requested the client will first attempt to fetch
@@ -93,15 +93,18 @@ private Flux processAsync(
}
}
- logger.info(String.format(StatusStrings.PROCESSING_DTMIS, targetDtmi));
+ logger.info(String.format(StatusStrings.PROCESSING_DTMIS, remainingWork.peek()));
return tryFromExpanded
- .flatMap(tryExpanded -> modelFetcher.fetchModelAsync(targetDtmi, repositoryUri, tryExpanded, context))
+ .flatMap(tryExpanded -> modelFetcher.fetchModelAsync(remainingWork.peek(), repositoryUri, tryExpanded, context))
.map(result -> new IntermediateFetchModelResult(result, currentResults))
- .expand(customType -> {
+ .expandDeep(customType -> {
+ if (remainingWork.isEmpty()) {
+ return Flux.empty();
+ }
Map results = customType.getMap();
FetchModelResult response = customType.getFetchModelResult();
-
+ String targetDtmi = remainingWork.poll();
if (response.isFromExpanded()) {
try {
Map expanded = new ModelsQuery(response.getDefinition()).listToMap();
From 5f57d2b624b3801bfcacf25a96865d80d71040a7 Mon Sep 17 00:00:00 2001
From: Azad Abbasi
Date: Tue, 5 Oct 2021 18:41:41 -0700
Subject: [PATCH 11/16] Fix test issues.
---
.../iot/modelsrepository/DtmiConventions.java | 11 ++++
.../implementation/FileModelFetcher.java | 47 +++++++-------
.../implementation/HttpModelFetcher.java | 44 +++++++------
.../implementation/RepositoryHandler.java | 62 ++++++++++---------
.../ModelRepositoryIntegrationTests.java | 14 ++---
.../iot/modelsrepository/TestHelper.java | 2 +-
6 files changed, 93 insertions(+), 87 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
index 25a613db8b749..02ad3095603da 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java
@@ -74,6 +74,17 @@ public static URI getModelUri(String dtmi, URI repositoryUri, boolean expanded)
}
}
+ public static String getModelPath(String dtmi, boolean expanded) {
+ String dtmiPath = dtmiToPath(dtmi);
+
+ if (expanded) {
+ dtmiPath = dtmiPath.replace(ModelsRepositoryConstants.JSON_EXTENSION,
+ ModelsRepositoryConstants.JSON_EXPANDED_EXTENSION);
+ }
+
+ return dtmiPath;
+ }
+
/**
* Generates the model repository's metadata URI.
*
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index e7f9c8f889a51..b74873dd85099 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -82,33 +82,30 @@ public Mono fetchModelAsync(String dtmi, URI repositoryUri, bo
@Override
public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
- return Mono.defer(() -> {
-
- try {
- String tryContentPath = getMetadataPath(repositoryUri);
- Path path = Paths.get(new File(tryContentPath).getPath());
-
- logger.info(StatusStrings.FETCHING_METADATA_CONTENT, path);
-
- if (Files.exists(path)) {
- try {
- return Mono.just(
- new FetchMetadataResult()
- .setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8))
- .setPath(tryContentPath));
- } catch (IOException e) {
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.",
- path.toString(), e.getMessage()));
- return Mono.empty();
- }
+ try {
+ String tryContentPath = getMetadataPath(repositoryUri);
+ Path path = Paths.get(new File(tryContentPath).getPath());
+
+ logger.info(StatusStrings.FETCHING_METADATA_CONTENT, path);
+
+ if (Files.exists(path)) {
+ try {
+ return Mono.just(
+ new FetchMetadataResult()
+ .setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8))
+ .setPath(tryContentPath));
+ } catch (IOException e) {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.",
+ path.toString(), e.getMessage()));
+ return Mono.empty();
}
-
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString()));
- return Mono.empty();
- } catch (MalformedURLException | URISyntaxException e) {
- return Mono.error(new AzureException(e));
}
- });
+
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString()));
+ return Mono.just(new FetchMetadataResult());
+ } catch (MalformedURLException | URISyntaxException e) {
+ return Mono.error(new AzureException(e));
+ }
}
private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException, MalformedURLException {
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
index 667c953a0d8f5..f5773f3cef9c9 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java
@@ -64,30 +64,28 @@ public Mono fetchModelAsync(String dtmi, URI repositoryUri, bo
@Override
public Mono fetchMetadataAsync(URI repositoryUri, Context context) {
- return Mono.defer(() -> {
- try {
- String tryContentPath = getMetadataPath(repositoryUri);
+ try {
+ String tryContentPath = getMetadataPath(repositoryUri);
- logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath);
+ logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath);
- return evaluatePath(tryContentPath, context)
- .onErrorResume(error -> {
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s",
- tryContentPath, error.getMessage()));
- return Mono.empty();
- })
- .map(s -> {
- try {
- return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
- } catch (JsonProcessingException e) {
- logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
- return null;
- }
- });
- } catch (MalformedURLException | URISyntaxException e) {
- return Mono.error(new AzureException(e));
- }
- });
+ return evaluatePath(tryContentPath, context)
+ .onErrorResume(error -> {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s",
+ tryContentPath, error.getMessage()));
+ return Mono.error(error);
+ })
+ .map(s -> {
+ try {
+ return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s);
+ } catch (JsonProcessingException e) {
+ logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath));
+ return null;
+ }
+ });
+ } catch (MalformedURLException | URISyntaxException e) {
+ return Mono.error(new AzureException(e));
+ }
}
private Mono evaluatePath(String tryContentPath, Context context) {
@@ -101,7 +99,7 @@ private Mono evaluatePath(String tryContentPath, Context context) {
}
private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException {
- return DtmiConventions.getModelUri(dtmi, repositoryUri, expanded).getPath();
+ return DtmiConventions.getModelPath(dtmi, expanded);
}
private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException {
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index d0f04a8aba2cb..df6af51d548be 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -36,8 +36,8 @@ public RepositoryHandler(URI repositoryUri, ModelsRepositoryAPIImpl protocolLaye
if (this.repositoryUri.getScheme() != null
&& this.repositoryUri.getScheme()
- .toLowerCase(Locale.getDefault())
- .startsWith(ModelsRepositoryConstants.HTTP)) {
+ .toLowerCase(Locale.getDefault())
+ .startsWith(ModelsRepositoryConstants.HTTP)) {
this.modelFetcher = new HttpModelFetcher(protocolLayer);
} else {
this.modelFetcher = new FileModelFetcher();
@@ -69,42 +69,23 @@ private Flux processAsync(
return Flux.empty();
}
- //String targetDtmi = remainingWork.poll();
- Mono tryFromExpanded = Mono.just(false);
-
- // If ModelDependencyResolution.Enabled is requested the client will first attempt to fetch
- // metadata.json content from the target repository. The metadata object includes supported features
- // of the repository.
- // If the metadata indicates expanded models are available. The client will try to fetch pre-computed model
- // dependencies using .expanded.json.
- // If the model expanded form does not exist fall back to computing model dependencies just-in-time.
- if (resolutionOption == ModelDependencyResolution.ENABLED) {
- Mono repositoryMetadata = modelFetcher.fetchMetadataAsync(repositoryUri, context);
-
- if (repositoryMetadata != null) {
- tryFromExpanded = repositoryMetadata
- .map(repo -> (
- repo != null && repo.getDefinition() != null
- && repo.getDefinition().getFeatures() != null
- && repo.getDefinition().getFeatures().isExpanded()
- )
- )
- .defaultIfEmpty(false);
- }
- }
-
logger.info(String.format(StatusStrings.PROCESSING_DTMIS, remainingWork.peek()));
- return tryFromExpanded
- .flatMap(tryExpanded -> modelFetcher.fetchModelAsync(remainingWork.peek(), repositoryUri, tryExpanded, context))
+ return isFromExpanded(resolutionOption, context)
+ .flatMap(tryExpanded -> {
+ logger.info("Try from expanded is " + tryExpanded);
+ return modelFetcher.fetchModelAsync(remainingWork.peek(), repositoryUri, tryExpanded, context);
+ })
.map(result -> new IntermediateFetchModelResult(result, currentResults))
.expandDeep(customType -> {
if (remainingWork.isEmpty()) {
return Flux.empty();
}
+
Map results = customType.getMap();
FetchModelResult response = customType.getFetchModelResult();
String targetDtmi = remainingWork.poll();
+
if (response.isFromExpanded()) {
try {
Map expanded = new ModelsQuery(response.getDefinition()).listToMap();
@@ -162,4 +143,29 @@ private Queue prepareWork(Iterable dtmis) {
return modelsToProcess;
}
+
+ private Mono isFromExpanded(ModelDependencyResolution resolutionOption, Context context) {
+ // If ModelDependencyResolution.Enabled is requested the client will first attempt to fetch
+ // metadata.json content from the target repository. The metadata object includes supported features
+ // of the repository.
+ // If the metadata indicates expanded models are available. The client will try to fetch pre-computed model
+ // dependencies using .expanded.json.
+ // If the model expanded form does not exist fall back to computing model dependencies just-in-time.
+ if (resolutionOption == ModelDependencyResolution.ENABLED) {
+ return modelFetcher.fetchMetadataAsync(repositoryUri, context)
+ .onErrorResume(error -> Mono.just(new FetchMetadataResult()))
+ .flatMap(result -> {
+ Boolean tryFromExpanded = false;
+ if (result != null) {
+ logger.error("got me some results: " + result);
+ tryFromExpanded = result != null && result.getDefinition() != null
+ && result.getDefinition().getFeatures() != null
+ && result.getDefinition().getFeatures().isExpanded();
+ }
+ return Mono.just(tryFromExpanded);
+ });
+ }
+
+ return Mono.just(false);
+ }
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
index 714ea1ae3f2f2..613b3c8d32cf4 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java
@@ -22,19 +22,13 @@ class ModelRepositoryIntegrationTests extends ModelsRepositoryTestBase {
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("com.azure.iot.modelsrepository.TestHelper#getTestParameters")
public void getModelsSingleDtmiNoDependencies(HttpClient httpClient, ModelsRepositoryServiceVersion serviceVersion, String repositoryUri) throws URISyntaxException {
- String dtmi= "";
- if (repositoryUri == TestHelper.MODELS_REPOSITORY_NO_METADATA_ENDPOINT) {
- dtmi = "Azure:iot;plugandplay;models:main:dtmi:com:example:abcThermostat;1";
- } else {
- dtmi = "dtmi:com:example:Thermostat;1";
- }
-
- final String DTMI = dtmi;
+ String dtmi = "dtmi:com:example:Thermostat;1";
+
ModelsRepositoryAsyncClient client = getAsyncClient(httpClient, serviceVersion, repositoryUri);
StepVerifier
- .create(client.getModels(DTMI))
- .assertNext(model -> Assertions.assertTrue(model.keySet().size() == 1 && model.containsKey(DTMI)))
+ .create(client.getModels(dtmi))
+ .assertNext(model -> Assertions.assertTrue(model.keySet().size() == 1 && model.containsKey(dtmi)))
.verifyComplete();
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
index 89729b8221d41..03bd3dcf97251 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java
@@ -24,7 +24,7 @@ class TestHelper {
private static final String AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS = "AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS";
private static final String LOCAL_TEST_REPOSITORY_PATH_WITH_METADATA = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/metadataModelsrepo/").replace("\\", "/");
private static final String LOCAL_TEST_REPOSITORY_NO_METADATA_PATH = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/").replace("\\", "/");
- public static final String MODELS_REPOSITORY_NO_METADATA_ENDPOINT = "https://raw.githubusercontent.com";
+ public static final String MODELS_REPOSITORY_NO_METADATA_ENDPOINT = "https://raw.githubusercontent.com/Azure/iot-plugandplay-models/main";
private static final String SERVICE_VERSION_FROM_ENV =
Configuration.getGlobalConfiguration().get(AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS);
From 13f1be784c3b7d1d8af7d4d40e712c8d688dc5c5 Mon Sep 17 00:00:00 2001
From: Azad Abbasi
Date: Wed, 6 Oct 2021 13:22:04 -0700
Subject: [PATCH 12/16] Update recorded tests
---
...nTests.getModelsEnsureNoDuplicates[1].json | 72 ++++----
...nTests.getModelsEnsureNoDuplicates[3].json | 136 ++++++++++++++
...nTests.getModelsEnsureNoDuplicates[4].json | 4 +
...ts.getModelsSingleDtmiDoesNotExist[1].json | 45 ++---
...ts.getModelsSingleDtmiDoesNotExist[3].json | 68 +++++++
...ts.getModelsSingleDtmiDoesNotExist[4].json | 4 +
....getModelsSingleDtmiNoDependencies[1].json | 36 ++--
....getModelsSingleDtmiNoDependencies[3].json | 70 ++++++++
....getModelsSingleDtmiNoDependencies[4].json | 4 +
...etModelsSingleDtmiWithDependencies[1].json | 36 ++--
...etModelsSingleDtmiWithDependencies[3].json | 166 ++++++++++++++++++
...etModelsSingleDtmiWithDependencies[4].json | 4 +
...ithDepsDisableDependencyResolution[1].json | 14 +-
...ithDepsDisableDependencyResolution[3].json | 40 +++++
...ithDepsDisableDependencyResolution[4].json | 4 +
15 files changed, 602 insertions(+), 101 deletions(-)
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json
create mode 100644 sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json
index e60c632ad73fd..91b113ce183c8 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json
@@ -3,8 +3,8 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "7dc7fe26-0ed1-4b3e-a715-eca833f8e803"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "25af01c9-d572-4418-9294-027f46a32981"
},
"Response" : {
"X-Cache" : "HIT",
@@ -12,49 +12,49 @@
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E179)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
- "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Cache-Control" : "max-age=600",
- "Etag" : "\"0x8D983861F20E768\"",
- "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
- "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
- "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
- "Age" : "88",
+ "Etag" : "\"0x8D988F70ADF0EEF\"",
+ "x-ms-error-code" : "ConditionNotMet",
+ "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT",
+ "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000",
+ "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}",
+ "Age" : "15",
"Content-Type" : "application/json"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "ca6f1a0e-34f7-48a0-84b3-e645316a5712"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "c3dde8f2-c996-49a3-87f5-1c9272c9d4c8"
},
"Response" : {
"X-Cache" : "HIT",
"content-length" : "2218",
"x-ms-version" : "2018-03-28",
- "Server" : "ECAcc (sed/E10D)",
+ "Server" : "ECAcc (sed/E16F)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"Last-Modified" : "Wed, 14 Apr 2021 00:08:03 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Content-MD5" : "Vw1WdSQoTBOhmiB9XXUwsw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Etag" : "\"0x8D8FED95F570217\"",
- "x-ms-error-code" : "ConditionNotMet",
- "x-ms-request-id" : "cd64bea0-001e-001e-6b16-b48ab4000000",
+ "x-ms-request-id" : "8f0a7681-b01e-0021-1b52-ba22ba000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]",
- "Age" : "153814",
+ "Age" : "67480",
"Content-Type" : "application/json"
},
"Exception" : null
@@ -62,8 +62,8 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "322d8b05-cd1e-4fd2-af64-0e214771a82e"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "99d53076-3314-4c8c-ac26-f5255a3ce57b"
},
"Response" : {
"X-Cache" : "HIT",
@@ -71,49 +71,49 @@
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E179)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
- "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Cache-Control" : "max-age=600",
- "Etag" : "\"0x8D983861F20E768\"",
- "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
- "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
- "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
- "Age" : "88",
+ "Etag" : "\"0x8D988F70ADF0EEF\"",
+ "x-ms-error-code" : "ConditionNotMet",
+ "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT",
+ "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000",
+ "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}",
+ "Age" : "15",
"Content-Type" : "application/json"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "01b6e25e-dee4-4932-8b41-763658708fee"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "5863f9ee-2fb7-446c-aee2-03167295300f"
},
"Response" : {
"X-Cache" : "HIT",
"content-length" : "2218",
"x-ms-version" : "2018-03-28",
- "Server" : "ECAcc (sed/E10D)",
+ "Server" : "ECAcc (sed/E16F)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"Last-Modified" : "Wed, 14 Apr 2021 00:08:03 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Content-MD5" : "Vw1WdSQoTBOhmiB9XXUwsw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Etag" : "\"0x8D8FED95F570217\"",
- "x-ms-error-code" : "ConditionNotMet",
- "x-ms-request-id" : "cd64bea0-001e-001e-6b16-b48ab4000000",
+ "x-ms-request-id" : "8f0a7681-b01e-0021-1b52-ba22ba000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]",
- "Age" : "153814",
+ "Age" : "67480",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json
new file mode 100644
index 0000000000000..1988688b1b698
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json
@@ -0,0 +1,136 @@
+{
+ "networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "373d3fb2-3224-4231-82b9-88317026322b"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3152",
+ "Date" : "Wed, 06 Oct 2021 20:20:38 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551639.640685,VS0,VE1",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4467-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT",
+ "X-Cache-Hits" : "1",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "d4b04e5c26caad09bfafe6fc4a34fbb2f9bbd722",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "fd2bb724-ce53-4876-82d5-dfa44781e212"
+ },
+ "Response" : {
+ "content-length" : "2212",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "16",
+ "X-Timer" : "S1633551639.657189,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4481-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "956E:278C:249C9:34469:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:38 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"7952e5f1274fe59fa4aa27c6ba55a1aebec0d5b2ac12f5c8124bbfb08eae4eee\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "5df4bd0e445a001660fc9bbc87a07e197269cd3b"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "7d8e24f6-1a2f-497e-a2b4-8476009e83b0"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3152",
+ "Date" : "Wed, 06 Oct 2021 20:20:38 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551639.680088,VS0,VE0",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4476-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT",
+ "X-Cache-Hits" : "3",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "6e6bca3cad481da68ff97ac490b38c49e575b967",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "0d61b93e-98bd-4a7a-9091-d05701c8a0f8"
+ },
+ "Response" : {
+ "content-length" : "2212",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "16",
+ "X-Timer" : "S1633551639.692640,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4479-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "956E:278C:249C9:34469:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:38 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"7952e5f1274fe59fa4aa27c6ba55a1aebec0d5b2ac12f5c8124bbfb08eae4eee\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "fab5c72ec9b38e981c9a9405ccd9db4ef5f0b69e"
+ },
+ "Exception" : null
+ } ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json
new file mode 100644
index 0000000000000..ba5f37f8f8555
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json
@@ -0,0 +1,4 @@
+{
+ "networkCallRecords" : [ ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json
index 90166cf65e312..df0d661c890b7 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json
@@ -3,8 +3,8 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "c9391aad-48fb-4676-adad-18d30bbcd39f"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "ef345dbe-e307-4889-a2f4-5578b581d5f4"
},
"Response" : {
"X-Cache" : "HIT",
@@ -12,29 +12,30 @@
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E179)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
- "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Cache-Control" : "max-age=600",
- "Etag" : "\"0x8D983861F20E768\"",
- "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
- "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
- "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
- "Age" : "88",
+ "Etag" : "\"0x8D988F70ADF0EEF\"",
+ "x-ms-error-code" : "ConditionNotMet",
+ "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT",
+ "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000",
+ "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}",
+ "Age" : "15",
"Content-Type" : "application/json"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostatddd-1.expanded.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "a5a24337-efd8-482e-89cc-630bcfc4358f"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "0d9db165-514f-4943-bc54-253613fa1327"
},
"Response" : {
"content-length" : "321",
@@ -44,21 +45,21 @@
"retry-after" : "0",
"StatusCode" : "404",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:06 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Access-Control-Expose-Headers" : "*",
"Vary" : "Origin",
"x-ms-error-code" : "WebContentNotFound",
- "x-ms-request-id" : "2ef2ac7f-401e-00a2-257c-b508e9000000",
- "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 2ef2ac7f-401e-00a2-257c-b508e9000000
- TimeStamp : 2021-09-29T21:52:07.4957322Z
",
+ "x-ms-request-id" : "c9d3efa3-e01e-00b8-2fef-bab6de000000",
+ "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : c9d3efa3-e01e-00b8-2fef-bab6de000000
- TimeStamp : 2021-10-06T20:20:38.0079901Z
",
"Content-Type" : "text/html"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostatddd-1.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "f12aca18-2bae-41e6-bb41-e72487de135e"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "6a9fbf15-79fe-4873-9013-d457ed632988"
},
"Response" : {
"content-length" : "321",
@@ -68,12 +69,12 @@
"retry-after" : "0",
"StatusCode" : "404",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:06 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Access-Control-Expose-Headers" : "*",
"Vary" : "Origin",
"x-ms-error-code" : "WebContentNotFound",
- "x-ms-request-id" : "5250b7e1-501e-006b-317c-b5ffbe000000",
- "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 5250b7e1-501e-006b-317c-b5ffbe000000
- TimeStamp : 2021-09-29T21:52:07.5558209Z
",
+ "x-ms-request-id" : "93e6433d-b01e-000d-42ef-ba4790000000",
+ "Body" : "WebContentNotFoundThe requested content does not exist.
- HttpStatusCode: 404
- ErrorCode: WebContentNotFound
- RequestId : 93e6433d-b01e-000d-42ef-ba4790000000
- TimeStamp : 2021-10-06T20:20:38.0458965Z
",
"Content-Type" : "text/html"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json
new file mode 100644
index 0000000000000..4971f92c95294
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json
@@ -0,0 +1,68 @@
+{
+ "networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "c1df76ad-7678-4dfb-8ff5-37d956634207"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3151",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.736753,VS0,VE1",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4481-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "8e1f2b87ec661ad60631285a5fe0d96514e365d2",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "fdd06ab2-74ce-4ffd-a880-919642f59d4d"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "14",
+ "Access-Control-Allow-Origin" : "*",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "404",
+ "Source-Age" : "15",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.793259,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Accept-Ranges" : "bytes",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4481-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-XSS-Protection" : "1; mode=block",
+ "X-Cache-Hits" : "1",
+ "Body" : "404: Not Found",
+ "X-Fastly-Request-ID" : "4b3fa9f84ad37624375c7db2b6d442ad910de934",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "7C18:1911:33727:48D74:615E0506"
+ },
+ "Exception" : null
+ } ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json
new file mode 100644
index 0000000000000..ba5f37f8f8555
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json
@@ -0,0 +1,4 @@
+{
+ "networkCallRecords" : [ ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
index f01fab5e51c8a..1dcb383a60c15 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json
@@ -3,8 +3,8 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "95e5e01c-6785-4402-bd80-d06d174a5dee"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "00415d68-70ee-473f-b39d-ee1f248ed207"
},
"Response" : {
"X-Cache" : "HIT",
@@ -12,49 +12,49 @@
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E179)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
- "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Cache-Control" : "max-age=600",
- "Etag" : "\"0x8D983861F20E768\"",
- "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
- "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
- "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
- "Age" : "88",
+ "Etag" : "\"0x8D988F70ADF0EEF\"",
+ "x-ms-error-code" : "ConditionNotMet",
+ "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT",
+ "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000",
+ "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}",
+ "Age" : "15",
"Content-Type" : "application/json"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.expanded.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostat-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "0ff85bcd-037a-44dd-9cbc-6d975ef85407"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "60edc1e3-fa3e-4f82-a6e6-36844278b264"
},
"Response" : {
"X-Cache" : "HIT",
"content-length" : "2651",
"x-ms-version" : "2018-03-28",
- "Server" : "ECAcc (sed/E120)",
+ "Server" : "ECAcc (sed/E132)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Content-MD5" : "pH51cS5+u5tWh2Krmys7qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Etag" : "\"0x8D8FED94ECA13B6\"",
- "x-ms-error-code" : "ConditionNotMet",
- "x-ms-request-id" : "e422263d-601e-005c-3c16-b40fa1000000",
+ "x-ms-request-id" : "2e9bccae-e01e-0000-5a52-ba988b000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n }\n]",
- "Age" : "153814",
+ "Age" : "67407",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json
new file mode 100644
index 0000000000000..3855d02c7d648
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json
@@ -0,0 +1,70 @@
+{
+ "networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "4cf03b8b-a770-42bc-a551-fc3158b12654"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3151",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.737897,VS0,VE1",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4476-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "2d22f0a88716101930a7091385594781d8e367b3",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "10ec23fa-79b5-4622-9fd0-552844bc945f"
+ },
+ "Response" : {
+ "content-length" : "2469",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "15",
+ "X-Timer" : "S1633551638.814445,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4479-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "2c5f259ced15caef70ac53d71618fdfe8db3a8b3"
+ },
+ "Exception" : null
+ } ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json
new file mode 100644
index 0000000000000..ba5f37f8f8555
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json
@@ -0,0 +1,4 @@
+{
+ "networkCallRecords" : [ ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
index ea57f4b8fdca8..1b6744067777d 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json
@@ -3,8 +3,8 @@
"Method" : "GET",
"Uri" : "https://REDACTED.azure.com/%2Fmetadata.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "84d9acca-021e-4282-95c0-eb64b823ae32"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "572a992d-15f7-4a0c-920c-0775171cff1b"
},
"Response" : {
"X-Cache" : "HIT",
@@ -12,49 +12,49 @@
"x-ms-version" : "2018-03-28",
"Server" : "ECAcc (sed/E179)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
- "Last-Modified" : "Wed, 29 Sep 2021 20:17:12 GMT",
+ "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
- "Content-MD5" : "qaVYpz9oxThaeAEdfv7cMg==",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Cache-Control" : "max-age=600",
- "Etag" : "\"0x8D983861F20E768\"",
- "Expires" : "Wed, 29 Sep 2021 22:02:07 GMT",
- "x-ms-request-id" : "e18a4033-501e-003f-387c-b53085000000",
- "Body" : "{\n \"commitId\": \"3651c9d3e80167f9226baacb145d196a1c0ba446\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-09-29T20:00:57.332025+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19018\n}",
- "Age" : "88",
+ "Etag" : "\"0x8D988F70ADF0EEF\"",
+ "x-ms-error-code" : "ConditionNotMet",
+ "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT",
+ "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000",
+ "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}",
+ "Age" : "15",
"Content-Type" : "application/json"
},
"Exception" : null
}, {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.expanded.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.expanded.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "f2fa1841-6f6e-499d-807b-6015ab5d271b"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "761203d7-f656-4862-a5d5-160ef466ea91"
},
"Response" : {
"X-Cache" : "HIT",
"content-length" : "6751",
"x-ms-version" : "2018-03-28",
- "Server" : "ECAcc (sed/E17F)",
+ "Server" : "ECAcc (sed/E17B)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Content-MD5" : "BnZpV2+7Z2t0sxAxOhmBdw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Etag" : "\"0x8D8FED94EBE03D1\"",
- "x-ms-error-code" : "ConditionNotMet",
- "x-ms-request-id" : "461deecb-f01e-004d-0e16-b49481000000",
+ "x-ms-request-id" : "08c2b7cc-301e-0015-4552-baafa3000000",
"Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:TemperatureController;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Temperature Controller\",\n \"description\": \"Device with two thermostats and remote reboot.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"DataSize\"\n ],\n \"name\": \"workingSet\",\n \"displayName\": \"Working Set\",\n \"description\": \"Current working set of the device memory in KiB.\",\n \"schema\": \"double\",\n \"unit\": \"kibibyte\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"serialNumber\",\n \"displayName\": \"Serial Number\",\n \"description\": \"Serial number of the device.\",\n \"schema\": \"string\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"reboot\",\n \"displayName\": \"Reboot\",\n \"description\": \"Reboots the device after waiting the number of seconds specified.\",\n \"request\": {\n \"name\": \"delay\",\n \"displayName\": \"Delay\",\n \"description\": \"Number of seconds to wait before rebooting the device.\",\n \"schema\": \"integer\"\n }\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat1\",\n \"displayName\": \"Thermostat One\",\n \"description\": \"Thermostat One of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat2\",\n \"displayName\": \"Thermostat Two\",\n \"description\": \"Thermostat Two of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"name\": \"deviceInformation\",\n \"displayName\": \"Device Information interface\",\n \"description\": \"Optional interface with basic device hardware information.\"\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]",
- "Age" : "153815",
+ "Age" : "67407",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json
new file mode 100644
index 0000000000000..08020e83e1d2d
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json
@@ -0,0 +1,166 @@
+{
+ "networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "944945f9-28df-45ce-95d9-b9a4e0bb757a"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3151",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.738065,VS0,VE1",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4425-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "753a5ba57fcb35261a05e41c5c3c56376b90d51a",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "afd14528-37d5-43f5-b17e-bb71455ec7a1"
+ },
+ "Response" : {
+ "content-length" : "1762",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "15",
+ "X-Timer" : "S1633551638.790204,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4430-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:TemperatureController;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Temperature Controller\",\n \"description\": \"Device with two thermostats and remote reboot.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"DataSize\"\n ],\n \"name\": \"workingSet\",\n \"displayName\": \"Working Set\",\n \"description\": \"Current working set of the device memory in KiB.\",\n \"schema\": \"double\",\n \"unit\": \"kibibyte\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"serialNumber\",\n \"displayName\": \"Serial Number\",\n \"description\": \"Serial number of the device.\",\n \"schema\": \"string\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"reboot\",\n \"displayName\": \"Reboot\",\n \"description\": \"Reboots the device after waiting the number of seconds specified.\",\n \"request\": {\n \"name\": \"delay\",\n \"displayName\": \"Delay\",\n \"description\": \"Number of seconds to wait before rebooting the device.\",\n \"schema\": \"integer\"\n }\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat1\",\n \"displayName\": \"Thermostat One\",\n \"description\": \"Thermostat One of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat2\",\n \"displayName\": \"Thermostat Two\",\n \"description\": \"Thermostat Two of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"name\": \"deviceInformation\",\n \"displayName\": \"Device Information interface\",\n \"description\": \"Optional interface with basic device hardware information.\"\n }\n ]\n}",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "3088:6400:89E1:16994:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"276d790fcfc6c0c7637965a33d2bf9cea2a8583f385ee2d1c5d16823814b3094\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "fbebc8be9c92c71f316deaf54b7377c57ffa3158"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "63cb65f7-5200-4e35-9a7e-427d41c863dd"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3151",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.806824,VS0,VE0",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4476-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "2",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "5493b55c016061f5c2732324e8a654246408f1e3",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "572b80d5-cff5-49c6-bfb7-7432b1155f1c"
+ },
+ "Response" : {
+ "content-length" : "2469",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "15",
+ "X-Timer" : "S1633551638.827640,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4425-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "c293bc980713d9739478bdfc73afb537758f0ba5"
+ },
+ "Exception" : null
+ }, {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "73b90be1-2ca8-4552-ba51-b5a0ed23d254"
+ },
+ "Response" : {
+ "X-Cache" : "HIT",
+ "content-length" : "117",
+ "Access-Control-Allow-Origin" : "*",
+ "Connection" : "keep-alive",
+ "retry-after" : "0",
+ "StatusCode" : "301",
+ "Source-Age" : "3151",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "X-Timer" : "S1633551638.839463,VS0,VE0",
+ "Accept-Ranges" : "bytes",
+ "X-Served-By" : "cache-sea4430-SEA",
+ "Vary" : "Authorization,Accept-Encoding",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "Body" : "Moved Permanently.\n\n",
+ "X-Fastly-Request-ID" : "c70431723262afd1fdf226a53fe090cb47db2fa8",
+ "Content-Type" : "text/html; charset=utf-8",
+ "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json",
+ "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6"
+ },
+ "Exception" : null
+ } ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json
new file mode 100644
index 0000000000000..ba5f37f8f8555
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json
@@ -0,0 +1,4 @@
+{
+ "networkCallRecords" : [ ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
index bd9a808e3413a..1f05d86e39471 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json
@@ -1,30 +1,30 @@
{
"networkCallRecords" : [ {
"Method" : "GET",
- "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.json",
+ "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostat-1.json",
"Headers" : {
- "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (16.0.1; Windows 10; 10.0)",
- "x-ms-client-request-id" : "9905c36a-b2ab-4747-9660-197dad311446"
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "1430d25e-3dd9-430d-b1b7-7ea24f5fd6a5"
},
"Response" : {
"X-Cache" : "HIT",
"content-length" : "2469",
"x-ms-version" : "2018-03-28",
- "Server" : "ECAcc (sed/E107)",
+ "Server" : "ECAcc (sed/E154)",
"Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS",
"Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Access-Control-Allow-Headers" : "*",
- "Date" : "Wed, 29 Sep 2021 21:52:07 GMT",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
"Content-MD5" : "U0VZgOgpfb6bwvG5UDVZuw==",
"Accept-Ranges" : "bytes",
"Access-Control-Expose-Headers" : "*",
"Etag" : "\"0x8D8FED94ED5FC94\"",
"x-ms-error-code" : "ConditionNotMet",
- "x-ms-request-id" : "22c4d7b0-d01e-0073-1816-b4178d000000",
+ "x-ms-request-id" : "8b667ceb-b01e-00a5-2757-b6d9e7000000",
"Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}",
- "Age" : "153814",
+ "Age" : "505072",
"Content-Type" : "application/json"
},
"Exception" : null
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json
new file mode 100644
index 0000000000000..011ac367502b4
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json
@@ -0,0 +1,40 @@
+{
+ "networkCallRecords" : [ {
+ "Method" : "GET",
+ "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json",
+ "Headers" : {
+ "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)",
+ "x-ms-client-request-id" : "9e54d0ce-4794-472b-bcb3-6f776c62d69c"
+ },
+ "Response" : {
+ "content-length" : "2469",
+ "Access-Control-Allow-Origin" : "*",
+ "retry-after" : "0",
+ "StatusCode" : "200",
+ "Source-Age" : "15",
+ "X-Timer" : "S1633551638.735210,VS0,VE1",
+ "X-Frame-Options" : "deny",
+ "Strict-Transport-Security" : "max-age=31536000",
+ "X-Served-By" : "cache-sea4430-SEA",
+ "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox",
+ "X-XSS-Protection" : "1; mode=block",
+ "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}",
+ "Content-Type" : "text/plain; charset=utf-8",
+ "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6",
+ "X-Cache" : "HIT",
+ "X-Content-Type-Options" : "nosniff",
+ "Connection" : "keep-alive",
+ "Date" : "Wed, 06 Oct 2021 20:20:37 GMT",
+ "Via" : "1.1 varnish",
+ "Accept-Ranges" : "bytes",
+ "Cache-Control" : "max-age=300",
+ "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"",
+ "Vary" : "Authorization,Accept-Encoding,Origin",
+ "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT",
+ "X-Cache-Hits" : "1",
+ "X-Fastly-Request-ID" : "7343f212515edee8dfd161a8a65c274ab6988010"
+ },
+ "Exception" : null
+ } ],
+ "variables" : [ ]
+}
\ No newline at end of file
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json
new file mode 100644
index 0000000000000..ba5f37f8f8555
--- /dev/null
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json
@@ -0,0 +1,4 @@
+{
+ "networkCallRecords" : [ ],
+ "variables" : [ ]
+}
\ No newline at end of file
From 4dc8d23e30384caafe69308f43f4be8bd5bd5e98 Mon Sep 17 00:00:00 2001
From: Avin Agrawal
Date: Thu, 7 Oct 2021 11:53:18 -0700
Subject: [PATCH 13/16] Refactoring and test fix
---
.../implementation/FileModelFetcher.java | 2 +-
.../implementation/RepositoryHandler.java | 142 ++++++++----------
...etModelsSingleDtmiWithDependencies[3].json | 38 ++++-
3 files changed, 98 insertions(+), 84 deletions(-)
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
index b74873dd85099..1361a0413eb43 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java
@@ -97,7 +97,7 @@ public Mono fetchMetadataAsync(URI repositoryUri, Context c
} catch (IOException e) {
logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.",
path.toString(), e.getMessage()));
- return Mono.empty();
+ return Mono.error(new AzureException(e));
}
}
diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
index df6af51d548be..c5f1db25386db 100644
--- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
+++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java
@@ -3,25 +3,26 @@
package com.azure.iot.modelsrepository.implementation;
-import com.azure.core.exception.AzureException;
import com.azure.core.util.Context;
+import com.azure.core.util.CoreUtils;
import com.azure.core.util.logging.ClientLogger;
+import com.azure.core.util.logging.LogLevel;
import com.azure.iot.modelsrepository.DtmiConventions;
import com.azure.iot.modelsrepository.ModelDependencyResolution;
-import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult;
import com.azure.iot.modelsrepository.implementation.models.FetchModelResult;
import com.azure.iot.modelsrepository.implementation.models.ModelMetadata;
+import com.fasterxml.jackson.core.JsonProcessingException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Map;
-import java.util.Queue;
import java.util.List;
-import java.util.LinkedList;
import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
public final class RepositoryHandler {
@@ -50,92 +51,76 @@ public Mono