Skip to main content

Loading the Schema from a SPARQL Endpoint

When a SPARQL 1.1 endpoint (e.g. Apache Jena Fuseki) hosts the CGMES RDFS schema as named graphs, CIMVocabCheck can discover the schema — and the per-graph profile scope — automatically. No namedGraphs config required.

The endpoint is a schema source, not a validation target

The endpoint names where the schema lives. CIMVocabCheck reads the RDFS profiles from it; it never validates live instance data and never executes your query against it.

How it works

EndpointSchemaLoader:

  1. enumerates the schema graphs — those declaring an rdfs:Class / owl:Ontology — and builds the index from them;
  2. classifies every other (instance) graph by sampling up to 400 of its terms — the predicates it uses and its rdf:type objects — and looking each one up in the schema. A term declared by exactly one profile is discriminating (the "this property is in EQ but in no other profile" signal); the graph is assigned to the profile with the most discriminating terms, with the total number of matching terms as a tie-break. A graph whose sampled terms match no profile is left unmatched.

Classification only ever samples a graph to decide which profile it is — it never validates the instance data.

Per-graph validation — terms used in the wrong graph become errors

Once every graph is mapped to a profile, your query is validated per graph: the terms inside a GRAPH <g> { ... } block are checked against only the profile detected for <g>, not the union of all profiles. This is what makes auto-resolution useful — it catches terms used in the wrong graph.

For example, if the dataset's equipment graph was detected as Equipment (EQ) and the query uses a Topology-only property inside it:

SELECT * WHERE {
GRAPH <urn:uuid:...-eq> {
?n cim:TopologicalNode.nominalVoltage ?v . # a TP property, inside the EQ graph
}
}

CIMVocabCheck reports UNKNOWN_PROPERTY for cim:TopologicalNode.nominalVoltage against the EQ graph — and because the property does exist in the Topology profile, the finding lists Topology in its found in other profiles hint, telling you the term is real but sits in the wrong graph. Graphs the query references that were left unmatched (or that don't exist in the dataset) produce a GRAPH_NOT_CONFIGURED warning, and terms inside them cannot be resolved.

When per-graph scoping applies

Auto-resolution is an endpoint feature. With a file-based schema and no namedGraphs mapping, every term is validated against all loaded profiles at once, so there are no per-graph cross-profile errors. Per-graph scoping happens either here (auto-detected from the endpoint) or when you map graphs to profiles by hand with namedGraphs.

From Java

import de.soptim.opencgmes.cimvocabcheck.core.schema.EndpointSchema;
import de.soptim.opencgmes.cimvocabcheck.core.schema.EndpointSchemaLoader;
import de.soptim.opencgmes.cimvocabcheck.core.SparqlValidationApi;
import de.soptim.opencgmes.cimvocabcheck.core.SparqlValidationResult;
import java.time.Duration;

EndpointSchema es = EndpointSchemaLoader.loadFromEndpoint(
"http://localhost:3030/cgmes/query", Duration.ofSeconds(30));

if (!es.hasSchema()) {
// Reachable, but no CIM schema graphs found — warn and fall back to syntax-only.
SparqlValidationResult r = SparqlValidationApi.checkSyntaxOnly(queryText);
} else {
SparqlValidationApi api = new SparqlValidationApi(es.index());
// es.namedGraphScope() maps each instance graph to its detected profile(s):
SparqlValidationResult r = api.validateSparql(queryText, es.namedGraphScope());
// es.unmatchedGraphs() lists instance graphs that matched no known profile.
}

A Fuseki …/update URL is tolerated (its …/query sibling is used automatically). For in-process datasets or tests, pass a SparqlGraphSource to EndpointSchemaLoader.load(...) instead.

!es.hasSchema() covers two different situations, both distinguishable via es.schemaGraphNames() and es.unresolvedReason():

  • No schema-like graphs at all (schemaGraphNames() empty) — the endpoint genuinely hosts no rdfs:Class/owl:Ontology graph.
  • Schema graphs found, but none resolved to a CIM profile (schemaGraphNames() non-empty, unresolvedReason() set) — almost always an unrecognized cim namespace. Register it with cimNamespaces in opencgmes.jsonc and reload.

The CLI and language server print distinct warnings for each case rather than a single generic "no schema" message.

From the CLI

java -jar cimvocabcheck-cli.jar \
--endpoint http://localhost:3030/cgmes/query path/to/query.rq

If the endpoint exposes no CIM schema graphs, validation falls back to a syntax-only check with a warning. Pass --strict-endpoint to make that case a hard failure (exit 2) instead — so a misconfigured pipeline breaks visibly rather than silently checking only syntax. See the CLI page.

From a SPARQL Notebook cell

In CIMNotebook, a notebook cell can name its schema endpoint inline:

# [endpoint=http://localhost:3030/cgmes/query]
SELECT * WHERE { ?s a cim:ACLineSegment }

Assumptions & limitations

  • The CGMES profiles must be stored in per-profile named graphs (graphs declaring rdfs:Class / owl:Ontology). A schema kept entirely in the default graph, or mixed with instance data in one graph, is not discovered.
  • A profile graph that declares neither an rdfs:Class nor an owl:Ontology (rare — e.g. some header/boundary profiles) is not picked up by the enumeration filter.
  • Graphs fetched over SPARQL usually carry no prefix declarations, so a custom cim namespace can only be recognized once it's registered — via cimNamespacesbefore the endpoint load runs; there's no way to auto-detect an unregistered custom namespace from namespace-less graph content alone.

See Known limitations for the broader picture.