Переглянути джерело

GitLab pipelines, refactored docker build, fixed filtering observations

Lukas Cerny 4 роки тому
батько
коміт
6dfbb0f036
35 змінених файлів з 727 додано та 115 видалено
  1. 26 0
      .gitlab-ci.yml
  2. 33 0
      Dockerfile
  3. 43 17
      build.gradle
  4. 18 18
      config/config.yaml
  5. 6 2
      connector-app/src/main/java/io/connector/app/Parameters.java
  6. 1 0
      connector-core/src/main/java/io/connector/core/VertxHttpServer.java
  7. 3 1
      connector-core/src/main/java/io/connector/core/config/file/FileConfigurationServiceImpl.java
  8. 5 0
      connector-core/src/main/java/io/connector/test/api/TestType.java
  9. 9 1
      connector-model/src/main/java/io/connector/model/sensorthings/Geometry.java
  10. 6 0
      connector-model/src/main/java/io/connector/model/sensorthings/Params.java
  11. 11 4
      connector-module-afarcloud/src/main/java/io/connector/module/afarcloud/AFCHttpClient.java
  12. 35 21
      connector-module-afarcloud/src/main/java/io/connector/module/afarcloud/gateway/OGCSensorThingsGateway.java
  13. 287 0
      connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsAssertions.java
  14. 80 0
      connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsOfflineIntegrationTest.java
  15. 28 0
      connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsOnlineIntegrationTest.java
  16. 1 0
      connector-module-afarcloud/src/test/resources/afc/getAllSensors.json
  17. 1 0
      connector-module-afarcloud/src/test/resources/afc/getObservationsBySensor.json
  18. 1 0
      connector-module-afarcloud/src/test/resources/afc/getSensor.json
  19. 0 0
      connector-module-afarcloud/src/test/resources/ogc/datastreams.json
  20. 1 0
      connector-module-afarcloud/src/test/resources/ogc/historicalLocations.json
  21. 1 0
      connector-module-afarcloud/src/test/resources/ogc/locations.json
  22. 1 0
      connector-module-afarcloud/src/test/resources/ogc/observationProperty.json
  23. 1 0
      connector-module-afarcloud/src/test/resources/ogc/observations.json
  24. 1 0
      connector-module-afarcloud/src/test/resources/ogc/sensor.json
  25. 1 0
      connector-module-afarcloud/src/test/resources/ogc/things.json
  26. 28 0
      connector-module-senslog1/src/test/java/io/connector/module/senslog1/OGCSensorThingsIntegrationTest.java
  27. 40 0
      docker-compose.yaml
  28. 0 14
      docker/Dockerfile
  29. 0 7
      docker/start.sh
  30. BIN
      gradle/wrapper/gradle-6.5.1-bin.zip
  31. BIN
      gradle/wrapper/gradle-wrapper.jar
  32. 3 3
      gradle/wrapper/gradle-wrapper.properties
  33. 33 20
      gradlew
  34. 21 1
      gradlew.bat
  35. 2 6
      settings.gradle

+ 26 - 0
.gitlab-ci.yml

@@ -0,0 +1,26 @@
+image: docker:20.10.5
+
+services:
+  - docker:20.10.5-dind
+
+before_script:
+  - docker info
+
+stages:
+  - build
+  - test
+
+build:
+  stage: build
+  script:
+    - docker build --target builder .
+
+unitTest:
+  stage: test
+  script:
+    - docker build --target unitTest .
+
+integrationTest:
+  stage: test
+  script:
+    - docker build --target integrationTest .

+ 33 - 0
Dockerfile

@@ -0,0 +1,33 @@
+FROM adoptopenjdk/openjdk11:jdk-11.0.10_9-debian AS builder
+
+ARG config_file
+ARG module
+
+COPY src /app/src
+COPY connector-app /app/connector-app
+COPY connector-core /app/connector-core
+COPY connector-model /app/connector-model
+COPY $module /app/$module
+COPY $config_file /app/config.yaml
+COPY gradle /app/gradle
+COPY build.gradle settings.gradle gradlew /app/
+WORKDIR /app/
+RUN ./gradlew assemble
+
+FROM adoptopenjdk/openjdk11:jdk-11.0.10_9-debian AS unitTest
+COPY . /app/
+WORKDIR /app
+RUN ./gradlew unitTest
+
+FROM adoptopenjdk/openjdk11:jdk-11.0.10_9-debian AS integrationTest
+COPY . /app/
+WORKDIR /app
+RUN ./gradlew integrationTest
+
+FROM adoptopenjdk/openjdk11:jre-11.0.10_9-alpine AS production
+ENV port 8080
+WORKDIR /app
+COPY --from=builder /app/bin/libs /app/bin
+COPY --from=builder /app/config.yaml /app/
+EXPOSE $port
+CMD java -cp "bin/*" io.connector.Main -cf config.yaml -p $port

+ 43 - 17
build.gradle

@@ -13,6 +13,19 @@ dependencies {
     compile project(":connector-app")
 }
 
