OpenSysML accepts OSLC Query 3.0 text as an element-identification query over the symbols in a parsed model, and over the objects a session holds of them. It is not an OSLC server: this implementation does not provide query capabilities, result containers, service providers, or resource shapes.
The text is a translation into the document-query plans of
QVTS: internal/doc/querytranslate parses it into a
transport-neutral query, compiles that to the plan IR of internal/ir/queryplan
(WhereType, WhereName, WhereFeature, WhereText, Project, OrderBy,
Objects, Except), and internal/doc/queryexec executes the plan exactly as it
executes a DocumentQueries query. The structured API Query of the gRPC
service is translated by the same package onto the same operations, so the
three query spellings read the model with one semantics and refuse with one
record, the query outcome.
The supported filter is a compound term:
compound ::= term (" and " term)*
term ::= identifier comparison_op value
| identifier " in" " "? "[" value ("," value)* "]"
| identifier "{" compound "}"
comparison_op ::= "=" | "!=" | "<" | ">" | "<=" | ">="
Identifiers are prefixed names. Values may be <uri> (with \> and \\
escapes, as the specification's uri_ref_esc), a prefixed name, quoted
strings (with \" and \\ escapes), true, false, or a decimal. A decimal
is the lexical form of xsd:decimal: an optional sign, digits and an optional
decimal point (42, -3.5, .5); an exponent, inf or NaN is refused
rather than read as a number. The supported typed literal suffixes are
^^xsd:string, ^^xsd:boolean, ^^xsd:integer, ^^xsd:decimal,
^^xsd:double, and ^^rdf:XMLLiteral, which the specification lets a server
read as a plain string and this implementation does.
A <uri> in the SysML namespace and the prefixed name that expands to it are
the same value, so rdf:type=<https://www.omg.org/spec/SysML#PartUsage>,
rdf:type=sysml:PartUsage, and rdf:type="PartUsage" select alike. A model
qualified name is a literal, not a prefixed name: write
sysml:qualifiedName="Robot::Platform::battery" with the quotes. The same
holds for sysml:type, whose values are the qualified names of typing
definitions. A bare name is not a value: sysml:name=battery is refused, and
the diagnostic names the quoted form to write.
A scoped term sysml:owner{sysml:name="Platform"} constrains a related
element: the term inside the braces is evaluated over the element the property
names, so the example keeps the elements owned by something named Platform.
Scoped terms nest (sysml:owner{sysml:owner{sysml:name="Robot"}}) and take
compound terms, and they apply to any element-valued property, a scoped
rdf:type reading the related element's metaclass.
The oslc.where, oslc.select, oslc.orderBy, oslc.searchTerms, and
oslc.prefix parameters may be supplied as a URL-encoded query-parameter
string. Standard decoding applies: + means a space and percent-encoded
sequences are decoded. A bare where-clause remains accepted. oslc.orderBy
takes the specification's sort terms: each property carries a + or -
(unsigned, it ascends), and a scoped term sysml:owner{+sysml:name,-sysml:qualifiedName}
orders by the related element's properties, signed inside the braces as
scoped_sort_terms writes them. A sign outside the braces,
-sysml:owner{sysml:name}, applies to the unsigned terms inside; a term signed
on both sides is refused. Selection and ordering are comma-separated, and
both take nested properties: oslc.select=sysml:name,sysml:owner{sysml:name}
reports the owner's name as the column owner.name, and
oslc.orderBy=sysml:owner{-sysml:name} orders by it. * in oslc.select,
alone or inside a nested selection, is every property the selected rows could
name, read of the reflective table Project reads (see query
kinds): the properties of the element rows'
metaclasses the evaluator serves (isComposite and portionKind of a
PartUsage, body of a Comment) with the evaluator's own (rdf:type,
sysx:multiplicityUpper), or the features an object row's model declares; a
column no row carries is left out, and a nested sysml:owner{*} reads the
related element's. A query that selects nothing reports every property but
sysml:elementId, the ones of particular metaclasses absent on the other rows.
oslc.searchTerms="wheel","axle" keeps the elements whose text properties
contain any of the quoted terms, case-insensitively, as WhereText matches.
A parameter this implementation does not recognize is a typed error, not something
to ignore, because ignoring it would answer a different question than the one asked:
a misspelt oslc.wheree would otherwise select the whole model. The two paging
parameters, oslc.paging and oslc.pageSize, are the exception: they ask how
the answer is delivered, not which answer, and OSLC Query 3.0 lets a server
ignore them, so they are accepted unread — every result arrives in one answer.
A parameter given twice is refused for the same reason, and so is a parameter
with no value: oslc.select= narrows nothing, so rather than quietly returning every
property (which is what omitting it means), it is refused. A property named
twice in one oslc.select, whether by the same prefix or by two prefixes that
name the same namespace, is refused as well: it is reported once, so the second
name could not be honored.
sysml:, sysx:, elmt: and rdf: are bound by default to the namespaces
the RDF export writes (internal/translate/rdf: the OMG SysML namespace,
OpenSysML's urn:opensysml:sysml:, the urn:sysmlv2:element: element
identifiers, and RDF). oslc.prefix adds or rebinds a prefix. An unbound
prefix is an error.
A property is one of three things, told apart by its namespace:
| Spelling | Property |
|---|---|
rdf:type |
The element's metaclass (@type); the elmt: form selects objects, below |
sysml:<property> |
A property the SysML metamodel declares, read reflectively from the model's metaclass declarations — sysml:name, sysml:qualifiedName, sysml:owner, sysml:isAbstract, sysml:documentation, sysml:type, sysml:satisfiedRequirement, … every property Project can read of the element |
sysx:<property> |
What the metamodel does not declare: the two evaluator-derived properties sysx:multiplicityLower and sysx:multiplicityUpper, and the features of the model itself (sysx:pressure, sysx:wheels.diameter), read of each row as a document query's WhereFeature reads them |
An element-valued property reads as the element's identity, and a scoped term
or nested selection continues through it. An expression element the metamodel
derives — a send's sysml:payloadArgument, sysml:senderArgument or
sysml:receiverArgument — has no identity of its own, so it reads, compares
and orders as written (new Alarm(3)), while a path through it reaches what
it refers to: sysml:senderArgument{rdf:type} is FeatureReferenceExpression,
sysml:senderArgument{sysml:referent{sysml:name}} the port it names.
A property the metamodel declares for some metaclass is never unknown: selected
of rows none of which carry it (oslc.select=sysml:body over a model without
comments), it is absent on every row; compared, it keeps no row; ordered by, it
leaves the order. So is a metamodel property OpenSysML does not derive yet,
such as an accept's sysml:payloadArgument. A sysml: spelling of a property
the metamodel does not declare is refused before any element is read, as a QVTS
path failure whose diagnostic lists the nearest spellings under the query's own
oslc.prefix bindings, so they are always writable as they read:
sysml:multiplicityUpper names sysx:multiplicityUpper, sysml:nmae names
sysml:name. A sysx: feature the rows do not carry is refused by the
evaluator the same way, naming the features the rows do have. @type and @id
are not OSLC query text: the first is written rdf:type, and identity is
reported for every result rather than asked for.
rdf:type=sysml:PartUsage selects the declared elements of that metaclass
(WhereType, exact), over the model's elements in declaration order.
rdf:type=elmt:<id> selects the held objects — the instances a session
created with -instantiate, %instantiate or the Instantiate RPC — whose
type is the element <id> identifies, over the objects the model holds
exactly as a document query's Objects(type) does. The id is the one the RDF
export writes for the element (rdf.EncodeElementID of its qualified name:
elmt:Garage__Wheel), and the full <urn:sysmlv2:element:…> IRI selects
alike. The two forms do not mix in one in [...] list, and an object term is
not negated or nested.
An object row answers under the path a session reaches it by
(Garage::car.wheels[2]), with the usage it instantiates as its identity and
metaclass; the gRPC QueryResultElement.path field carries the path, and the
REPL prints it in place of the qualified name. sysx: features
(sysx:pressure, sysx:engine{sysx:power} — the column engine.power) read
the object's values, through the objects its features hold, so
rdf:type=elmt:Garage__Wheel and sysx:pressure<25 keeps the under-inflated
wheels and rdf:type=elmt:Garage__Car and sysx:engine{sysx:power>50} the
cars with a strong engine. Two object terms joined by and keep the objects
both select.
Every term is one plan operation over the rows the terms before it kept, so
and is nesting and the terms compare as the document-query evaluator
compares: sysml:name terms are WhereName, rdf:type terms WhereType,
every other term a WhereFeature with tolerate=true, which keeps a row whose
property is absent out of the answer without failing the query. Equality,
inequality and in compare typed values — a number against a number, a
boolean against true/false, a string lexically — and a multi-valued
property matches when any value equals an operand. Of the three string
semantics OSLC Query 3.0 lets a server choose, this is the first: a
case-sensitive comparison of the whole value, in which % and _ are ordinary
characters, not pattern wildcards (sysml:name="battery" does not select
Battery, and sysml:name="Batt%" selects nothing). in [...] keeps the rows
any alternative keeps, in source order (Except of the rows no alternative
kept). Ordered comparisons take exactly one numeric operand and apply to the
numeric properties: the two multiplicity bounds, where * is positive
infinity for model values and operands alike (sysx:multiplicityUpper=*
identifies the unbounded usages), and the model's own attributes. An ordered
comparison on a text property, a boolean operand that is not true/false,
and a metaclass the library does not declare are refused before any element
is read.
Results keep declaration order, with parents before their children, unless
oslc.orderBy is supplied; oslc.searchTerms computes no relevance score, so
a search is ordered by oslc.orderBy alone, or stays in declaration order. oslc.select is a Project; identity and
metamodel type are always present on every result. oslc.orderBy=+a,-b is a
nested OrderBy per term, applied in reverse precedence so the stable sort
keeps b within equal a; it compares values as the evaluator orders them
(numbers numerically, * as positive infinity, text lexically); rows missing
the property sort as the smallest value would — first ascending, last
descending — and keep their existing order among themselves.
OSLC compound terms have no or, so OSLC text and the structured API Query
are deliberately not interchangeable: an or in OSLC text is refused with a
typed error, while the API's composite or constraint translates to the same
plan algebra. Which query is
which places the two
beside the project's other query surfaces.
| Construct | Behavior |
|---|---|
term and term |
Supported: nested plan operations. |
identifier in [...] |
Supported: the rows any alternative keeps, in source order. |
scoped_term / nested property query |
Supported: the inner compound is evaluated over the related element the property names, to any depth. |
Nested oslc.select / oslc.orderBy (sysml:owner{sysml:name}) |
Supported: reported and ordered as the property path owner.name. |
Property wildcard * in oslc.select |
Supported: every property the selected rows could name — their metaclasses' that the evaluator serves, the evaluator's own, an object's declared features — at any nesting level, sorted; a column no row carries is left out. |
Property wildcard * in oslc.where or oslc.orderBy |
Typed error. A term compares one property and an order has one key; the wildcard names every property. |
Value wildcard * on the multiplicity bounds |
Supported: * is the model's own infinity value, not a wildcard. |
Value wildcard * on any other property |
Typed error. A * value would be a wildcard, which no plan operation evaluates; refusing it avoids a lexical comparison that silently matches nothing. |
oslc.searchTerms |
Supported: WhereText over the result's text properties, any quoted term matching, case-insensitively. Terms are quoted strings; an empty parameter or an unquoted term is refused. No relevance score is computed, so oslc.orderBy orders a search alone. |
Scoped sort terms sysml:owner{+sysml:name,-sysml:qualifiedName} |
Supported: the sign sits on each property inside the braces, as the specification writes it; a sign outside the braces applies to the unsigned terms inside. |
oslc.paging, oslc.pageSize |
Accepted and ignored, as the specification allows: every result arrives in one answer. |
rdf:type=elmt:<id> |
Supported: the held objects of that element, under their paths. |
or |
Typed error. OSLC Query 3.0 defines no disjunction; the structured API Query does. |
oslc.properties |
Typed error naming oslc.select, which reports the property projection. |
Any other oslc.* parameter, or a repeated one |
Typed error. |
| Language-tagged literals | Typed error; model properties do not carry language tags. |
^^rdf:XMLLiteral |
Supported: read as a plain string, as the specification allows. |
Other non-xsd: or unsupported xsd: datatypes |
Typed error rather than a potentially misleading comparison. |
The gRPC QueryRequest.oslc_query field carries this text and is mutually
exclusive with the structured query field. The service advertises the
oslc_query capability in addition to query.
The REPL accepts %query <oslc-query>. The sysml command accepts
-query <oslc-query> alongside the other model modes. Both print one matched
element per line as qualified name and metamodel type, followed by selected
properties. A reported property carries the name the query asked for it by, so
oslc.select=rdf:type reports rdf:type=PartUsage and a reported row can be
written back into a query; rebinding a prefix renames it in the answer too. The
gRPC response instead keys properties by their query property names (name,
owner.name, pressure), which the structured query field also uses.
A refused query carries the query outcome
as a QueryOutcome status detail on every transport, as RunDocumentQuery
does, so a client reads the failing step, the frontier and the nearest spelling
rather than parsing prose.
The REPL's %query and sysml -query identify unnamed elements with the same
positional @N IDs as the service query; see the query model.
A query that matches nothing says so: the REPL prints no elements matched, and the command reports it on standard error, so the result
rows on standard output stay one line per match. -query with empty text is
treated as a mistake rather than as an absent flag: it is refused instead of
starting the interactive REPL.