linkedfactory / linkedfactory-pod

The reference implementation of the LinkedFactory APIs.
Apache License 2.0
0 stars 2 forks source link

Support querying of AAS via SPARQL #7

Open kenwenzel opened 10 months ago

kenwenzel commented 10 months ago

We should support the querying of AAS via the HTTP API defined in https://industrialdigitaltwin.org/wp-content/uploads/2023/04/IDTA-01002-3-0_SpecificationAssetAdministrationShell_Part2_API.pdf

The idea is to use a special federated service for IRIs prefixed by "aas-api:":

prefix aas: <https://admin-shell.io/aas/3/0/>
select ?sm ?element ?p ?o {
  service <aas-api:https://v3.admin-shell-io.com> {
    { select ?shell { <aas-api:endpoint> <aas-api:shells> ?shell } limit 2 }

    ?shell aas:submodels ?sm . ?sm aas:semanticId ?semId . ?semId aas:keys [ !<:> ?key ] .
    ?key aas:value "https://admin-shell.io/zvei/nameplate/1/0/Nameplate" .
    ?sm (!<:>)+ ?element .

    { ?element a aas:Property } union { ?element a aas:MultiLanguageProperty }
    ?element ?p ?o .
  }
}
kenwenzel commented 6 months ago

Conversion of key elements to IRIs:

prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix aas: <https://admin-shell.io/aas/3/0/>
base <aas://>
select distinct (group_concat(?typedKey; separator=", ") as ?ref) (group_concat(?iriPart; separator="") as ?iri) {
  { select distinct ?keys ?lp ?keyType ?keyValue {
    service <aas-api:https://v3.admin-shell-io.com> {
      { select distinct ?sm ?keys {
          { select ?shell { <aas-api:endpoint> <aas-api:shells> ?shell } limit 2 }
          ?shell aas:submodels ?sm . ?sm (!<:>)* ?element . ?element aas:keys ?keys .
        }}
      ?keys ?lp [aas:type ?keyType ; aas:value ?keyValue] .
    }
  } order by ?keys ?lp}

  bind(concat("(", ?keyType, ")", ?keyValue) as ?typedKey) .

  bind(regex(?keyValue, """^[A-Za-z][\\d+-.A-Za-z]*:[^\u0000-\u0020"<>\\^`{|}]*$""") as ?isIri)
  bind((?keyType in ("GlobalReference", "Submodel") && ?lp = rdf:_1) as ?convertToIri) 

  bind(
    if (?convertToIri, 
      if (?isIri, ?keyValue, iri(encode_for_uri(?keyValue))),
      concat(if (?lp = rdf:_2, "#", "."), encode_for_uri(?keyValue))
    ) as ?iriPart)    
} group by ?keys
VladimirAlexiev commented 4 months ago

@kenwenzel I commiserate with you! :-)

Everything in these queries cries "Help!".

I'm curious how ChatGPT would explain these queries :-) ok, not bad in general...

This expression retrieves a key (?key) linked to the semantic ID, filtering out specific relationships using the !<:> operator which excludes specific predicates.

kenwenzel commented 4 months ago

@VladimirAlexiev The second query can be used to construct IRIs for lists with aas:keys. It was based on our first idea to use existing IRIs as they are and append local identifiers (short IDs) to a base IRI.

The problem with this approach is that some external data sets (like EClass) use a very specific mapping to convert IRDIs to IRIs. That would require to consider all those specifics within a mapping algorithm for converting keys to IRIs.