Trying to write out a Turtle serialized class definition

75 views
Skip to first unread message

Steve Ray

unread,
Mar 17, 2021, 7:01:58 PM3/17/21
to TopBraid Suite Users
Hi,
I'm using SWP to generate a bunch of .ttl files that will be available to the LinkedData community for resolving class definitions. I'm hoping to use the code below that works fine for our instance data, but this code doesn't do the right thing when there are bnodes (such as restriction classes). 
This is written as a ui prototype that is a subClass of ui:TurtleServices.

Is there some setting to have it also serialize the bnodes? Here's the ui:prototype code:

<ui:group let:extension=".ttl"

          let:myGraphU="{= ui:graphWithImports(IRI(?graph)) }"

          let:myInstance="{= IRI(?instance) }"

          let:newPath="{= CONCAT(&quot;/generatedFiles/&quot;, xsd:string(?folder), &quot;/&quot;) }">

    <ui:debug>

        <span>Inside VersionlessIndividual. Value of ?newPath is {= ?newPath }</span>

    </ui:debug>

    <ui:dumpScope ui:message="AAA:VersionlessIndividual, newPath= {= ?newPath }"/>

    <ui:group let:localName="{= afn:localname(?myInstance) }">

        <ui:group let:newFile="{= CONCAT(?newPath, ?localName, ?extension) }">

            <ui:dumpResultSet ui:message="AAA:VersionlessGraph, newUnit= " ui:resultSet="{= ?instance }"/>

            <ui:setContext ui:silentTransactions="true">

                <ui:setContext ui:queryGraph="ui:tempGraph">

                    <!-- Clear out the working graph-->

                    <ui:update ui:updateQuery="{!

                            DELETE {

                                GRAPH ui:tempGraph {

                                    ?s ?p ?o .

                                } .

                            }

                            WHERE {

                                ?s ?p ?o .

                            } }"/>

                    <ui:update ui:updateQuery="{!

                            INSERT {

                                GRAPH ui:tempGraph {

                                    ?myInstance ?p ?o .

                                } .

                            }

                            WHERE {

                                GRAPH ?myGraphU {

                                    ?myInstance ?p ?o .

                                } .

                            } }"/>

                    <ui:return/>

                </ui:setContext>

            </ui:setContext>

        </ui:group>

    </ui:group>

</ui:group>



...which produces the following file:


image.png

I want all the stuff inside the [] to show up as well!



Steve


Holger Knublauch

unread,
Mar 17, 2021, 7:08:07 PM3/17/21
to topbrai...@googlegroups.com

Hi Steve,

you could just use SPARQL DESCRIBE queries, which will compute the graph for a resource including its depending blank nodes, e.g.

DESCRIBE <http://topquadrant.com/ns/examples/geography#Country>

via the SPARQL endpoint.

Holger

--
You received this message because you are subscribed to the Google Groups "TopBraid Suite Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topbraid-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/topbraid-users/CAGUep85DXyHFA%3DwmgdArgZnw-k6EHPJ5AsRDwYsHBT65sU2csg%40mail.gmail.com.

Steve Ray

unread,
Mar 17, 2021, 8:12:05 PM3/17/21
to TopBraid Suite Users
Interesting. The DESCRIBE query sounds intriguing, but I need to create the .ttl files so that when somebody types 


...it resolves to the Turtle code, without using a SPARQL endpoint.

Just like if you type http://qudt.org/vocab/unit/A you get the definition of the Ampere. (Content negotiation will give you either html or ttl depending on the header, so a browser yields html).

Can I use DESCRIBE inside a ui:TurtleServices web service? I tried with ui:update, but that expects an INSERT or DELETE. Am I making this more complicated than it needs to be?


Steve




Holger Knublauch

unread,
Mar 17, 2021, 8:43:14 PM3/17/21
to topbrai...@googlegroups.com

On the server that hosts your namespace, can't you set up a rewrite that generates

http://mytopbraid...:8083/tbl/sparql?query=DESCRIBE%20<XY>

where you replace XY with the URL-encoded URI of the resource that was requested? See e.g.

    https://httpd.apache.org/docs/2.4/rewrite/remapping.html

