@prefix schema: <http://schema.org/> .
@prefix adms: <http://www.w3.org/ns/adms#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix org: <http://www.w3.org/ns/org#> .
@prefix xls2rdf: <https://xls2rdf.sparna.fr/vocabulary#> .
@prefix this: <https://data.mydomain.com/ontologies/sparnatural-config/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix skosthes: <http://purl.org/iso25964/skos-thes#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix odb: <http://example.com/ontology/odb#> .
@prefix core: <http://data.sparna.fr/ontologies/sparnatural-config-core#> .
@prefix qb: <http://purl.org/linked-data/cube#> .
@prefix datasources: <http://data.sparna.fr/ontologies/sparnatural-config-datasources#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix euvoc: <http://publications.europa.eu/ontology/euvoc#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix skosxl: <http://www.w3.org/2008/05/skos-xl#> .

<https://data.mydomain.com/ontologies/sparnatural-config> a owl:Ontology;
  owl:imports <http://data.sparna.fr/ontologies/sparnatural-config-core>, <http://data.sparna.fr/ontologies/sparnatural-config-datasources> .

odb:Manufacturer a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Manufacturer"@en, "Constructeur"@fr;
  core:faIcon "fa-solid fa-industry";
  core:tooltip "A car manufacturer is a company whose main activity is the design, construction and marketing of cars."@en,
    "Un constructeur automobile est une entreprise qui a pour activité principale la conception, la construction et la commercialisation de voitures."@fr;
  core:order "2"^^xsd:integer;
  core:defaultLabelProperty odb:name .

odb:Vehicle a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Vehicle"@en, "Véhicule"@fr;
  core:faIcon "fa-solid fa-car";
  core:tooltip "A vehicle is a car model for a specific brand."@en, "Un véhicule est un modèle de voiture pour une marque spécifique."@fr;
  core:order "1"^^xsd:integer;
  core:defaultLabelProperty odb:VIN .

odb:Diagnostic a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Diagnosis"@en, "Diagnostic"@fr;
  core:faIcon "fa-solid fa-stethoscope";
  core:tooltip "A diagnosis identifies a possible problem on your vehicle. You can request a diagnosis when you suspect a breakdown or malfunction. Using an auto diagnosis kit, the mechanic identifies the problem with your vehicle."@en,
    "Un diagnostic permet d'identifier un éventuel problème sur votre véhicule. Vous pouvez demander un diagnostic quand vous suspectez une panne ou un dysfonctionnement. À l'aide d'une valise de diagnostic auto, le mécanicien identifie le problème subi par votre véhicule."@fr;
  core:order "3"^^xsd:integer .

odb:Error a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Error"@en, "Erreur"@fr;
  core:faIcon "fa-solid fa-circle-exclamation";
  core:tooltip "An error is an element that comes up during a diagnosis, which indicates that the vehicle on which the analysis was carried out is encountering a problem."@en,
    "Une erreur est un élément qui remonte lors d'un diagnostic, qui indique que le véhicule sur lequel on a fait l'analyse rencontre un problème."@fr;
  core:order "4"^^xsd:integer .

odb:ErrorCode a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Error code"@en, "Code d'erreur"@fr;
  core:faIcon "fa-solid fa-ticket";
  core:tooltip "An error code is a set of numbers following a letter corresponding to a problem detected on your vehicle. The letter gives an indication of the family of the defect."@en,
    "Un code erreur, est un ensemble de chiffres suivant une lettre correspondant à un problème détecté sur votre véhicule. La lettre donne une indication sur la famille du défaut."@fr;
  core:order "5"^^xsd:integer .

odb:Symptom a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Symptom"@en, "Symptôme"@fr;
  core:faIcon "fa-solid fa-magnifying-glass";
  core:tooltip "A symptom is a phenomenon, perceptible or observable character linked to a state, a problem that it allows to detect, of which it is the sign."@en,
    "Un symptôme est un Phénomène, caractère perceptible ou observable lié à un état, un problème qu'il permet de déceler, dont il est le signe."@fr;
  core:order "7"^^xsd:integer;
  core:defaultLabelProperty this:symptomLabel .

odb:Component a owl:Class;
  rdfs:subClassOf core:SparnaturalClass;
  rdfs:label "Component"@en, "Composant"@fr;
  core:faIcon "fa-solid fa-gear";
  core:tooltip "A class representing a component of a vehicle."@en, "Une classe représentant un composant d'un véhicule."@fr;
  core:order "6"^^xsd:integer;
  core:defaultLabelProperty this:componentLabel .

this:Attribute a owl:Class;
  rdfs:subClassOf rdfs:Literal;
  rdfs:label "Attribute"@en, "Attribut (littéral)"@fr;
  core:faIcon "fa-solid fa-pen-to-square";
  core:tooltip "A class to display literal values (as example : text, boolean, date, etc.)"@en,
    "Une classe pour afficher les valeurs littérales."@fr .

odb:name a owl:ObjectProperty;
  rdfs:label "has name"@en, "nom"@fr;
  rdfs:subPropertyOf core:NonSelectableProperty;
  core:tooltip "Specifies the name of the manufacturer."@en, "Spécifie le nom du constructeur."@fr;
  rdfs:domain odb:Manufacturer;
  rdfs:range this:Attribute .

odb:VIN a owl:ObjectProperty;
  rdfs:label "has VIN"@en, "a pour VIN"@fr;
  rdfs:subPropertyOf core:AutocompleteProperty;
  core:tooltip "Specifies the Vehicle Identification Number (VIN) of the vehicle."@en,
    "Spécifie le numéro d'identification du véhicule (VIN)."@fr;
  rdfs:domain odb:Vehicle;
  rdfs:range this:Attribute .

odb:hasManufacturer a owl:ObjectProperty;
  rdfs:label "has manufacturer"@en, "a pour constructeur"@fr;
  rdfs:subPropertyOf core:ListProperty;
  core:tooltip "Specifies the manufacturer of the vehicle."@en, "Spécifie le constructeur d'un véhicule."@fr;
  rdfs:domain odb:Vehicle;
  rdfs:range odb:Manufacturer;
  datasources:datasource this:list_odbname_alpha;
  core:enableNegation "true"^^xsd:boolean .

this:hasDiagnosis a owl:ObjectProperty;
  rdfs:label "has diagnosis"@en, "a pour diagnostic"@fr;
  rdfs:subPropertyOf core:NonSelectableProperty;
  core:tooltip "The property is the inverse of odb:analysedVehicle."@en, "Propriété inverse de odb:analysedVehicle."@fr;
  rdfs:domain odb:Vehicle;
  rdfs:range odb:Diagnostic;
  core:sparqlString "^<http://example.com/ontology/odb#analysedVehicle>";
  core:enableNegation "true"^^xsd:boolean .

odb:diagnosticDate a owl:ObjectProperty;
  rdfs:label "has diagnosis date"@en, "date du diagnostic"@fr;
  rdfs:subPropertyOf core:TimeProperty-Date;
  core:tooltip "Defines the date on which the diagnosis occurs."@en, "Définit la date à laquelle le diagnostic a eu lieu."@fr;
  rdfs:domain odb:Diagnostic;
  rdfs:range this:Attribute;
  core:enableNegation "true"^^xsd:boolean .

odb:analysedVehicle a owl:ObjectProperty;
  rdfs:label "analysed vehicle"@en, "véhicule analysé"@fr;
  rdfs:subPropertyOf core:AutocompleteProperty;
  core:tooltip "Specifies that the vehicle has been analyzed, to identify a potential problem."@en,
    "Spécifie que le véhicule a été analysé, pour identifier un potentiel problème."@fr;
  rdfs:domain odb:Diagnostic;
  rdfs:range odb:Vehicle;
  datasources:datasource this:search_VIN_strstarts .

odb:hasResults a owl:ObjectProperty;
  rdfs:label "has results"@en, "a pour résultat"@fr;
  rdfs:subPropertyOf core:NonSelectableProperty;
  core:tooltip "Specifies the results, from the analysis."@en, "Spécifie les résultats issus de l'analyse."@fr;
  rdfs:domain odb:Diagnostic;
  rdfs:range odb:Error .

odb:diagnosticPlace a owl:ObjectProperty;
  rdfs:label "has diagnosis place"@en, "lieu du diagnostic"@fr;
  rdfs:subPropertyOf core:MapProperty;
  core:tooltip "Defines the place where the diagnosis occurs."@en, "Définit le lieu où le diagnostic a été effectué."@fr;
  rdfs:domain odb:Diagnostic;
  rdfs:range this:Attribute .

this:returnsCode a owl:ObjectProperty;
  rdfs:label "returns code"@en, "renvoie le code"@fr;
  rdfs:subPropertyOf core:ListProperty;
  core:tooltip "The property is a shortcut between Diagnosis and Error Code."@en, "Cette propriété est un raccourci entre Diagnostic et Code d'erreur."@fr;
  rdfs:domain odb:Diagnostic;
  rdfs:range odb:ErrorCode;
  core:sparqlString "<http://example.com/ontology/odb#hasResults>/<http://example.com/ontology/odb#hasErrorCode>" .

odb:alreadyRaised a owl:ObjectProperty;
  rdfs:label "already raised"@en, "déjà signalée"@fr;
  rdfs:subPropertyOf core:BooleanProperty;
  core:tooltip "Attribute indicating whether an error has already been detected previously."@en,
    "Attribut permettant de savoir si une erreur a déjà été relevée précédemment."@fr;
  rdfs:domain odb:Error;
  rdfs:range this:Attribute;
  core:enableOptional "true"^^xsd:boolean;
  core:enableNegation "true"^^xsd:boolean .

odb:hasErrorCode a owl:ObjectProperty;
  rdfs:label "has error code"@en, "a pour code d'erreur"@fr;
  rdfs:subPropertyOf core:ListProperty;
  core:tooltip "Specifies the error code relating to an error reported during a diagnostic."@en,
    "Spécifie le code erreur relatif à une erreur remontée lors d'un diagnostic."@fr;
  rdfs:domain odb:Error;
  rdfs:range odb:ErrorCode;
  core:enableNegation "true"^^xsd:boolean .

odb:hasSymptom a owl:ObjectProperty;
  rdfs:label "has symptom"@en, "a pour symptôme"@fr;
  rdfs:subPropertyOf core:ListProperty;
  core:tooltip "Specifies the symptoms associated with an error code."@en, "Spécifie le symptôme associé à un code erreur."@fr;
  rdfs:domain odb:ErrorCode;
  rdfs:range odb:Symptom;
  datasources:datasource datasources:list_rdfslabel_alpha;
  core:enableNegation "true"^^xsd:boolean .

this:hasComponentList a owl:ObjectProperty;
  rdfs:label "has component (list)"@en, "concerne le composant (liste)"@fr;
  rdfs:subPropertyOf core:ListProperty;
  core:tooltip "Specifies the components impacted by an error code."@en, "Spécifie le composant impacté par un code erreur."@fr;
  rdfs:domain odb:ErrorCode;
  rdfs:range odb:Component;
  datasources:datasource this:list_componentCode_alpha;
  core:sparqlString "<http://example.com/ontology/odb#hasComponent>";
  core:enableNegation "true"^^xsd:boolean .

this:hasComponentTree a owl:ObjectProperty;
  rdfs:label "has component (tree)"@en, "concerne le composant (arbre)"@fr;
  rdfs:subPropertyOf core:TreeProperty;
  core:tooltip "Specifies the components impacted by an error code."@en, "Spécifie le composant impacté par un code erreur."@fr;
  rdfs:domain odb:ErrorCode;
  rdfs:range odb:Component;
  core:sparqlString "<http://example.com/ontology/odb#hasComponent>";
  core:enableNegation "true"^^xsd:boolean;
  datasources:treeRootsDatasource this:tree_root_Component;
  datasources:treeChildrenDatasource this:tree_children_Component .

this:symptomLabel a owl:ObjectProperty;
  rdfs:label "label"@en, "a pour libellé"@fr;
  rdfs:subPropertyOf core:SearchProperty;
  core:tooltip "Specifies the name of the object."@en, "Spécifie le nom du Sympôme"@fr;
  rdfs:domain odb:Symptom;
  rdfs:range this:Attribute;
  core:sparqlString "<http://www.w3.org/2000/01/rdf-schema#label>" .

odb:componentCode a owl:ObjectProperty;
  rdfs:label "has component code"@en, "a pour code composant"@fr;
  rdfs:subPropertyOf core:SearchProperty;
  core:tooltip "Specifies the unique code of the component."@en, "Spécifie le code unique relatif à un composant."@fr;
  rdfs:domain odb:Component;
  rdfs:range this:Attribute .

