diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7f42602..c4bda6e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -142,7 +142,7 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} - type=raw,value=1.12.17-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} + type=raw,value=1.12.18-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} # build in any case, but push only main and version tag settings @@ -181,7 +181,7 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} - type=raw,value=1.12.17-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} + type=raw,value=1.12.18-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} # build in any case, but push only main and version tag settings @@ -220,7 +220,7 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} - type=raw,value=1.12.17-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} + type=raw,value=1.12.18-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} # build in any case, but push only main and version tag settings @@ -280,6 +280,6 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} - type=raw,value=1.12.17-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} + type=raw,value=1.12.18-SNAPSHOT,enable=${{ github.event.inputs.deploy_docker == 'true' || github.ref == format('refs/heads/{0}', 'main') }} type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} diff --git a/DEPENDENCIES b/DEPENDENCIES index c5ca6413..938e4dab 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -269,7 +269,7 @@ maven/mavencentral/org.glassfish.hk2/hk2-locator/2.6.1, EPL-2.0 OR GPL-2.0-only maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.4, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-utils/2.6.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-utils/3.0.4, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish -maven/mavencentral/org.glassfish.hk2/osgi-resource-locator/1.0.3, CDDL-1.0, approved, CQ10889 +maven/mavencentral/org.glassfish.hk2/osgi-resource-locator/1.0.3, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.jersey.containers/jersey-container-jetty-http/3.1.3, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jersey maven/mavencentral/org.glassfish.jersey.containers/jersey-container-servlet-core/2.40, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jersey maven/mavencentral/org.glassfish.jersey.containers/jersey-container-servlet-core/3.1.3, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jersey @@ -312,9 +312,9 @@ maven/mavencentral/org.junit.platform/junit-platform-commons/1.9.2, EPL-2.0, app maven/mavencentral/org.junit.platform/junit-platform-engine/1.9.2, EPL-2.0, approved, #3128 maven/mavencentral/org.jvnet.mimepull/mimepull/1.9.15, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ21484 maven/mavencentral/org.latencyutils/LatencyUtils/2.0.3, BSD-2-Clause, approved, CQ17408 -maven/mavencentral/org.locationtech.jts/jts-core/1.18.2, BSD-3-Clause AND EPL-1.0, approved, #13160 -maven/mavencentral/org.locationtech.proj4j/proj4j/1.1.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.locationtech.spatial4j/spatial4j/0.8, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.locationtech.jts/jts-core/1.18.2, EPL-2.0, approved, locationtech.jts +maven/mavencentral/org.locationtech.proj4j/proj4j/1.1.1, Apache-2.0, approved, locationtech.proj4j +maven/mavencentral/org.locationtech.spatial4j/spatial4j/0.8, Apache-2.0, approved, locationtech.spatial4j maven/mavencentral/org.lwjgl/lwjgl-lmdb/3.3.3, BSD-3-Clause, approved, #3055 maven/mavencentral/org.lwjgl/lwjgl/3.3.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.mapdb/mapdb/1.0.9, Apache-2.0, approved, CQ8246 diff --git a/README.md b/README.md index 65c81a71..ae65905f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # remoting-agent -![Version: 1.12.17-SNAPSHOT](https://img.shields.io/badge/Version-1.12.17--SNAPSHOT-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.12.17-SNAPSHOT](https://img.shields.io/badge/AppVersion-1.12.17--SNAPSHOT-informational?style=flat-square) +![Version: 1.12.18-SNAPSHOT](https://img.shields.io/badge/Version-1.12.17--SNAPSHOT-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.12.18-SNAPSHOT](https://img.shields.io/badge/AppVersion-1.12.17--SNAPSHOT-informational?style=flat-square) A Helm chart for the Tractus-X Remoting Agent which is a container to Bridge Agent-Enabled Connector and REST APIs. @@ -30,7 +30,7 @@ This chart has no prerequisites. ## TL;DR ```shell $ helm repo add eclipse-tractusx https://eclipse-tractusx.github.io/charts/dev -$ helm install my-release eclipse-tractusx/remoting-agent --version 1.12.17-SNAPSHOT +$ helm install my-release eclipse-tractusx/remoting-agent --version 1.12.18-SNAPSHOT ``` ## Maintainers diff --git a/conforming/README.md b/conforming/README.md index 4afed5e0..46805873 100644 --- a/conforming/README.md +++ b/conforming/README.md @@ -54,15 +54,15 @@ mvn package This will generate -- a [plugin jar](target/original-conforming-agent-1.12.17-SNAPSHOT.jar) containing all necessary components to be dropped into a Jakarta-Compatible Web Server. -- a [standalone jar](target/conforming-agent-1.12.17-SNAPSHOT.jar) including the Jakarta-Reference Implementation (Glassfish). +- a [plugin jar](target/original-conforming-agent-1.12.18-SNAPSHOT.jar) containing all necessary components to be dropped into a Jakarta-Compatible Web Server. +- a [standalone jar](target/conforming-agent-1.12.18-SNAPSHOT.jar) including the Jakarta-Reference Implementation (Glassfish). ### Run Locally -The [standalone jar](target/conforming-agent-1.12.17-SNAPSHOT.jar) may be started as follows +The [standalone jar](target/conforming-agent-1.12.18-SNAPSHOT.jar) may be started as follows ```console -java -cp target/conforming-agent-1.12.17-SNAPSHOT.jar org.eclipse.tractusx.agents.conforming.Bootstrap" +java -cp target/conforming-agent-1.12.18-SNAPSHOT.jar org.eclipse.tractusx.agents.conforming.Bootstrap" ``` ### Containerizing @@ -76,7 +76,7 @@ mvn install -Pwith-docker-image or invoke the following docker command after a successful package run ```console -docker build -t tractusx/conforming-agent:1.12.17-SNAPSHOT -f src/main/docker/Dockerfile . +docker build -t tractusx/conforming-agent:1.12.18-SNAPSHOT -f src/main/docker/Dockerfile . ``` This will create a docker image based on a minimal java environment for running the Glassfish-based standalone jar. @@ -85,7 +85,7 @@ To run the docker image, you could invoke this command ```console docker run -p 8080:8080 \ - tractusx/conforming-agent:1.12.17-SNAPSHOT + tractusx/conforming-agent:1.12.18-SNAPSHOT ```` Afterwards, you should be able to access the [local SparQL endpoint](http://localhost:8080/) via @@ -143,7 +143,7 @@ It can be added to your umbrella chart.yaml by the following snippet dependencies: - name: conforming-agent repository: https://eclipse-tractusx.github.io/charts/dev - version: 1.12.17-SNAPSHOT + version: 1.12.18-SNAPSHOT alias: my-conforming-agent ``` diff --git a/conforming/pom.xml b/conforming/pom.xml index 2864f9df..310eab51 100644 --- a/conforming/pom.xml +++ b/conforming/pom.xml @@ -27,7 +27,7 @@ org.eclipse.tractusx agents - 1.12.17-SNAPSHOT + 1.12.18-SNAPSHOT ../pom.xml diff --git a/matchmaking/README.md b/matchmaking/README.md index 0b5a7f20..11f15707 100644 --- a/matchmaking/README.md +++ b/matchmaking/README.md @@ -66,10 +66,10 @@ This will generate ### Run Locally -The [standalone jar](target/matchmaking-agent-1.12.17-SNAPSHOT.jar) may be started as follows +The [standalone jar](target/matchmaking-agent-1.12.18-SNAPSHOT.jar) may be started as follows ```console -java -Dproperty.file.location="dataplane.properties" -cp ../matchmaking-agent-1.12.17-SNAPSHOT.jar org.eclipse.tractusx.agents.conforming.Bootstrap +java -Dproperty.file.location="dataplane.properties" -cp ../matchmaking-agent-1.12.18-SNAPSHOT.jar org.eclipse.tractusx.agents.conforming.Bootstrap ``` Make sure that jar file, properties file and dataspace.ttl are in the same directory Then you should be able to reach the /graph endpoint @@ -126,7 +126,7 @@ It can be added to your umbrella chart.yaml by the following snippet dependencies: - name: matchmaking-agent repository: https://eclipse-tractusx.github.io/charts/dev - version: 1.12.17-SNAPSHOT + version: 1.12.18-SNAPSHOT alias: my-matchmmaking-agent ``` diff --git a/matchmaking/pom.xml b/matchmaking/pom.xml index 3dbe7bf5..6509d5b3 100644 --- a/matchmaking/pom.xml +++ b/matchmaking/pom.xml @@ -27,7 +27,7 @@ org.eclipse.tractusx agents - 1.12.17-SNAPSHOT + 1.12.18-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 498da771..8a8c2a61 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ 4.0.0 org.eclipse.tractusx agents - 1.12.17-SNAPSHOT + 1.12.18-SNAPSHOT pom Tractus-X Knowledge Agents Reference Implementations Provides Reference Implementations and Artifacts to Realize Semantic Dataspace Backends diff --git a/provisioning/README.md b/provisioning/README.md index 1d6fcd5f..0625dc26 100644 --- a/provisioning/README.md +++ b/provisioning/README.md @@ -111,7 +111,7 @@ mvn package ``` This will generate -- a [pluging jar](target/provisioning-agent-1.12.17-SNAPSHOT.jar) which maybe dropped into an Ontop server (into the lib folder) +- a [pluging jar](target/provisioning-agent-1.12.18-SNAPSHOT.jar) which maybe dropped into an Ontop server (into the lib folder) ### Containerizing (Provisioning Agent) @@ -124,7 +124,7 @@ mvn install -Pwith-docker-image or invoke the following docker command after a successful package run ```console -docker build -t tractusx/provisioning-agent:1.12.17-SNAPSHOT -f src/main/docker/Dockerfile . +docker build -t tractusx/provisioning-agent:1.12.18-SNAPSHOT -f src/main/docker/Dockerfile . ``` The image contains @@ -144,7 +144,7 @@ docker run -p 8080:8080 \ -v $(pwd)/resources/university-role1.obda:/input/mapping.obda \ -v $(pwd)/resources/university-role1.properties:/input/settings.properties \ -v $(pwd)/resources/university.sql:/tmp/university.sql \ - tractusx/provisioning-agent:1.12.17-SNAPSHOT + tractusx/provisioning-agent:1.12.18-SNAPSHOT ```` Afterwards, you should be able to access the [local SparQL endpoint](http://localhost:8080/) via @@ -192,7 +192,7 @@ docker run -p 8080:8080 -p 8082:8082 \ -e ONTOP_MAPPING_FILE="/input/role1.obda /input/role2.obda" \ -e ONTOP_PROPERTIES_FILE="/input/role1.properties /input/role2.properties" \ -e ONTOP_DEV_MODE="false false" \ - tractusx/provisioning-agent:1.12.17-SNAPSHOT + tractusx/provisioning-agent:1.12.18-SNAPSHOT ```` Accessing entities spanning two schemas using the first role/endpoint delivers a greater count @@ -297,7 +297,7 @@ It can be added to your umbrella chart.yaml by the following snippet dependencies: - name: provisioning-agent repository: https://eclipse-tractusx.github.io/charts/dev - version: 1.12.17-SNAPSHOT + version: 1.12.18-SNAPSHOT alias: my-provider-agent ``` diff --git a/provisioning/pom.xml b/provisioning/pom.xml index 8cae1c2e..2c1d3bdd 100644 --- a/provisioning/pom.xml +++ b/provisioning/pom.xml @@ -27,7 +27,7 @@ org.eclipse.tractusx agents - 1.12.17-SNAPSHOT + 1.12.18-SNAPSHOT ../pom.xml diff --git a/remoting/README.md b/remoting/README.md index 3bee0278..2319d882 100644 --- a/remoting/README.md +++ b/remoting/README.md @@ -134,15 +134,15 @@ mvn package ``` This will generate -- a [standalone jar](target/remoting-agent-1.12.17-SNAPSHOT.jar) containing all necessary rdf4j components to build your own repository server. -- a [pluging jar](target/original-remoting-agent-1.12.17-SNAPSHOT.jar) which maybe dropped into an rdf4j server for remoting support. +- a [standalone jar](target/remoting-agent-1.12.18-SNAPSHOT.jar) containing all necessary rdf4j components to build your own repository server. +- a [pluging jar](target/original-remoting-agent-1.12.18-SNAPSHOT.jar) which maybe dropped into an rdf4j server for remoting support. ### Run Locally -The standalone jar](target/remoting-agent-1.12.17-SNAPSHOT.jar) contains an example application that runs a sample repository against a sample source +The standalone jar](target/remoting-agent-1.12.18-SNAPSHOT.jar) contains an example application that runs a sample repository against a sample source ```console -java -jar target/remoting-agent-1.12.17-SNAPSHOT.jar -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG +java -jar target/remoting-agent-1.12.18-SNAPSHOT.jar -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG ``` ### Containerizing @@ -156,7 +156,7 @@ mvn install -Pwith-docker-image or invoke the following docker command after a successful package run ```console -docker build -t tractusx/remoting-agent:1.12.17-SNAPSHOT -f src/main/docker/Dockerfile . +docker build -t tractusx/remoting-agent:1.12.18-SNAPSHOT -f src/main/docker/Dockerfile . ``` This will create a docker image including an extended rdf4j-server as well as an interactive rdf4j-workbench. @@ -166,7 +166,7 @@ To run the docker image, you could invoke this command ```console docker run -p 8081:8081 \ -v $(pwd)/src/test:/var/rdf4j/config \ - tractusx/remoting-agent:1.12.17-SNAPSHOT + tractusx/remoting-agent:1.12.18-SNAPSHOT ```` Afterwards, you should be able to access the [local SparQL endpoint](http://localhost:8081/) via @@ -224,7 +224,7 @@ It can be added to your umbrella chart.yaml by the following snippet dependencies: - name: remoting-agent repository: https://eclipse-tractusx.github.io/charts/dev - version: 1.12.17-SNAPSHOT + version: 1.12.18-SNAPSHOT alias: my-remoting-agent ``` diff --git a/remoting/pom.xml b/remoting/pom.xml index 2dc6f2eb..276eca51 100644 --- a/remoting/pom.xml +++ b/remoting/pom.xml @@ -26,7 +26,7 @@ org.eclipse.tractusx agents - 1.12.17-SNAPSHOT + 1.12.18-SNAPSHOT ../pom.xml diff --git a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/Invocation.java b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/Invocation.java index 1b62e1f1..a9c56ce1 100644 --- a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/Invocation.java +++ b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/Invocation.java @@ -1,4 +1,4 @@ -// Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +// Copyright (c) 2022,2024 Contributors to the Eclipse Foundation // // See the NOTICE file(s) distributed with this work for additional // information regarding copyright ownership. @@ -150,32 +150,40 @@ public Invocation(RemotingSailConnection connection) { * * @param binding value to convert * @param target class to convert to + * @param strip an optional suffix to strip from the result * @return converted value */ - public static TARGET convertToObject(Value binding, Class target) throws SailException { + public static TARGET convertToObject(Value binding, Class target, String strip) throws SailException { + String renderString = binding.stringValue(); + if (strip != null) { + int lastIndex = renderString.lastIndexOf(strip); + if (lastIndex >= 0) { + renderString = renderString.substring(lastIndex + strip.length()); + } + } if (target.isAssignableFrom(String.class)) { - return (TARGET) binding.stringValue(); + return (TARGET) renderString; } else if (target.isAssignableFrom(int.class)) { try { - return (TARGET) Integer.valueOf(Integer.parseInt(binding.stringValue())); + return (TARGET) Integer.valueOf(Integer.parseInt(renderString)); } catch (NumberFormatException nfe) { throw new SailException(String.format("Conversion from %s to %s failed.", binding, target), nfe); } } else if (target.isAssignableFrom(long.class)) { try { - return (TARGET) Long.valueOf(Long.parseLong(binding.stringValue())); + return (TARGET) Long.valueOf(Long.parseLong(renderString)); } catch (NumberFormatException nfe) { throw new SailException(String.format("Conversion from %s to %s failed.", binding, target), nfe); } } else if (target.isAssignableFrom(double.class)) { try { - return (TARGET) Double.valueOf(Double.parseDouble(binding.stringValue())); + return (TARGET) Double.valueOf(Double.parseDouble(renderString)); } catch (NumberFormatException nfe) { throw new SailException(String.format("Conversion from %s to %s failed.", binding, target), nfe); } } else if (target.isAssignableFrom(float.class)) { try { - return (TARGET) Float.valueOf(Float.parseFloat(binding.stringValue())); + return (TARGET) Float.valueOf(Float.parseFloat(renderString)); } catch (NumberFormatException nfe) { throw new SailException(String.format("Conversion from %s to %s failed.", binding, target), nfe); } @@ -185,62 +193,62 @@ public static TARGET convertToObject(Value binding, Class targe String dataTypeName = dataType.stringValue(); switch (dataTypeName) { case "http://www.w3.org/2001/XMLSchema#string": - return (TARGET) objectMapper.getNodeFactory().textNode(binding.stringValue()); + return (TARGET) objectMapper.getNodeFactory().textNode(renderString); case "http://www.w3.org/2001/XMLSchema#int": try { - return (TARGET) objectMapper.getNodeFactory().numberNode(Integer.valueOf(binding.stringValue())); + return (TARGET) objectMapper.getNodeFactory().numberNode(Integer.valueOf(renderString)); } catch (NumberFormatException nfe) { - throw new SailException(String.format("Could not convert %s to datatype %s.", binding.stringValue(), dataTypeName), nfe); + throw new SailException(String.format("Could not convert %s to datatype %s.", renderString, dataTypeName), nfe); } case "http://www.w3.org/2001/XMLSchema#long": try { - return (TARGET) objectMapper.getNodeFactory().numberNode(Long.valueOf(binding.stringValue())); + return (TARGET) objectMapper.getNodeFactory().numberNode(Long.valueOf(renderString)); } catch (NumberFormatException nfe) { - throw new SailException(String.format("Could not convert %s to datatype %s.", binding.stringValue(), dataTypeName), nfe); + throw new SailException(String.format("Could not convert %s to datatype %s.", renderString, dataTypeName), nfe); } case "http://www.w3.org/2001/XMLSchema#double": try { - return (TARGET) objectMapper.getNodeFactory().numberNode(Double.valueOf(binding.stringValue())); + return (TARGET) objectMapper.getNodeFactory().numberNode(Double.valueOf(renderString)); } catch (NumberFormatException nfe) { - throw new SailException(String.format("Could not convert %s to datatype %s.", binding.stringValue(), dataTypeName), nfe); + throw new SailException(String.format("Could not convert %s to datatype %s.", renderString, dataTypeName), nfe); } case "http://www.w3.org/2001/XMLSchema#float": try { - return (TARGET) objectMapper.getNodeFactory().numberNode(Float.valueOf(binding.stringValue())); + return (TARGET) objectMapper.getNodeFactory().numberNode(Float.valueOf(renderString)); } catch (NumberFormatException nfe) { - throw new SailException(String.format("Could not convert %s to datatype %s.", binding.stringValue(), dataTypeName), nfe); + throw new SailException(String.format("Could not convert %s to datatype %s.", renderString, dataTypeName), nfe); } case "http://www.w3.org/2001/XMLSchema#dateTime": try { - return (TARGET) objectMapper.getNodeFactory().textNode(objectMapper.getDateFormat().format(objectMapper.getDateFormat().parse(binding.stringValue()))); + return (TARGET) objectMapper.getNodeFactory().textNode(objectMapper.getDateFormat().format(objectMapper.getDateFormat().parse(renderString))); } catch (ParseException pe) { - throw new SailException(String.format("Could not convert %s to json date.", binding), pe); + throw new SailException(String.format("Could not convert %s to json date.", renderString), pe); } case "http://www.w3.org/2001/XMLSchema#date": try { - return (TARGET) objectMapper.getNodeFactory().textNode(dateFormat.format(dateFormat.parse(binding.stringValue()))); + return (TARGET) objectMapper.getNodeFactory().textNode(dateFormat.format(dateFormat.parse(renderString))); } catch (ParseException pe) { - throw new SailException(String.format("Could not convert %s to json date.", binding), pe); + throw new SailException(String.format("Could not convert %s to json date.", renderString), pe); } case "https://json-schema.org/draft/2020-12/schema#Object": try { - String representation = binding.stringValue(); + String representation = renderString; // remove UTF8 linefeeds. representation = representation.replace("\\x0A", ""); return (TARGET) objectMapper.readTree(representation); } catch (JsonProcessingException jpe) { - throw new SailException(String.format("Could not convert %s to json object.", binding), jpe); + throw new SailException(String.format("Could not convert %s to json object.", renderString), jpe); } default: - throw new SailException(String.format("Could not convert %s of data type %s.", binding, dataTypeName)); + throw new SailException(String.format("Could not convert %s of data type %s.", renderString, dataTypeName)); } } else if (binding.isIRI()) { - return (TARGET) objectMapper.getNodeFactory().textNode(binding.stringValue()); + return (TARGET) objectMapper.getNodeFactory().textNode(renderString); } else { - throw new SailException(String.format("Could not convert %s.", binding)); + throw new SailException(String.format("Could not convert %s.", renderString)); } } - throw new SailException(String.format("No conversion from %s to %s possible.", binding, target)); + throw new SailException(String.format("No conversion from %s to %s possible.", renderString, target)); } @Override @@ -337,10 +345,6 @@ public Value convertOutputToValue(Object target, String resultKey, IRI output) t String[] resultPath = service.getResult().getOutputProperty().split("\\."); target = traversePath(target, resultPath); } - ReturnValueConfig cf = service.getResult().getOutputs().get(output.stringValue()); - if (cf == null) { - throw new SailException(String.format("No output specification for %s", output)); - } if (resultKey != null) { if (target.getClass().isArray()) { if (service.getResult().getResultIdProperty() != null) { @@ -400,7 +404,21 @@ public Value convertOutputToValue(Object target, String resultKey, IRI output) t } } } - return convertOutputToValue(target, connection.remotingSail.getValueFactory(), cf.getPath(), cf.getDataType()); + // support nested output as json object for complex result types + String outputString = output.stringValue(); + String path = null; + String dataType = "https://json-schema.org/draft/2020-12/schema#Object"; + boolean isCollectiveResult = service.getResultName().equals(output.stringValue()); + if (!isCollectiveResult) { + ReturnValueConfig cf = null; + cf = service.getResult().getOutputs().get(output.stringValue()); + if (cf == null) { + throw new SailException(String.format("No output specification for %s", output)); + } + path = cf.getPath(); + dataType = cf.getDataType(); + } + return convertOutputToValue(target, connection.remotingSail.getValueFactory(), path, dataType); } /** @@ -541,7 +559,7 @@ public void executeRest(RemotingSailConnection connection, BindingHost host) thr } else { value = binding.getValue(mapping.getName()); } - Object render = convertToObject(value, String.class); + Object render = convertToObject(value, String.class, argument.getValue().getStrip()); if (isFirstArg[0]) { url[0] = url[0] + argument.getValue().getArgumentName(); } else { @@ -698,7 +716,7 @@ public void executeRest(RemotingSailConnection connection, BindingHost host) thr for (MutableBindingSet binding : batch) { String key = null; if (service.getResult().getCorrelationInput() != null) { - key = resolve(binding, service.getResult().getCorrelationInput(), null, String.class); + key = resolve(binding, service.getResult().getCorrelationInput(), null, String.class, null); } else if (service.getBatch() > 1) { key = "0"; } @@ -733,7 +751,7 @@ public void executeRest(RemotingSailConnection connection, BindingHost host) thr * @param argumentConfig config of the argument */ protected void processArgument(ObjectMapper objectMapper, ObjectNode finalinput, MutableBindingSet binding, AtomicBoolean isCorrect, String argumentKey, ArgumentConfig argumentConfig) { - JsonNode render = resolve(binding, argumentKey, (JsonNode) argumentConfig.getDefaultValue(), JsonNode.class); + JsonNode render = resolve(binding, argumentKey, (JsonNode) argumentConfig.getDefaultValue(), JsonNode.class, argumentConfig.getStrip()); if (render != null) { String paths = argumentConfig.getArgumentName(); Matcher matcher = ARGUMENT_PATTERN.matcher(paths); @@ -741,7 +759,9 @@ protected void processArgument(ObjectMapper objectMapper, ObjectNode finalinput, int end = 0; while (matcher.find()) { resultPaths.append(paths.substring(end, matcher.start())); - String result = resolve(binding, matcher.group("arg"), "", String.class); + String toResolve = matcher.group("arg"); + ArgumentConfig targetArg = service.getArguments().get(toResolve); + String result = resolve(binding, toResolve, (String) targetArg.getDefaultValue(), String.class, targetArg.getStrip()); resultPaths.append(result); end = matcher.end(); } @@ -759,14 +779,14 @@ protected void processArgument(ObjectMapper objectMapper, ObjectNode finalinput, /** * resolves a given input predicate against a binding * - * @param binding the binding - * @param input predicate as uri string - * @param defaultValue a possible default value - * @param forClass target class to convert binding into - * @param template type + * @param binding the binding + * @param input predicate as uri string + * @param defaultValue a possible default value + * @param forClass target class to convert binding into + * @param template type * @return found binding of predicate, null if not bound */ - private TARGET resolve(MutableBindingSet binding, String input, TARGET defaultValue, Class forClass) { + private TARGET resolve(MutableBindingSet binding, String input, TARGET defaultValue, Class forClass, String strip) { String key; Var variable = inputs.get(input); Value value = null; @@ -779,7 +799,7 @@ private TARGET resolve(MutableBindingSet binding, String input, TARGET } if (value != null) { - return convertToObject(value, forClass); + return convertToObject(value, forClass, strip); } if (defaultValue != null) { @@ -818,7 +838,7 @@ protected Iterator> produceBatches(BindingHost hos } } else { key = new BatchKey(batchGroup.stream().map( - batch -> resolve(binding, batch.getKey(), null, String.class) + batch -> resolve(binding, batch.getKey(), null, String.class, null) ).toArray(size -> new String[size])); } Collection targetCollection; @@ -839,7 +859,7 @@ protected Iterator> produceBatches(BindingHost hos * @param source the ObjectNodes to be merged * @param target the ObjectNodes where source needs to be merged into */ - public static ObjectNode mergeObjectNodes(ObjectNode target, ObjectNode source) { + public static ObjectNode mergeObjectNodes(ObjectNode target, ObjectNode source) { if (source == null) { return target; } @@ -850,7 +870,7 @@ public static ObjectNode mergeObjectNodes(ObjectNode target, ObjectNode source) String key = entry.getKey(); JsonNode sourceValue = entry.getValue(); JsonNode targetValue = target.get(key); - + if (targetValue != null && targetValue.isObject() && sourceValue.isObject()) { // Recursively merge nested objects mergeObjectNodes((ObjectNode) targetValue, (ObjectNode) sourceValue); @@ -862,10 +882,10 @@ public static ObjectNode mergeObjectNodes(ObjectNode target, ObjectNode source) target.set(key, sourceValue); } } - + return target; } - + /** * merges two given ArrayNodes * @@ -895,8 +915,8 @@ private static void mergeArrays(ArrayNode target, ArrayNode source) { } } } - - + + /** * sets a given node under a possible recursive path * @@ -915,7 +935,7 @@ public static void setNode(ObjectMapper objectMapper, ObjectNode finalInput, Str finalInput = (ObjectNode) mergeObjectNodes(finalInput, (ObjectNode) render); return; } - for (String argField : argPath) { + for (String argField : argPath) { if (depth != argPath.length - 1) { if (hasField(traverse, argField)) { JsonNode next = getField(traverse, argField); @@ -935,7 +955,7 @@ public static void setNode(ObjectMapper objectMapper, ObjectNode finalInput, Str } depth++; } // set argument in input - } + } } /** @@ -1060,7 +1080,7 @@ public void executeClass(RemotingSailConnection connection, BindingHost host) th } else { value = arg.getValue(); } - targetParams[argIndex++] = convertToObject(value, param.getType()); + targetParams[argIndex++] = convertToObject(value, param.getType(), aconfig.getStrip()); break; } } diff --git a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/QueryExecutor.java b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/QueryExecutor.java index 0b958105..1377df5a 100644 --- a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/QueryExecutor.java +++ b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/QueryExecutor.java @@ -1,4 +1,4 @@ -// Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +// Copyright (c) 2022,2024 Contributors to the Eclipse Foundation // // See the NOTICE file(s) distributed with this work for additional // information regarding copyright ownership. @@ -545,17 +545,35 @@ public void meet(Slice node) throws SailException { throw new SailException(String.format("No support for %s", node)); } + /** + * implements the actual preparation/binding and invocation/execution of triple based API calls + */ @Override public void meet(StatementPattern statement) throws SailException { - Var predicate = statement.getPredicateVar(); - Var object = statement.getObjectVar(); if (bindings.isEmpty()) { bindings.add(new MapBindingSet()); } - if (!predicate.hasValue() || !predicate.getValue().isIRI()) { - throw new SailException(String.format("No support for non-IRI predicate binding %s", predicate)); - } else if ("http://www.w3.org/1999/02/22-rdf-syntax-ns#type".equals(predicate.getValue().stringValue())) { - if (!object.hasValue() || !object.getValue().isIRI()) { + Var predicate = statement.getPredicateVar(); + if (!predicate.hasValue()) { + if (!bindings.get(0).hasBinding(predicate.getName())) { + throw new SailException(String.format("Predicate %s is not bound", predicate)); + } + predicate = new Var(predicate.getName(), bindings.get(0).getValue(predicate.getName())); + checkConsistentBindings(predicate); + } + if (!predicate.getValue().isIRI()) { + throw new SailException(String.format("No support for non-IRI predicate %s", predicate)); + } + if ("http://www.w3.org/1999/02/22-rdf-syntax-ns#type".equals(predicate.getValue().stringValue())) { + Var object = statement.getObjectVar(); + if (!object.hasValue()) { + if (!bindings.get(0).hasBinding(object.getName())) { + throw new SailException(String.format("Invocation type %s is not bound", object)); + } + object = new Var(object.getName(), bindings.get(0).getValue(object.getName())); + checkConsistentBindings(object); + } + if (!object.getValue().isIRI()) { throw new SailException(String.format("No support for non-IRI invocation type binding %s", object)); } IRI objectIri = (IRI) object.getValue(); @@ -606,16 +624,28 @@ public void meet(StatementPattern statement) throws SailException { } Invocation invocation = invocations.get(subject.getValue()); IRI argument = (IRI) predicate.getValue(); - if (invocation.service.getResult().getOutputs().containsKey(argument.stringValue())) { - invocation.outputs.put(object, argument); + if (invocation.service.getResultName().equals(argument.stringValue()) || invocation.service.getResult().getOutputs().containsKey(argument.stringValue())) { + invocation.outputs.put(statement.getObjectVar(), argument); } else if (invocation.service.getArguments().containsKey(argument.stringValue())) { - invocation.inputs.put(argument.stringValue(), object); + invocation.inputs.put(argument.stringValue(), statement.getObjectVar()); } else { throw new SailException(String.format("Predicate %s is neither output nor input predicate for invocation %s", argument, subject)); } } } + /** + * check that all bindings coincide on the comparison object + */ + private void checkConsistentBindings(final Var compareObject) { + bindings.forEach(binding -> { + Value val = binding.getValue(compareObject.getName()); + if (!val.equals(compareObject.getValue())) { + throw new SailException(String.format("Having different invocation types %s is currently not supported", compareObject)); + } + }); + } + @Override public void meet(Str node) throws SailException { throw new SailException(String.format("No support for %s", node)); diff --git a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/ArgumentConfig.java b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/ArgumentConfig.java index 3531d297..e63e2e68 100644 --- a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/ArgumentConfig.java +++ b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/ArgumentConfig.java @@ -1,4 +1,4 @@ -// Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +// Copyright (c) 2022,2024 Contributors to the Eclipse Foundation // // See the NOTICE file(s) distributed with this work for additional // information regarding copyright ownership. @@ -31,6 +31,11 @@ public class ArgumentConfig { */ protected boolean mandatory = true; + /** + * strip everything before the last appearance of that string + */ + protected String strip = null; + /** * an optional default value */ @@ -100,6 +105,25 @@ public int getPriority() { return priority; } + /** + * strip string + * + * @return current strip string + */ + public String getStrip() { + return strip; + } + + /** + * sets the strip string + * + * @param strip a string to strip after + */ + public void setStrip(String strip) { + this.strip = strip; + } + + /** * validate the argument * @@ -114,7 +138,7 @@ public void validate(String context) throws SailConfigException { @Override public String toString() { - return super.toString() + "/argument(" + String.valueOf(mandatory) + ")"; + return super.toString() + "/argument(" + mandatory + ")"; } } diff --git a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/RemotingSailConfig.java b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/RemotingSailConfig.java index 610da98d..92ccd656 100644 --- a/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/RemotingSailConfig.java +++ b/remoting/src/main/java/org/eclipse/tractusx/agents/remoting/config/RemotingSailConfig.java @@ -1,4 +1,4 @@ -// Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +// Copyright (c) 2022,2024 Contributors to the Eclipse Foundation // // See the NOTICE file(s) distributed with this work for additional // information regarding copyright ownership. @@ -64,6 +64,7 @@ public class RemotingSailConfig extends AbstractSailImplConfig { public static final String CORRELATION_INPUT_ATTRIBUTE = "correlationInput"; public static final String OUTPUT_PROPERTY_ATTRIBUTE = "outputProperty"; public static final String ARGUMENT_ATTRIBUTE = "argumentName"; + public static final String STRIP_ATTRIBUTE = "strip"; public static final String MANDATORY_ATTRIBUTE = "mandatory"; public static final String DEFAULT_ATTRIBUTE = "default"; public static final String GROUP_ATTRIBUTE = "formsBatchGroup"; @@ -91,6 +92,7 @@ public class RemotingSailConfig extends AbstractSailImplConfig { protected IRI outputPredicate = vf.createIRI(CONFIG_NAMESPACE, OUTPUT_ATTRIBUTE); protected IRI resultPredicate = vf.createIRI(CONFIG_NAMESPACE, RESULT_ATTRIBUTE); protected IRI argumentNamePredicate = vf.createIRI(CONFIG_NAMESPACE, ARGUMENT_ATTRIBUTE); + protected IRI stripPredicate = vf.createIRI(CONFIG_NAMESPACE, STRIP_ATTRIBUTE); protected IRI mandatoryPredicate = vf.createIRI(CONFIG_NAMESPACE, MANDATORY_ATTRIBUTE); protected IRI defaultPredicate = vf.createIRI(CONFIG_NAMESPACE, DEFAULT_ATTRIBUTE); @@ -240,6 +242,9 @@ public Resource export(Model model) { model.add(argumentNode, mandatoryPredicate, vf.createLiteral(arg.getValue().mandatory)); model.add(argumentNode, priorityPredicate, vf.createLiteral(arg.getValue().priority)); model.add(argumentNode, groupPredicate, vf.createLiteral(arg.getValue().formsBatchGroup)); + if (arg.getValue().getStrip() != null) { + model.add(argumentNode, stripPredicate, vf.createLiteral(arg.getValue().getStrip())); + } model.add(argumentNode, defaultPredicate, Invocation.convertOutputToValue(arg.getValue().defaultValue, vf, "", "https://json-schema.org/draft/2020-12/schema#Object")); } IRI resultNode = vf.createIRI(func.getValue().resultName); @@ -335,7 +340,11 @@ public void parse(Model model, Resource implNode) throws SailConfigException { Models.objectLiteral(model.filter(argumentNode, groupPredicate, null)) .ifPresent(group -> ac.formsBatchGroup = Boolean.parseBoolean(group.stringValue())); Models.objectLiteral(model.filter(argumentNode, defaultPredicate, null)) - .ifPresent(def -> ac.defaultValue = Invocation.convertToObject(def, JsonNode.class)); + .ifPresent(def -> ac.defaultValue = Invocation.convertToObject(def, JsonNode.class, null)); + Models.objectLiteral(model.filter(argumentNode, stripPredicate, null)) + .ifPresent(strip -> ac.setStrip(strip.stringValue())); + Models.objectIRI(model.filter(argumentNode, stripPredicate, null)) + .ifPresent(strip -> ac.setStrip(strip.stringValue())); } ); Models.objectIRI(model.filter(functionNode, resultPredicate, null)) diff --git a/remoting/src/test/java/org/eclipse/tractusx/agents/remoting/RemotingSailTest.java b/remoting/src/test/java/org/eclipse/tractusx/agents/remoting/RemotingSailTest.java index 80e1e663..e6efa39f 100644 --- a/remoting/src/test/java/org/eclipse/tractusx/agents/remoting/RemotingSailTest.java +++ b/remoting/src/test/java/org/eclipse/tractusx/agents/remoting/RemotingSailTest.java @@ -1,4 +1,4 @@ -// Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +// Copyright (c) 2022,2024 Contributors to the Eclipse Foundation // // See the NOTICE file(s) distributed with this work for additional // information regarding copyright ownership. @@ -16,6 +16,10 @@ // SPDX-License-Identifier: Apache-2.0 package org.eclipse.tractusx.agents.remoting; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.rdf4j.model.*; import org.eclipse.rdf4j.model.util.*; @@ -38,145 +42,145 @@ */ public class RemotingSailTest { - public static String REPO_NAMESPACE="http://www.openrdf.org/config/repository#"; + public static String REPO_NAMESPACE = "http://www.openrdf.org/config/repository#"; /** * tests parsing a config */ - @Test + @Test public void testConfig() throws Exception { Model graph = Rio.parse(RemotingSailTest.class.getResourceAsStream("/config.ttl"), REPO_NAMESPACE, - RDFFormat.TURTLE); - RemotingSailConfig rsc=new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); - rsc.parse(graph,Models.subjectBNode(graph.filter(null,rsc.getValueFactory().createIRI("http://www.openrdf.org/config/sail#","sailType"),rsc.getValueFactory().createLiteral("org.eclipse.tractusx.agents:Remoting"))).get()); + RDFFormat.TURTLE); + RemotingSailConfig rsc = new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); + rsc.parse(graph, Models.subjectBNode(graph.filter(null, rsc.getValueFactory().createIRI("http://www.openrdf.org/config/sail#", "sailType"), rsc.getValueFactory().createLiteral("org.eclipse.tractusx.agents:Remoting"))).get()); rsc.validate(); - assertEquals(5,rsc.listServices().size(),"correct number of invocation configs"); + assertEquals(5, rsc.listServices().size(), "correct number of invocation configs"); ServiceConfig health = rsc.getService("https://w3id.org/catenax/ontology/health#HealthIndication"); - assertEquals(100, health.getBatch(),"Correct batch size"); - assertEquals("https://w3id.org/catenax/ontology/health#requestComponentId", health.getResult().getCorrelationInput(),"Correct correlation input"); + assertEquals(100, health.getBatch(), "Correct batch size"); + assertEquals("https://w3id.org/catenax/ontology/health#requestComponentId", health.getResult().getCorrelationInput(), "Correct correlation input"); ServiceConfig rul = rsc.getService("https://w3id.org/catenax/ontology/rul#RemainingUsefulLife"); - assertNotNull(rul.getCallbackProperty(),"Correct asynchronous mode"); - ArgumentConfig notificationTemplate= rul.getArguments().get("https://w3id.org/catenax/ontology/rul#notification"); - assertNotNull(notificationTemplate,"Found the notification template argument"); - assertEquals(-1, notificationTemplate.getPriority(),"Notification template has default value"); - assertNotNull(notificationTemplate.getDefaultValue(),"Notification template has default value"); - ArgumentConfig component= rul.getArguments().get("https://w3id.org/catenax/ontology/rul#component"); - assertNotNull( component,"Found the component argument"); - assertTrue(component.isFormsBatchGroup(),"Component is marked as batch group"); - ReturnValueConfig responseResult= rul.getResult().getOutputs().get("https://w3id.org/catenax/ontology/rul#content"); - assertNotNull(responseResult,"Notification content found"); + assertNotNull(rul.getCallbackProperty(), "Correct asynchronous mode"); + ArgumentConfig notificationTemplate = rul.getArguments().get("https://w3id.org/catenax/ontology/rul#notification"); + assertNotNull(notificationTemplate, "Found the notification template argument"); + assertEquals(-1, notificationTemplate.getPriority(), "Notification template has default value"); + assertNotNull(notificationTemplate.getDefaultValue(), "Notification template has default value"); + ArgumentConfig component = rul.getArguments().get("https://w3id.org/catenax/ontology/rul#component"); + assertNotNull(component, "Found the component argument"); + assertTrue(component.isFormsBatchGroup(), "Component is marked as batch group"); + ReturnValueConfig responseResult = rul.getResult().getOutputs().get("https://w3id.org/catenax/ontology/rul#content"); + assertNotNull(responseResult, "Notification content found"); } - + /** * tests basic invocation features */ - @Test + @Test public void testInvocation() { - - RemotingSailConfig rsc=new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); - ServiceConfig ic=new ServiceConfig(); - rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis",ic); + + RemotingSailConfig rsc = new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); + ServiceConfig ic = new ServiceConfig(); + rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis", ic); ic.setTargetUri("class:org.eclipse.tractusx.agents.remoting.test.TestFunction#test"); - ArgumentConfig ac=new ArgumentConfig(); + ArgumentConfig ac = new ArgumentConfig(); ac.setArgumentName("arg0"); - ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#input-1",ac); - ac=new ArgumentConfig(); + ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#input-1", ac); + ac = new ArgumentConfig(); ac.setArgumentName("arg1"); - ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#input-2",ac); - ResultConfig rc=new ResultConfig(); + ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#input-2", ac); + ResultConfig rc = new ResultConfig(); ic.setResult(rc); ic.setResultName("https://w3id.org/catenax/ontology/prognosis#Result"); - ReturnValueConfig rvc=new ReturnValueConfig(); + ReturnValueConfig rvc = new ReturnValueConfig(); - rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#output",rvc); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#output", rvc); rsc.validate(); Repository rep = new SailRepository(new RemotingSail(rsc)); try (RepositoryConnection conn = rep.getConnection()) { - TupleQuery query=(TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, - "PREFIX xsd: "+ - "PREFIX prognosis: "+ - "SELECT ?invocation ?output "+ - "WHERE { "+ - "?invocation a prognosis:Prognosis; "+ - " prognosis:input-1 \"1\"^^xsd:string; "+ - " prognosis:input-2 \"2\"^^xsd:string; "+ - " prognosis:output ?output. "+ - //" prognosis:hasResult [ prognosis:output ?output ]. "+ - "}"); + TupleQuery query = (TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, + "PREFIX xsd: " + + "PREFIX prognosis: " + + "SELECT ?invocation ?output " + + "WHERE { " + + "?invocation a prognosis:Prognosis; " + + " prognosis:input-1 \"1\"^^xsd:string; " + + " prognosis:input-2 \"2\"^^xsd:string; " + + " prognosis:output ?output. " + + //" prognosis:hasResult [ prognosis:output ?output ]. "+ + "}"); final TupleQueryResult result = query.evaluate(); - final String[] names = result.getBindingNames().toArray(new String[0]); - assertEquals(2,names.length,"Correct number of binding names"); - assertEquals("invocation",names[0],"Correct binding name 1"); - assertEquals("output",names[1],"Correct binding name 2"); + final String[] names = result.getBindingNames().toArray(new String[0]); + assertEquals(2, names.length, "Correct number of binding names"); + assertEquals("invocation", names[0], "Correct binding name 1"); + assertEquals("output", names[1], "Correct binding name 2"); java.util.List bindings = Iterations.asList(result); - assertEquals(1,bindings.size(),"Correct number of bindings"); - BindingSet firstBindingSet=bindings.get(0); - assertTrue(firstBindingSet.getBindingNames().contains("invocation"),"Found invocation binding"); - assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"),"Invocation binding has the right prefix"); - assertEquals(2,firstBindingSet.size(),"Correct number of variables in binding 0"); - assertTrue(firstBindingSet.getBindingNames().contains("output"),"Found output binding"); - assertEquals("3",firstBindingSet.getValue("output").stringValue()); + assertEquals(1, bindings.size(), "Correct number of bindings"); + BindingSet firstBindingSet = bindings.get(0); + assertTrue(firstBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertEquals(2, firstBindingSet.size(), "Correct number of variables in binding 0"); + assertTrue(firstBindingSet.getBindingNames().contains("output"), "Found output binding"); + assertEquals("3", firstBindingSet.getValue("output").stringValue()); } } - + /** * tests basic invocation features */ - @Test + @Test public void testRemoting() { - - RemotingSailConfig rsc=new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); - ServiceConfig ic=new ServiceConfig(); - rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis",ic); + + RemotingSailConfig rsc = new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); + ServiceConfig ic = new ServiceConfig(); + rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis", ic); ic.setTargetUri("https://api.agify.io"); - ArgumentConfig ac=new ArgumentConfig(); + ArgumentConfig ac = new ArgumentConfig(); ac.setArgumentName("name"); - ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#name",ac); - ReturnValueConfig rvc=new ReturnValueConfig(); + ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#name", ac); + ReturnValueConfig rvc = new ReturnValueConfig(); rvc.setPath("age"); rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); - ResultConfig rc=new ResultConfig(); + ResultConfig rc = new ResultConfig(); ic.setResult(rc); ic.setResultName("https://w3id.org/catenax/ontology/prognosis#Result"); - rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#prediction",rvc); - rvc=new ReturnValueConfig(); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#prediction", rvc); + rvc = new ReturnValueConfig(); rvc.setPath("count"); rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); - rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#count",rvc); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#count", rvc); rsc.validate(); Repository rep = new SailRepository(new RemotingSail(rsc)); try (RepositoryConnection conn = rep.getConnection()) { - TupleQuery query=(TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, - "PREFIX xsd: "+ - "PREFIX prognosis: "+ - "SELECT ?invocation ?prediction ?count "+ - "WHERE { "+ - "?invocation a prognosis:Prognosis; "+ - " prognosis:name \"Schorsch\"^^xsd:string; "+ - " prognosis:prediction ?prediction; "+ - " prognosis:count ?count. "+ - "}"); + TupleQuery query = (TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, + "PREFIX xsd: " + + "PREFIX prognosis: " + + "SELECT ?invocation ?prediction ?count " + + "WHERE { " + + "?invocation a prognosis:Prognosis; " + + " prognosis:name \"Schorsch\"^^xsd:string; " + + " prognosis:prediction ?prediction; " + + " prognosis:count ?count. " + + "}"); final TupleQueryResult result = query.evaluate(); - final String[] names = result.getBindingNames().toArray(new String[0]); - assertEquals(3,names.length,"Correct number of binding names"); - assertEquals("invocation",names[0],"Correct binding name 1"); - assertEquals("prediction",names[1],"Correct binding name 2"); - assertEquals("count",names[2],"Correct binding name 3"); + final String[] names = result.getBindingNames().toArray(new String[0]); + assertEquals(3, names.length, "Correct number of binding names"); + assertEquals("invocation", names[0], "Correct binding name 1"); + assertEquals("prediction", names[1], "Correct binding name 2"); + assertEquals("count", names[2], "Correct binding name 3"); java.util.List bindings = Iterations.asList(result); - assertEquals(1,bindings.size(),"Correct number of bindings"); - BindingSet firstBindingSet=bindings.get(0); - assertTrue(firstBindingSet.getBindingNames().contains("invocation"),"Found invocation binding"); - assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"),"Invocation binding has the right prefix"); - assertEquals(3,firstBindingSet.size(),"Correct number of variables in binding 0"); - assertTrue(firstBindingSet.getBindingNames().contains("prediction"),"Found prediction binding"); - assertTrue(61<=((Literal) firstBindingSet.getValue("prediction")).intValue(),"Correct prediction value"); - assertTrue(firstBindingSet.getBindingNames().contains("count"),"Found count binding"); - assertTrue(((Literal) firstBindingSet.getValue("count")).intValue()>50,"Correct cound value"); + assertEquals(1, bindings.size(), "Correct number of bindings"); + BindingSet firstBindingSet = bindings.get(0); + assertTrue(firstBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertEquals(3, firstBindingSet.size(), "Correct number of variables in binding 0"); + assertTrue(firstBindingSet.getBindingNames().contains("prediction"), "Found prediction binding"); + assertTrue(61 <= ((Literal) firstBindingSet.getValue("prediction")).intValue(), "Correct prediction value"); + assertTrue(firstBindingSet.getBindingNames().contains("count"), "Found count binding"); + assertTrue(((Literal) firstBindingSet.getValue("count")).intValue() > 50, "Correct cound value"); } } @@ -184,74 +188,144 @@ public void testRemoting() { * tests basic invocation features */ @Test - public void testRemotingBatch() { + public void testRemotingBatch() { - RemotingSailConfig rsc=new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); - ServiceConfig ic=new ServiceConfig(); - rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis",ic); + RemotingSailConfig rsc = new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); + ServiceConfig ic = new ServiceConfig(); + rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis", ic); ic.setTargetUri("https://api.agify.io"); - ArgumentConfig ac=new ArgumentConfig(); + ArgumentConfig ac = new ArgumentConfig(); ac.setArgumentName("name"); - ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#name",ac); - ReturnValueConfig rvc=new ReturnValueConfig(); + ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#name", ac); + ReturnValueConfig rvc = new ReturnValueConfig(); rvc.setPath("age"); rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); - ResultConfig rc=new ResultConfig(); + ResultConfig rc = new ResultConfig(); ic.setResult(rc); ic.setResultName("https://w3id.org/catenax/ontology/prognosis#Result"); - rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#prediction",rvc); - rvc=new ReturnValueConfig(); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#prediction", rvc); + rvc = new ReturnValueConfig(); rvc.setPath("count"); rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); - rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#count",rvc); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#count", rvc); rsc.validate(); Repository rep = new SailRepository(new RemotingSail(rsc)); try (RepositoryConnection conn = rep.getConnection()) { - TupleQuery query=(TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, - "PREFIX xsd: "+ - "PREFIX prognosis: "+ - "SELECT ?invocation ?input ?prediction ?count "+ - "WHERE { "+ - " VALUES(?input) { (\"Schorsch\"^^xsd:string) (\"Christoph\"^^xsd:string)}"+ - " ?invocation a prognosis:Prognosis; "+ - " prognosis:name ?input; "+ - " prognosis:prediction ?prediction; "+ - " prognosis:count ?count. "+ + TupleQuery query = (TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, + "PREFIX xsd: " + + "PREFIX prognosis: " + + "SELECT ?invocation ?input ?prediction ?count " + + "WHERE { " + + " VALUES(?input) { (\"Schorsch\"^^xsd:string) (\"Christoph\"^^xsd:string)}" + + " ?invocation a prognosis:Prognosis; " + + " prognosis:name ?input; " + + " prognosis:prediction ?prediction; " + + " prognosis:count ?count. " + "}"); final TupleQueryResult result = query.evaluate(); final String[] names = result.getBindingNames().toArray(new String[0]); - assertEquals(4,names.length,"Correct number of binding names"); - assertEquals("invocation",names[0],"Correct binding name 1"); - assertEquals("input",names[1],"Correct binding name 2"); - assertEquals("prediction",names[2],"Correct binding name 3"); - assertEquals("count",names[3],"Correct binding name 4"); + assertEquals(4, names.length, "Correct number of binding names"); + assertEquals("invocation", names[0], "Correct binding name 1"); + assertEquals("input", names[1], "Correct binding name 2"); + assertEquals("prediction", names[2], "Correct binding name 3"); + assertEquals("count", names[3], "Correct binding name 4"); java.util.List bindings = Iterations.asList(result); - assertEquals(2,bindings.size(),"Correct number of bindings"); - BindingSet firstBindingSet=bindings.get(0); - assertEquals(4,firstBindingSet.size(),"Correct number of variables in binding 0"); - assertTrue(firstBindingSet.getBindingNames().contains("invocation"),"Found invocation binding"); - assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"),"Invocation binding has the right prefix"); - assertTrue(firstBindingSet.getBindingNames().contains("input"),"Found input binding"); + assertEquals(2, bindings.size(), "Correct number of bindings"); + BindingSet firstBindingSet = bindings.get(0); + assertEquals(4, firstBindingSet.size(), "Correct number of variables in binding 0"); + assertTrue(firstBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertTrue(firstBindingSet.getBindingNames().contains("input"), "Found input binding"); assertEquals("Schorsch", firstBindingSet.getValue("input").stringValue()); - assertTrue(firstBindingSet.getBindingNames().contains("prediction"),"Found prediction binding"); - assertTrue(61<=((Literal) firstBindingSet.getValue("prediction")).intValue(),"Correct prediction value"); - assertTrue(firstBindingSet.getBindingNames().contains("count"),"Found count binding"); - assertTrue(((Literal) firstBindingSet.getValue("count")).intValue()>50,"Correct cound value"); - BindingSet secondBindingSet=bindings.get(1); - assertEquals(4,secondBindingSet.size(),"Correct number of variables in binding 0"); - assertTrue(secondBindingSet.getBindingNames().contains("invocation"),"Found invocation binding"); - assertTrue(secondBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"),"Invocation binding has the right prefix"); - assertTrue(secondBindingSet.getBindingNames().contains("input"),"Found input binding"); + assertTrue(firstBindingSet.getBindingNames().contains("prediction"), "Found prediction binding"); + assertTrue(61 <= ((Literal) firstBindingSet.getValue("prediction")).intValue(), "Correct prediction value"); + assertTrue(firstBindingSet.getBindingNames().contains("count"), "Found count binding"); + assertTrue(((Literal) firstBindingSet.getValue("count")).intValue() > 50, "Correct count value"); + BindingSet secondBindingSet = bindings.get(1); + assertEquals(4, secondBindingSet.size(), "Correct number of variables in binding 1"); + assertTrue(secondBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(secondBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertTrue(secondBindingSet.getBindingNames().contains("input"), "Found input binding"); assertEquals("Christoph", secondBindingSet.getValue("input").stringValue()); - assertTrue(secondBindingSet.getBindingNames().contains("prediction"),"Found prediction binding"); - assertTrue(41<=((Literal) secondBindingSet.getValue("prediction")).intValue(),"Correct prediction value"); - assertTrue(secondBindingSet.getBindingNames().contains("count"),"Found count binding"); - assertTrue(((Literal) secondBindingSet.getValue("count")).intValue()>15000,"Correct cound value"); + assertTrue(secondBindingSet.getBindingNames().contains("prediction"), "Found prediction binding"); + assertTrue(41 <= ((Literal) secondBindingSet.getValue("prediction")).intValue(), "Correct prediction value"); + assertTrue(secondBindingSet.getBindingNames().contains("count"), "Found count binding"); + assertTrue(((Literal) secondBindingSet.getValue("count")).intValue() > 15000, "Correct count value"); } } + /** + * tests basic invocation features + */ + @Test + public void testRemotingResult() throws JsonProcessingException { + + RemotingSailConfig rsc = new RemotingSailConfig(RemotingSailFactory.SAIL_TYPE); + ServiceConfig ic = new ServiceConfig(); + rsc.putService("https://w3id.org/catenax/ontology/prognosis#Prognosis", ic); + ic.setTargetUri("https://api.agify.io"); + ArgumentConfig ac = new ArgumentConfig(); + ac.setArgumentName("name"); + ic.getArguments().put("https://w3id.org/catenax/ontology/prognosis#name", ac); + ReturnValueConfig rvc = new ReturnValueConfig(); + rvc.setPath("age"); + rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); + ResultConfig rc = new ResultConfig(); + ic.setResult(rc); + ic.setResultName("https://w3id.org/catenax/ontology/prognosis#Result"); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#prediction", rvc); + rvc = new ReturnValueConfig(); + rvc.setPath("count"); + rvc.setDataType("http://www.w3.org/2001/XMLSchema#int"); + rc.getOutputs().put("https://w3id.org/catenax/ontology/prognosis#count", rvc); + rsc.validate(); + + Repository rep = new SailRepository(new RemotingSail(rsc)); + + try (RepositoryConnection conn = rep.getConnection()) { + TupleQuery query = (TupleQuery) conn.prepareQuery(QueryLanguage.SPARQL, + "PREFIX xsd: " + + "PREFIX prognosis: " + + "SELECT ?invocation ?input ?response " + + "WHERE { " + + " VALUES(?input) { (\"Schorsch\"^^xsd:string) (\"Christoph\"^^xsd:string)}" + + " ?invocation a prognosis:Prognosis; " + + " prognosis:name ?input; " + + " prognosis:Result ?response. " + + "}"); + final TupleQueryResult result = query.evaluate(); + final String[] names = result.getBindingNames().toArray(new String[0]); + assertEquals(3, names.length, "Correct number of binding names"); + assertEquals("invocation", names[0], "Correct binding name 1"); + assertEquals("input", names[1], "Correct binding name 2"); + assertEquals("response", names[2], "Correct binding name 3"); + java.util.List bindings = Iterations.asList(result); + assertEquals(2, bindings.size(), "Correct number of bindings"); + BindingSet firstBindingSet = bindings.get(1); + assertEquals(3, firstBindingSet.size(), "Correct number of variables in binding 0"); + assertTrue(firstBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(firstBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertTrue(firstBindingSet.getBindingNames().contains("input"), "Found input binding"); + assertEquals("Schorsch", firstBindingSet.getValue("input").stringValue()); + assertTrue(firstBindingSet.getBindingNames().contains("response"), "Found response binding"); + ObjectMapper mapper = new ObjectMapper(); + JsonNode response = mapper.readTree(((Literal) firstBindingSet.getValue("response")).stringValue()); + assertTrue(61 <= response.get("age").intValue(), "Correct age response property"); + assertTrue(response.get("count").intValue() > 50, "Correct count response property"); + BindingSet secondBindingSet = bindings.get(0); + assertEquals(3, secondBindingSet.size(), "Correct number of variables in binding 1"); + assertTrue(secondBindingSet.getBindingNames().contains("invocation"), "Found invocation binding"); + assertTrue(secondBindingSet.getValue("invocation").stringValue().startsWith("https://w3id.org/catenax/ontology/prognosis#"), "Invocation binding has the right prefix"); + assertTrue(secondBindingSet.getBindingNames().contains("input"), "Found input binding"); + assertEquals("Christoph", secondBindingSet.getValue("input").stringValue()); + assertTrue(secondBindingSet.getBindingNames().contains("response"), "Found response binding"); + response = mapper.readTree(((Literal) secondBindingSet.getValue("response")).stringValue()); + assertTrue(41 <= response.get("age").intValue(), "Correct age response property"); + assertTrue(response.get("count").intValue() > 15000, "Correct count response property"); + } + } } \ No newline at end of file diff --git a/remoting/src/test/resources/config.ttl b/remoting/src/test/resources/config.ttl index c504ed99..de45d5c6 100644 --- a/remoting/src/test/resources/config.ttl +++ b/remoting/src/test/resources/config.ttl @@ -331,6 +331,7 @@ cx-rul:component rdf:type cx-fx:Argument; cx-rul:observationType rdf:type cx-fx:Argument; dcterms:description "The type of observation made."@en ; dcterms:title "Observation Type"; + cx-fx:strip "#"; cx-fx:argumentName "content.endurancePredictorInputs.0.classifiedLoadSpectrum{https://w3id.org/catenax/ontology/rul#observationType}.metadata.componentDescription"; cx-fx:dataType xsd:string. diff --git a/upgrade_version.sh b/upgrade_version.sh index 77d4e8e5..d4df3391 100755 --- a/upgrade_version.sh +++ b/upgrade_version.sh @@ -16,7 +16,7 @@ # # SPDX-License-Identifier: Apache-2.0 -OLD_VERSION=1.12.17-SNAPSHOT +OLD_VERSION=1.12.18-SNAPSHOT echo Upgrading from $OLD_VERSION to $1 PATTERN=s/$OLD_VERSION/$1/g LC_ALL=C