but this sounds like a problem someone must have solved before. Given that you plan to call a SWP service, how do you currently redirect the URLs to invoke said service?

You cannot use DESCRIBE in ui:TurtleService and I am not aware of a magic property that would get all depending triples of the concise bounded description. SPARQL is not good at recursion.

Holger

robatki...@gmail.com

unread,
Mar 18, 2021, 1:08:25 AM3/18/21
to TopBraid Suite Users

To take this one step further,  EDG supports using SHACL to provide view options in the UI.

it strikes me this is equally relevant to the serialisation of a specific object in TTL (or anything else).

Is there an equivalent service that can do this?  

 One option that occurred to me would be to create a graphQL template based on a nodeshape - then  the result (currently serialised as json) could perhaps be serialised as json-ld and ttl

This also leads to the question of how to best work with blank nodes in SHACL 

this seems to be bypassed in the UI - it does this traversal with a function. 

query: "query getSuitableViewShapes($uri: ID!) {↵ resources(uri: $uri) {↵           

Is there any way of doing something similar with a user defined shape that can traverse blank nodes?



Holger Knublauch

unread,
Mar 18, 2021, 1:26:38 AM3/18/21
to topbrai...@googlegroups.com


On 2021-03-18 3:08 pm, robatki...@gmail.com wrote:

To take this one step further,  EDG supports using SHACL to provide view options in the UI.

it strikes me this is equally relevant to the serialisation of a specific object in TTL (or anything else).

Is there an equivalent service that can do this?  

 One option that occurred to me would be to create a graphQL template based on a nodeshape - then  the result (currently serialised as json) could perhaps be serialised as json-ld and ttl

GraphQL is not good at recursion - it can only produce JSON that has a similar structure to the query clauses. So a query with depth 3 can only go 3 levels of bnodes deep. In cases like OWL rdfs:subClassOf ... owl:Restriction ... where the structure of the classes is difficult to predict it will be an overkill to first try to build such a complex GraphQL query.

In SWP this can be achieved through a recursive helper element that walks objects as long as they are blank nodes and collects all triples in the ui:tempGraph. In Active Data Shapes (ADS) such recursion is easily done because it's JavaScript, yet ADS doesn't have a simple way to produce Turtle yet.


This also leads to the question of how to best work with blank nodes in SHACL 

this seems to be bypassed in the UI - it does this traversal with a function. 

query: "query getSuitableViewShapes($uri: ID!) {↵ resources(uri: $uri) {↵           

Is there any way of doing something similar with a user defined shape that can traverse blank nodes?

Potentially yes, and I probably prototyped something along those lines at some stage.

In cases like our form editors and viewers, the system only fetches the top-level triples and if it's a blank node then each widget may make additional requests to walk the structure. For many types of blank nodes we also already have string/label renderers.

Holger


Holger Knublauch

unread,
Mar 18, 2021, 2:19:40 AM3/18/21
to topbrai...@googlegroups.com


On 2021-03-18 3:26 pm, Holger Knublauch wrote:
In Active Data Shapes (ADS) such recursion is easily done because it's JavaScript, yet ADS doesn't have a simple way to produce Turtle yet.

This info is now outdated. I have just added a quick new function IO.serializeRDF to ADS for 7.0, and it can be used to produce any subgraphs including the concise bounded description as follows:

This can be combined with the newly added support for defining ADS Web services in 7.0:

    http://datashapes.org/active/service.html#response-rdf

and then be called like this:

BTW the query behind the Source Code panel can also be used for this particular task, which is why I am showing it in the first screenshot. However, I wanted to come up with a more general solution here.

HTH
Holger


Steve Ray

unread,
Mar 24, 2021, 10:07:31 PM3/24/21
to TopBraid Suite Users
Holger,
I was excited to try out 7.0 with the Turtle output, and indeed, it works as advertised. We should be able to use this in the future with our SHACL version of QUDT. 
However, I have one big gotcha, which is that I cannot use it for the OWL version of QUDT, since those classes are not NodeShapes. I'm still trying to satisfy the needs of the Linked Data community.
So I plan to return to your earlier suggestion of using DESCRIBE and see if I can do something with that.
I am curious, though, how TBC generates the Turtle serialization of regular OWL files today? Can I use whatever is used "under the hood" for this?

Steve




--
You received this message because you are subscribed to the Google Groups "TopBraid Suite Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topbraid-user...@googlegroups.com.

Holger Knublauch

unread,
Mar 25, 2021, 2:07:40 AM3/25/21
to topbrai...@googlegroups.com

There is an undocumented SPARQL function

    BIND (<http://datashapes.org/generic#getTurtleSourceCode>(?this) AS ?src)

that corresponds to what the Source Code panel of the EDG editor shows. The Linked Data community may not be happy because this only produces TTL, not RDF/XML though.

Holger

Steve Ray

unread,
Mar 25, 2021, 9:02:08 PM3/25/21
to TopBraid Suite Users
Holger,
Apologies for drawing this out for so long. 

I realized that since owl:Class is actually declared as a NodeShape in TBC, then the classes defined in our OWL schema, which are instances of owl:Class, should be able to take advantage of the ADS approach, right?

So I proceeded to study your reference to ADS web services at http://datashapes.org/active/service.html#response-rdf, and if I understand correctly, I can simply declare a dash:ResourceService with a dash:responseContentType of "text/turtle" and I will automatically get the Turtle serialization, yes? So, I tried a very simple service called qudt:TurtleSnippet, to see if I could get a web service to deliver me the Turtle "snippet" for a defined class. The file is attached.
I succeeded in getting EDG to recognize the service. (I wasn't sure whether I need to create an EDG collection, but I went ahead and did that, and imported both the OWL schema file and the ADS service file into that single collection).
Here's the Swagger view:

image.png
You can see that it failed, even though I did associate owl:Class with the new service, as shown in the attached file.
(In case it is too small, the error is "Cannot call service qudt:TurtleSnippet on focus node <http%3A%2F%2Fqudt.org%2Fschema%2Fqudt%2FUnit>: service is not declared as dash:resourceService for any of the (indirect) types of the focus node, or the type associated with the service is not a shape"

I also made our QUDT OWL schema file import my ADS service ontology file.

Finally, I also tried pasting this URL into a Chrome browser window:

which resulted in :
Cannot evaluate Script:org.topbraid.core.servlet.HttpErrorException: Failed service request /qudt_owl_schema/qudt/TurtleSnippet/URI/http://qudt.org/schema/qudt/Unit: http://qudt.org/schema/qudt/Unit is not a literal node

So, I'm still not getting it, clearly.
Once more, you are a tremendous help, and I'm hoping others will benefit from my crawling progress with active data shapes web services.


--
You received this message because you are subscribed to the Google Groups "TopBraid Suite Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topbraid-user...@googlegroups.com.
ADS_QUDT-WEBSITE-v2-1.shapes.ttl

Holger Knublauch

unread,
Mar 26, 2021, 5:49:02 AM3/26/21
to topbrai...@googlegroups.com

Hi Steve,

you were really close, mate. When you enter URLs from the Swagger UI, it will do the URL-encoding for you, so just use URI and then http://qudt.org/schema/qudt/Unit as second param and it will work. As written, it would have been double-escaped.

This however assumes that you change the dash:js to

graph.triples(focusNode, null, null)

because the engine will only return Turtle if the result of the JS is an array of triples. Just doing "focusNode" would not have been an array. (You can of course produce the array differently - the above graph.triples() function was just the quickest way. Note this won't include transitive bnodes, but I sent you that snippet in case you need it earlier in this thread.

HTH
Holger

Steve Ray

unread,
Mar 26, 2021, 2:56:59 PM3/26/21
to TopBraid Suite Users
This is great - it works! 
The one "hack" I had to do in my service file was to declare various other owl entities as NodeShapes. I tried just declaring rdfs:Resource as a NodeShape, hoping all the subClasses would inherit the NodeShapeness, but that did not work. So instead, I have added lines like the following in my service file:

owl:ObjectProperty
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
owl:DatatypeProperty
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
rdf:Property
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
qudt:Unit
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.

I recognize that I'm trying to get the benefit of ADS while servicing "pure" OWL ontologies, without altering the OWL schema file, but it works.

One final question - the output lists an enormous number of prefix declarations, most of which are not relevant to the entity. Does the service just dump all defined prefixes? Any way I can throttle that?
Here is a sample output for a datatype property:

@prefix ADS_QUDT-WEBSITE-v2-1: <http://r2.qudt.org/website/ADS_QUDT-WEBSITE-v2-1#> .
@prefix afn: <http://jena.hpl.hp.com/ARQ/function#> .
@prefix arg: <http://spinrdf.org/arg#> .
@prefix constant: <http://qudt.org/vocab/constant/> .
@prefix creativecommons: <http://creativecommons.org/ns#> .
@prefix dash: <http://datashapes.org/dash#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix dtype: <http://www.linkedmodel.org/schema/dtype#> .
@prefix edg: <http://edg.topbraid.solutions/model/> .
@prefix fn: <http://www.w3.org/2005/xpath-functions#> .
@prefix functions: <http://qudt.org/2.1/schema/extensions/functions#> .
@prefix graphql: <http://datashapes.org/graphql#> .
@prefix imports: <http://qudt.org/2.1/schema/extensions/imports#> .
@prefix mc: <http://www.linkedmodel.org/owl/schema/core#> .
@prefix metadata: <http://topbraid.org/metadata#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix prefix: <http://qudt.org/vocab/prefix/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix qkdv: <http://qudt.org/vocab/dimensionvector/> .
@prefix quantitykind: <http://qudt.org/vocab/quantitykind/> .
@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix qudt.type: <http://qudt.org/vocab/type/> .
@prefix qudt_owl_schema: <http://example.org/ontologies/QUDT_OWL_Schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix skosxl: <http://www.w3.org/2008/05/skos-xl#> .
@prefix smf: <http://topbraid.org/sparqlmotionfunctions#> .
@prefix sou: <http://qudt.org/vocab/sou/> .
@prefix sp: <http://spinrdf.org/sp#> .
@prefix spif: <http://spinrdf.org/spif#> .
@prefix spin: <http://spinrdf.org/spin#> .
@prefix spl: <http://spinrdf.org/spl#> .
@prefix swa: <http://topbraid.org/swa#> .
@prefix teamwork: <http://topbraid.org/teamwork#> .
@prefix teamworkconstraints: <http://topbraid.org/teamworkconstraints#> .
@prefix tosh: <http://topbraid.org/tosh#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix vaem: <http://www.linkedmodel.org/schema/vaem#> .
@prefix voag: <http://voag.linkedmodel.org/schema/voag#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

qudt:acronym
  rdf:type owl:DatatypeProperty ;
  rdfs:isDefinedBy <http://qudt.org/2.1/schema/qudt> ;
  rdfs:label "acronym" ;
  rdfs:range xsd:string ;
.

Steve




Holger Knublauch

unread,
Mar 26, 2021, 6:14:54 PM3/26/21
to topbrai...@googlegroups.com


On 27/03/2021 4:56 am, Steve Ray wrote:
This is great - it works! 
The one "hack" I had to do in my service file was to declare various other owl entities as NodeShapes. I tried just declaring rdfs:Resource as a NodeShape, hoping all the subClasses would inherit the NodeShapeness, but that did not work. So instead, I have added lines like the following in my service file:

owl:ObjectProperty
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
owl:DatatypeProperty
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
rdf:Property
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.
qudt:Unit
rdf:type sh:NodeShape ;
dash:resourceService qudt:TurtleSnippet ;
.

I recognize that I'm trying to get the benefit of ADS while servicing "pure" OWL ontologies, without altering the OWL schema file, but it works.
You don't really have to use SHACL to benefit from ADS. For generic services that just use functions like graph.triples you can simply make them dash:GraphService and pass in the focus node by some other means, as a named parameter. Such GraphServices can then be called for any resource.


One final question - the output lists an enormous number of prefix declarations, most of which are not relevant to the entity. Does the service just dump all defined prefixes? Any way I can throttle that?

No, the algorithm isn't smart enough to analyze which prefixes are actually used. If that's bothering you, you could first build the string with IO.serializeRDF(triples) and then delete certain lines. That is quite a hack though. In the end it's just cosmetic I guess - the receiving apps shouldn't bother.

Holger


Reply all
Reply to author
Forward
0 new messages