this:componentLabel a owl:ObjectProperty;
  rdfs:label "label"@en, "a pour libellé"@fr;
  rdfs:subPropertyOf core:SearchProperty;
  core:tooltip "Specifies the name of the object."@en, "Spécifie le nom du Composant"@fr;
  rdfs:domain odb:Component;
  rdfs:range this:Attribute;
  core:sparqlString "<http://www.w3.org/2000/01/rdf-schema#label>";
  core:isMultilingual "true"^^xsd:boolean .

this:labelOrCode a owl:ObjectProperty;
  rdfs:label "label or code"@en, "a pour libellé ou code"@fr;
  rdfs:subPropertyOf core:SearchProperty;
  core:tooltip "Allows to get a label or a code."@en, "Permet de rechercher un libellé ou un code."@fr;
  rdfs:domain odb:Component;
  rdfs:range this:Attribute;
  core:sparqlString "<http://example.com/ontology/odb#componentCode>|<http://www.w3.org/2000/01/rdf-schema#label>" .

this:list_myname_count a datasources:SparqlDatasource;
  datasources:queryTemplate datasources:query_list_label_count;
  datasources:labelProperty "<http://example.com/ontology/myname>" .

this:list_skosprefLabel_alpha_with_count_langfr a datasources:SparqlDatasource;
  datasources:queryTemplate this:query_list_label_alpha_with_count_langfr;
  datasources:labelProperty skos:prefLabel .

this:list_odbname_alpha a datasources:SparqlDatasource;
  datasources:queryTemplate datasources:query_list_label_alpha;
  datasources:labelProperty odb:name .

this:search_VIN_strstarts a datasources:SparqlDatasource;
  datasources:queryTemplate datasources:query_search_label_strstarts;
  datasources:labelProperty odb:VIN .

this:list_componentCode_alpha a datasources:SparqlDatasource;
  datasources:queryString """PREFIX odb: <http://example.com/ontology/odb#>
 SELECT DISTINCT ?uri ?label
 WHERE {
 ?domain $type $domain .
 ?domain $property ?uri .
 # Note how the range criteria is not used in this query
 FILTER(isIRI(?uri))
 ?uri rdfs:label ?libelleComposant .
 FILTER(lang(?libelleComposant) = \"\" || lang(?libelleComposant) = $lang)
 ?uri odb:componentCode ?codeComposant .
 # Concat component code + component label
 BIND(CONCAT(STR(?codeComposant),\" - \",STR(?libelleComposant)) AS ?label)
 }
 ORDER BY UCASE(?label)
 LIMIT 500""" .

this:tree_root_Component a datasources:SparqlDatasource;
  datasources:queryString """PREFIX odb: <http://example.com/ontology/odb#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#label>
SELECT ?uri ?label ?hasChildren (COUNT(?x) AS ?count) WHERE {
 ?uri a odb:Component .
 # Keep only roots, that do not have any parent
 FILTER NOT EXISTS {
 ?uri odb:parentComponent ?parent .
 }
 ?uri rdfs:label ?libelleComposant .
 FILTER(lang(?libelleComposant) = \"\" || lang(?libelleComposant) = $lang)
 ?uri odb:componentCode ?codeComposant .
 # Concat component code + component label
 BIND(CONCAT(STR(?codeComposant),\" - \",STR(?libelleComposant)) AS ?label)
 OPTIONAL { ?uri ^odb:parentComponent ?children }
 BIND(IF(bound(?children),true,false) AS ?hasChildren)
 OPTIONAL {
 ?x a $domain .
 ?x $property ?uri .
 }
}
GROUP BY ?uri ?label ?hasChildren
ORDER BY ?label""" .

this:tree_children_Component a datasources:SparqlDatasource;
  datasources:queryString """PREFIX odb: <http://example.com/ontology/odb#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#label>
SELECT DISTINCT ?uri ?label ?hasChildren (COUNT(?x) AS ?count) WHERE {

 $node ^odb:parentComponent ?uri .

 ?uri rdfs:label ?libelleComposant .
 FILTER(lang(?libelleComposant) = \"\" || lang(?libelleComposant) = $lang)
 ?uri odb:componentCode ?codeComposant .
 # Concat component code + component label
 BIND(CONCAT(STR(?codeComposant),\" - \",STR(?libelleComposant)) AS ?label)
 
 OPTIONAL { ?uri ^odb:parentComponent ?children }
 BIND(IF(bound(?children),true,false) AS ?hasChildren)

 OPTIONAL {
 ?x a $domain .
 ?x $property ?uri .
 }
}
GROUP BY ?uri ?label ?hasChildren
ORDER BY ?label""" .

