diff --git a/packages/core/src/browser/new-element-contribution.ts b/packages/core/src/browser/new-element-contribution.ts index dcfbafa5..b9f71048 100644 --- a/packages/core/src/browser/new-element-contribution.ts +++ b/packages/core/src/browser/new-element-contribution.ts @@ -15,6 +15,8 @@ import { RelationshipType, TargetObjectType, findNextUnique, + getCrossModelEdition, + getCrossModelVersion, isMemberPermittedInModel, quote, toId, @@ -57,12 +59,21 @@ interface NewElementTemplate; } -const INITIAL_DATAMODEL_CONTENT = `datamodel: +/** + * Generates the initial datamodel content with current CrossModel version. + * The version is read from CROSSMODEL_VERSION constant which is sourced from package.json. + */ +function getInitialDataModelContent(): string { + return `datamodel: id: _ name: "" type: ${DataModelTypeInfos.logical.value} version: 1.0.0 + crossmodel: + edition: ${getCrossModelEdition()} + version: ${getCrossModelVersion()} `; +} const INITIAL_ENTITY_CONTENT = `entity: id: _ @@ -152,7 +163,7 @@ const NEW_ELEMENT_TEMPLATES: ReadonlyArray = [ validateName: validateDataModelName, iconClass: ModelStructure.DataModel.ICON_CLASS, toUri: (parent, name) => parent.resolve(toId(name)).resolve(DATAMODEL_FILE), - content: INITIAL_DATAMODEL_CONTENT + content: getInitialDataModelContent } ]; diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts index 11bd261e..74d2ecec 100644 --- a/packages/protocol/src/index.ts +++ b/packages/protocol/src/index.ts @@ -11,3 +11,4 @@ export * from './integration'; export * from './model'; export * from './model-service/protocol'; export * from './util'; +export * from './version'; diff --git a/packages/protocol/src/util.ts b/packages/protocol/src/util.ts index 94b87084..2acc844a 100644 --- a/packages/protocol/src/util.ts +++ b/packages/protocol/src/util.ts @@ -28,6 +28,7 @@ export const RESERVED_KEYWORDS = [ 'childRole', 'conceptual', 'conditions', + 'crossmodel', 'cross-join', 'customProperties', 'datamodel', diff --git a/packages/protocol/src/version.ts b/packages/protocol/src/version.ts new file mode 100644 index 00000000..58ec48ce --- /dev/null +++ b/packages/protocol/src/version.ts @@ -0,0 +1,65 @@ +/******************************************************************************** + * Copyright (c) 2026 CrossBreeze. + ********************************************************************************/ + +/** + * Current CrossModel edition and version information. + * These are automatically written to datamodel.cm files to enable detection of breaking changes + * when models are opened in different CrossModel versions. + * + * The version and edition are sourced from the package.json file, + * which is kept in sync with lerna.json by the monorepo build system. + */ + +// Cache for version and edition to avoid repeated file reads +let cachedVersion: string | undefined; +let cachedEdition: string | undefined; +const CROSSMODEL_EDITION_PREFIX = 'crossmodel-'; + +function getPackageJson(): { name?: string; version?: string } | undefined { + try { + // Try to read using require (Node.js environment) + // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require, import/no-dynamic-require + const pkg = require('../package.json'); + if (pkg?.version) { + return pkg; + } + return pkg; + } catch { + // If require fails (browser environment), version will be set to 0.0.0 + return undefined; + } +} + +function populatePackageMetadata(): void { + if (cachedVersion !== undefined && cachedEdition !== undefined) { + // Already cached, no need to read again + return; + } + const pkg = getPackageJson(); + cachedVersion = pkg?.version ?? '0.0.0'; + if (pkg?.name?.startsWith(CROSSMODEL_EDITION_PREFIX)) { + // Extract edition from package name (e.g., 'crossmodel-core' -> 'core') + cachedEdition = pkg.name.substring(CROSSMODEL_EDITION_PREFIX.length); + } else { + cachedEdition = 'core'; // fallback + } +} + +function getVersionFromPackage(): string { + populatePackageMetadata(); + return cachedVersion!; +} + +function getEditionFromPackage(): string { + populatePackageMetadata(); + return cachedEdition!; +} + +export function getCrossModelVersion(): string { + return getVersionFromPackage(); +} + +export function getCrossModelEdition(): string { + return getEditionFromPackage(); +} diff --git a/packages/server/src/language-server/cross-model-datamodel-manager.ts b/packages/server/src/language-server/cross-model-datamodel-manager.ts index 3b3b7a15..88389b4e 100644 --- a/packages/server/src/language-server/cross-model-datamodel-manager.ts +++ b/packages/server/src/language-server/cross-model-datamodel-manager.ts @@ -238,12 +238,14 @@ export class CrossModelDataModelManager { `[DataModel] Re-build affected documents (${docs.length}): ${docs.map(doc => workspace.wsRelativePath(doc.uri)).join(', ')}` ); docs.forEach(doc => { - this.langiumDocuments.invalidateDocument(doc.uri); + // Force re-parse/re-build of the document + this.documentBuilder.resetToState(doc, DocumentState.Changed); changed.push(doc.uri); }); } } + // Adds the data model for the given URI. Returns the ID of the added data model. protected addDataModel(uri: URI, dataModel: DataModel): string[] { const dataModelInfo = new DataModelInfo(uri, dataModel); if (!dataModelInfo.isUnknown) { @@ -285,6 +287,7 @@ export class CrossModelDataModelManager { return []; } + // Updates (or adds) the data model for the given URI. Returns the IDs of data models that were added/updated. protected async updateDataModel(uri: URI): Promise { const newDataModel = await parseDataModelFile(uri, this.langiumDocuments); if (!newDataModel) { @@ -294,10 +297,12 @@ export class CrossModelDataModelManager { const toUpdate = []; const existingDataModelInfo = this.uriToDataModel.get(uri.toString()); const newDataModelId = createDataModelId(newDataModel.id, newDataModel.version); + // data model ID changed, remove old one if (existingDataModelInfo && existingDataModelInfo?.id !== newDataModelId) { this.logger.info(`[DataModel] Replace data model "${existingDataModelInfo.id}" with "${newDataModelId}"`); toUpdate.push(...this.deleteDataModel(uri)); } + // add new/updated data model toUpdate.push(...this.addDataModel(uri, newDataModel)); return toUpdate; } diff --git a/packages/server/src/language-server/generated/ast.ts b/packages/server/src/language-server/generated/ast.ts index e118e6ba..5fe72460 100644 --- a/packages/server/src/language-server/generated/ast.ts +++ b/packages/server/src/language-server/generated/ast.ts @@ -45,6 +45,7 @@ export type CrossModelKeywordNames = | "conceptual" | "conditions" | "cross-join" + | "crossmodel" | "customProperties" | "datamodel" | "datatype" @@ -52,6 +53,7 @@ export type CrossModelKeywordNames = | "description" | "diagram" | "edges" + | "edition" | "entity" | "expression" | "expressions" @@ -197,6 +199,23 @@ export function isCardinality(item: unknown): item is Cardinality { return item === '0..1' || item === '1..1' || item === '0..N' || item === '1..N'; } +export interface CrossModelEditionInfo extends langium.AstNode { + readonly $container: DataModel; + readonly $type: 'CrossModelEditionInfo'; + edition: string; + version: string; +} + +export const CrossModelEditionInfo = { + $type: 'CrossModelEditionInfo', + edition: 'edition', + version: 'version' +} as const; + +export function isCrossModelEditionInfo(item: unknown): item is CrossModelEditionInfo { + return reflection.isInstance(item, CrossModelEditionInfo.$type); +} + export interface CrossModelRoot extends langium.AstNode { readonly $type: 'CrossModelRoot'; datamodel?: DataModel; @@ -316,6 +335,7 @@ export function isDataElementMapping(item: unknown): item is DataElementMapping export interface DataModel extends NamedObject, WithCustomProperties { readonly $container: CrossModelRoot; readonly $type: 'DataModel'; + crossmodel?: CrossModelEditionInfo; dependencies: Array; type: string; version?: string; @@ -323,6 +343,7 @@ export interface DataModel extends NamedObject, WithCustomProperties { export const DataModel = { $type: 'DataModel', + crossmodel: 'crossmodel', customProperties: 'customProperties', dependencies: 'dependencies', description: 'description', @@ -854,6 +875,7 @@ export type CrossModelAstType = { AttributeMappingTarget: AttributeMappingTarget BinaryExpression: BinaryExpression BooleanExpression: BooleanExpression + CrossModelEditionInfo: CrossModelEditionInfo CrossModelRoot: CrossModelRoot CustomProperty: CustomProperty DataElement: DataElement @@ -967,6 +989,18 @@ export class CrossModelAstReflection extends langium.AbstractAstReflection { }, superTypes: [] }, + CrossModelEditionInfo: { + name: CrossModelEditionInfo.$type, + properties: { + edition: { + name: CrossModelEditionInfo.edition + }, + version: { + name: CrossModelEditionInfo.version + } + }, + superTypes: [] + }, CrossModelRoot: { name: CrossModelRoot.$type, properties: { @@ -1075,6 +1109,9 @@ export class CrossModelAstReflection extends langium.AbstractAstReflection { DataModel: { name: DataModel.$type, properties: { + crossmodel: { + name: DataModel.crossmodel + }, customProperties: { name: DataModel.customProperties, defaultValue: [] diff --git a/packages/server/src/language-server/generated/grammar.ts b/packages/server/src/language-server/generated/grammar.ts index 5b2dd39a..8c7d04cf 100644 --- a/packages/server/src/language-server/generated/grammar.ts +++ b/packages/server/src/language-server/generated/grammar.ts @@ -39,7 +39,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@20" + "$ref": "#/rules@21" }, "arguments": [] } @@ -51,7 +51,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@24" + "$ref": "#/rules@25" }, "arguments": [] } @@ -63,7 +63,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@26" + "$ref": "#/rules@27" }, "arguments": [] } @@ -75,7 +75,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@31" + "$ref": "#/rules@32" }, "arguments": [] } @@ -106,14 +106,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -132,7 +132,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@2" + "$ref": "#/rules@3" }, "arguments": [] } @@ -155,7 +155,33 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@6" + "$ref": "#/rules@7" + }, + "arguments": [] + } + } + ], + "cardinality": "?" + }, + { + "$type": "Group", + "elements": [ + { + "$type": "Keyword", + "value": "crossmodel" + }, + { + "$type": "Keyword", + "value": ":" + }, + { + "$type": "Assignment", + "feature": "crossmodel", + "operator": "=", + "terminal": { + "$type": "RuleCall", + "rule": { + "$ref": "#/rules@2" }, "arguments": [] } @@ -177,7 +203,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -187,7 +213,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -198,7 +224,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@3" + "$ref": "#/rules@4" }, "arguments": [] } @@ -209,7 +235,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -219,17 +245,86 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" }, + { + "$type": "RuleCall", + "rule": { + "$ref": "#/rules@13" + }, + "arguments": [] + } + ] + }, + "entry": false, + "fragment": false, + "parameters": [] + }, + { + "$type": "ParserRule", + "name": "CrossModelEditionInfo", + "returnType": { + "$ref": "#/interfaces@1" + }, + "definition": { + "$type": "Group", + "elements": [ { "$type": "RuleCall", "rule": { "$ref": "#/rules@12" }, "arguments": [] + }, + { + "$type": "Keyword", + "value": "edition" + }, + { + "$type": "Keyword", + "value": ":" + }, + { + "$type": "Assignment", + "feature": "edition", + "operator": "=", + "terminal": { + "$type": "RuleCall", + "rule": { + "$ref": "#/rules@9" + }, + "arguments": [] + } + }, + { + "$type": "Keyword", + "value": "version" + }, + { + "$type": "Keyword", + "value": ":" + }, + { + "$type": "Assignment", + "feature": "version", + "operator": "=", + "terminal": { + "$type": "RuleCall", + "rule": { + "$ref": "#/rules@7" + }, + "arguments": [] + } + }, + { + "$type": "RuleCall", + "rule": { + "$ref": "#/rules@13" + }, + "arguments": [] } ] }, @@ -266,7 +361,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "DataModelDependency", "returnType": { - "$ref": "#/interfaces@1" + "$ref": "#/interfaces@2" }, "definition": { "$type": "Group", @@ -291,7 +386,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -317,7 +412,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@6" + "$ref": "#/rules@7" }, "arguments": [] } @@ -393,7 +488,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "TerminalRuleCall", "rule": { - "$ref": "#/rules@5" + "$ref": "#/rules@6" }, "parenthesized": false }, @@ -408,7 +503,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "TerminalRuleCall", "rule": { - "$ref": "#/rules@5" + "$ref": "#/rules@6" }, "parenthesized": false }, @@ -423,7 +518,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "TerminalRuleCall", "rule": { - "$ref": "#/rules@5" + "$ref": "#/rules@6" }, "parenthesized": false } @@ -455,7 +550,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "TerminalRuleCall", "rule": { - "$ref": "#/rules@5" + "$ref": "#/rules@6" }, "parenthesized": false }, @@ -473,7 +568,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "TerminalRuleCall", "rule": { - "$ref": "#/rules@5" + "$ref": "#/rules@6" }, "parenthesized": false } @@ -508,7 +603,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@8" + "$ref": "#/rules@9" }, "arguments": [] }, @@ -522,7 +617,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@8" + "$ref": "#/rules@9" }, "arguments": [] } @@ -632,7 +727,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@8" + "$ref": "#/rules@9" }, "arguments": [] }, @@ -653,7 +748,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -675,7 +770,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -701,7 +796,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -732,7 +827,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -742,7 +837,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -753,7 +848,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@19" + "$ref": "#/rules@20" }, "arguments": [] } @@ -764,7 +859,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -777,7 +872,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "CustomProperty", "returnType": { - "$ref": "#/interfaces@11" + "$ref": "#/interfaces@12" }, "definition": { "$type": "Group", @@ -785,7 +880,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -807,7 +902,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -825,7 +920,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "LogicalEntity", "returnType": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "definition": { "$type": "Group", @@ -841,14 +936,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -866,7 +961,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -876,7 +971,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -887,12 +982,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -906,7 +1001,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -927,7 +1022,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -937,7 +1032,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -948,7 +1043,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@21" + "$ref": "#/rules@22" }, "arguments": [] } @@ -959,7 +1054,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -980,7 +1075,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -990,7 +1085,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -1001,7 +1096,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@22" + "$ref": "#/rules@23" }, "arguments": [] } @@ -1012,7 +1107,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1022,7 +1117,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -1030,7 +1125,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1044,7 +1139,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "LogicalAttribute", "returnType": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" }, "definition": { "$type": "Group", @@ -1052,7 +1147,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -1074,7 +1169,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -1100,7 +1195,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1126,7 +1221,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1152,7 +1247,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1195,7 +1290,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -1210,7 +1305,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "LogicalIdentifier", "returnType": { - "$ref": "#/interfaces@14" + "$ref": "#/interfaces@15" }, "definition": { "$type": "Group", @@ -1218,7 +1313,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -1268,7 +1363,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -1278,7 +1373,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -1289,12 +1384,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1308,7 +1403,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1318,7 +1413,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -1362,7 +1457,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "Relationship", "returnType": { - "$ref": "#/interfaces@15" + "$ref": "#/interfaces@16" }, "definition": { "$type": "Group", @@ -1378,14 +1473,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@17" + "$ref": "#/rules@18" }, "arguments": [] }, @@ -1407,12 +1502,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1441,7 +1536,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -1467,7 +1562,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@23" + "$ref": "#/rules@24" }, "arguments": [] } @@ -1493,12 +1588,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1527,7 +1622,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -1553,7 +1648,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@23" + "$ref": "#/rules@24" }, "arguments": [] } @@ -1575,7 +1670,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -1585,7 +1680,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -1596,7 +1691,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@25" + "$ref": "#/rules@26" }, "arguments": [] } @@ -1607,7 +1702,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1617,7 +1712,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -1625,7 +1720,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1639,7 +1734,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "RelationshipAttribute", "returnType": { - "$ref": "#/interfaces@16" + "$ref": "#/interfaces@17" }, "definition": { "$type": "Group", @@ -1659,12 +1754,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1688,12 +1783,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1705,7 +1800,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -1720,7 +1815,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "SystemDiagram", "returnType": { - "$ref": "#/interfaces@17" + "$ref": "#/interfaces@18" }, "definition": { "$type": "Group", @@ -1745,14 +1840,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -1770,7 +1865,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -1780,7 +1875,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -1791,7 +1886,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@27" + "$ref": "#/rules@28" }, "arguments": [] } @@ -1802,7 +1897,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1823,7 +1918,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -1833,7 +1928,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -1844,7 +1939,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@28" + "$ref": "#/rules@29" }, "arguments": [] } @@ -1855,7 +1950,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1865,7 +1960,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -1879,7 +1974,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "LogicalEntityNode", "returnType": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" }, "definition": { "$type": "Group", @@ -1887,7 +1982,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -1906,12 +2001,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -1934,7 +2029,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1954,7 +2049,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1974,7 +2069,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -1994,7 +2089,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -2009,7 +2104,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "SystemDiagramEdge", "returnType": { - "$ref": "#/interfaces@20" + "$ref": "#/interfaces@21" }, "definition": { "$type": "Alternatives", @@ -2017,14 +2112,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@29" + "$ref": "#/rules@30" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@30" + "$ref": "#/rules@31" }, "arguments": [] } @@ -2038,7 +2133,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "RelationshipEdge", "returnType": { - "$ref": "#/interfaces@21" + "$ref": "#/interfaces@22" }, "definition": { "$type": "Group", @@ -2046,7 +2141,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -2065,12 +2160,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@15" + "$ref": "#/interfaces@16" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2093,12 +2188,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2121,12 +2216,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2144,7 +2239,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "InheritanceEdge", "returnType": { - "$ref": "#/interfaces@22" + "$ref": "#/interfaces@23" }, "definition": { "$type": "Group", @@ -2152,7 +2247,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -2171,12 +2266,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2199,12 +2294,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2222,7 +2317,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "Mapping", "returnType": { - "$ref": "#/interfaces@25" + "$ref": "#/interfaces@26" }, "definition": { "$type": "Group", @@ -2238,14 +2333,14 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -2263,7 +2358,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2273,7 +2368,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -2284,7 +2379,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@32" + "$ref": "#/rules@33" }, "arguments": [] } @@ -2295,7 +2390,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2320,7 +2415,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@39" + "$ref": "#/rules@40" }, "arguments": [] } @@ -2331,7 +2426,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -2339,7 +2434,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2353,7 +2448,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "SourceObject", "returnType": { - "$ref": "#/interfaces@26" + "$ref": "#/interfaces@27" }, "definition": { "$type": "Group", @@ -2361,7 +2456,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@16" + "$ref": "#/rules@17" }, "arguments": [] }, @@ -2383,12 +2478,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2417,7 +2512,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@33" + "$ref": "#/rules@34" }, "arguments": [] } @@ -2439,7 +2534,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2449,7 +2544,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -2460,7 +2555,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@34" + "$ref": "#/rules@35" }, "arguments": [] } @@ -2471,7 +2566,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2492,7 +2587,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2502,7 +2597,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -2513,7 +2608,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@35" + "$ref": "#/rules@36" }, "arguments": [] } @@ -2524,7 +2619,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2534,7 +2629,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -2588,12 +2683,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@26" + "$ref": "#/interfaces@27" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2611,7 +2706,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "definition": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@36" + "$ref": "#/rules@37" }, "arguments": [] }, @@ -2629,7 +2724,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@37" + "$ref": "#/rules@38" }, "arguments": [] } @@ -2651,7 +2746,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@38" + "$ref": "#/rules@39" }, "arguments": [] } @@ -2697,7 +2792,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@38" + "$ref": "#/rules@39" }, "arguments": [] } @@ -2735,7 +2830,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@7" + "$ref": "#/rules@8" }, "arguments": [] } @@ -2759,7 +2854,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -2783,12 +2878,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@23" + "$ref": "#/interfaces@24" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2808,7 +2903,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "TargetObject", "returnType": { - "$ref": "#/interfaces@27" + "$ref": "#/interfaces@28" }, "definition": { "$type": "Group", @@ -2816,7 +2911,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2835,12 +2930,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -2863,7 +2958,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2873,7 +2968,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -2884,7 +2979,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@40" + "$ref": "#/rules@41" }, "arguments": [] } @@ -2895,7 +2990,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2905,7 +3000,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -2913,7 +3008,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -2927,7 +3022,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "AttributeMapping", "returnType": { - "$ref": "#/interfaces@28" + "$ref": "#/interfaces@29" }, "definition": { "$type": "Group", @@ -2947,7 +3042,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@42" + "$ref": "#/rules@43" }, "arguments": [] }, @@ -2967,7 +3062,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -2977,7 +3072,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -2988,7 +3083,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@43" + "$ref": "#/rules@44" }, "arguments": [] } @@ -2999,7 +3094,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -3020,7 +3115,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@11" + "$ref": "#/rules@12" }, "arguments": [] }, @@ -3030,7 +3125,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@13" + "$ref": "#/rules@14" }, "arguments": [] }, @@ -3041,7 +3136,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@41" + "$ref": "#/rules@42" }, "arguments": [] } @@ -3052,7 +3147,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@12" + "$ref": "#/rules@13" }, "arguments": [] } @@ -3062,7 +3157,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load { "$type": "RuleCall", "rule": { - "$ref": "#/rules@18" + "$ref": "#/rules@19" }, "arguments": [], "cardinality": "?" @@ -3077,7 +3172,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "$type": "ParserRule", "name": "AttributeMappingExpression", "returnType": { - "$ref": "#/interfaces@29" + "$ref": "#/interfaces@30" }, "definition": { "$type": "Group", @@ -3097,7 +3192,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -3117,7 +3212,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@4" + "$ref": "#/rules@5" }, "arguments": [] } @@ -3138,12 +3233,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@24" + "$ref": "#/interfaces@25" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -3165,12 +3260,12 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "terminal": { "$type": "CrossReference", "type": { - "$ref": "#/interfaces@23" + "$ref": "#/interfaces@24" }, "terminal": { "$type": "RuleCall", "rule": { - "$ref": "#/rules@9" + "$ref": "#/rules@10" }, "arguments": [] }, @@ -3189,10 +3284,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataModel", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3214,6 +3309,17 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "primitiveType": "string" } }, + { + "$type": "TypeAttribute", + "name": "crossmodel", + "isOptional": true, + "type": { + "$type": "SimpleType", + "typeRef": { + "$ref": "#/interfaces@1" + } + } + }, { "$type": "TypeAttribute", "name": "dependencies", @@ -3222,7 +3328,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@1" + "$ref": "#/interfaces@2" } } }, @@ -3230,6 +3336,31 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load } ] }, + { + "$type": "Interface", + "name": "CrossModelEditionInfo", + "attributes": [ + { + "$type": "TypeAttribute", + "name": "edition", + "type": { + "$type": "SimpleType", + "primitiveType": "string" + }, + "isOptional": false + }, + { + "$type": "TypeAttribute", + "name": "version", + "type": { + "$type": "SimpleType", + "primitiveType": "string" + }, + "isOptional": false + } + ], + "superTypes": [] + }, { "$type": "Interface", "name": "DataModelDependency", @@ -3282,7 +3413,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "NamedObject", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [ @@ -3311,7 +3442,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataElementContainer", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" } ], "attributes": [] @@ -3321,7 +3452,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataElementContainerLink", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" } ], "attributes": [] @@ -3331,7 +3462,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataElementContainerMapping", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [] @@ -3341,7 +3472,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "SourceDataElementContainer", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [] @@ -3351,7 +3482,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataElementMapping", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [] @@ -3361,7 +3492,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "DataElement", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" } ], "attributes": [ @@ -3388,7 +3519,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@11" + "$ref": "#/interfaces@12" } } }, @@ -3402,7 +3533,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "CustomProperty", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" } ], "attributes": [ @@ -3422,10 +3553,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "LogicalEntity", "superTypes": [ { - "$ref": "#/interfaces@4" + "$ref": "#/interfaces@5" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3439,7 +3570,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -3455,7 +3586,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } } }, @@ -3469,7 +3600,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@14" + "$ref": "#/interfaces@15" } } }, @@ -3482,10 +3613,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "LogicalAttribute", "superTypes": [ { - "$ref": "#/interfaces@9" + "$ref": "#/interfaces@10" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3532,10 +3663,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "LogicalIdentifier", "superTypes": [ { - "$ref": "#/interfaces@3" + "$ref": "#/interfaces@4" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3558,7 +3689,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } }, "isMulti": false @@ -3573,10 +3704,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "Relationship", "superTypes": [ { - "$ref": "#/interfaces@5" + "$ref": "#/interfaces@6" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3589,7 +3720,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -3622,7 +3753,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -3654,7 +3785,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@16" + "$ref": "#/interfaces@17" } } }, @@ -3667,7 +3798,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "RelationshipAttribute", "superTypes": [ { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3680,7 +3811,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } }, "isMulti": false @@ -3695,7 +3826,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } }, "isMulti": false @@ -3708,7 +3839,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "SystemDiagram", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [ @@ -3720,7 +3851,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" } } }, @@ -3734,7 +3865,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@20" + "$ref": "#/interfaces@21" } } }, @@ -3747,7 +3878,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "LogicalEntityNode", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [ @@ -3759,7 +3890,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -3809,7 +3940,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "LogicalEntityNodeAttribute", "superTypes": [ { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } ], "attributes": [] @@ -3819,7 +3950,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "SystemDiagramEdge", "superTypes": [ { - "$ref": "#/interfaces@2" + "$ref": "#/interfaces@3" } ], "attributes": [] @@ -3829,7 +3960,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "RelationshipEdge", "superTypes": [ { - "$ref": "#/interfaces@20" + "$ref": "#/interfaces@21" } ], "attributes": [ @@ -3841,7 +3972,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@15" + "$ref": "#/interfaces@16" } }, "isMulti": false @@ -3856,7 +3987,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" } }, "isMulti": false @@ -3871,7 +4002,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" } }, "isMulti": false @@ -3885,7 +4016,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "InheritanceEdge", "superTypes": [ { - "$ref": "#/interfaces@20" + "$ref": "#/interfaces@21" } ], "attributes": [ @@ -3897,7 +4028,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" } }, "isMulti": false @@ -3912,7 +4043,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@18" + "$ref": "#/interfaces@19" } }, "isMulti": false @@ -3926,7 +4057,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "SourceObjectAttribute", "superTypes": [ { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } ], "attributes": [] @@ -3936,7 +4067,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "TargetObjectAttribute", "superTypes": [ { - "$ref": "#/interfaces@13" + "$ref": "#/interfaces@14" } ], "attributes": [] @@ -3946,10 +4077,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "Mapping", "superTypes": [ { - "$ref": "#/interfaces@6" + "$ref": "#/interfaces@7" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -3961,7 +4092,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@26" + "$ref": "#/interfaces@27" } } }, @@ -3973,7 +4104,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "type": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@27" + "$ref": "#/interfaces@28" } }, "isOptional": false @@ -3985,10 +4116,10 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "SourceObject", "superTypes": [ { - "$ref": "#/interfaces@7" + "$ref": "#/interfaces@8" }, { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -4001,7 +4132,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -4024,7 +4155,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/rules@34" + "$ref": "#/rules@35" } } }, @@ -4038,7 +4169,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/rules@35" + "$ref": "#/rules@36" } } }, @@ -4051,7 +4182,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "TargetObject", "superTypes": [ { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -4064,7 +4195,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "referenceType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@12" + "$ref": "#/interfaces@13" } }, "isMulti": false @@ -4078,7 +4209,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@28" + "$ref": "#/interfaces@29" } } }, @@ -4091,7 +4222,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "name": "AttributeMapping", "superTypes": [ { - "$ref": "#/interfaces@10" + "$ref": "#/interfaces@11" } ], "attributes": [ @@ -4102,7 +4233,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "type": { "$type": "SimpleType", "typeRef": { - "$ref": "#/rules@42" + "$ref": "#/rules@43" } } }, @@ -4114,7 +4245,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/rules@43" + "$ref": "#/rules@44" } } }, @@ -4128,7 +4259,7 @@ export const CrossModelGrammar = (): Grammar => loadedCrossModelGrammar ?? (load "elementType": { "$type": "SimpleType", "typeRef": { - "$ref": "#/interfaces@29" + "$ref": "#/interfaces@30" } } }, diff --git a/packages/server/src/language-server/grammar/datamodel.langium b/packages/server/src/language-server/grammar/datamodel.langium index b2715edb..de5780be 100644 --- a/packages/server/src/language-server/grammar/datamodel.langium +++ b/packages/server/src/language-server/grammar/datamodel.langium @@ -4,15 +4,22 @@ import 'common' interface DataModel extends NamedObject, WithCustomProperties { type: string; version?: string; + crossmodel?: CrossModelEditionInfo; dependencies: DataModelDependency[]; } +interface CrossModelEditionInfo { + edition: string; + version: string; +} + DataModel returns DataModel: 'datamodel' ':' INDENT NamedObjectFragment 'type' ':' type=DataModelType ('version' ':' version=VERSION)? + ('crossmodel' ':' crossmodel=CrossModelEditionInfo)? ('dependencies' ':' INDENT (LIST_ITEM dependencies+=DataModelDependency)+ @@ -22,7 +29,15 @@ DataModel returns DataModel: DEDENT ; -DataModelType returns string: 'conceptual' | 'logical' | 'relational'; +CrossModelEditionInfo returns CrossModelEditionInfo: + INDENT + 'edition' ':' edition=ID + 'version' ':' version=VERSION + DEDENT +; + +DataModelType returns string: + 'conceptual' | 'logical' | 'relational'; interface DataModelDependency { datamodel: @DataModel; diff --git a/packages/server/src/language-server/util/serialization-util.ts b/packages/server/src/language-server/util/serialization-util.ts index 2c0dabdb..116d3a78 100644 --- a/packages/server/src/language-server/util/serialization-util.ts +++ b/packages/server/src/language-server/util/serialization-util.ts @@ -8,6 +8,7 @@ import { AttributeMappingExpression, AttributeMappingSource, AttributeMappingTarget, + CrossModelEditionInfo, CustomProperty, DataModel, DataModelDependency, @@ -56,6 +57,8 @@ const UNQUOTED_PROPERTIES = new Set([ `${SourceObject.$type}.${SourceObject.join}`, `${DataModel.$type}.${DataModel.type}`, `${DataModel.$type}.${DataModel.version}`, + `${CrossModelEditionInfo.$type}.${CrossModelEditionInfo.edition}`, + `${CrossModelEditionInfo.$type}.${CrossModelEditionInfo.version}`, `${DataModelDependency.$type}.${DataModelDependency.version}` ]); @@ -232,8 +235,12 @@ const PROPERTY_ORDER = new Map([ [AttributeMappingExpression.$type, [AttributeMappingExpression.language, AttributeMappingExpression.expression]], [CustomProperty.$type, [...NAMED_OBJECT_PROPERTIES, CustomProperty.value]], [LogicalIdentifier.$type, [...NAMED_OBJECT_PROPERTIES, LogicalIdentifier.primary, LogicalIdentifier.attributes, ...CUSTOM_PROPERTIES]], - [DataModel.$type, [...NAMED_OBJECT_PROPERTIES, DataModel.type, DataModel.version, DataModel.dependencies, ...CUSTOM_PROPERTIES]], - [DataModelDependency.$type, [DataModelDependency.datamodel, DataModelDependency.version]] + [ + DataModel.$type, + [...NAMED_OBJECT_PROPERTIES, DataModel.type, DataModel.version, DataModel.crossmodel, DataModel.dependencies, ...CUSTOM_PROPERTIES] + ], + [DataModelDependency.$type, [DataModelDependency.datamodel, DataModelDependency.version]], + [CrossModelEditionInfo.$type, [CrossModelEditionInfo.edition, CrossModelEditionInfo.version]] ]); PROPERTY_ORDER.set(SourceObjectAttribute.$type, PROPERTY_ORDER.get(LogicalAttribute.$type) ?? []); PROPERTY_ORDER.set(TargetObjectAttribute.$type, PROPERTY_ORDER.get(LogicalAttribute.$type) ?? []); diff --git a/packages/server/src/model-server/crossmodel-version-util.ts b/packages/server/src/model-server/crossmodel-version-util.ts new file mode 100644 index 00000000..c58ef9c4 --- /dev/null +++ b/packages/server/src/model-server/crossmodel-version-util.ts @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (c) 2026 CrossBreeze. + ********************************************************************************/ + +import { getCrossModelEdition, getCrossModelVersion } from '@crossmodel/protocol'; +import { CrossModelEditionInfo, DataModel } from '../language-server/generated/ast.js'; + +/** + * Checks if a datamodel's stored CrossModel version/edition differs from the current one. + * + * @param dataModel the datamodel to check + * @returns true if the datamodel needs an update + */ +export function needsCrossModelVersionUpdate(dataModel: DataModel): boolean { + const currentVersion = getCrossModelVersion(); + if (!dataModel.crossmodel) { + // No crossmodel info stored, needs update + return true; + } + return dataModel.crossmodel.edition !== getCrossModelEdition() || dataModel.crossmodel.version !== currentVersion; +} + +/** + * Updates the CrossModel version and edition in a datamodel to the current values. + * Creates the crossmodel object if it doesn't exist. + * + * @param dataModel the datamodel to update + */ +export function updateCrossModelVersion(dataModel: DataModel): void { + const currentVersion = getCrossModelVersion(); + if (!dataModel.crossmodel) { + // Create the crossmodel object + (dataModel as any).crossmodel = { + $type: 'CrossModelEditionInfo', + edition: getCrossModelEdition(), + version: currentVersion + } as CrossModelEditionInfo; + } else { + dataModel.crossmodel.edition = getCrossModelEdition(); + dataModel.crossmodel.version = currentVersion; + } +} + +/** + * Ensures a datamodel has the current CrossModel version/edition info. + * Updates it if needed. + * + * @param dataModel the datamodel to update + * @returns true if an update was performed + */ +export function ensureCrossModelVersion(dataModel: DataModel): boolean { + if (needsCrossModelVersionUpdate(dataModel)) { + updateCrossModelVersion(dataModel); + return true; + } + return false; +} diff --git a/packages/server/src/model-server/model-service.ts b/packages/server/src/model-server/model-service.ts index e00a06fe..f03715a5 100644 --- a/packages/server/src/model-server/model-service.ts +++ b/packages/server/src/model-server/model-service.ts @@ -23,8 +23,9 @@ import { Disposable, OptionalVersionedTextDocumentIdentifier, Range, TextDocumen import { URI } from 'vscode-uri'; import { CrossModelLangiumDocument, CrossModelLangiumDocuments } from '../language-server/cross-model-langium-documents.js'; import { CrossModelServices, CrossModelSharedServices } from '../language-server/cross-model-module.js'; -import { CrossModelRoot, isCrossModelRoot } from '../language-server/generated/ast.js'; +import { CrossModelRoot, isCrossModelRoot, isDataModel } from '../language-server/generated/ast.js'; import { findDocument } from '../language-server/util/ast-util.js'; +import { ensureCrossModelVersion } from './crossmodel-version-util.js'; import { AstCrossModelDocument } from './open-text-document-manager.js'; import { LANGUAGE_CLIENT_ID } from './openable-text-documents.js'; @@ -141,8 +142,30 @@ export class ModelService { if (!isAstNode(root)) { throw new Error(`No AST node to update exists in '${args.uri}'`); } + + // Ensure CrossModel version is up to date for data models + let text: string; + if (typeof args.model === 'string') { + const parsed = this.shared.workspace.LangiumDocumentFactory.fromString(args.model, documentUri); + const parsedRoot = parsed.parseResult.value; + if (isCrossModelRoot(parsedRoot)) { + if (parsedRoot.datamodel) { + ensureCrossModelVersion(parsedRoot.datamodel); + } + text = this.serialize(documentUri, parsedRoot); + } else { + text = args.model; + } + } else { + if (isDataModel(args.model)) { + ensureCrossModelVersion(args.model); + } else if (isCrossModelRoot(args.model) && args.model.datamodel) { + ensureCrossModelVersion(args.model.datamodel); + } + text = this.serialize(documentUri, args.model); + } + const textDocument = document.textDocument; - const text = typeof args.model === 'string' ? args.model : this.serialize(documentUri, args.model); if (text === textDocument.getText()) { return { diagnostics: document.diagnostics ?? [], @@ -190,9 +213,29 @@ export class ModelService { async save(args: SaveModelArgs): Promise { // sync: implicit update of internal data structure to match file system (similar to workspace initialization) const documentUri = URI.parse(args.uri); - const text = typeof args.model === 'string' ? args.model : this.serialize(documentUri, args.model); + // Ensure CrossModel version is up to date for data models + let text: string; + if (typeof args.model === 'string') { + const parsed = this.shared.workspace.LangiumDocumentFactory.fromString(args.model, documentUri); + const parsedRoot = parsed.parseResult.value; + if (isCrossModelRoot(parsedRoot)) { + if (parsedRoot.datamodel) { + ensureCrossModelVersion(parsedRoot.datamodel); + } + text = this.serialize(documentUri, parsedRoot); + } else { + text = args.model; + } + } else { + if (isDataModel(args.model)) { + ensureCrossModelVersion(args.model); + } else if (isCrossModelRoot(args.model) && args.model.datamodel) { + ensureCrossModelVersion(args.model.datamodel); + } + text = this.serialize(documentUri, args.model); + } if (this.documents.hasDocument(documentUri)) { - await this.update(args); + await this.update({ ...args, model: text }); } else { this.documents.createDocument(documentUri, text); await this.documentBuilder.update([documentUri], []); diff --git a/packages/server/syntaxes/cross-model.tmLanguage.json b/packages/server/syntaxes/cross-model.tmLanguage.json index 5325bde7..0bd36a72 100644 --- a/packages/server/syntaxes/cross-model.tmLanguage.json +++ b/packages/server/syntaxes/cross-model.tmLanguage.json @@ -10,7 +10,7 @@ }, { "name": "keyword.control.cross-model", - "match": "\\b(0\\.\\.N|1\\.\\.N|TRUE|apply|attribute|attributes|baseNode|child|childCardinality|childRole|conceptual|conditions|cross-join|customProperties|datamodel|datatype|dependencies|description|diagram|edges|entity|expression|expressions|from|height|id|identifiers|inherits|inner-join|join|language|left-join|length|logical|mandatory|mapping|mappings|name|nodes|parent|parentCardinality|parentRole|precision|primary|relational|relationship|scale|sourceNode|sources|superNode|systemDiagram|target|targetNode|true|type|value|version|width|x|y)\\b" + "match": "\\b(0\\.\\.N|1\\.\\.N|TRUE|apply|attribute|attributes|baseNode|child|childCardinality|childRole|conceptual|conditions|cross-join|crossmodel|customProperties|datamodel|datatype|dependencies|description|diagram|edges|edition|entity|expression|expressions|from|height|id|identifiers|inherits|inner-join|join|language|left-join|length|logical|mandatory|mapping|mappings|name|nodes|parent|parentCardinality|parentRole|precision|primary|relational|relationship|scale|sourceNode|sources|superNode|systemDiagram|target|targetNode|true|type|value|version|width|x|y)\\b" }, { "name": "string.quoted.double.cross-model",