+// create fat JAR
+jar {
+    manifest {
+        attributes "Main-Class": "$mainClassName"
+    }
+
+    from {
+        configurations.runtimeClasspath.collect {
+            it.isDirectory() ? it : zipTree(it)
+        }
+    }
+}
+
 // setting for all projects
 allprojects {
 
@@ -35,18 +48,28 @@ allprojects {
     dependencies {
         compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.12.0'
         compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.0'
+
+//        compile fileTree(include: ['*.jar'], dir: 'drivers')
+        testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.0-M1'
     }
 
-    // create fat JAR
-    jar {
-        manifest {
-            attributes "Main-Class": "$mainClassName"
+    test {
+        useJUnitPlatform()
+    }
+
+    task unitTest(type: Test) {
+        description = 'Runs JUnit tests.'
+
+        useJUnitPlatform {
+            excludeTags 'integration'
         }
+    }
+
+    task integrationTest(type: Test) {
+        description = 'Runs integration tests.'
 
-        from {
-            configurations.runtimeClasspath.collect {
-                it.isDirectory() ? it : zipTree(it)
-            }
+        useJUnitPlatform {
+            includeTags 'integration'
         }
     }
 }
@@ -80,14 +103,6 @@ project(":connector-model") {
     }
 }
 
-project(":connector-module-senslog1") {
-
-    dependencies {
-        compile group: 'org.jdbi', name: 'jdbi3-core', version: '3.17.0'
-        compile group: 'org.postgresql', name: 'postgresql', version: '42.1.4'
-    }
-}
-
 // settings for all 'connector-module-*'
 configure(moduleNames) {
 
@@ -97,4 +112,15 @@ configure(moduleNames) {
 
         compile group: 'io.vertx', name: 'vertx-core', version: '3.9.1'
     }
-}
+}
+
+
+// settings for each project
+project(":connector-module-senslog1") {
+
+    dependencies {
+        compile group: 'org.jdbi', name: 'jdbi3-core', version: '3.18.0'
+//        compile group: 'org.jdbi', name: 'jdbi3-postgres', version: '3.18.0'
+        compile group: 'org.postgresql', name: 'postgresql', version: '42.2.19'
+    }
+}

+ 18 - 18
config/config.yaml

@@ -1,24 +1,24 @@
 
 
 services:
-  SensLog1:
-    name: "SensLogV1"
-    provider: "io.connector.module.senslog1.SensLog1ModuleProvider"
-
-    user: "<user>"
-    group: "<group>"
-
-    sensorServiceHost:
-      domain: ""
-      path: ""
-
-    dataServiceHost:
-      domain: ""
-      path: ""
-
-    feederServiceHost:
-      domain: ""
-      path: ""
+#  SensLog1:
+#    name: "SensLogV1"
+#    provider: "io.connector.module.senslog1.SensLog1ModuleProvider"
+#
+#    user: "<user>"
+#    group: "<group>"
+#
+#    sensorServiceHost:
+#      domain: ""
+#      path: ""
+#
+#    dataServiceHost:
+#      domain: ""
+#      path: ""
+#
+#    feederServiceHost:
+#      domain: ""
+#      path: ""
 
   AFC:
       retrievalApi:

+ 6 - 2
connector-app/src/main/java/io/connector/app/Parameters.java

@@ -10,6 +10,8 @@ import org.apache.logging.log4j.Logger;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 
 import static io.connector.core.util.StringUtils.isNotBlank;
@@ -51,8 +53,10 @@ final class Parameters {
 
         String configFileName = parameters.getConfigFileName();
         logger.debug("Checking existence of configuration file {}", configFileName);
-        if (isNotBlank(configFileName) && notExists(get(configFileName))) {
-            throw new FileNotFoundException(format("Config file %s does not exist.", configFileName));
+        Path configPath = Paths.get(configFileName);
+        if (isNotBlank(configFileName) && notExists(configPath)) {
+            logger.warn("Actual working dir: " + System.getProperty("user.dir"));
+            throw new FileNotFoundException("Can not find the config file: " + configPath);
         }
 
         logger.info("Parsing input parameters {} were parsed successfully.", Arrays.toString(args));

+ 1 - 0
connector-core/src/main/java/io/connector/core/VertxHttpServer.java

@@ -101,6 +101,7 @@ public class VertxHttpServer extends AbstractVerticle {
         router.get(create(domainPrefix, INFO)).handler(ctx -> {
             List<Future> futures = new ArrayList<>(modules.size());
             for (Module module : modules) {
+                if (!(module instanceof AbstractModule)) continue;
                 final Promise<ModuleInfo> promise = Promise.promise();
                 eventBus.<ModuleInfo>request(create(module.id(), INFO), new JsonObject(), reply -> {
                     if (reply.succeeded()) {

+ 3 - 1
connector-core/src/main/java/io/connector/core/config/file/FileConfigurationServiceImpl.java

@@ -55,7 +55,7 @@ class FileConfigurationServiceImpl  implements FileConfigurationService {
 
         Path filePath = Paths.get(fileName);
         if (Files.notExists(filePath)) {
-            throw new FileNotFoundException(fileName + " does not exist");
+            throw new FileNotFoundException(fileName + " does not exist at the path: " + filePath);
         }
 
         Map<String, Object> properties;
@@ -120,6 +120,8 @@ class FileConfigurationServiceImpl  implements FileConfigurationService {
                     providerClass = Class.forName(providerString);
                 } catch (ClassNotFoundException e) {
                     logger.catching(e);
+                    logger.warn("Skipping creating the module: " + serviceId);
+                    continue;
                 }
 
                 DefaultConfig serviceConfig = new DefaultConfig(serviceId, providerClass);

+ 5 - 0
connector-core/src/main/java/io/connector/test/api/TestType.java

@@ -0,0 +1,5 @@
+package io.connector.test.api;
+
+public final class TestType {
+    public static final String INTEGRATION = "integration";
+}

+ 9 - 1
connector-model/src/main/java/io/connector/model/sensorthings/Geometry.java

@@ -6,6 +6,7 @@ package io.connector.model.sensorthings;
 import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -29,6 +30,13 @@ public class Geometry extends JsonObject {
     }
 
     public List<Double> getCoordinates() {
-        return (List<Double>) getJsonArray("coordinates").getList();
+        List<?> jsonArr = getJsonArray("coordinates").getList();
+        List<Double> result = new ArrayList<>(jsonArr.size());
+        for (Object val : jsonArr) {
+            if (val instanceof Double) {
+                result.add((Double)val);
+            }
+        }
+        return result;
     }
 }

+ 6 - 0
connector-model/src/main/java/io/connector/model/sensorthings/Params.java

@@ -0,0 +1,6 @@
+package io.connector.model.sensorthings;
+
+public final class Params {
+
+    public static final String FILTER = "$filter";
+}

+ 11 - 4
connector-module-afarcloud/src/main/java/io/connector/module/afarcloud/AFCHttpClient.java

@@ -109,14 +109,21 @@ public class AFCHttpClient {
         logger.info("Received a response with a status: {} for the domain {}.", response.getStatus(), host.getDomain());
 
         if (response.isError()) {
-            logger.error("Can not get data from the server {}. Error {} {}",
-                    host.getDomain(), response.getStatus(), response.getBody());
-            throw new RuntimeException(response.getBody());
+            throw logger.throwing(new RuntimeException(String.format(
+                    "Can not get data from the server %s. Error %d %s",
+                    host.getDomain(), response.getStatus(), response.getBody())
+            ));
         }
 
         logger.debug("Parsing body of the response to the class {}.", ResponseOfMeasurement.class);
         ResponseOfMeasurement responseModel = Json.decodeValue(response.getBody(), ResponseOfMeasurement.class);
-        if (responseModel == null || responseModel.results == null || responseModel.results.resources == null) {
+        if (responseModel == null) {
+            throw logger.throwing(new RuntimeException(String.format(
+                    "Received JSON data can not be parsed. Data: %s", response.getBody()
+            )));
+        }
+
+        if (responseModel.results == null || responseModel.results.resources == null) {
             return Collections.emptyList();
         }
         return responseModel.results.resources;

+ 35 - 21
connector-module-afarcloud/src/main/java/io/connector/module/afarcloud/gateway/OGCSensorThingsGateway.java

@@ -11,6 +11,7 @@ import io.connector.model.afarcloud.SensorTelemetry;
 import io.connector.model.sensorthings.*;
 import io.connector.module.afarcloud.AFCHttpClient;
 import io.connector.module.afarcloud.Filter;
+import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -230,7 +231,7 @@ public class OGCSensorThingsGateway extends AbstractGateway {
             ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON);
             RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
             String id = ctx.pathParam("id"); // resourceUrn + observedProperty
-            String filterParam = ctx.request().getParam("filter");
+            String filterParam = ctx.request().getParam(Params.FILTER);
 
             io.connector.model.sensorthings.Filter filter = null;
             try {
@@ -262,16 +263,20 @@ public class OGCSensorThingsGateway extends AbstractGateway {
                 );
             }
 
-            final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
+            if (measurements.isEmpty()) {
+                ctx.response().end(new JsonArray().encode());
+            } else {
+                final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find Datastream with @iot.id \"" + id + "\".");
 
-            Optional<ResourceMeasurement> measurementOpt = ofNullable(measurements.size() == 1 ? measurements.get(0) : null);
-            ResourceMeasurement afcMeasurement = measurementOpt.orElseThrow(exception);
+                Optional<ResourceMeasurement> measurementOpt = ofNullable(measurements.size() == 1 ? measurements.get(0) : null);
+                ResourceMeasurement afcMeasurement = measurementOpt.orElseThrow(exception);
 
-            Optional<SensorTelemetry> telemetryOpt = ofNullable(afcMeasurement.getMeasurements().size() == 1 ? afcMeasurement.getMeasurements().get(0) : null);
-            SensorTelemetry afcTelemetry = telemetryOpt.orElseThrow(exception);
+                Optional<SensorTelemetry> telemetryOpt = ofNullable(afcMeasurement.getMeasurements().size() == 1 ? afcMeasurement.getMeasurements().get(0) : null);
+                SensorTelemetry afcTelemetry = telemetryOpt.orElseThrow(exception);
 
-            List<Observation> ogcObservations = Converter.convertToObservations(afcMeasurement, afcTelemetry, uriComponent);
-            ctx.response().end(encode(ogcObservations));
+                List<Observation> ogcObservations = Converter.convertToObservations(afcMeasurement, afcTelemetry, uriComponent);
+                ctx.response().end(encode(ogcObservations));
+            }
         });
 
         router().get(create("FeaturesOfInterest(:id)")).handler(ctx -> {
@@ -376,7 +381,7 @@ public class OGCSensorThingsGateway extends AbstractGateway {
             ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON);
             RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
             String resourceUrn = ctx.pathParam("id"); // resourceUrn
-            String filterParam = ctx.request().getParam("filter");
+            String filterParam = ctx.request().getParam(Params.FILTER);
 
             io.connector.model.sensorthings.Filter filter = null;
             try {
@@ -404,15 +409,19 @@ public class OGCSensorThingsGateway extends AbstractGateway {
                 );
             }
 
-            final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find HistoricalLocations of the Thing with @iot.id \"" + resourceUrn + "\".");
+            if (afcMeasurements.isEmpty()) {
+                ctx.response().end(new JsonArray().encode());
+            } else {
+                final Supplier<IllegalArgumentException> exception = () -> new IllegalArgumentException("Can not find HistoricalLocations of the Thing with @iot.id \"" + resourceUrn + "\".");
 
-            Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
-            ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
+                Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
+                ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
 
-            AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
+                AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
 
-            List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
-            ctx.response().end(encode(locations));
+                List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
+                ctx.response().end(encode(locations));
+            }
         });
 
         router().get(create("Locations(:id)/HistoricalLocations")).handler(ctx -> {
@@ -420,7 +429,7 @@ public class OGCSensorThingsGateway extends AbstractGateway {
             ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON);
             RequestUriComponent uriComponent = parseUriToComponents(ctx.request());
             String id = ctx.pathParam("id"); // resourceUrn + observedProperty + time
-            String filterParam = ctx.request().getParam("filter");
+            String filterParam = ctx.request().getParam(Params.FILTER);
 
             io.connector.model.sensorthings.Filter filter = null;
             try {
@@ -458,13 +467,18 @@ public class OGCSensorThingsGateway extends AbstractGateway {
                     .entityNames(afcMultiSensor.getResourceId()).measurements(observedProperty)
             );
 
-            Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
-            ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
+            if (afcMeasurements.isEmpty()) {
+                ctx.response().end(new JsonArray().encode());
+            } else {
 
-            AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
+                Optional<ResourceMeasurement> afcMeasurementOpt = ofNullable(afcMeasurements.size() == 1 ? afcMeasurements.get(0) : null);
+                ResourceMeasurement afcMeasurement = afcMeasurementOpt.orElseThrow(exception);
 
-            List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
-            ctx.response().end(encode(locations));
+                AFCLocationList afcLocations = AFCLocationUtils.sort(afcMeasurement);
+
+                List<HistoricalLocation> locations = Converter.convertToHistoricalLocation(afcMultiSensor, afcLocations.getList(), uriComponent);
+                ctx.response().end(encode(locations));
+            }
         });
     }
 

+ 287 - 0
connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsAssertions.java

@@ -0,0 +1,287 @@
+package io.connector.module.afarcloud;
+
+import io.vertx.core.json.JsonArray;
+import io.vertx.core.json.JsonObject;
+
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class OGCSensorThingsAssertions {
+
+    private static JsonObject findSensorAFC(JsonArray afc, Map<String, String> properties) {
+        if (afc.size() == 1) {
+            return afc.getJsonObject(0);
+        } else {
+            for (int i = 0; i < afc.size(); i++) {
+                JsonObject sensor = afc.getJsonObject(i);
+                if (sensor.getString("resourceId").equalsIgnoreCase(properties.get("multiSensorId"))) {
+                    return sensor;
+                }
+            }
+        }
+        return new JsonObject();
+    }
+
+    private static JsonObject findSensorOGC(JsonArray ogc, Map<String, String> properties) {
+        if (ogc.size() == 1) {
+            return ogc.getJsonObject(0);
+        } else {
+            for (int i = 0; i < ogc.size(); i++) {
+                JsonObject sensor = ogc.getJsonObject(i);
+                if (sensor.getString("@iot.id").contains(properties.get("multiSensorId"))) {
+                    return sensor;
+                }
+            }
+        }
+        return new JsonObject();
+    }
+
+    private static JsonObject findResourceAFC(JsonArray resourcesAFC, Map<String, String> properties) {
+        for (int i = 0; i < resourcesAFC.size(); i++) {
+            JsonObject resource = resourcesAFC.getJsonObject(i);
+            if (resource.getString("resource").equalsIgnoreCase(properties.get("multiSensorId"))) {
+                return resource;
+            }
+        }
+        return new JsonObject();
+    }
+
+    private static JsonObject findSensorInfoAFC(String observedProperty, JsonArray observationsAFC) {
+        for (int i = 0; i < observationsAFC.size(); i++) {
+            JsonObject observationAFC = observationsAFC.getJsonObject(i);
+            String observedPropertyAFC = observationAFC.getString("observedProperty");
+            if (observedPropertyAFC.equals(observedProperty)) {
+                return observationAFC;
+            }
+        }
+        return new JsonObject();
+    };
+
+    private static JsonObject findMeasurementAFC(String observedProperty, JsonArray measurements) {
+        for (int i = 0; i < measurements.size(); i++) {
+            JsonObject measurement = measurements.getJsonObject(i);
+            if (measurement.getString("measurement").equals(observedProperty)) {
+                return measurement;
+            }
+        }
+        return new JsonObject();
+    };
+
+    public static void assertThings(String jsonAFC, String jsonOGC, Map<String, String> properties) {
+        JsonObject sensorAFC = findSensorAFC(new JsonArray(jsonAFC), properties);
+        JsonObject sensorOGC = findSensorOGC(new JsonArray(jsonOGC), properties);
+
+        assertEquals(sensorAFC.getString("resourceUrn"), sensorOGC.getString("@iot.id"));
+        assertEquals(sensorAFC.getString("resourceType"), sensorOGC.getString("name"));
+        assertEquals(sensorAFC.getString("resourceType"), sensorOGC.getString("description"));
+    }
+    
+    public static void assertSensor(String jsonAFC, String jsonOGC, Map<String, String> properties) {
+        JsonObject sensorAFC = new JsonObject(jsonAFC);
+        JsonObject sensorOGC = new JsonObject(jsonOGC);
+
+        assertEquals(sensorAFC.getString("resourceUrn"), sensorOGC.getString("@iot.id"));
+        assertEquals(sensorAFC.getString("resourceType"), sensorOGC.getString("name"));
+        assertEquals(sensorAFC.getString("resourceType"), sensorOGC.getString("description"));
+
+    }
+
+    public static void assertDataStream(String jsonAFCSensor, String jsonAFCData, String jsonOGC, Map<String, String> properties) {
+
+        JsonObject sensorAFC = new JsonObject(jsonAFCSensor);
+        JsonArray observationsAFC = sensorAFC.getJsonArray("observations");
+
+        JsonObject dataAFC = new JsonObject(jsonAFCData);
+        JsonArray resourcesAFC = dataAFC.getJsonObject("results").getJsonArray("resources");
+
+        JsonObject resourceAFC = findResourceAFC(resourcesAFC, properties);
+        JsonArray measurements = resourceAFC.getJsonArray("measurements");
+
+        JsonArray dataStreamOGC = new JsonArray(jsonOGC);
+
+        String resourceUrnAFC = sensorAFC.getString("resourceUrn");
+        for (int i = 0; i < dataStreamOGC.size(); i++) {
+            JsonObject dataStream = dataStreamOGC.getJsonObject(i);
+            String id = dataStream.getString("@iot.id");
+            String [] idParts = id.split("&");
+            String resourceUrnOGC = idParts[0];
+            String observedPropertyOGC = idParts[1];
+            assertEquals(resourceUrnAFC, resourceUrnOGC);
+
+            JsonObject sensorInfoAFC = findSensorInfoAFC(observedPropertyOGC, observationsAFC);
+            String observedPropertyAFC = sensorInfoAFC.getString("observedProperty");
+            assertEquals(observedPropertyAFC, observedPropertyOGC);
+            assertEquals(observedPropertyAFC, dataStream.getString("name"));
+            assertEquals(observedPropertyAFC, dataStream.getString("description"));
+
+            JsonObject unitOfMeasurementOGC = dataStream.getJsonObject("unitOfMeasurement");
+            assertEquals(observedPropertyAFC, unitOfMeasurementOGC.getString("name"));
+
+            JsonObject measurementAFC = findMeasurementAFC(observedPropertyOGC, measurements);
+            JsonArray afc = measurementAFC.getJsonArray("observations");
+            JsonObject observationAFC = afc.size() == 1 ? afc.getJsonObject(0) : new JsonObject();
+
+            String uomAFC = observationAFC.getString("uom");
+            String definitionOGC = unitOfMeasurementOGC.getString("definition");
+            assertEquals(uomAFC, definitionOGC);
+
+            String observationTypeOGC = dataStream.getString("observationType");
+            assertEquals("http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement", observationTypeOGC);
+
+            JsonObject observedAreaOGC = dataStream.getJsonObject("observedArea");
+            assertEquals("Point", observedAreaOGC.getString("type"));
+            JsonArray coordinatesOGC = observedAreaOGC.getJsonArray("coordinates");
+            Integer latitudeAFC = observationAFC.getInteger("latitude");
+            Integer longitudeAFC = observationAFC.getInteger("longitude");
+            assertEquals(longitudeAFC, coordinatesOGC.getInteger(0));
+            assertEquals(latitudeAFC, coordinatesOGC.getInteger(1));
+
+            String timeAFC = observationAFC.getString("time");
+            String phenomenonTimeOGC = dataStream.getString("phenomenonTime");
+            String [] phTimeParts = phenomenonTimeOGC.split("/");
+            assertEquals("<none>", phTimeParts[0]);
+            assertEquals(timeAFC, phTimeParts[1]);
+
+            String resultTimeOGC = dataStream.getString("resultTime");
+            String [] rsTimeParts = resultTimeOGC.split("/");
+            assertEquals("<none>", rsTimeParts[0]);
+            assertEquals(timeAFC, rsTimeParts[1]);
+        }
+    }
+    
+    public static void assertObservedProperty(String jsonAFCSensor, String jsonAFCData, String jsonOGC, Map<String, String> properties) {
+        JsonObject sensorAFC = new JsonObject(jsonAFCSensor);
+        JsonArray observationsAFC = sensorAFC.getJsonArray("observations");
+
+        JsonObject dataAFC = new JsonObject(jsonAFCData);
+        JsonArray resourcesAFC = dataAFC.getJsonObject("results").getJsonArray("resources");
+
+        JsonObject resourceAFC = findResourceAFC(resourcesAFC, properties);
+        JsonArray measurements = resourceAFC.getJsonArray("measurements");
+
+        JsonObject observedPropertyOGC = new JsonObject(jsonOGC);
+        String idOGC = observedPropertyOGC.getString("@iot.id");
+        String [] idParts = idOGC.split("&");
+        String resourceUrnOGC = idParts[0];
+        String propertyOGC = idParts[1];
+
+        JsonObject sensorInfoAFC = findSensorInfoAFC(propertyOGC, observationsAFC);
+
+        assertEquals(sensorAFC.getString("resourceUrn"), resourceUrnOGC);
+
+        String observedPropertyAFC = sensorInfoAFC.getString("observedProperty");
+        assertEquals(observedPropertyAFC, propertyOGC);
+        assertEquals(observedPropertyAFC, observedPropertyOGC.getString("name"));
+        assertEquals(observedPropertyAFC, observedPropertyOGC.getString("description"));
+
+        JsonObject measurementAFC = findMeasurementAFC(propertyOGC, measurements);
+        JsonArray afc = measurementAFC.getJsonArray("observations");
+        JsonObject observationAFC = afc.size() == 1 ? afc.getJsonObject(0) : new JsonObject();
+        assertEquals(observationAFC.getString("uom"), observedPropertyOGC.getString("definition"));
+    }
+
+    public static void assertObservation(String jsonAFCData, String jsonOGC, Map<String, String> properties) {
+        JsonObject dataAFC = new JsonObject(jsonAFCData);
+        JsonArray resourcesAFC = dataAFC.getJsonObject("results").getJsonArray("resources");
+
+        JsonObject resourceAFC = findResourceAFC(resourcesAFC, properties);
+
+        JsonArray observationsOGC = new JsonArray(jsonOGC);
+        JsonObject observationOGC = observationsOGC.size() == 1 ? observationsOGC.getJsonObject(0) : new JsonObject();
+        String idOGC = observationOGC.getString("@iot.id");
+        String [] idParts = idOGC.split("&");
+        String resourceOGC = idParts[0];
+        String measurementOGC = idParts[1];
+        String timeOGC = idParts[2];
+
+        assertEquals(resourceAFC.getString("resource"), resourceOGC);
+
+        JsonObject measurementAFC = findMeasurementAFC(measurementOGC, resourceAFC.getJsonArray("measurements"));
+        assertEquals(measurementAFC.getString("measurement"), measurementOGC);
+
+        JsonArray observationsAFC = measurementAFC.getJsonArray("observations");
+        JsonObject observationAFC = observationsAFC.size() == 1 ? observationsAFC.getJsonObject(0) : new JsonObject();
+        String timeAFC = observationAFC.getString("time");
+        assertEquals(timeAFC, timeOGC);
+        assertEquals(timeAFC, observationOGC.getString("phenomenonTime"));
+        assertEquals(timeAFC, observationOGC.getString("resultTime"));
+        assertEquals(observationAFC.getDouble("value"), observationOGC.getDouble("result"));
+
+    }
+    
+    public static void assertLocations(String jsonAFCSensor, String jsonAFCData, String jsonOGC, Map<String, String> properties) {
+        JsonObject sensorAFC = new JsonObject(jsonAFCSensor);
+
+        JsonArray locationsOGC = new JsonArray(jsonOGC);
+        JsonObject locationOGC = locationsOGC.size() == 1 ? locationsOGC.getJsonObject(0) : new JsonObject();
+
+        JsonObject dataAFC = new JsonObject(jsonAFCData);
+        JsonArray resourcesAFC = dataAFC.getJsonObject("results").getJsonArray("resources");
+        JsonObject resourceAFC = findResourceAFC(resourcesAFC, properties);
+
+        String idOGC = locationOGC.getString("@iot.id");
+        String [] idParts = idOGC.split("&");
+        String resourceUrnOGC = idParts[0];
+        String observedPropertyOGC = idParts[1];
+        String timeOGC = idParts[2];
+
+        JsonArray observationsAFC = sensorAFC.getJsonArray("observations");
+        JsonObject sensorInfoAFC = findSensorInfoAFC(observedPropertyOGC, observationsAFC);
+
+        assertEquals(sensorAFC.getString("resourceUrn"), resourceUrnOGC);
+        assertEquals(sensorInfoAFC.getString("observedProperty"), observedPropertyOGC);
+        assertEquals(sensorAFC.getString("resourceType"), locationOGC.getString("name"));
+
+        JsonObject geoLocationOGC = locationOGC.getJsonObject("location");
+        assertEquals("Feature", geoLocationOGC.getString("type"));
+
+        JsonObject geometryOGC = geoLocationOGC.getJsonObject("geometry");
+        assertEquals("Point", geometryOGC.getString("type"));
+
+        JsonArray coordinatesOGC = geometryOGC.getJsonArray("coordinates");
+        assertEquals(sensorAFC.getDouble("longitude"), coordinatesOGC.getDouble(0));
+        assertEquals(sensorAFC.getDouble("latitude"), coordinatesOGC.getDouble(1));
+        assertEquals(sensorAFC.getDouble("altitude"), coordinatesOGC.getDouble(2));
+
+        JsonObject measurementAFC = findMeasurementAFC(observedPropertyOGC, resourceAFC.getJsonArray("measurements"));
+        assertEquals(measurementAFC.getString("measurement"), observedPropertyOGC);
+
+        JsonArray observationsDataAFC = measurementAFC.getJsonArray("observations");
+        JsonObject observationDataAFC = observationsDataAFC.size() == 1 ? observationsDataAFC.getJsonObject(0) : new JsonObject();
+        assertEquals(observationDataAFC.getString("time"), timeOGC);
+        assertEquals(observationDataAFC.getString("provider"), locationOGC.getString("description"));
+    }
+
+    public static void assertHistoricalLocation(String jsonAFCSensor, String jsonAFCData, String jsonOGC, Map<String, String> properties) {
+        JsonObject sensorAFC = new JsonObject(jsonAFCSensor);
+
+        JsonArray hisLocsOGC = new JsonArray(jsonOGC);
+        JsonObject hisLocationOGC = hisLocsOGC.size() == 1 ? hisLocsOGC.getJsonObject(0) : new JsonObject();
+
+        JsonObject dataAFC = new JsonObject(jsonAFCData);
+        JsonArray resourcesAFC = dataAFC.getJsonObject("results").getJsonArray("resources");
+        JsonObject resourceAFC = findResourceAFC(resourcesAFC, properties);
+
+        String idOGC = hisLocationOGC.getString("@iot.id");
+        String [] idParts = idOGC.split("&");
+        String resourceUrnOGC = idParts[0];
+        String observedPropertyOGC = idParts[1];
+        String timeOGC = idParts[2];
+
+        JsonArray observationsAFC = sensorAFC.getJsonArray("observations");
+        JsonObject sensorInfoAFC = findSensorInfoAFC(observedPropertyOGC, observationsAFC);
+
+        assertEquals(sensorAFC.getString("resourceUrn"), resourceUrnOGC);
+        assertEquals(sensorInfoAFC.getString("observedProperty"), observedPropertyOGC);
+
+        JsonObject measurementAFC = findMeasurementAFC(observedPropertyOGC, resourceAFC.getJsonArray("measurements"));
+        assertEquals(measurementAFC.getString("measurement"), observedPropertyOGC);
+
+        JsonArray observationsDataAFC = measurementAFC.getJsonArray("observations");
+        JsonObject observationDataAFC = observationsDataAFC.size() == 1 ? observationsDataAFC.getJsonObject(0) : new JsonObject();
+        String timeAFC = observationDataAFC.getString("time");
+        assertEquals(timeAFC, timeOGC);
+        assertEquals(timeAFC, hisLocationOGC.getString("time"));
+    }
+}

+ 80 - 0
connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsOfflineIntegrationTest.java

@@ -0,0 +1,80 @@
+package io.connector.module.afarcloud;
+
+import io.connector.test.api.TestType;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static io.connector.module.afarcloud.OGCSensorThingsAssertions.*;
+import static java.nio.file.Files.readAllBytes;
+import static java.nio.file.Paths.get;
+
+@Tag(TestType.INTEGRATION)
+class OGCSensorThingsOfflineIntegrationTest {
+
+    private static final String RESOURCES_DIR = "src/test/resources";
+
+    private static final Map<String, String> DEFAULT_PROPERTIES;
+
+    static {
+        DEFAULT_PROPERTIES = new HashMap<>();
+
+        DEFAULT_PROPERTIES.put("multiSensorId", "10002222");
+    }
+
+    @Test
+    void things() throws IOException {
+        String jsonAFCAllSensors = new String(readAllBytes(get(RESOURCES_DIR,"afc/getAllSensors.json")));
+        String jsonOGCThings = new String(readAllBytes(get(RESOURCES_DIR,"ogc/things.json")));
+        assertThings(jsonAFCAllSensors, jsonOGCThings, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void sensor() throws IOException {
+        String jsonAFCSensor = new String(readAllBytes(get(RESOURCES_DIR, "afc/getSensor.json")));
+        String jsonOGCDataStream = new String(readAllBytes(get(RESOURCES_DIR,"ogc/sensor.json")));
+        assertSensor(jsonAFCSensor, jsonOGCDataStream, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void dataStreams() throws IOException {
+        String jsonAFCSensor = new String(readAllBytes(get(RESOURCES_DIR, "afc/getSensor.json")));
+        String jsonAFCData = new String(readAllBytes(get(RESOURCES_DIR, "afc/getObservationsBySensor.json")));
+        String jsonOGC = new String(readAllBytes(get(RESOURCES_DIR,"ogc/datastreams.json")));
+        assertDataStream(jsonAFCSensor, jsonAFCData, jsonOGC, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void observationProperty() throws IOException {
+        String jsonAFCSensor = new String(readAllBytes(get(RESOURCES_DIR, "afc/getSensor.json")));
+        String jsonAFCData = new String(readAllBytes(get(RESOURCES_DIR, "afc/getObservationsBySensor.json")));
+        String jsonOGC = new String(readAllBytes(get(RESOURCES_DIR,"ogc/observationProperty.json")));
+        assertObservedProperty(jsonAFCSensor, jsonAFCData, jsonOGC, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void observations() throws IOException {
+        String jsonAFCData = new String(readAllBytes(get(RESOURCES_DIR, "afc/getObservationsBySensor.json")));
+        String jsonOGC = new String(readAllBytes(get(RESOURCES_DIR,"ogc/observations.json")));
+        assertObservation(jsonAFCData, jsonOGC, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void locations() throws IOException {
+        String jsonAFCSensor = new String(readAllBytes(get(RESOURCES_DIR, "afc/getSensor.json")));
+        String jsonAFCData = new String(readAllBytes(get(RESOURCES_DIR, "afc/getObservationsBySensor.json")));
+        String jsonOGC = new String(readAllBytes(get(RESOURCES_DIR,"ogc/locations.json")));
+        assertLocations(jsonAFCSensor, jsonAFCData, jsonOGC, DEFAULT_PROPERTIES);
+    }
+
+    @Test
+    void historicalLocations() throws IOException {
+        String jsonAFCSensor = new String(readAllBytes(get(RESOURCES_DIR, "afc/getSensor.json")));
+        String jsonAFCData = new String(readAllBytes(get(RESOURCES_DIR, "afc/getObservationsBySensor.json")));
+        String jsonOGC = new String(readAllBytes(get(RESOURCES_DIR,"ogc/historicalLocations.json")));
+        assertHistoricalLocation(jsonAFCSensor, jsonAFCData, jsonOGC, DEFAULT_PROPERTIES);
+    }
+}

+ 28 - 0
connector-module-afarcloud/src/test/java/io/connector/module/afarcloud/OGCSensorThingsOnlineIntegrationTest.java

@@ -0,0 +1,28 @@
+package io.connector.module.afarcloud;
+
+import io.connector.test.api.TestType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@Tag(TestType.INTEGRATION)
+class OGCSensorThingsOnlineIntegrationTest {
+
+    @BeforeEach
+    void setUp() {
+
+    }
+
+    @AfterEach
+    void tearDown() {
+
+    }
+
+    @Test
+    void run() {
+        assertEquals("hello_AFC", "hello_AFC");
+    }
+}

+ 1 - 0
connector-module-afarcloud/src/test/resources/afc/getAllSensors.json

@@ -0,0 +1 @@
+[{"resourceId":"10002222","resourceType":"air_sensor","resourceUrn":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222","latitude":50.0382589,"longitude":14.6112164,"altitude":280.0,"preprocessing":false,"pythonScript":"","dataIntegrity":false,"observations":[{"observedProperty":"air_temperature","uom":"http://qudt.org/vocab/unit/DEG_C","min_value":-40.0,"max_value":100.0,"accuracy":0.1},{"observedProperty":"air_humidity","uom":"http://qudt.org/vocab/unit/PERCENT","min_value":0.0,"max_value":150.0,"accuracy":0.01},{"observedProperty":"battery","uom":"http://qudt.org/vocab/unit/V","min_value":0.0,"max_value":10.0,"accuracy":0.01}],"supportedProtocol":"REST","hardwareVersion":"1","softwareVersion":"1.0","firmwareVersion":"Rev.1"}]

+ 1 - 0
connector-module-afarcloud/src/test/resources/afc/getObservationsBySensor.json

@@ -0,0 +1 @@
+{"query":"/getObservationsBySensor/latest","params":{"limit":"1"},"numResults":26,"results":{"resources":[{"resource":"10002222","measurements":[{"measurement":"battery","observations":[{"time":"2020-10-27T14:53:06Z","altitude":280.0,"geohash":"u2fksmptfp89","latitude":50.0382589,"longitude":14.6112164,"value":3.359999895095825,"entityName":"10002222","service":"environmentalObservations","provider":"IMA","type":"air_sensor","uom":"http://qudt.org/vocab/unit/V"}]},{"measurement":"air_temperature","observations":[{"time":"2020-10-27T05:06:32Z","altitude":280.0,"geohash":"u2fksmptfp89","latitude":50.0382589,"longitude":14.6112164,"value":9.399999618530273,"entityName":"10002222","service":"environmentalObservations","provider":"IMA","type":"air_sensor","uom":"http://qudt.org/vocab/unit/DEG_C"}]},{"measurement":"air_humidity","observations":[{"time":"2020-10-27T14:53:06Z","altitude":280.0,"geohash":"u2fksmptfp89","latitude":50.0382589,"longitude":14.6112164,"value":78.47000122070312,"entityName":"10002222","service":"environmentalObservations","provider":"IMA","type":"air_sensor","uom":"http://qudt.org/vocab/unit/PERCENT"}]}]}]}}

+ 1 - 0
connector-module-afarcloud/src/test/resources/afc/getSensor.json

@@ -0,0 +1 @@
+{"resourceId":"10002222","resourceType":"air_sensor","resourceUrn":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222","latitude":50.0382589,"longitude":14.6112164,"altitude":280.0,"preprocessing":false,"pythonScript":"","dataIntegrity":false,"observations":[{"observedProperty":"air_temperature","uom":"http://qudt.org/vocab/unit/DEG_C","min_value":-40.0,"max_value":100.0,"accuracy":0.1},{"observedProperty":"air_humidity","uom":"http://qudt.org/vocab/unit/PERCENT","min_value":0.0,"max_value":150.0,"accuracy":0.01},{"observedProperty":"battery","uom":"http://qudt.org/vocab/unit/V","min_value":0.0,"max_value":10.0,"accuracy":0.01}],"supportedProtocol":"REST","hardwareVersion":"1","softwareVersion":"1.0","firmwareVersion":"Rev.1"}

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
connector-module-afarcloud/src/test/resources/ogc/datastreams.json


+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/historicalLocations.json

@@ -0,0 +1 @@
+[{"@iot.id":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/HistoricalLocations(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z)","Locations@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/HistoricalLocations(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z)/Locations","Thing@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/HistoricalLocations(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z)/Thing","time":"2020-10-27T05:06:32Z"}]

+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/locations.json

@@ -0,0 +1 @@
+[{"@iot.id":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Locations(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z)","HistoricalLocations@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Locations(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature&2020-10-27T05:06:32Z)/HistoricalLocations","name":"air_sensor","description":"IMA","encodingType":"application/vnd.geo+json","location":{"type":"Feature","geometry":{"type":"Point","coordinates":[14.6112164,50.0382589,280.0]}}}]

+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/observationProperty.json

@@ -0,0 +1 @@
+{"@iot.id":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/ObservedProperties(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature)","Datastreams@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/ObservedProperties(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222&air_temperature)/Datastream","name":"air_temperature","description":"air_temperature","definition":"http://qudt.org/vocab/unit/DEG_C"}

+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/observations.json

@@ -0,0 +1 @@
+[{"@iot.id":"10002222&air_temperature&2020-10-27T05:06:32Z","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Observations(10002222&air_temperature&2020-10-27T05:06:32Z)","FeatureOfInterest@iot.navigationLink":"https://storage07-afarcloud.qa.pdmfc.com/storage/rest/registry/getAllObservationTypes","Datastreams@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Observations(10002222&air_temperature&2020-10-27T05:06:32Z)/Datastream","phenomenonTime":"2020-10-27T05:06:32Z","resultTime":"2020-10-27T05:06:32Z","result":9.399999618530273}]

+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/sensor.json

@@ -0,0 +1 @@
+{"@iot.id":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Sensors(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)","Datastreams@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Sensors(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)/Datastreams","name":"air_sensor","description":"air_sensor","encodingType":"application/json","metadata":"https://storage07-afarcloud.qa.pdmfc.com/storage/rest/registry/getSensor/10002222"}

+ 1 - 0
connector-module-afarcloud/src/test/resources/ogc/things.json

@@ -0,0 +1 @@
+[{"@iot.id":"urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222","@iot.selfLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Things(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)","Locations@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Things(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)/Locations","Datastreams@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Things(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)/Datastreams","HistoricalLocations@iot.navigationLink":"http://127.0.0.1:8080/api/AFarCloud/OGCSensorThings/Things(urn:afc:AS07:environmentalObservations:IMA:air_sensor:10002222)/HistoricalLocations","name":"air_sensor","description":"air_sensor"}]

+ 28 - 0
connector-module-senslog1/src/test/java/io/connector/module/senslog1/OGCSensorThingsIntegrationTest.java

@@ -0,0 +1,28 @@
+package io.connector.module.senslog1;
+
+import io.connector.test.api.TestType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@Tag(TestType.INTEGRATION)
+class OGCSensorThingsIntegrationTest {
+
+    @BeforeEach
+    void setUp() {
+
+    }
+
+    @AfterEach
+    void tearDown() {
+
+    }
+
+    @Test
+    void run() {
+        assertEquals("hello_senslog", "hello_senslog");
+    }
+}

+ 40 - 0
docker-compose.yaml

@@ -0,0 +1,40 @@
+version: "3.9"
+
+services:
+
+  afc:
+    container_name: connector_ogc2afc
+    image: connector/ogc2afc
+    build:
+      target: production
+      context: .
+      args:
+        config_file: config/config.yaml
+        module: connector-module-afarcloud
+    ports:
+      - "8080:8080"
+    restart: always
+
+#  senslog1:
+#    container_name: senslog_connector
+#    build:
+#      target: production
+#      context: .
+#      args:
+#        config_file: config/config.yaml
+#        module: connector-module-senslog1
+#    ports:
+#      - "80:8080"
+#    restart: always
+#
+#  ima:
+#    container_name: ima_connector
+#    build:
+#      target: production
+#      context: .
+#      args:
+#        config_file: config/config.yaml
+#        module: connector-module-ima
+#    ports:
+#      - "80:8080"
+#    restart: always

+ 0 - 14
docker/Dockerfile

@@ -1,14 +0,0 @@
-FROM java:8-alpine
-
-ARG config_file
-ARG port
-
-ENV APP_PARAMS "-cf config/$config_file -p $port"
-
-COPY docker/start.sh /app/
-COPY bin/libs/ /app/bin
-COPY config/$config_file /app/config/$config_file
-
-WORKDIR /app
-
-ENTRYPOINT ["/bin/sh", "-C", "start.sh"]

+ 0 - 7
docker/start.sh

@@ -1,7 +0,0 @@
-#!/bin/sh
-
-BUILD_FOLDER="bin"
-MAIN_CLASS="io.connector.Main"
-LOG_PATH="/var/log/connector-app"
-
-java -cp "$BUILD_FOLDER/*" -DlogPath=$LOG_PATH $MAIN_CLASS $APP_PARAMS

BIN
gradle/wrapper/gradle-6.5.1-bin.zip


BIN
gradle/wrapper/gradle-wrapper.jar


+ 3 - 3
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Tue Jul 07 11:00:55 CEST 2020
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-zipStorePath=wrapper/dists
+#distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
+distributionUrl=gradle-6.5.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists

+ 33 - 20
gradlew

@@ -1,5 +1,21 @@
 #!/usr/bin/env sh
 
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
 ##############################################################################
 ##
 ##  Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
 # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m"'
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
@@ -66,6 +82,7 @@ esac
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
+
 # Determine the Java command to use to start the JVM.
 if [ -n "$JAVA_HOME" ] ; then
     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
 fi
 
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
         else
             eval `echo args$i`="\"$arg\""
         fi
-        i=$((i+1))
+        i=`expr $i + 1`
     done
     case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
     esac
 fi
 
@@ -159,14 +177,9 @@ save () {
     for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
     echo " "
 }
-APP_ARGS=$(save "$@")
+APP_ARGS=`save "$@"`
 
 # Collect all arguments for the java command, following the shell quoting and substitution rules
 eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
 
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
 exec "$JAVACMD" "$@"

+ 21 - 1
gradlew.bat

@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
 @if "%DEBUG%" == "" @echo off
 @rem ##########################################################################
 @rem
@@ -13,8 +29,11 @@ if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
 @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m"
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
 
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
@@ -65,6 +84,7 @@ set CMD_LINE_ARGS=%*
 
 set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 
+
 @rem Execute Gradle
 "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
 

+ 2 - 6
settings.gradle

@@ -1,9 +1,5 @@
 rootProject.name = 'connector'
-include 'connector-core'
-include 'connector-model'
+include 'connector-app', 'connector-core', 'connector-model'
 include 'connector-module-afarcloud'
-include 'connector-module-ima'
-include 'connector-app'
 include 'connector-module-senslog1'
-include 'connector-module-ogc-sensorthings'
-
+include 'connector-module-ima'

Деякі файли не було показано, через те що забагато файлів було змінено