this:query_list_label_alpha_with_count_langfr a datasources:SPARQLQuery;
  datasources:queryString """SELECT DISTINCT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label)
WHERE {
{
 SELECT DISTINCT ?uri (COUNT(?domain) AS ?count)
 WHERE {
 ?domain a $domain .
 ?domain $property ?uri .
 FILTER(isIRI(?uri))
 # Note how the range criteria is not used in this query
 }
 GROUP BY ?uri
}
OPTIONAL { ?uri $labelPath ?theLabelLang . FILTER(lang(?theLabelLang) = $lang) }
OPTIONAL { ?uri $labelPath ?theLabelNone . FILTER(lang(?theLabelNone) = \"\") }
OPTIONAL { ?uri $labelPath ?theLabelFr . FILTER(lang(?theLabelFr) = \"fr\") }
BIND(COALESCE(?theLabelLang, ?theLabelNone, ?theLabelFr, STR(?uri)) AS ?theLabel)
}
ORDER BY UCASE(?label)
LIMIT 500""";
  rdfs:comment "A query that will list entries alphabetically with number of occurrences in parenthesis by fetching first in the user language but will default to French"@en .

this:query_list_label_count_langfr a datasources:SPARQLQuery;
  datasources:queryString """SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label)
WHERE {
{
 SELECT DISTINCT ?uri (COUNT(?domain) AS ?count)
 WHERE {
 ?domain a $domain .
 ?domain $property ?uri .
 FILTER(isIRI(?uri))
 # Note how the range criteria is not used in this query
 }
 GROUP BY ?uri
}
OPTIONAL { ?uri $labelPath ?theLabelLang . FILTER(lang(?theLabelLang) = $lang) }
OPTIONAL { ?uri $labelPath ?theLabelNone . FILTER(lang(?theLabelNone) = \"\") }
OPTIONAL { ?uri $labelPath ?theLabelFr . FILTER(lang(?theLabelFr) = \"fr\") }
BIND(COALESCE(?theLabelLang, ?theLabelNone, ?theLabelFr) AS ?theLabel)
}
ORDER BY DESC(?count) UCASE(?label)
LIMIT 500""";
  rdfs:comment "A query that will list entries by descending number of occurrences by fetching first in the user langauge but will default to French"@en .

this:query_list_label_alpha_langfr a datasources:SPARQLQuery;
  datasources:queryString """SELECT DISTINCT ?uri ?label
WHERE {
 ?domain a $domain .
 ?domain $property ?uri .
 # Note how the range criteria is not used in this query
 FILTER(isIRI(?uri))

 OPTIONAL { ?uri $labelPath ?theLabelLang . FILTER(lang(?theLabelLang) = $lang) }
 OPTIONAL { ?uri $labelPath ?theLabelNone . FILTER(lang(?theLabelNone) = \"\") }
 OPTIONAL { ?uri $labelPath ?theLabelFr . FILTER(lang(?theLabelFr) = \"fr\") }
 BIND(COALESCE(?theLabelLang, ?theLabelNone, ?theLabelFr) AS ?label)
}
ORDER BY UCASE(?label)
LIMIT 500""";
  rdfs:comment "A query that will list entries alphabetically by fetching first in the user language but will default to French"@en .

this:query_search_label_contains_langfr a datasources:SPARQLQuery;
  datasources:queryString """SELECT DISTINCT ?uri ?label
WHERE {
 ?domain a $domain .
 ?domain $property ?uri .
 ?uri a $range .
 ?uri $labelPath ?label .
 FILTER(isIRI(?uri))
 FILTER(CONTAINS(LCASE(STR(?label)), LCASE(\"$key\"))) 
 FILTER(lang(?label) = '' || lang(?label) = \"fr\")
} 
ORDER BY UCASE(?label)
LIMIT 50""";
  rdfs:comment "A query that will search in labels using contains function, first in the user language but will default to French."@en .
