Closed danaivach closed 6 months ago
ArtifactProfileGraphWriterTest.java:352
fails as follows (see sh:path hmas:hasInput
):
Sept 18, 2023 1:51:15 PM ch.unisg.ics.interactions.hmas.interaction.io.ArtifactProfileGraphWriterTest assertIsomorphicGraphs
INFO: Expected:
@prefix hmas: <https://purl.org/hmas/> .
@prefix hctl: <https://www.w3.org/2019/wot/hypermedia#> .
@prefix prs: <http://example.org/prs#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix urn: <http://example.org/urn#> .
@prefix xs: <http://www.w3.org/2001/XMLSchema#> .
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix ex: <http://example.org/> .
@prefix htv: <http://www.w3.org/2011/http#> .
<urn:profile> a hmas:ResourceProfile ;
hmas:isProfileOf [ a hmas:Artifact ] ;
hmas:exposesSignifier ex:signifier .
ex:signifier a hmas:Signifier ;
hmas:signifies ex:moveGripperSpecification .
ex:moveGripperSpecification a sh:NodeShape ;
sh:class hmas:ActionExecution ;
sh:property [
sh:path prov:used ;
sh:minCount "1"^^xs:int;
sh:maxCount "1"^^xs:int ;
sh:hasValue ex:httpForm
] ;
sh:property [
sh:path hmas:hasInput;
sh:qualifiedValueShape ex:gripperJointShape ;
sh:qualifiedMinCount "1"^^xs:int ;
sh:qualifiedMaxCount "1"^^xs:int
] .
ex:httpForm a hctl:Form ;
hctl:hasTarget <https://api.interactions.ics.unisg.ch/leubot1/v1.3.4/gripper> ;
hctl:forContentType "application/json" ;
htv:methodName "PUT" .
ex:gripperJointShape a sh:NodeShape ;
sh:class ex:GripperJoint ;
sh:property [
sh:path ex:hasGripperValue ;
sh:minCount "1"^^xs:int;
sh:maxCount "1"^^xs:int;
sh:datatype xs:integer
] .
Sept 18, 2023 1:51:15 PM ch.unisg.ics.interactions.hmas.interaction.io.ArtifactProfileGraphWriterTest assertIsomorphicGraphs
INFO: Actual:
@prefix prs: <http://example.org/prs#> .
@prefix hctl: <https://www.w3.org/2019/wot/hypermedia#> .
@prefix htv: <http://www.w3.org/2011/http#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix urn: <http://example.org/urn#> .
@prefix ex: <http://example.org/> .
@prefix xs: <http://www.w3.org/2001/XMLSchema#> .
@prefix hmas: <https://purl.org/hmas/> .
<urn:profile> a hmas:ResourceProfile;
hmas:exposesSignifier ex:signifier;
hmas:isProfileOf [ a hmas:Artifact
] .
ex:signifier a hmas:Signifier;
hmas:signifies ex:moveGripperSpecification .
ex:moveGripperSpecification a sh:NodeShape;
sh:class hmas:ActionExecution;
sh:property [
sh:path prov:used;
sh:minCount "1"^^xs:int;
sh:maxCount "1"^^xs:int;
sh:hasValue ex:httpForm
], [
sh:qualifiedValueShape ex:gripperJointShape;
sh:path hmas:hasInput
] .
ex:httpForm a hctl:Form;
hctl:hasTarget <https://api.interactions.ics.unisg.ch/leubot1/v1.3.4/gripper>;
htv:methodName "PUT";
hctl:forContentType "application/json" .
ex:gripperJointShape a sh:NodeShape;
sh:class ex:GripperJoint;
sh:property [
sh:path ex:hasGripperValue;
sh:datatype xs:integer
] .
expected: <true> but was: <false>
Expected :true
Actual :false
Notes:
@base
of a serialized resource profile should be equal to the IRI of the ResourceProfile
object.ActionSpecification actionSpec = (ActionSpecification) signifier.getResource();
should be ActionSpecification actionSpec = signifier.getActionSpecification()
;CompoundInput
could be of type SHACL.TERM.NODE_SHAPE
, like ActionSpecification
. It could also be renamed to InputSpecification
(and respectively, CompoundInputSpecification
) since it has the attributes of a SHACL shape.ActionExecution
, e.g. if a signifier specifies that
ex:actionSpec a sh:NodeShape ; sh:class hmas:ActionExecution, saref:ToggleCommand
, then we could test the following:
Set<String> actionTypes = actionSpec.getRequiredSemanticTypes(); // or something similar
assertEquals(1, actionTypes.size());
actionTypes.contains("https://saref.etsi.org/core/ToggleCommand");
inputSpec.getRequiredSemanticTypes()
.Input
(or CompoundInput
) could be: getClazz()
-> getRequiredSemanticTypes()
, getPath()
-> getRequiredProperties()
, getDataType()
-> getRequiredDataType()
. ActionSpecification
could be: withInput()
-> setRequiredInput()
SimpleInput
, CompoundInput
and the relationships between them? Also, would you mind taking a look at this SHACL implementation for Java: https://github.com/TopQuadrant/shacl/tree/master/src/main/java/org/topbraid/shacl/model? It may provide some input on how different SHACL-related classes relate to each other, so that the dependencies become more generic and less example-driven. Are any classes there that you consider subclassable to save work? We should discuss the case of SimpleInput
, again. Changes on this class (and, generally, this last bullet point) are not a priority.Suggested test related to the above (the test is for the reader, but the example could be used on the writer too):
@Test
public void testReadArtifactProfileSemanticTypes() {
String expectedProfile = PREFIXES +
".\n" +
"@prefix saref: <https://saref.etsi.org/core/> .\n" +
"@prefix xs: <https://www.w3.org/2001/XMLSchema#> .\n" +
"@prefix htv: <http://www.w3.org/2011/http#> .\n" +
"<http://example.org/workspaces/meetingroom/artifacts/lightbulb1> a hmas:ResourceProfile ;\n" +
" hmas:isProfileOf <http://example.org/workspaces/meetingroom/artifacts/lightbulb1#artifact>;\n" +
" hmas:exposesSignifier [ a hmas:Signifier ;\n" +
" hmas:signifies <http://example.org/workspaces/meetingroom/artifacts/lightbulb1#toggle> ; ] .\n" +
"\n" +
"<http://example.org/workspaces/meetingroom/artifacts/lightbulb1#artifact> a hmas:Artifact, saref:LightSwitch .\n" +
"\n" +
"<http://example.org/workspaces/meetingroom/artifacts/lightbulb1#toggle> a sh:NodeShape;\n" +
" sh:class hmas:ActionExecution, saref:ToggleCommand ;\n" +
" sh:property [\n" +
" sh:path prov:used ;\n" +
" sh:minCount 1;\n" +
" sh:maxCount 1 ;\n" +
" sh:hasValue <http://example.org/workspaces/meetingroom/artifacts/lightbulb1#form> ;\n" +
" ] ;\n" +
" sh:property [\n" +
" sh:path hmas:hasInput;\n" +
" sh:qualifiedValueShape <http://example.org/workspaces/meetingroom/artifacts/lightbulb1#input> ;\n" +
" sh:qualifiedMinCount 1 ;\n" +
" sh:qualifiedMaxCount 1 \n" +
" ] .\n" +
"\n" +
"<http://example.org/workspaces/meetingroom/artifacts/lightbulb1#input> a sh:NodeShape ;\n" +
" sh:class saref:OnOffState ;\n" +
" sh:property [\n" +
" sh:path saref:hasValue ;\n" +
" sh:minCount 1;\n" +
" sh:maxCount 1 ;\n" +
" sh:datatype xs:integer\n" +
" ] .\n" +
"\n" +
"<http://example.org/workspaces/meetingroom/artifacts/lightbulb1#form> a hctl:Form ;\n" +
" hctl:hasTarget <https://example.org/light> ;\n" +
" hctl:forContentType \"application/json\" ;\n" +
" htv:methodName \"PUT\" .";
ArtifactProfile profile = ArtifactProfileGraphReader.readFromString(expectedProfile);
Artifact artifact = profile.getArtifact();
assertEquals(ARTIFACT, artifact.getTypeAsIRI());
assertTrue(artifact.getIRI().isPresent());
assertTrue(artifact.getSemanticTypes().contains("https://saref.etsi.org/core/LightSwitch"));
assertEquals(1, profile.getExposedSignifiers().size());
Set<Signifier> signifiers = profile.getExposedSignifiers();
List<Signifier> signifiersList = new ArrayList<>(signifiers);
Signifier signifier = signifiersList.get(0);
assertEquals(0, signifier.getRecommendedAbilities().size());
ActionSpecification actionSpec = signifier.getActionSpecification();
Set<Form> forms = actionSpec.getForms();
assertEquals(1, forms.size());
Set<String> actionTypes = actionSpec.getRequiredSemanticTypes();
assertEquals(1, actionTypes.size());
actionTypes.contains("https://saref.etsi.org/core/ToggleCommand");
Optional<InputSpcefication> inputSpec = actionSpec.getInputSpecfication();
assertTrue(inputSpec.isPresent());
CompoundInput comInputSpec = (CompoundInput) inputSpec.get();
Set<String> inputTypes = comInputSpec.getRequiredSemanticTypes(); //defined as a `Set` since there can be more than one objects for the property `sh:class`
assertEquals(1, inputTypes.size());
actionTypes.contains("https://saref.etsi.org/core/OnOffState");
assertEquals("https://saref.etsi.org/core/hasValue",
((SimpleInput) comInputSpec.getInputs().stream().findFirst().get()).getRequiredProperties());
assertEquals("https://www.w3.org/2001/XMLSchema#integer",
((SimpleInput) input.getInputs().stream().findFirst().get()).getRequiredDataType());
/* To be discussed
Set<Property> properties = comInputSpec.getRequiredProperties();
assertEquals(1, inputTypes.size());
actionTypes.contains("https://saref.etsi.org/core/OnOffState");
assertTrue((comInputSpec.getRequiredProperties.stream().findFirst().get()).getSemanticTypes().contains(https://saref.etsi.org/core/hasValue));
assertEquals("https://www.w3.org/2001/XMLSchema#integer", (comInputSpec.getRequiredProperties.stream().findFirst().get()).getRequiredDataType());
*/
}
Feature: read and write a signifier like the following: