From 9c9360bf78d66fb862b52652884164d48bc86823 Mon Sep 17 00:00:00 2001 From: "Dr. Christoph \"Schorsch\" Jung" Date: Thu, 1 Feb 2024 09:12:56 +0100 Subject: [PATCH 1/5] feat: move the asset shapes graph into the default graph for easier inference. Adapt to CX 24.05 standards. --- .../edc/service/DataspaceSynchronizer.java | 439 +++++++++++++----- .../service/TestDataspaceSynchronizer.java | 49 +- 2 files changed, 348 insertions(+), 140 deletions(-) diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java index 4953f16..561bb9a 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java @@ -28,7 +28,9 @@ import org.apache.jena.riot.system.ErrorHandlerFactory; import org.apache.jena.riot.system.StreamRDF; import org.apache.jena.riot.system.StreamRDFLib; +import org.apache.jena.sparql.AlreadyExists; import org.apache.jena.sparql.core.Quad; +import org.apache.jena.vocabulary.RDF; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.Criterion; import org.eclipse.edc.spi.query.QuerySpec; @@ -43,42 +45,104 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * A service which keeps a triple store and - * the associated dataspace in sync + * the associated dataspace (partner catalogues) in sync */ public class DataspaceSynchronizer implements Runnable { /** * constants */ - protected static final Node CX_ASSET = NodeFactory.createURI("https://w3id.org/catenax/ontology/common#offers"); - protected static final Map ASSET_PROPERTY_MAP = new HashMap<>(); + + public static final String COMMON_NAMESPACE = "https://w3id.org/catenax/ontology/common#"; + public static final String TAXO_NAMESPACE = "https://w3id.org/catenax/taxonomy#"; + public static final String EDC_NAMESPACE = "https://w3id.org/edc/v0.0.1/ns/"; + public static final String RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + public static final Node RDF_TYPE = createUri(RDF_NAMESPACE, "type"); + public static final String RDF_SCHEMA_NAMESPACE = "http://www.w3.org/2000/01/rdf-schema#"; + public static final String DC_NAMESPACE = "https://purl.org/dc/terms/"; + public static final String DC_TYPE = DC_NAMESPACE + "type"; + public static final String SHACL_NAMESPACE = "http://www.w3.org/ns/shacl#"; + public static final String SHAPES_GRAPH = SHACL_NAMESPACE + "shapesGraph"; + public static final String CX_SCHEMA_NAMESPACE = "https://w3id.org/catenax/ontology/schema#"; + public static final String XML_SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema#"; + + public static final Node SHAPE_OBJECT = createUri(CX_SCHEMA_NAMESPACE, "shapeObject"); + protected static final Node CX_ASSET = createUri(COMMON_NAMESPACE, "offers"); + protected static final Set EXPECTED_COMPLEX_OBJECTS = new HashSet<>(); protected static final QuerySpec FEDERATED_ASSET_QUERY = QuerySpec.Builder.newInstance() - .filter(List.of(new Criterion("https://w3id.org/catenax/ontology/common#isFederated", "=", "true^^xsd:boolean"))).build(); + .filter(List.of(new Criterion(COMMON_NAMESPACE + "isFederated", "=", "true^^xsd:boolean"))).build(); - protected MonitorWrapper monitorWrapper; + protected static final Map ASSET_PROPERTY_MAP = new HashMap<>(); static { - ASSET_PROPERTY_MAP.put("https://w3id.org/edc/v0.0.1/ns/id", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#id")); - ASSET_PROPERTY_MAP.put("https://w3id.org/edc/v0.0.1/ns/name", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#name")); - ASSET_PROPERTY_MAP.put("https://w3id.org/edc/v0.0.1/ns/description", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#description")); - ASSET_PROPERTY_MAP.put("https://w3id.org/edc/v0.0.1/ns/version", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#version")); - ASSET_PROPERTY_MAP.put("https://w3id.org/edc/v0.0.1/ns/contenttype", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#contentType")); - ASSET_PROPERTY_MAP.put("http://www.w3.org/1999/02/22-rdf-syntax-ns#type", NodeFactory.createURI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); - ASSET_PROPERTY_MAP.put("http://www.w3.org/2000/01/rdf-schema#isDefinedBy", NodeFactory.createURI("http://www.w3.org/2000/01/rdf-schema#isDefinedBy")); - ASSET_PROPERTY_MAP.put("https://w3id.org/catenax/ontology/common#implementsProtocol", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#implementsProtocol")); - ASSET_PROPERTY_MAP.put("http://www.w3.org/ns/shacl#shapesGraph", NodeFactory.createURI("http://www.w3.org/ns/shacl#shapesGraph")); - ASSET_PROPERTY_MAP.put("https://w3id.org/catenax/ontology/common#isFederated", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#isFederated")); - ASSET_PROPERTY_MAP.put("https://w3id.org/catenax/ontology/common#publishedUnderContract", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#publishedUnderContract")); - ASSET_PROPERTY_MAP.put("https://w3id.org/catenax/ontology/common#satisfiesRole", NodeFactory.createURI("https://w3id.org/catenax/ontology/common#satisfiesRole")); + registerPredicate(COMMON_NAMESPACE, "id", false); + registerPredicate(COMMON_NAMESPACE, "name", false); + registerPredicate(COMMON_NAMESPACE, "description", false); + registerPredicate(COMMON_NAMESPACE, "version", false); + registerPredicate(COMMON_NAMESPACE, "contenttype", false); + registerPredicate(DC_NAMESPACE, "type", true); + // map the rdf definition to dublin core + ASSET_PROPERTY_MAP.put(RDF_NAMESPACE + "type", createUri(DC_NAMESPACE, "type")); + registerPredicate(RDF_SCHEMA_NAMESPACE, "isDefinedBy", true); + registerPredicate(COMMON_NAMESPACE, "implementsProtocol", true); + registerPredicate(SHACL_NAMESPACE, "shapesGraph", false); + registerPredicate(COMMON_NAMESPACE, "isFederated", true); + registerPredicate(COMMON_NAMESPACE, "publishedUnderContract", true); + registerPredicate(COMMON_NAMESPACE, "satisfiesRole", true); + } + + protected static final Map PREDEFINED_NS = new HashMap<>( + ); + + static { + PREDEFINED_NS.put("cx-common:", COMMON_NAMESPACE); + PREDEFINED_NS.put("cx-taxo:", TAXO_NAMESPACE); + PREDEFINED_NS.put("edc:", EDC_NAMESPACE); + PREDEFINED_NS.put("rdf:", RDF_NAMESPACE); + PREDEFINED_NS.put("rdfs:", RDF_SCHEMA_NAMESPACE); + PREDEFINED_NS.put("sh:", SHACL_NAMESPACE); + PREDEFINED_NS.put("cx-sh:", CX_SCHEMA_NAMESPACE); + PREDEFINED_NS.put("dc:", DC_NAMESPACE); + PREDEFINED_NS.put("xsd:", XML_SCHEMA_NAMESPACE); + } + + /** + * static helper to create an uri node from a prefix and name + * + * @param prefix namespace + * @param name entity name + * @return uri node + */ + protected static Node createUri(String prefix, String name) { + return NodeFactory.createURI(prefix + name); + } + + /** + * make sure these asset properties can be defined with or without prefix + * + * @param prefix namespace + * @param name id + */ + protected static void registerPredicate(String prefix, String name, boolean isUri) { + String key = prefix + name; + if (isUri) { + EXPECTED_COMPLEX_OBJECTS.add(key); + } + Node target = createUri(prefix, name); + ASSET_PROPERTY_MAP.put(key, target); + key = EDC_NAMESPACE + name; + ASSET_PROPERTY_MAP.put(key, target); } /** @@ -89,6 +153,7 @@ public class DataspaceSynchronizer implements Runnable { protected final DataManagement dataManagement; protected final RdfStore rdfStore; protected final Monitor monitor; + protected final MonitorWrapper monitorWrapper; /** * internal state @@ -98,11 +163,11 @@ public class DataspaceSynchronizer implements Runnable { /** * creates the synchronizer * - * @param service scheduler - * @param config edc config + * @param service scheduler + * @param config edc config * @param dataManagement data management service remoting - * @param rdfStore a triple store for persistance - * @param monitor logging subsystem + * @param rdfStore a triple store for persistance + * @param monitor logging subsystem */ public DataspaceSynchronizer(ScheduledExecutorService service, AgentConfig config, DataManagement dataManagement, RdfStore rdfStore, Monitor monitor) { this.service = service; @@ -154,44 +219,8 @@ public void run() { DcatCatalog catalog = dataManagement.getCatalog(remote, FEDERATED_ASSET_QUERY); Node graph = rdfStore.getDefaultGraph(); Node connector = NodeFactory.createURI(remote.replace("https", "edcs").replace("http", "edc")); - Quad findAssets = Quad.create(graph, connector, CX_ASSET, Node.ANY); - Iterator assetQuads = rdfStore.getDataSet().find(findAssets); - int tupleCount = 0; - while (assetQuads.hasNext()) { - Quad quadAsset = assetQuads.next(); - Quad findAssetProps = Quad.create(graph, quadAsset.getObject(), Node.ANY, Node.ANY); - Iterator propQuads = rdfStore.getDataSet().find(findAssetProps); - while (propQuads.hasNext()) { - Quad quadProp = propQuads.next(); - if (quadProp.getPredicate().isURI() && quadProp.getPredicate().getURI().equals("http://www.w3.org/ns/shacl#shapesGraph") && quadProp.getObject().isURI()) { - Quad findSubGraphsProps = Quad.create(quadProp.getObject(), Node.ANY, Node.ANY, Node.ANY); - Iterator subGraphQuads = rdfStore.getDataSet().find(findSubGraphsProps); - while (subGraphQuads.hasNext()) { - rdfStore.getDataSet().delete(subGraphQuads.next()); - tupleCount++; - } - } - rdfStore.getDataSet().delete(quadProp); - tupleCount++; - } - rdfStore.getDataSet().delete(quadAsset); - tupleCount++; - } - monitor.debug(String.format("About to delete %d old tuples.", tupleCount)); - List offers = catalog.getDatasets(); - tupleCount = 0; - if (offers != null) { - monitor.debug(String.format("Found a catalog with %d entries for remote connector %s", offers.size(), remote)); - for (DcatDataset offer : catalog.getDatasets()) { - for (Quad quad : convertToQuads(graph, connector, offer)) { - tupleCount++; - rdfStore.getDataSet().add(quad); - } - } - } else { - monitor.warning(String.format("Found an empty catalog for remote connector %s", remote)); - } - monitor.debug(String.format("About to add %d new tuples.", tupleCount)); + deleteConnectorFacts(graph, connector); + addConnectorFacts(remote, catalog, graph, connector); rdfStore.commit(); } catch (Throwable io) { monitor.warning(String.format("Could not synchronize remote connector %s because of %s. Going ahead.", remote, io)); @@ -211,6 +240,120 @@ public void run() { } } + /** + * adds new facts about the catalog thats been collected from the given connector + * + * @param remote url of the remote connector + * @param catalog retrieved catalogue + * @param graph to store the facts + * @param connector uri node representing the connector + * @return number of fact triples/quads added + */ + public int addConnectorFacts(String remote, DcatCatalog catalog, Node graph, Node connector) { + int tupleCount; + List offers = catalog.getDatasets(); + tupleCount = 0; + if (offers != null) { + monitor.debug(String.format("Found a catalog with %d entries for remote connector %s", offers.size(), remote)); + for (DcatDataset offer : catalog.getDatasets()) { + tupleCount += addOfferFacts(graph, connector, offer); + } + } else { + monitor.warning(String.format("Found an empty catalog for remote connector %s", remote)); + } + monitor.debug(String.format("About to add %d new tuples.", tupleCount)); + return tupleCount; + } + + /** + * adds new facts about a concrete data offer collected from a given connector + * + * @param graph to store the facts + * @param connector uri node representing the connector + * @param offer to convert into facts + * @return number of facts triples/quads added + */ + public int addOfferFacts(Node graph, Node connector, DcatDataset offer) { + int tupleCount = 0; + var quads = convertToQuads(graph, connector, offer); + for (Quad quad : quads) { + tupleCount++; + rdfStore.getDataSet().add(quad); + } + return tupleCount; + } + + /** + * deletes existing facts about a connector + * + * @param graph to delete the facts from + * @param connector to clean up the facts for + * @return number of fact triples/quads deleted + */ + public int deleteConnectorFacts(Node graph, Node connector) { + // find all offers attached to the connector + Quad findAssets = Quad.create(graph, connector, CX_ASSET, Node.ANY); + Iterator assetQuads = rdfStore.getDataSet().find(findAssets); + int tupleCount = 0; + while (assetQuads.hasNext()) { + Quad quadAsset = assetQuads.next(); + Node assetNode = quadAsset.getObject(); + tupleCount += deleteShaclShapes(graph, assetNode); + tupleCount += deleteAssetProperties(graph, assetNode); + rdfStore.getDataSet().delete(quadAsset); + tupleCount++; + } + monitor.debug(String.format("About to delete %d old tuples.", tupleCount)); + return tupleCount; + } + + /** + * deletes properties of a given offer/asset + * + * @param graph where facts are stored + * @param assetNode to delete properties from + * @return number of property facts deleted + */ + public int deleteAssetProperties(Node graph, Node assetNode) { + int tupleCount = 0; + // remove all remaining properties associated to the offer/asset + Quad findAssetProps = Quad.create(graph, assetNode, Node.ANY, Node.ANY); + Iterator propQuads = rdfStore.getDataSet().find(findAssetProps); + while (propQuads.hasNext()) { + Quad quadProp = propQuads.next(); + rdfStore.getDataSet().delete(quadProp); + tupleCount++; + } + return tupleCount; + } + + /** + * delete all shacl shapes associated to an asset node + * + * @param graph where the shapes are stored + * @param assetNode to delete the shapes from + * @return number of associated shapes (and their properties) + */ + public int deleteShaclShapes(Node graph, Node assetNode) { + int tupleCount = 0; + // remove all shacl shapes associated to the offer/asset + Quad findAssetShapes = Quad.create(graph, assetNode, SHAPE_OBJECT, Node.ANY); + Iterator shapesQuad = rdfStore.getDataSet().find(findAssetShapes); + while (shapesQuad.hasNext()) { + Quad shapeQuad = shapesQuad.next(); + Node shapesObject = shapeQuad.getObject(); + Quad findShapesPredicates = Quad.create(graph, shapesObject, Node.ANY, Node.ANY); + Iterator shapesFacts = rdfStore.getDataSet().find(findShapesPredicates); + while (shapesFacts.hasNext()) { + rdfStore.getDataSet().delete(shapesFacts.next()); + tupleCount++; + } + rdfStore.getDataSet().delete(shapeQuad); + tupleCount++; + } + return tupleCount; + } + /** * Workaround the castration of the IDS catalogue * @@ -219,13 +362,13 @@ public void run() { */ public static Map getProperties(DcatDataset offer) { Map assetProperties = new HashMap<>(offer.getProperties()); - if (!assetProperties.containsKey("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) { + if (!assetProperties.containsKey(DC_TYPE) && !assetProperties.containsKey(RDF_TYPE.getURI()) && !assetProperties.containsKey(EDC_NAMESPACE + "type")) { String assetType = JsonLd.asString(assetProperties.getOrDefault("@id", Json.createValue("cx-common:Asset"))); int indexOfQuestion = assetType.indexOf("?"); if (indexOfQuestion > 0) { assetType = assetType.substring(0, indexOfQuestion - 1); } - assetProperties.put("http://www.w3.org/1999/02/22-rdf-syntax-ns#type", Json.createValue(assetType)); + assetProperties.put(DC_TYPE, Json.createValue(assetType)); } if (!assetProperties.containsKey("@id")) { assetProperties.put("@id", Json.createValue(UUID.randomUUID().toString())); @@ -236,14 +379,13 @@ public static Map getProperties(DcatDataset offer) { /** * convert a given contract offer into quads * - * @param graph default graph + * @param graph default graph * @param connector parent connector hosting the offer - * @param offer the contract offer + * @param offer the contract offer * @return a collection of quads */ public Collection convertToQuads(Node graph, Node connector, DcatDataset offer) { Map assetProperties = getProperties(offer); - List quads = new ArrayList<>(); String offerId = assetProperties.get("@id").toString(); Node assetNode = NodeFactory.createURI(offerId); @@ -254,77 +396,32 @@ public Collection convertToQuads(Node graph, Node connector, DcatDataset o for (Map.Entry assetProp : assetProperties.entrySet()) { String key = assetProp.getKey(); Node node = ASSET_PROPERTY_MAP.get(key); + // strip down complex properties, mayxbe not needed anymore while (node == null && key.indexOf('.') >= 0) { key = key.substring(key.lastIndexOf(".") + 1); node = ASSET_PROPERTY_MAP.get(key); } + // strip off language modifiers + if (node == null && key.indexOf("@") >= 0) { + String langSuffix = key.substring(key.lastIndexOf("@")); + key = key.substring(key.lastIndexOf("@")); + node = ASSET_PROPERTY_MAP.get(key); + if (node != null) { + node = createUri(node.getURI(), "@" + langSuffix); + } + } + // did we find some result if (node != null) { String pureProperty = JsonLd.asString(assetProp.getValue()); if (pureProperty != null) { try { - switch (key) { - case "https://w3id.org/catenax/ontology/common#publishedUnderContract": - case "http://www.w3.org/2000/01/rdf-schema#isDefinedBy": - case "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": - case "https://w3id.org/catenax/ontology/common#isFederated": - case "https://w3id.org/catenax/ontology/common#satisfiesRole": - case "https://w3id.org/catenax/ontology/common#implementsProtocol": - String[] urls = pureProperty.split(","); - for (String url : urls) { - Node o; - url = url.trim(); - if (url.startsWith("<") && url.endsWith(">")) { - url = url.substring(1, url.length() - 1); - o = NodeFactory.createURI(url); - } else if (url.startsWith("\"") && url.endsWith("\"")) { - url = url.substring(1, url.length() - 1); - o = NodeFactory.createLiteral(url); - } else if (url.startsWith("cx-common:")) { - url = url.substring(10); - o = NodeFactory.createURI("https://w3id.org/catenax/ontology/common#" + url); - } else if (url.contains("^^")) { - int typeAnnotation = url.indexOf("^^"); - String type = url.substring(typeAnnotation + 2); - url = url.substring(0, typeAnnotation); - o = NodeFactory.createLiteral(url, NodeFactory.getType(type)); - } else { - o = NodeFactory.createLiteral(url); - } - quads.add(Quad.create(graph, assetNode, node, o)); - } - break; - case "http://www.w3.org/ns/shacl#shapesGraph": - Node newGraph = NodeFactory.createURI("https://w3id.org/catenax/ontology/common#GraphShape?id=" + offerId.hashCode()); - quads.add(Quad.create(graph, assetNode, node, newGraph)); - Sink quadSink = new Sink<>() { - - @Override - public void close() { - } - - @Override - public void send(Quad quad) { - quads.add(quad); - } - - @Override - public void flush() { - } - }; - StreamRDF dest = StreamRDFLib.sinkQuads(quadSink); - StreamRDF graphDest = StreamRDFLib.extendTriplesToQuads(newGraph, dest); - StreamRDFCounting countingDest = StreamRDFLib.count(graphDest); - ErrorHandler errorHandler = ErrorHandlerFactory.errorHandlerStd(monitorWrapper); - RDFParser.create() - .errorHandler(errorHandler) - .source(new StringReader(pureProperty)) - .lang(Lang.TTL) - .parse(countingDest); - monitor.debug(String.format("Added shapes subgraph %s with %d triples", newGraph, countingDest.countTriples())); - break; - default: - quads.add(Quad.create(graph, assetNode, node, NodeFactory.createLiteral(pureProperty))); - } //switch + if (SHAPES_GRAPH.equals(key)) { + addShapesFacts(graph, quads, assetNode, pureProperty); + } else if (EXPECTED_COMPLEX_OBJECTS.contains(node.getURI())) { + addComplexFacts(graph, quads, assetNode, node, pureProperty); + } else { + quads.add(Quad.create(graph, assetNode, node, NodeFactory.createLiteral(pureProperty))); + } } catch (Throwable t) { monitor.debug(String.format("Could not correctly add asset triples for predicate %s with original value %s because of %s", node, pureProperty, t.getMessage())); } @@ -334,4 +431,92 @@ public void flush() { return quads; } + /** + * converts the given object string into complex facts + * + * @param graph to store the facts + * @param quads list to add the facts to + * @param assetNode subject to attach the facts to + * @param node the predicated under which the facts are holding + * @param objectString the actual value(s) to attach the predicate to + */ + private static void addComplexFacts(Node graph, List quads, Node assetNode, Node node, String objectString) { + // do we expect our predicate to hit a uri + String[] urls = objectString.split(","); + for (String url : urls) { + Node o = null; + url = url.trim(); + if (url.startsWith("<") && url.endsWith(">")) { + url = url.substring(1, url.length() - 1); + o = NodeFactory.createURI(url); + } else if (url.startsWith("\"") && url.endsWith("\"")) { + url = url.substring(1, url.length() - 1); + o = NodeFactory.createLiteral(url); + } else if (url.contains("^^")) { + int typeAnnotation = url.indexOf("^^"); + String type = url.substring(typeAnnotation + 2); + url = url.substring(0, typeAnnotation); + o = NodeFactory.createLiteral(url, NodeFactory.getType(type)); + } else { + for (var entry : PREDEFINED_NS.entrySet()) { + if (url.startsWith(entry.getKey())) { + url = url.substring(entry.getKey().length()); + o = NodeFactory.createURI(entry.getValue() + url); + break; + } + } + if (o == null) { + o = NodeFactory.createLiteral(url); + } + } + quads.add(Quad.create(graph, assetNode, node, o)); + // make sure both rdf:type and dc:type are set + if (node.getURI().equals(DC_TYPE)) { + quads.add(Quad.create(graph, assetNode, RDF_TYPE, o)); + } + } + } + + /** + * converts the given object string into a shapes graph + * + * @param graph to store the facts in + * @param quads to add the facts to + * @param assetNode asset to attach the shapes to + * @param shapesDescription a hopefully valid shacl shape turtle + */ + private void addShapesFacts(Node graph, List quads, Node assetNode, String shapesDescription) { + StreamRDF dest = StreamRDFLib.sinkQuads(new Sink<>() { + + protected Set connectedSubjects = new HashSet<>(); + + @Override + public void close() { + } + + @Override + public void send(Quad quad) { + String subject = quad.getSubject().toString(false); + if (!connectedSubjects.contains(subject)) { + quads.add(new Quad(graph, assetNode, SHAPE_OBJECT, quad.getSubject())); + connectedSubjects.add(subject); + } + quads.add(quad); + } + + @Override + public void flush() { + } + }); + StreamRDF graphDest = StreamRDFLib.extendTriplesToQuads(graph, dest); + StreamRDFCounting countingDest = StreamRDFLib.count(graphDest); + ErrorHandler errorHandler = ErrorHandlerFactory.errorHandlerStd(monitorWrapper); + RDFParser.create() + .errorHandler(errorHandler) + .source(new StringReader(shapesDescription)) + .lang(Lang.TTL) + .parse(countingDest); + monitor.debug(String.format("Added shapes subgraph to asset %s with %d triples", assetNode, countingDest.countTriples())); + } + } diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java index 5add5b1..7e78268 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java @@ -84,9 +84,33 @@ public void tearDown() throws Exception { public void testQuadRepresentation() { Node graph = store.getDefaultGraph(); Node connector = NodeFactory.createURI("edc://test"); + JsonObjectBuilder offerBuilder = createOffer(); + DcatDataset offer = new DcatDataset(offerBuilder.build()); + Collection result = synchronizer.convertToQuads(graph, connector, offer); + assertEquals(1 + 13 + 16 + 5, result.size(), "Got correct number of quads (1 connector subject and 12 asset subjects + 16 shape triples + 5 node to shape relations)."); + } + + + /** + * test quad representation of a contract offer + */ + @Test + public void testAddRemove() { + Node graph = store.getDefaultGraph(); + Node connector = NodeFactory.createURI("edc://test"); + JsonObjectBuilder offerBuilder = createOffer(); + DcatDataset offer = new DcatDataset(offerBuilder.build()); + int added = synchronizer.addOfferFacts(graph, connector, offer); + assertEquals(store.getDataSet().getDefaultGraph().size(), added, "All added tuples have been stored"); + int removed = synchronizer.deleteConnectorFacts(graph, connector); + assertEquals(0, store.getDataSet().getDefaultGraph().size(), "All stored tuples have been removed"); + assertEquals(added, removed, "All added tuples have been removed"); + } + + private static JsonObjectBuilder createOffer() { JsonObjectBuilder offerBuilder = Json.createObjectBuilder() .add("@id", "4bf62562-9026-4dcf-93b5-42ea0de25490") - .add("https://w3id.org/edc/v0.0.1/ns/id", "https://w3id.org/catenax/ontology/common#GraphAsset?test:ExampleAsset") + .add("https://w3id.org/edc/v0.0.1/ns/id", "https://w3id.org/catenax/ontology/common#GraphAsset?test=ExampleAsset") .add("https://w3id.org/edc/v0.0.1/ns/contenttype", "application/json, application/xml") .add("https://w3id.org/edc/v0.0.1/ns/version", "1.11.16-SNAPSHOT") .add("https://w3id.org/edc/v0.0.1/ns/name", "Test Asset") @@ -96,7 +120,7 @@ public void testQuadRepresentation() { .add("http://www.w3.org/2000/01/rdf-schema#isDefinedBy", ",") .add("https://w3id.org/catenax/ontology/common#implementsProtocol", "cx-common:Protocol?w3c:http:SPARQL") .add("http://www.w3.org/ns/shacl#shapesGraph", - "@prefix : .\n" + + "@prefix : .\n" + "@prefix cx-common: .\n" + "@prefix cx-part: .\n" + "@prefix cx-diag: .\n" + @@ -123,9 +147,7 @@ public void testQuadRepresentation() { " sh:hasValue ;\n" + " ] .\n") .add("https://w3id.org/catenax/ontology/common#isFederated", "true"); - DcatDataset offer = new DcatDataset(offerBuilder.build()); - Collection result = synchronizer.convertToQuads(graph, connector, offer); - assertEquals(1 + 12 + 16, result.size(), "Got correct number of quads (1 connector subject and 12 asset subjects + 16 shape triples)."); + return offerBuilder; } @Test @@ -140,10 +162,10 @@ public void testCatalogDeserialization() { " \"@id\": \"9cb29be7-e0fa-45f4-b575-eb1ec98e7562\",\n" + " \"@type\": \"dcat:Dataset\",\n" + " \"odrl:hasPolicy\": {\n" + - " \"@id\": \"https://w3id.org/catenax/ontology/common#Contract?oem:GraphContract:https://w3id.org/catenax/ontology/common#GraphAsset?oem:Diagnosis2022:3e247899-e690-43a9-9c42-91c5a853a78b\",\n" + + " \"@id\": \"aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNDb250cmFjdD9vZW09R3JhcGhDb250cmFjdA==:aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNHcmFwaEFzc2V0P29lbT1EaWFnbm9zaXMyMDIy:3e247899-e690-43a9-9c42-91c5a853a78b\",\n" + " \"@type\": \"odrl:Set\",\n" + " \"odrl:permission\": {\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:Diagnosis2022\",\n" + + " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=Diagnosis2022\",\n" + " \"odrl:action\": {\n" + " \"odrl:type\": \"USE\"\n" + " },\n" + @@ -169,7 +191,7 @@ public void testCatalogDeserialization() { " },\n" + " \"odrl:prohibition\": [],\n" + " \"odrl:obligation\": [],\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:Diagnosis2022\"\n" + + " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=Diagnosis2022\"\n" + " },\n" + " \"dcat:distribution\": {\n" + " \"@type\": \"dcat:Distribution\",\n" + @@ -181,7 +203,7 @@ public void testCatalogDeserialization() { " \"edc:version\": \"1.11.16-SNAPSHOT\",\n" + " \"http://www.w3.org/2000/01/rdf-schema#isDefinedBy\": \"\",\n" + " \"edc:name\": \"Diagnostic Trouble Code Catalogue Version 2022\",\n" + - " \"http://www.w3.org/ns/shacl#shapeGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-diag: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n:OemDTC rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DTC ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:version ;\\n sh:hasValue 0^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:affects ;\\n sh:class :OemDiagnosedParts ;\\n ] ;\\n\\n:OemDiagnosedParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DiagnosedPart ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n\",\n" + + " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-diag: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n:OemDTC rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DTC ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:affects ;\\n sh:class :OemDiagnosedParts ;\\n ].\\n\\n:OemDiagnosedParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DiagnosedPart ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + " \"edc:description\": \"A sample graph asset/offering referring to a specific diagnosis resource.\",\n" + " \"https://w3id.org/catenax/ontology/common#publishedUnderContract\": \"cx-common:Contract?oem:Graph\",\n" + " \"edc:id\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:Diagnosis2022\",\n" + @@ -194,10 +216,10 @@ public void testCatalogDeserialization() { " \"@id\": \"f3cbefa3-3ef9-464b-8f99-e342b578e182\",\n" + " \"@type\": \"dcat:Dataset\",\n" + " \"odrl:hasPolicy\": {\n" + - " \"@id\": \"https://w3id.org/catenax/ontology/common#Contract?oem:GraphContract:https://w3id.org/catenax/ontology/common#GraphAsset?oem:BehaviourTwin:5d12f720-29dd-40d4-b9ef-f0b81c9740b4\",\n" + + " \"@id\": \"aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNDb250cmFjdD9vZW09R3JhcGhDb250cmFjdA==:aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNHcmFwaEFzc2V0P29lbT1CZWhhdmlvdXJUd2lu:5d12f720-29dd-40d4-b9ef-f0b81c9740b4\",\n" + " \"@type\": \"odrl:Set\",\n" + " \"odrl:permission\": {\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:BehaviourTwin\",\n" + + " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=BehaviourTwin\",\n" + " \"odrl:action\": {\n" + " \"odrl:type\": \"USE\"\n" + " },\n" + @@ -223,7 +245,7 @@ public void testCatalogDeserialization() { " },\n" + " \"odrl:prohibition\": [],\n" + " \"odrl:obligation\": [],\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:BehaviourTwin\"\n" + + " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=BehaviourTwin\"\n" + " },\n" + " \"dcat:distribution\": {\n" + " \"@type\": \"dcat:Distribution\",\n" + @@ -235,7 +257,7 @@ public void testCatalogDeserialization() { " \"edc:version\": \"CX_RuL_Testdata_v1.0.0\",\n" + " \"http://www.w3.org/2000/01/rdf-schema#isDefinedBy\": \"\",\n" + " \"edc:name\": \"OEM portion of the Behaviour Twin RUL/HI Testdataset.\",\n" + - " \"http://www.w3.org/ns/shacl#shapeGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-tele: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .@prefix : .\\n\\nOemLoadSpectrum rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:LoadSpectrum ;\\n sh:property [\\n sh:path cx-tele:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:Version ;\\n sh:hasValue 0^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:component ;\\n sh:class SupplierParts ;\\n ] ;\\n\\nSupplierParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:VehicleComponent ;\\n sh:property [\\n sh:path cx-tele:isProducedBy ;\\n sh:hasValue ;\\n ] ;\\n\",\n" + + " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-tele: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n :OemLoadSpectrum rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:LoadSpectrum ;\\n sh:property [\\n sh:path cx-tele:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:Version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:component ;\\n sh:class :SupplierParts ;\\n ] .\\n\\n:SupplierParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:VehicleComponent ;\\n sh:property [\\n sh:path cx-tele:isProducedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + " \"edc:description\": \"A graph asset/offering mounting Carena-X Testdata for Behaviour Twin.\",\n" + " \"https://w3id.org/catenax/ontology/common#publishedUnderContract\": \"cx-common:Contract?oem:Graph\",\n" + " \"edc:id\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:BehaviourTwin\",\n" + @@ -263,6 +285,7 @@ public void testCatalogDeserialization() { "}"; DcatCatalog cat = JsonLd.processCatalog(catDesc); Collection results = cat.getDatasets().stream().flatMap(offer -> synchronizer.convertToQuads(graph, connector, offer).stream()).collect(Collectors.toList()); + assertEquals(2 + 24 + 32 + 10, results.size(), "Got correct number of quads (2 connector subject and 22 asset subjects + 32 shape triples + 10 node to shape relations)."); } } \ No newline at end of file From e1e2546dc100ed8f2b2cca0401898b71be227b54 Mon Sep 17 00:00:00 2001 From: "Dr. Christoph \"Schorsch\" Jung" Date: Thu, 1 Feb 2024 09:17:42 +0100 Subject: [PATCH 2/5] fix: checkstyle redundant imports. --- .../tractusx/agents/edc/service/DataspaceSynchronizer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java index 561bb9a..7ac8b41 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java @@ -28,9 +28,7 @@ import org.apache.jena.riot.system.ErrorHandlerFactory; import org.apache.jena.riot.system.StreamRDF; import org.apache.jena.riot.system.StreamRDFLib; -import org.apache.jena.sparql.AlreadyExists; import org.apache.jena.sparql.core.Quad; -import org.apache.jena.vocabulary.RDF; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.Criterion; import org.eclipse.edc.spi.query.QuerySpec; From f59dec9f28a9c6969f56d9d264991a0483b23043 Mon Sep 17 00:00:00 2001 From: "Dr. Christoph \"Schorsch\" Jung" Date: Thu, 1 Feb 2024 14:26:21 +0100 Subject: [PATCH 3/5] fix: deal with literal subjects correctly. --- .../edc/service/DataspaceSynchronizer.java | 11 ++--- .../service/TestDataspaceSynchronizer.java | 45 +++++++++++-------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java index 7ac8b41..a28fb21 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java @@ -111,7 +111,7 @@ public class DataspaceSynchronizer implements Runnable { PREDEFINED_NS.put("rdfs:", RDF_SCHEMA_NAMESPACE); PREDEFINED_NS.put("sh:", SHACL_NAMESPACE); PREDEFINED_NS.put("cx-sh:", CX_SCHEMA_NAMESPACE); - PREDEFINED_NS.put("dc:", DC_NAMESPACE); + PREDEFINED_NS.put("dct:", DC_NAMESPACE); PREDEFINED_NS.put("xsd:", XML_SCHEMA_NAMESPACE); } @@ -385,7 +385,7 @@ public static Map getProperties(DcatDataset offer) { public Collection convertToQuads(Node graph, Node connector, DcatDataset offer) { Map assetProperties = getProperties(offer); List quads = new ArrayList<>(); - String offerId = assetProperties.get("@id").toString(); + String offerId = JsonLd.asString(assetProperties.get("@id")); Node assetNode = NodeFactory.createURI(offerId); quads.add(Quad.create(graph, connector, @@ -394,15 +394,10 @@ public Collection convertToQuads(Node graph, Node connector, DcatDataset o for (Map.Entry assetProp : assetProperties.entrySet()) { String key = assetProp.getKey(); Node node = ASSET_PROPERTY_MAP.get(key); - // strip down complex properties, mayxbe not needed anymore - while (node == null && key.indexOf('.') >= 0) { - key = key.substring(key.lastIndexOf(".") + 1); - node = ASSET_PROPERTY_MAP.get(key); - } // strip off language modifiers if (node == null && key.indexOf("@") >= 0) { String langSuffix = key.substring(key.lastIndexOf("@")); - key = key.substring(key.lastIndexOf("@")); + key = key.substring(0, key.lastIndexOf("@")); node = ASSET_PROPERTY_MAP.get(key); if (node != null) { node = createUri(node.getURI(), "@" + langSuffix); diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java index 7e78268..4562320 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java @@ -41,6 +41,8 @@ import org.mockito.MockitoAnnotations; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; @@ -90,7 +92,6 @@ public void testQuadRepresentation() { assertEquals(1 + 13 + 16 + 5, result.size(), "Got correct number of quads (1 connector subject and 12 asset subjects + 16 shape triples + 5 node to shape relations)."); } - /** * test quad representation of a contract offer */ @@ -102,6 +103,16 @@ public void testAddRemove() { DcatDataset offer = new DcatDataset(offerBuilder.build()); int added = synchronizer.addOfferFacts(graph, connector, offer); assertEquals(store.getDataSet().getDefaultGraph().size(), added, "All added tuples have been stored"); + Quad findAssets = Quad.create(graph, connector, DataspaceSynchronizer.CX_ASSET, Node.ANY); + var allAssets = store.getDataSet().find(findAssets); + Map assetSet = new HashMap<>(); + while (allAssets.hasNext()) { + Quad assetQuad = allAssets.next(); + assetSet.put(assetQuad.getObject().toString(false), assetQuad); + } + assertEquals(true, assetSet.containsKey("cx-taxo:GraphAsset?test=ExampleAsset"), "Found the first asset from the catalogue"); + assertEquals(1, assetSet.size(), "Assets/offers are complete"); + assertEquals(store.getDataSet().getDefaultGraph().size(), added, "All added tuples have been stored"); int removed = synchronizer.deleteConnectorFacts(graph, connector); assertEquals(0, store.getDataSet().getDefaultGraph().size(), "All stored tuples have been removed"); assertEquals(added, removed, "All added tuples have been removed"); @@ -109,14 +120,14 @@ public void testAddRemove() { private static JsonObjectBuilder createOffer() { JsonObjectBuilder offerBuilder = Json.createObjectBuilder() - .add("@id", "4bf62562-9026-4dcf-93b5-42ea0de25490") - .add("https://w3id.org/edc/v0.0.1/ns/id", "https://w3id.org/catenax/ontology/common#GraphAsset?test=ExampleAsset") + .add("@id", "cx-taxo:GraphAsset?test=ExampleAsset") .add("https://w3id.org/edc/v0.0.1/ns/contenttype", "application/json, application/xml") - .add("https://w3id.org/edc/v0.0.1/ns/version", "1.11.16-SNAPSHOT") - .add("https://w3id.org/edc/v0.0.1/ns/name", "Test Asset") - .add("https://w3id.org/edc/v0.0.1/ns/description", "Test Asset for RDF Representation") + .add("https://w3id.org/catenax/ontology/common#version", "1.11.16-SNAPSHOT") + .add("https://w3id.org/catenax/ontology/common#name", "Test Asset") + .add("https://w3id.org/catenax/ontology/common#description", "Test Asset for RDF Representation") + .add("https://w3id.org/catenax/ontology/common#description@de", "Beispiel Asset für RDF Darstellung") .add("https://w3id.org/catenax/ontology/common#publishedUnderContract", "") - .add("http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "cx-common:GraphAsset") + .add("https://purl.org/dc/terms/type", "cx-common:GraphAsset") .add("http://www.w3.org/2000/01/rdf-schema#isDefinedBy", ",") .add("https://w3id.org/catenax/ontology/common#implementsProtocol", "cx-common:Protocol?w3c:http:SPARQL") .add("http://www.w3.org/ns/shacl#shapesGraph", @@ -146,7 +157,7 @@ private static JsonObjectBuilder createOffer() { " sh:path cx-part:provisionedBy ;\n" + " sh:hasValue ;\n" + " ] .\n") - .add("https://w3id.org/catenax/ontology/common#isFederated", "true"); + .add("https://w3id.org/catenax/ontology/common#isFederated", "true^^^sd:boolean"); return offerBuilder; } @@ -159,13 +170,13 @@ public void testCatalogDeserialization() { " \"@type\": \"dcat:Catalog\",\n" + " \"dcat:dataset\": [\n" + " {\n" + - " \"@id\": \"9cb29be7-e0fa-45f4-b575-eb1ec98e7562\",\n" + + " \"@id\": \"cx-taxo:GraphAsset?oem=Diagnosis2022\",\n" + " \"@type\": \"dcat:Dataset\",\n" + " \"odrl:hasPolicy\": {\n" + " \"@id\": \"aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNDb250cmFjdD9vZW09R3JhcGhDb250cmFjdA==:aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNHcmFwaEFzc2V0P29lbT1EaWFnbm9zaXMyMDIy:3e247899-e690-43a9-9c42-91c5a853a78b\",\n" + " \"@type\": \"odrl:Set\",\n" + " \"odrl:permission\": {\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=Diagnosis2022\",\n" + + " \"odrl:target\": \"cx-taxo:GraphAsset?oem=Diagnosis2022\",\n" + " \"odrl:action\": {\n" + " \"odrl:type\": \"USE\"\n" + " },\n" + @@ -191,7 +202,7 @@ public void testCatalogDeserialization() { " },\n" + " \"odrl:prohibition\": [],\n" + " \"odrl:obligation\": [],\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=Diagnosis2022\"\n" + + " \"odrl:target\": \"cx-taxo:GraphAsset?oem=Diagnosis2022\"\n" + " },\n" + " \"dcat:distribution\": {\n" + " \"@type\": \"dcat:Distribution\",\n" + @@ -203,23 +214,22 @@ public void testCatalogDeserialization() { " \"edc:version\": \"1.11.16-SNAPSHOT\",\n" + " \"http://www.w3.org/2000/01/rdf-schema#isDefinedBy\": \"\",\n" + " \"edc:name\": \"Diagnostic Trouble Code Catalogue Version 2022\",\n" + - " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-diag: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n:OemDTC rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DTC ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:affects ;\\n sh:class :OemDiagnosedParts ;\\n ].\\n\\n:OemDiagnosedParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DiagnosedPart ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + + " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-diag: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n:OemDTC rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DTC ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:affects ;\\n sh:class :OemDiagnosedParts ;\\n ].\\n\\n:OemDiagnosedParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DiagnosedPart ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + " \"edc:description\": \"A sample graph asset/offering referring to a specific diagnosis resource.\",\n" + " \"https://w3id.org/catenax/ontology/common#publishedUnderContract\": \"cx-common:Contract?oem:Graph\",\n" + - " \"edc:id\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:Diagnosis2022\",\n" + " \"edc:contenttype\": \"application/json, application/xml\",\n" + " \"https://w3id.org/catenax/ontology/common#isFederated\": \"true\",\n" + " \"https://w3id.org/catenax/ontology/common#implementsProtocol\": \"cx-common:Protocol?w3c:http:SPARQL\",\n" + " \"http://www.w3.org/1999/02/22-rdf-syntax-ns#type\": \"cx-common:GraphAsset\"\n" + " },\n" + " {\n" + - " \"@id\": \"f3cbefa3-3ef9-464b-8f99-e342b578e182\",\n" + + " \"@id\": \"cx-taxo:GraphAsset?oem=BehaviourTwin\",\n" + " \"@type\": \"dcat:Dataset\",\n" + " \"odrl:hasPolicy\": {\n" + " \"@id\": \"aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNDb250cmFjdD9vZW09R3JhcGhDb250cmFjdA==:aHR0cHM6Ly93M2lkLm9yZy9jYXRlbmF4L29udG9sb2d5L2NvbW1vbiNHcmFwaEFzc2V0P29lbT1CZWhhdmlvdXJUd2lu:5d12f720-29dd-40d4-b9ef-f0b81c9740b4\",\n" + " \"@type\": \"odrl:Set\",\n" + " \"odrl:permission\": {\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=BehaviourTwin\",\n" + + " \"odrl:target\": \"cx-taxo:GraphAsset?oem=BehaviourTwin\",\n" + " \"odrl:action\": {\n" + " \"odrl:type\": \"USE\"\n" + " },\n" + @@ -245,7 +255,7 @@ public void testCatalogDeserialization() { " },\n" + " \"odrl:prohibition\": [],\n" + " \"odrl:obligation\": [],\n" + - " \"odrl:target\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem=BehaviourTwin\"\n" + + " \"odrl:target\": \"cx-taxo:GraphAsset?oem=BehaviourTwin\"\n" + " },\n" + " \"dcat:distribution\": {\n" + " \"@type\": \"dcat:Distribution\",\n" + @@ -260,7 +270,6 @@ public void testCatalogDeserialization() { " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-tele: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n :OemLoadSpectrum rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:LoadSpectrum ;\\n sh:property [\\n sh:path cx-tele:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:Version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-tele:component ;\\n sh:class :SupplierParts ;\\n ] .\\n\\n:SupplierParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-tele:VehicleComponent ;\\n sh:property [\\n sh:path cx-tele:isProducedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + " \"edc:description\": \"A graph asset/offering mounting Carena-X Testdata for Behaviour Twin.\",\n" + " \"https://w3id.org/catenax/ontology/common#publishedUnderContract\": \"cx-common:Contract?oem:Graph\",\n" + - " \"edc:id\": \"https://w3id.org/catenax/ontology/common#GraphAsset?oem:BehaviourTwin\",\n" + " \"edc:contenttype\": \"application/json, application/xml\",\n" + " \"https://w3id.org/catenax/ontology/common#isFederated\": \"true\",\n" + " \"https://w3id.org/catenax/ontology/common#implementsProtocol\": \"cx-common:Protocol?w3c:http:SPARQL\",\n" + @@ -285,7 +294,7 @@ public void testCatalogDeserialization() { "}"; DcatCatalog cat = JsonLd.processCatalog(catDesc); Collection results = cat.getDatasets().stream().flatMap(offer -> synchronizer.convertToQuads(graph, connector, offer).stream()).collect(Collectors.toList()); - assertEquals(2 + 24 + 32 + 10, results.size(), "Got correct number of quads (2 connector subject and 22 asset subjects + 32 shape triples + 10 node to shape relations)."); + assertEquals(2 + 22 + 32 + 10, results.size(), "Got correct number of quads (2 connector subject and 22 asset subjects + 32 shape triples + 10 node to shape relations)."); } } \ No newline at end of file From 73b23aa5bc1ef2c759e25909cf8fcfcf379f4c0c Mon Sep 17 00:00:00 2001 From: "Dr. Christoph \"Schorsch\" Jung" Date: Fri, 9 Feb 2024 14:16:28 +0100 Subject: [PATCH 4/5] feat: move asset-shapes onto the top level of the federated data catalogue for easier inference. allow to register service patterns with skills. --- .../tractusx/agents/edc/SkillStore.java | 4 +- .../agents/edc/http/AgentController.java | 36 +++++++------ .../agents/edc/service/DataManagement.java | 52 ++++++++++++------- .../agents/edc/service/EdcSkillStore.java | 6 ++- .../edc/service/InMemorySkillStore.java | 2 +- .../agents/edc/http/TestAgentController.java | 6 ++- .../service/TestDataspaceSynchronizer.java | 4 +- .../edc/sparql/TestSparqlProcessor.java | 2 +- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java index 0fc32e5..6014cbc 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java @@ -53,10 +53,12 @@ static Matcher matchSkill(String key) { * @param contract of skill optional * @param dist of skill required * @param isFederated whether skill maybe synchronized in catalogue + * @param allowServicePattern regex for service to call in skill + * @param denyServicePattern regex for services denied in skill * @param ontologies a set of ontologies * @return skill id */ - String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String... ontologies); + String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String allowServicePattern, String denyServicePattern, String... ontologies); /** * return the skill distribution diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java index 627c5b1..46c8410 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java @@ -63,13 +63,13 @@ public class AgentController { protected final SparqlQueryProcessor processor; protected final DelegationService delegationService; - /** + /** * creates a new agent controller * - * @param monitor logging subsystem + * @param monitor logging subsystem * @param agreementController agreement controller for remote skill/queries - * @param config configuration - * @param processor sparql processor + * @param config configuration + * @param processor sparql processor */ public AgentController(Monitor monitor, AgreementController agreementController, AgentConfig config, SparqlQueryProcessor processor, SkillStore skillStore, DelegationService delegationService) { this.monitor = monitor; @@ -95,7 +95,7 @@ public String toString() { * @return response */ @POST - @Consumes({"application/sparql-query", "application/sparql-results+json"}) + @Consumes({ "application/sparql-query", "application/sparql-results+json" }) public Response postSparqlQuery(@QueryParam("asset") String asset, @Context HttpHeaders headers, @Context HttpServletRequest request, @@ -118,7 +118,7 @@ public Response postSparqlQuery(@QueryParam("asset") String asset, * @return response compatible with graphdb convention */ @POST - @Consumes({"application/x-www-form-urlencoded"}) + @Consumes({ "application/x-www-form-urlencoded" }) public Response postFormQuery(@QueryParam("asset") String asset, @Context HttpHeaders headers, @Context HttpServletRequest request, @@ -143,7 +143,7 @@ public Response postFormQuery(@QueryParam("asset") String asset, */ @POST @Path("/repositories/AGENT") - @Consumes({"application/x-www-form-urlencoded"}) + @Consumes({ "application/x-www-form-urlencoded" }) public Response postFormRepositoryQuery(@QueryParam("asset") String asset, @Context HttpHeaders headers, @Context HttpServletRequest request, @@ -429,15 +429,15 @@ public Response executeQuery(String asset, HttpHeaders headers, HttpServletReque /** * endpoint for posting a skill * - * @param query mandatory query - * @param asset asset key - * @param name asset name + * @param query mandatory query + * @param asset asset key + * @param name asset name * @param description asset description - * @param version asset version - * @param contract asset contract - * @param mode asset mode + * @param version asset version + * @param contract asset contract + * @param mode asset mode * @param isFederated whether it appears in fed catalogue - * @param ontologies list of ontologies + * @param ontologies list of ontologies * @return only status */ @POST @@ -451,11 +451,13 @@ public Response postSkill(String query, @QueryParam("contract") String contract, @QueryParam("distributionMode") SkillDistribution mode, @QueryParam("isFederated") boolean isFederated, + @QueryParam("allowServicesPattern") String allowServicePattern, + @QueryParam("denyServicesPattern") String denyServicePattern, @QueryParam("ontology") String[] ontologies ) { - monitor.debug(String.format("Received a POST skill request %s %s %s %s %s %b %s ", asset, name, description, version, contract, mode.getMode(), isFederated, query)); + monitor.debug(String.format("Received a POST skill request %s %s %s %s %s %b %s %s %s ", asset, name, description, version, contract, mode.getMode(), isFederated, allowServicePattern, denyServicePattern, query)); Response.ResponseBuilder rb; - if (skillStore.put(asset, query, name, description, version, contract, mode, isFederated, ontologies) != null) { + if (skillStore.put(asset, query, name, description, version, contract, mode, isFederated, allowServicePattern, denyServicePattern, ontologies) != null) { rb = Response.ok(); } else { rb = Response.status(HttpStatus.SC_CREATED); @@ -471,7 +473,7 @@ public Response postSkill(String query, */ @GET @Path("/skill") - @Produces({"application/sparql-query"}) + @Produces({ "application/sparql-query" }) public Response getSkill(@QueryParam("asset") String asset) { monitor.debug(String.format("Received a GET skill request %s", asset)); Response.ResponseBuilder rb; diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataManagement.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataManagement.java index 27740a6..f5e42fb 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataManagement.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataManagement.java @@ -105,8 +105,9 @@ public class DataManagement { " \"proxyPath\": \"false\",\n" + " \"proxyMethod\": \"true\",\n" + " \"proxyQueryParams\": \"true\",\n" + - " \"proxyBody\": \"true\"\n" + - " }\n" + + " \"proxyBody\": \"true\",\n" + + " \"cx-common:allowServicePattern\": \"%10$s\",\n" + + " \"cx-common:denyServicePattern\": \"%11$s\"\n" + "}\n"; public static final String SKILL_ASSET_CREATE_BODY_V3 = "{\n" + @@ -140,7 +141,9 @@ public class DataManagement { " \"proxyPath\": \"false\",\n" + " \"proxyMethod\": \"true\",\n" + " \"proxyQueryParams\": \"true\",\n" + - " \"proxyBody\": \"true\"\n" + + " \"proxyBody\": \"true\",\n" + + " \"cx-common:allowServicePattern\": \"%10$s\",\n" + + " \"cx-common:denyServicePattern\": \"%11$s\"\n" + " }\n" + "}\n"; @@ -215,10 +218,10 @@ public class DataManagement { /** * creates a service wrapper * - * @param monitor logger + * @param monitor logger * @param typeManager serialization - * @param httpClient remoting - * @param config typed config + * @param httpClient remoting + * @param config typed config */ public DataManagement(Monitor monitor, TypeManager typeManager, OkHttpClient httpClient, AgentConfig config) { this.monitor = monitor; @@ -233,7 +236,7 @@ public DataManagement(Monitor monitor, TypeManager typeManager, OkHttpClient htt * TODO replace by accessing the federated data catalogue * * @param remoteControlPlaneIdsUrl url of the remote control plane ids endpoint - * @param assetId (connector-unique) identifier of the asset + * @param assetId (connector-unique) identifier of the asset * @return a collection of contract options to access the given asset * @throws IOException in case that the remote call did not succeed */ @@ -248,7 +251,7 @@ public DcatCatalog findContractOffers(String remoteControlPlaneIdsUrl, String as * Access the catalogue * * @param remoteControlPlaneIdsUrl url of the remote control plane ids endpoint - * @param spec query specification + * @param spec query specification * @return catalog object * @throws IOException in case something went wrong */ @@ -313,19 +316,23 @@ public List listAssets(QuerySpec spec) throws IOException { /** * creates or updates a given asset * - * @param assetId key - * @param name of skill - * @param description of skill - * @param version of skill - * @param contract of skill - * @param ontologies of skill - * @param distributionMode of skill - * @param isFederated whether it should be distributed - * @param query of skill + * @param assetId key + * @param name of skill + * @param description of skill + * @param version of skill + * @param contract of skill + * @param ontologies of skill + * @param distributionMode of skill + * @param isFederated whether it should be distributed + * @param query of skill + * @param allowServicePattern option allow service pattern + * @param denyServicePattern optional deny service pattern * @return idresponse * @throws IOException in case interaction with EDC went wrong */ - public IdResponse createOrUpdateSkill(String assetId, String name, String description, String version, String contract, String ontologies, String distributionMode, boolean isFederated, String query) throws IOException { + public IdResponse createOrUpdateSkill(String assetId, String name, String description, String version, String contract, + String ontologies, String distributionMode, boolean isFederated, String query, String allowServicePattern, + String denyServicePattern) throws IOException { String apiVersion = config.isPrerelease() ? "/v2" : "/v3"; var url = String.format(ASSET_CREATE_CALL, config.getControlPlaneManagementProviderUrl(), apiVersion); @@ -336,7 +343,14 @@ public IdResponse createOrUpdateSkill(String assetId, String name, String descri } String spec = config.isPrerelease() ? ASSET_CREATE_BODY : SKILL_ASSET_CREATE_BODY_V3; - var assetSpec = String.format(spec, assetId, name, description, version, contract, ontologies, distributionMode, isFederated, query); + if (allowServicePattern == null) { + allowServicePattern = config.getServiceAllowPattern().pattern(); + } + if (denyServicePattern == null) { + denyServicePattern = config.getServiceDenyPattern().pattern(); + } + var assetSpec = String.format(spec, assetId, name, description, version, contract, ontologies, distributionMode, + isFederated, query, allowServicePattern, denyServicePattern); var request = new Request.Builder().url(url).post(RequestBody.create(assetSpec, MediaType.parse("application/json"))); config.getControlPlaneManagementHeaders().forEach(request::addHeader); diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java index 2a5f26e..e9cd105 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java @@ -51,7 +51,7 @@ public boolean isSkill(String key) { } @Override - public String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String... ontologies) { + public String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String allowServicePatern, String denyServicePattern, String... ontologies) { if (name == null) { name = "No name given"; } @@ -75,7 +75,9 @@ public String put(String key, String skill, String name, String description, Str ontologiesString, dist.getDistributionMode(), isFederated, - typeManager.getMapper().writeValueAsString(TextNode.valueOf(skill)) + typeManager.getMapper().writeValueAsString(TextNode.valueOf(skill)), + allowServicePatern, + denyServicePattern ).getId(); } catch (IOException e) { return null; diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java index a0909f2..3ae3677 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java @@ -43,7 +43,7 @@ public boolean isSkill(String key) { } @Override - public String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String... ontologies) { + public String put(String key, String skill, String name, String description, String version, String contract, SkillDistribution dist, boolean isFederated, String allowServicePattern, String denyServicePattern, String... ontologies) { skills.put(key, skill); return key; } diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java index 6b52444..90e5818 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java @@ -381,7 +381,8 @@ public void testParameterizedQueryFilterContains() throws IOException { public void testParameterizedSkill() throws IOException { String query="PREFIX xsd: SELECT ?what WHERE { VALUES (?what) { (\"@input\"^^xsd:int)} }"; String asset="urn:cx:Skill:cx:Test"; - try (var response=agentController.postSkill(query,asset,null,null,null,null,SkillDistribution.ALL,false,null)) { + try (var response=agentController.postSkill(query,asset,null,null,null,null, + SkillDistribution.ALL,false,null, null, null)) { assertEquals(200,response.getStatus(),"post skill successful"); String result = testExecute("GET", null, asset, "*/*", List.of(new AbstractMap.SimpleEntry<>("input", "84"))); JsonNode root = mapper.readTree(result); @@ -399,7 +400,8 @@ public void testParameterizedSkill() throws IOException { public void testRemotingSkill() throws IOException { String query="PREFIX xsd: SELECT ?subject WHERE { SERVICE { VALUES (?subject) { (<@input>)} } }"; String asset="urn:cx:Skill:cx:Test"; - try(var response=agentController.postSkill(query,asset,null,null,null,null,SkillDistribution.ALL,false,null)) { + try(var response=agentController.postSkill(query,asset,null,null,null,null,SkillDistribution.ALL, + false,null, null, null)) { assertEquals(200,response.getStatus(),"post skill successful"); String result = testExecute("GET", null, asset, "*/*", List.of(new AbstractMap.SimpleEntry<>("input", "urn:cx:AnonymousSerializedPart#GB4711"))); JsonNode root = mapper.readTree(result); diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java index 4562320..e11894d 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/service/TestDataspaceSynchronizer.java @@ -122,7 +122,7 @@ private static JsonObjectBuilder createOffer() { JsonObjectBuilder offerBuilder = Json.createObjectBuilder() .add("@id", "cx-taxo:GraphAsset?test=ExampleAsset") .add("https://w3id.org/edc/v0.0.1/ns/contenttype", "application/json, application/xml") - .add("https://w3id.org/catenax/ontology/common#version", "1.11.16-SNAPSHOT") + .add("https://w3id.org/catenax/ontology/common#version", "1.12.17-SNAPSHOT") .add("https://w3id.org/catenax/ontology/common#name", "Test Asset") .add("https://w3id.org/catenax/ontology/common#description", "Test Asset for RDF Representation") .add("https://w3id.org/catenax/ontology/common#description@de", "Beispiel Asset für RDF Darstellung") @@ -211,7 +211,7 @@ public void testCatalogDeserialization() { " },\n" + " \"dcat:accessService\": \"ddd4b79e-f785-4e71-9fe5-4a177b3ccf54\"\n" + " },\n" + - " \"edc:version\": \"1.11.16-SNAPSHOT\",\n" + + " \"edc:version\": \"1.12.17-SNAPSHOT\",\n" + " \"http://www.w3.org/2000/01/rdf-schema#isDefinedBy\": \"\",\n" + " \"edc:name\": \"Diagnostic Trouble Code Catalogue Version 2022\",\n" + " \"http://www.w3.org/ns/shacl#shapesGraph\": \"@prefix cx-common: . \\n@prefix : .\\n@prefix cx-diag: .\\n@prefix owl: .\\n@prefix rdf: .\\n@prefix xsd: .\\n@prefix sh: .\\n\\n:OemDTC rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DTC ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:version ;\\n sh:hasValue \\\"0\\\"^^xsd:long ;\\n ] ;\\n sh:property [\\n sh:path cx-diag:affects ;\\n sh:class :OemDiagnosedParts ;\\n ].\\n\\n:OemDiagnosedParts rdf:type sh:NodeShape ;\\n sh:targetClass cx-diag:DiagnosedPart ;\\n sh:property [\\n sh:path cx-diag:provisionedBy ;\\n sh:hasValue ;\\n ] .\\n\",\n" + diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java index 8ce99d0..61f0539 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java @@ -305,7 +305,7 @@ public void testDefaultService() throws IOException { builder.url("http://localhost:8080"); builder.addHeader("Accept","application/sparql-results+json"); builder.put(RequestBody.create(query, MediaType.parse("application/sparql-query"))); - try (Response response=processor.execute(builder.build(),null,null,Map.of())) { + try (Response response=processor.execute(builder.build(),null,null,Map.of(DataspaceServiceExecutor.ALLOW_SYMBOL.getSymbol(),"(http|edc)s://.*"))) { assertTrue(response.isSuccessful(), "Successful result"); JsonNode root = mapper.readTree(Objects.requireNonNull(response.body()).string()); JsonNode bindings = root.get("results").get("bindings"); From f2330952ec588b68165a54ed9842d8b4dbd81df1 Mon Sep 17 00:00:00 2001 From: "Dr. Christoph \"Schorsch\" Jung" Date: Wed, 13 Mar 2024 12:38:48 +0100 Subject: [PATCH 5/5] chore: fix copyright period upper limit for changed files. --- .../main/java/org/eclipse/tractusx/agents/edc/SkillStore.java | 2 +- .../org/eclipse/tractusx/agents/edc/http/AgentController.java | 2 +- .../tractusx/agents/edc/service/DataspaceSynchronizer.java | 2 +- .../org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java | 2 +- .../eclipse/tractusx/agents/edc/service/InMemorySkillStore.java | 2 +- .../eclipse/tractusx/agents/edc/http/TestAgentController.java | 2 +- .../eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java index 6014cbc..aef5c27 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/SkillStore.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. diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java index 46c8410..c7fb97d 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/http/AgentController.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. diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java index a28fb21..d670322 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/DataspaceSynchronizer.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. diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java index e9cd105..c722cdf 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/EdcSkillStore.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. diff --git a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java index 3ae3677..cd7a4ac 100644 --- a/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.java +++ b/agent-plane/agent-plane-protocol/src/main/java/org/eclipse/tractusx/agents/edc/service/InMemorySkillStore.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. diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java index 90e5818..6ab99da 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/http/TestAgentController.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. diff --git a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java index 61f0539..3687801 100644 --- a/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.java +++ b/agent-plane/agent-plane-protocol/src/test/java/org/eclipse/tractusx/agents/edc/sparql/TestSparqlProcessor.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.