feat(grpc): read any metamodel property of an element by its specification name

Aperta
#2,012 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
go, grpc, python, rust, typescript, wasm

Direzione di ricerca

Start by reading internal/semantic/metamodel and its Evaluator.Property and Structure interfaces, then trace GetSymbol in the gRPC service and newAPIJSONEvaluation in internal/translate/export. Compare the two proposed structure routes and check the differential baseline in docs/project/api-json-differential.md. Done means the RPC and all five client bindings meet the acceptance criteria, including parity with api-json over examples/.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Problem

OpenSysML has no per-element client API shaped like the KerML/SysML abstract syntax.
A client that wants inheritedFeature, connectorEnd, relatedFeature, directedFeature,
portDefinition, payloadType, subjectParameter, entryAction, isComposite, the
FeatureValue behind a feature, the operands of an expression, … has three routes and none
of them answers per element over gRPC:

  • GetSymbol (SymbolInfo) is a curated surface: id, name, kind, metadata map, owned
    child_ids, attributes, type/multiplicity/specializations and, since #1974, members.
    Each metamodel property it lacks is a new field, a new proto message and four client
    bindings (#1974, #1978, #1979, #1981, #1983, #1992, #1993, #1994 each add one or two).
  • Query admits exactly the 22 queryable properties of the SysML v2 API & Services
    projection (internal/semantic/query PropertyNames): @id, @type, body,
    declaredName, declaredShortName, documentation, elementId, general, isAbstract,
    isIndividual, language, locale, multiplicityLower, multiplicityUpper, name,
    owner, qualifiedName, satisfiedRequirement, satisfyingFeature, shortName,
    textualRepresentation, type. Anything else is INVALID_ARGUMENT: unknown query property.
  • Convert to api-json exports the whole model as API element JSON with the derived
    properties completed, but that is a model-level export, not an element read.

The derivation itself already exists and is the most carefully measured part of the
metamodel in the tree:

  • internal/semantic/metamodel (Evaluator.Property(element, definingClass, name))
    serves 297 derived properties by specification clause and omits 58
    (Omitted(), each with the engine fact it would need). It covers every property named
    above, plus Connector::sourceFeature/targetFeature, Feature::isComposite/isReference,
    FeatureValue::value, OperatorExpression::operand/operator,
    InvocationExpression::argument, SendActionUsage::payloadArgument/senderArgument/
    receiverArgument, StateDefinition::entryAction/doAction/exitAction,
    ConjugatedPortTyping::portDefinition, ConjugatedPortDefinition::originalPortDefinition.
  • It is refereed against the pinned pilot's JSON export over 935 corpus files
    (docs/project/api-json-differential.md): 1,925,327 properties equal, 125,740 different,
    321,317 missing on our side, bucketed per (metaclass, property).
  • The in-model query executor (internal/doc/queryexec metaclassPropertyValues) and
    meta reflection already answer metaclass properties on a live model through
    semantics.ReflectiveElements / ReflectiveFeatureValues.

An external conformance suite (hideo67/sysmlv2-tests, 1,630 static reads of exactly these
properties, pilot EMF as oracle) scores the gRPC surface at 504 pass / 364 fail /
753 unsupported, against 1,527 / 53 / 50 for sysml-toolkit's ResolvedModel.derived(element, "<spec name>") and 1,580 / 0 / 50 for the pilot. The 753 are properties the surface has no
route to; 87 of the 364 are inherited members the suite's adapter does not yet read from
members. The gap is the surface, not the derivation.

Proposal

1. One RPC: element properties by specification name
rpc GetElementProperties(GetElementPropertiesRequest) returns (GetElementPropertiesResponse);

message GetElementPropertiesRequest {
  string model_id   = 1;
  string element_id = 2;           // qualified name, or a positional id for an unnamed member (#1978)
  repeated string properties = 3;  // spec names; empty = every property the metaclass declares
  bool include_library = 4;        // library-inherited members etc., as `members` does
}

message GetElementPropertiesResponse {
  string metaclass = 1;            // "ConnectionUsage"
  repeated ElementProperty properties = 2;
}

message ElementProperty {
  string name = 1;                 // "connectorEnd"
  string defining_class = 2;       // "Connector"
  bool many = 3;                   // ordered list vs single
  repeated PropertyValue values = 4;
  string unsupported_reason = 5;   // set when OpenSysML does not derive it; from Evaluator.Explain / Omitted
}

message PropertyValue {
  oneof value {
    string element_id = 1;         // qualified or positional id
    string literal = 2;            // string / integer / real / boolean spelled as the API JSON spells it
    string enumeration = 3;        // "in", "public", …
  }
}

Backing: metamodel.Evaluator over the model, resolving the metaclass and the declared
property set from internal/translate/rdf/ontology (so an unknown name is an error, a
declared-but-underived name is unsupported_reason, and a derived one is a value). Element
values are returned as the ids GetSymbol accepts, positional ids included, so a client can
walk the graph (feature → ownedRelationship → FeatureValue::value → operand) without a
second vocabulary.

2. Structure for a live model

Evaluator reads containment and owned attributes through a metamodel.Structure. Two
routes, in order:

  1. Reuse the API-JSON graph structure (internal/translate/export newAPIJSONEvaluation):
    build the model's graph once per model revision and cache it on the service's model
    entry. This is the path the differential measures today, so its fidelity is known.
  2. If the per-model graph is too expensive for editor-sized models, implement
    metamodel.Structure directly over symbols/semantics side tables and run the
    differential over both to prove they agree.
3. Clients

client/opensysml (Go), Python, Rust, TypeScript and WASM each gain
ElementProperties(id, names...) returning name → values | reason, mirroring the Go
Query row shape. The Python Symbol gets .property("connectorEnd").

4. What stays as it is
  • SymbolInfo remains the curated editor/client surface and stops growing metamodel fields.
  • Query keeps the API & Services projection. A later step may admit metaclass property
    names in select through the same evaluator; not part of this issue.
  • Convert api-json is unchanged; the RPC and the export must agree per property, and the
    differential baseline is the gate for both.

Effect on open pull requests

PR What it changes Under this proposal
#1978 unnamed members get positional ids identity of Owner::@3 on child_ids, GetSymbol, Python Keep. Any surface needs addressable unnamed elements; the RPC returns these ids.
#1980 conjugated port typed by P::'~P' semantics, export, views Keep. Engine fix; ConjugatedPortTyping::portDefinition reads it.
#1992 send action is a SendActionUsage semantics, runtime, query, export Keep. Engine fix; metaclass and payloadArgument/senderArgument/receiverArgument read it.
#1994 positional parameter redefinition semantics, migrate Keep. Engine fix.
#1983 connector related features from the ends' reference subsettings semantics derivation + SymbolInfo/query fields Keep the derivation, drop the new fields. Connector::relatedFeature/sourceFeature/targetFeature/connectorEnd are served by the evaluator once the derivation is right.
#1993 isComposite/isReference on symbols and in queries surface only Supersede. Feature::isComposite/isReference are served.
#1981 Symbol.valuation with expression text/structure bespoke valuation shape on symbol, gRPC, query Supersede. FeatureValue::value → OperatorExpression::operand/operator, InvocationExpression::argument, LiteralExpression::value give the structure in the specification's own shape.
#1979 instance owner and paths runtime objects, not metamodel Independent. Unaffected either way.

Acceptance

  • GetElementProperties answers every property in metamodel.servedRules for a declared
    element and reports the recorded reason for every Omitted() one; tests/grpc
    conformance cases per metaclass family (Type, Feature, Connector, Flow, SendActionUsage,
    StateDefinition, FeatureValue/Expression, Membership/Import).
  • The RPC's answer and the api-json export agree on every (element, property) pair over
    examples/ (a hygiene test, not a new baseline).
  • All five clients expose it; the Python and Go clients have the same differential test
    they have for Query.
  • docs/project/spec-compliance/08-grpc-service-layer.md and the gRPC guide document the
    RPC and the capability flag.
Lingua principale
Go
Stelle
56
Fork
17
Merge medio
12h 31m
PR unite (30g)
909

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Open-MBEE/OpenSysML

Tutte le issue di Open-MBEE/OpenSysML

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.