diff --git a/diagrams/metametamodel-gen.md b/diagrams/metametamodel-gen.md index 7625c179..8d780e4d 100644 --- a/diagrams/metametamodel-gen.md +++ b/diagrams/metametamodel-gen.md @@ -1,45 +1,53 @@ ```mermaid classDiagram + class Classifier + <> Classifier + LanguageEntity <|-- Classifier + class Concept { +Boolean abstract + +Boolean partition } - FeaturesContainer <|-- Concept + Classifier <|-- Concept class ConceptInterface - FeaturesContainer <|-- ConceptInterface + Classifier <|-- ConceptInterface class Containment Link <|-- Containment class DataType <> DataType - LanguageElement <|-- DataType + LanguageEntity <|-- DataType class Enumeration DataType <|-- Enumeration class EnumerationLiteral - NamespacedEntity <|-- EnumerationLiteral class Feature { +Boolean optional } <> Feature - NamespacedEntity <|-- Feature - class FeaturesContainer - <> FeaturesContainer - LanguageElement <|-- FeaturesContainer + class IKeyed { + +String key + } + <> IKeyed + INamed <|-- IKeyed - class Language { + class INamed { +String name + } + <> INamed + + class Language { +String version } - class LanguageElement - <> LanguageElement - NamespacedEntity <|-- LanguageElement + class LanguageEntity + <> LanguageEntity class Link { +Boolean multiple @@ -47,15 +55,6 @@ classDiagram <> Link Feature <|-- Link - class NamespaceProvider - <> NamespaceProvider - - class NamespacedEntity { - +String name - +String key - } - <> NamespacedEntity - class PrimitiveType DataType <|-- PrimitiveType @@ -66,6 +65,7 @@ classDiagram Link <|-- Reference + Classifier "1" o-- "*" Feature: features Concept "*" -- "0..1" Concept: extends Concept "*" -- "*" ConceptInterface: implements ConceptInterface "*" -- "*" ConceptInterface: extends @@ -74,13 +74,12 @@ classDiagram Enumeration "1" o-- "*" EnumerationLiteral: literals - FeaturesContainer "1" o-- "*" Feature: features - Language "1" o-- "*" LanguageElement: elements - Language "*" -- "*" Language: dependsOn - Link "*" -- "1" FeaturesContainer: type + Language "1" o-- "*" LanguageEntity: entities + Language "*" -- "*" Language: dependsOn + Link "*" -- "1" Classifier: type Property "*" -- "1" DataType: type diff --git a/diagrams/metametamodel-gen.puml b/diagrams/metametamodel-gen.puml index e413da62..3fff3499 100644 --- a/diagrams/metametamodel-gen.puml +++ b/diagrams/metametamodel-gen.puml @@ -4,43 +4,45 @@ hide empty members ' qualified name: "LIonCore.M3" -class Concept extends FeaturesContainer { +abstract class Classifier extends LanguageEntity + +class Concept extends Classifier { abstract: Boolean + partition: Boolean } -class ConceptInterface extends FeaturesContainer +class ConceptInterface extends Classifier class Containment extends Link -abstract class DataType extends LanguageElement +abstract class DataType extends LanguageEntity -class Enumeration extends DataType implements NamespaceProvider +class Enumeration extends DataType -class EnumerationLiteral extends NamespacedEntity +class EnumerationLiteral implements IKeyed -abstract class Feature extends NamespacedEntity { +abstract class Feature implements IKeyed { optional: Boolean } -abstract class FeaturesContainer extends LanguageElement implements NamespaceProvider +interface IKeyed extends INamed { + key: String +} -class Language implements NamespaceProvider { +interface INamed { name: String +} + +class Language implements IKeyed { version: String } -abstract class LanguageElement extends NamespacedEntity +abstract class LanguageEntity implements IKeyed abstract class Link extends Feature { multiple: Boolean } -interface NamespaceProvider -abstract class NamespacedEntity { - name: String - key: String -} - class PrimitiveType extends DataType class Property extends Feature @@ -51,6 +53,7 @@ class Reference extends Link ' relations: +Classifier "1" o-- "*" Feature: features Concept "*" -- "0..1" Concept: extends Concept "*" -- "*" ConceptInterface: implements ConceptInterface "*" -- "*" ConceptInterface: extends @@ -59,13 +62,12 @@ ConceptInterface "*" -- "*" ConceptInterface: extends Enumeration "1" o-- "*" EnumerationLiteral: literals -FeaturesContainer "1" o-- "*" Feature: features -Language "1" o-- "*" LanguageElement: elements -Language "*" -- "*" Language: dependsOn -Link "*" -- "1" FeaturesContainer: type +Language "1" o-- "*" LanguageEntity: entities +Language "*" -- "*" Language: dependsOn +Link "*" -- "1" Classifier: type Property "*" -- "1" DataType: type diff --git a/models/meta/builtins.json b/models/meta/builtins.json index 41251dce..906cf2fe 100644 --- a/models/meta/builtins.json +++ b/models/meta/builtins.json @@ -7,24 +7,32 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Language" + "key": "LIonCore.M3-Language" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "Language_name" + "key": "LIonCore.M3-Language-version" }, - "value": "LIonCore.builtins" + "value": "1" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "version" + "key": "LIonCore.M3-INamed-key" }, - "value": "1" + "value": "LIonCore_builtins" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "LIonCore.builtins" } ], "children": [ @@ -32,7 +40,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "elements" + "key": "LIonCore.M3-Language-entities" }, "children": [ "LIonCore_builtins_String", @@ -49,14 +57,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "PrimitiveType" + "key": "LIonCore.M3-PrimitiveType" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "String" }, @@ -64,7 +72,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "String" } @@ -78,14 +86,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "PrimitiveType" + "key": "LIonCore.M3-PrimitiveType" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "Boolean" }, @@ -93,7 +101,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "Boolean" } @@ -107,14 +115,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "PrimitiveType" + "key": "LIonCore.M3-PrimitiveType" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "Integer" }, @@ -122,7 +130,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "Integer" } @@ -136,14 +144,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "PrimitiveType" + "key": "LIonCore.M3-PrimitiveType" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "JSON" }, @@ -151,7 +159,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "JSON" } diff --git a/models/meta/library.json b/models/meta/library.json index 3f94c5ff..bc401ffe 100644 --- a/models/meta/library.json +++ b/models/meta/library.json @@ -7,24 +7,32 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Language" + "key": "LIonCore.M3-Language" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "Language_name" + "key": "LIonCore.M3-Language-version" }, - "value": "library" + "value": "1" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "version" + "key": "LIonCore.M3-INamed-key" }, - "value": "1" + "value": "txjxNU9yRzEuyghtmgJK_l-nF93qWt7d1vErz5RbLow" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "library" } ], "children": [ @@ -32,7 +40,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "elements" + "key": "LIonCore.M3-Language-entities" }, "children": [ "OcDK2GESljInG-ApIqtkXUoA2UeviB97u0UuiZzM0Hs", @@ -50,14 +58,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -65,7 +73,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "Book" }, @@ -73,7 +81,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "Book" } @@ -83,7 +91,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ "Ei9m_HbdmEYg_EwMLLVZ71ERRBZyXH8GHVyOVia8Sqg", @@ -100,14 +108,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -115,7 +123,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "title" }, @@ -123,7 +131,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "title" } @@ -134,7 +142,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -150,14 +158,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -165,7 +173,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "pages" }, @@ -173,7 +181,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "pages" } @@ -184,7 +192,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -200,14 +208,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, "value": "false" }, @@ -215,7 +223,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -223,7 +231,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "author" }, @@ -231,7 +239,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "author" } @@ -242,7 +250,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { @@ -258,14 +266,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -273,7 +281,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "Library" }, @@ -281,7 +289,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "Library" } @@ -291,7 +299,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ "LdgCnVXNgZD7CLbBhBin2Rcdumx4qZUYz_jh2QnP5z8", @@ -307,14 +315,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -322,17 +330,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "name" + "value": "library_Library_name" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "library_Library_name" + "value": "name" } ], "children": [], @@ -341,7 +349,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -357,14 +365,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Containment" + "key": "LIonCore.M3-Containment" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, "value": "true" }, @@ -372,7 +380,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -380,7 +388,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "books" }, @@ -388,7 +396,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "books" } @@ -399,7 +407,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { @@ -415,14 +423,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -430,7 +438,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "Writer" }, @@ -438,7 +446,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "Writer" } @@ -448,7 +456,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ "onRRrZaasiOtDU2qFJgyW8OVz8p5-hqQu0Vlc_7Aq6s" @@ -463,14 +471,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -478,17 +486,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "name" + "value": "library_Writer_name" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "library_Writer_name" + "value": "name" } ], "children": [], @@ -497,7 +505,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -513,14 +521,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -528,7 +536,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "GuideBookWriter" }, @@ -536,7 +544,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "GuideBookWriter" } @@ -546,7 +554,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ "PoZyl6WXh-Cz5h2RspK1NL6zX9DdLwGpUUC-ygQmHMA" @@ -558,7 +566,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { @@ -574,14 +582,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -589,7 +597,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "countries" }, @@ -597,7 +605,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "countries" } @@ -608,7 +616,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -624,14 +632,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -639,7 +647,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "SpecialistBookWriter" }, @@ -647,7 +655,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "SpecialistBookWriter" } @@ -657,7 +665,7 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ "DbVixG73dI8xIF9TAoq2GOZru4CRQfRD8gG7TkFCZuU" @@ -669,7 +677,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { @@ -685,14 +693,14 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -700,7 +708,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, "value": "subject" }, @@ -708,7 +716,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, "value": "subject" } @@ -719,7 +727,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { diff --git a/models/meta/lioncore.json b/models/meta/lioncore.json index fdf05408..2a097e67 100644 --- a/models/meta/lioncore.json +++ b/models/meta/lioncore.json @@ -7,24 +7,32 @@ "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Language" + "key": "LIonCore.M3-Language" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "Language_name" + "key": "LIonCore.M3-Language-version" }, - "value": "LIonCore.M3" + "value": "2" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-key" + }, + "value": "LIonCore_M3" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "version" + "key": "LIonCore.M3-INamed-name" }, - "value": "1" + "value": "LIonCore.M3" } ], "children": [ @@ -32,61 +40,53 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "elements" + "key": "LIonCore.M3-Language-entities" }, "children": [ - "LIonCore_M3_NamespacedEntity", - "LIonCore_M3_NamespaceProvider", - "LIonCore_M3_Language", - "LIonCore_M3_LanguageElement", - "LIonCore_M3_FeaturesContainer", - "LIonCore_M3_Concept", - "LIonCore_M3_ConceptInterface", + "LIonCore_M3_INamed", + "LIonCore_M3_IKeyed", "LIonCore_M3_Feature", + "LIonCore_M3_Property", "LIonCore_M3_Link", + "LIonCore_M3_Containment", "LIonCore_M3_Reference", - "LIonCore_M3_Property", + "LIonCore_M3_LanguageEntity", + "LIonCore_M3_Classifier", + "LIonCore_M3_Concept", + "LIonCore_M3_ConceptInterface", "LIonCore_M3_DataType", "LIonCore_M3_PrimitiveType", - "LIonCore_M3_Containment", "LIonCore_M3_Enumeration", - "LIonCore_M3_EnumerationLiteral" + "LIonCore_M3_EnumerationLiteral", + "LIonCore_M3_Language" ] } ], "references": [] }, { - "id": "LIonCore_M3_NamespacedEntity", + "id": "LIonCore_M3_INamed", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-ConceptInterface" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-INamed-key" }, - "value": "true" - }, - { - "property": { - "language": "LIonCore_M3", - "version": "1", - "key": "NamespacedEntity_name" - }, - "value": "NamespacedEntity" + "value": "LIonCore.M3-INamed" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "NamespacedEntity" + "value": "INamed" } ], "children": [ @@ -94,11 +94,10 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ - "LIonCore_M3_NamespacedEntity_name", - "LIonCore_M3_NamespacedEntity_key" + "LIonCore_M3_INamed_name" ] } ], @@ -106,18 +105,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_NamespacedEntity_name", + "id": "LIonCore_M3_INamed_name", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -125,17 +124,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "name" + "value": "LIonCore.M3-INamed-name" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "NamespacedEntity_name" + "value": "name" } ], "children": [], @@ -144,7 +143,7 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { @@ -153,118 +152,142 @@ ] } ], - "parent": "LIonCore_M3_NamespacedEntity" + "parent": "LIonCore_M3_INamed" }, { - "id": "LIonCore_M3_NamespacedEntity_key", + "id": "LIonCore_M3_IKeyed", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-ConceptInterface" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-INamed-key" }, - "value": "false" + "value": "LIonCore.M3-IKeyed" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-name" }, - "value": "key" - }, + "value": "IKeyed" + } + ], + "children": [ { - "property": { + "containment": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-Classifier-features" }, - "value": "NamespacedEntity_key" + "children": [ + "LIonCore_M3_INamed_key" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-ConceptInterface-extends" }, "targets": [ { - "reference": "LIonCore_builtins_String" + "reference": "LIonCore_M3_INamed" } ] } ], - "parent": "LIonCore_M3_NamespacedEntity" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_NamespaceProvider", + "id": "LIonCore_M3_INamed_key", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "ConceptInterface" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "NamespaceProvider" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "NamespaceProvider" + "value": "LIonCore.M3-INamed-key" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "key" } ], "children": [], - "references": [], - "parent": "LIonCore_M3" + "references": [ + { + "reference": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-Property-type" + }, + "targets": [ + { + "reference": "LIonCore_builtins_String" + } + ] + } + ], + "parent": "LIonCore_M3_IKeyed" }, { - "id": "LIonCore_M3_Language", + "id": "LIonCore_M3_Feature", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Language" + "value": "LIonCore.M3-Feature" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Language" + "value": "Feature" } ], "children": [ @@ -272,13 +295,10 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ - "LIonCore_M3_Language_name", - "LIonCore_M3_Language_version", - "LIonCore_M3_Language_elements", - "LIonCore_M3_Language_dependsOn" + "LIonCore_M3_Feature_optional" ] } ], @@ -287,11 +307,11 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "implements" + "key": "LIonCore.M3-Concept-implements" }, "targets": [ { - "reference": "LIonCore_M3_NamespaceProvider" + "reference": "LIonCore_M3_IKeyed" } ] } @@ -299,18 +319,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Language_name", + "id": "LIonCore_M3_Feature_optional", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -318,17 +338,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "name" + "value": "LIonCore.M3-Feature-optional" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Language_name" + "value": "optional" } ], "children": [], @@ -337,30 +357,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { - "reference": "LIonCore_builtins_String" + "reference": "LIonCore_builtins_Boolean" } ] } ], - "parent": "LIonCore_M3_Language" + "parent": "LIonCore_M3_Feature" }, { - "id": "LIonCore_M3_Language_version", + "id": "LIonCore_M3_Property", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -368,75 +388,86 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "version" + "value": "LIonCore.M3-Property" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "version" + "value": "Property" + } + ], + "children": [ + { + "containment": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-Classifier-features" + }, + "children": [ + "LIonCore_M3_Property_type" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_builtins_String" + "reference": "LIonCore_M3_Feature" } ] } ], - "parent": "LIonCore_M3_Language" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Language_elements", + "id": "LIonCore_M3_Property_type", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Containment" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "elements" + "value": "LIonCore.M3-Property-type" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "elements" + "value": "type" } ], "children": [], @@ -445,30 +476,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_LanguageElement" + "reference": "LIonCore_M3_DataType" } ] } ], - "parent": "LIonCore_M3_Language" + "parent": "LIonCore_M3_Property" }, { - "id": "LIonCore_M3_Language_dependsOn", + "id": "LIonCore_M3_Link", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Concept-abstract" }, "value": "true" }, @@ -476,75 +507,79 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-INamed-key" }, - "value": "true" + "value": "LIonCore.M3-Link" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-name" }, - "value": "dependsOn" - }, + "value": "Link" + } + ], + "children": [ { - "property": { + "containment": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-Classifier-features" }, - "value": "dependsOn" + "children": [ + "LIonCore_M3_Link_multiple", + "LIonCore_M3_Link_type" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_Language" + "reference": "LIonCore_M3_Feature" } ] } ], - "parent": "LIonCore_M3_Language" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_LanguageElement", + "id": "LIonCore_M3_Link_multiple", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Feature-optional" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "LanguageElement" + "value": "LIonCore.M3-Link-multiple" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "LanguageElement" + "value": "multiple" } ], "children": [], @@ -553,129 +588,106 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Property-type" }, "targets": [ { - "reference": "LIonCore_M3_NamespacedEntity" + "reference": "LIonCore_builtins_Boolean" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Link" }, { - "id": "LIonCore_M3_FeaturesContainer", + "id": "LIonCore_M3_Link_type", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Link-multiple" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "FeaturesContainer" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "FeaturesContainer" - } - ], - "children": [ + "value": "LIonCore.M3-Link-type" + }, { - "containment": { + "property": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-INamed-name" }, - "children": [ - "LIonCore_M3_FeaturesContainer_features" - ] + "value": "type" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_LanguageElement" - } - ] - }, - { - "reference": { - "language": "LIonCore_M3", - "version": "1", - "key": "implements" - }, - "targets": [ - { - "reference": "LIonCore_M3_NamespaceProvider" + "reference": "LIonCore_M3_Classifier" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Link" }, { - "id": "LIonCore_M3_FeaturesContainer_features", + "id": "LIonCore_M3_Containment", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Containment" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" - }, - "value": "true" - }, - { - "property": { - "language": "LIonCore_M3", - "version": "1", - "key": "optional" + "key": "LIonCore.M3-Concept-abstract" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "features" + "value": "LIonCore.M3-Containment" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "features" + "value": "Containment" } ], "children": [], @@ -684,30 +696,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_Feature" + "reference": "LIonCore_M3_Link" } ] } ], - "parent": "LIonCore_M3_FeaturesContainer" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Concept", + "id": "LIonCore_M3_Reference", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -715,43 +727,30 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Concept" + "value": "LIonCore.M3-Reference" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Concept" - } - ], - "children": [ - { - "containment": { - "language": "LIonCore_M3", - "version": "1", - "key": "features" - }, - "children": [ - "LIonCore_M3_Concept_abstract", - "LIonCore_M3_Concept_extends", - "LIonCore_M3_Concept_implements" - ] + "value": "Reference" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_FeaturesContainer" + "reference": "LIonCore_M3_Link" } ] } @@ -759,36 +758,36 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Concept_abstract", + "id": "LIonCore_M3_LanguageEntity", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Concept-abstract" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "abstract" + "value": "LIonCore.M3-LanguageEntity" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "abstract" + "value": "LanguageEntity" } ], "children": [], @@ -797,88 +796,91 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Concept-implements" }, "targets": [ { - "reference": "LIonCore_builtins_Boolean" + "reference": "LIonCore_M3_IKeyed" } ] } ], - "parent": "LIonCore_M3_Concept" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Concept_extends", + "id": "LIonCore_M3_Classifier", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Concept-abstract" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-INamed-key" }, - "value": "true" + "value": "LIonCore.M3-Classifier" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-name" }, - "value": "extends" - }, + "value": "Classifier" + } + ], + "children": [ { - "property": { + "containment": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-Classifier-features" }, - "value": "Concept_extends" + "children": [ + "LIonCore_M3_Classifier_features" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_Concept" + "reference": "LIonCore_M3_LanguageEntity" } ] } ], - "parent": "LIonCore_M3_Concept" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Concept_implements", + "id": "LIonCore_M3_Classifier_features", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Containment" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, "value": "true" }, @@ -886,7 +888,7 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, "value": "true" }, @@ -894,17 +896,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "implements" + "value": "LIonCore.M3-Classifier-features" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "implements" + "value": "features" } ], "children": [], @@ -913,30 +915,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_ConceptInterface" + "reference": "LIonCore_M3_Feature" } ] } ], - "parent": "LIonCore_M3_Concept" + "parent": "LIonCore_M3_Classifier" }, { - "id": "LIonCore_M3_ConceptInterface", + "id": "LIonCore_M3_Concept", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -944,17 +946,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "ConceptInterface" + "value": "LIonCore.M3-Concept" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "ConceptInterface" + "value": "Concept" } ], "children": [ @@ -962,10 +964,13 @@ "containment": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-Classifier-features" }, "children": [ - "LIonCore_M3_ConceptInterface_extends" + "LIonCore_M3_Concept_abstract", + "LIonCore_M3_Concept_partition", + "LIonCore_M3_Concept_extends", + "LIonCore_M3_Concept_implements" ] } ], @@ -974,11 +979,11 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_FeaturesContainer" + "reference": "LIonCore_M3_Classifier" } ] } @@ -986,44 +991,36 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_ConceptInterface_extends", + "id": "LIonCore_M3_Concept_abstract", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Feature-optional" }, - "value": "true" - }, - { - "property": { - "language": "LIonCore_M3", - "version": "1", - "key": "optional" - }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "extends" + "value": "LIonCore.M3-Concept-abstract" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "ConceptInterface_extends" + "value": "abstract" } ], "children": [], @@ -1032,91 +1029,80 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Property-type" }, "targets": [ { - "reference": "LIonCore_M3_ConceptInterface" + "reference": "LIonCore_builtins_Boolean" } ] } ], - "parent": "LIonCore_M3_ConceptInterface" + "parent": "LIonCore_M3_Concept" }, { - "id": "LIonCore_M3_Feature", + "id": "LIonCore_M3_Concept_partition", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Feature-optional" }, - "value": "true" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Feature" + "value": "LIonCore.M3-Concept-partition" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Feature" - } - ], - "children": [ - { - "containment": { - "language": "LIonCore_M3", - "version": "1", - "key": "features" - }, - "children": [ - "LIonCore_M3_Feature_optional" - ] + "value": "partition" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Property-type" }, "targets": [ { - "reference": "LIonCore_M3_NamespacedEntity" + "reference": "LIonCore_builtins_Boolean" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Concept" }, { - "id": "LIonCore_M3_Feature_optional", + "id": "LIonCore_M3_Concept_extends", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Link-multiple" }, "value": "false" }, @@ -1124,17 +1110,25 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "optional" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "optional" + "value": "LIonCore.M3-Concept-extends" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "extends" } ], "children": [], @@ -1143,30 +1137,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_builtins_Boolean" + "reference": "LIonCore_M3_Concept" } ] } ], - "parent": "LIonCore_M3_Feature" + "parent": "LIonCore_M3_Concept" }, { - "id": "LIonCore_M3_Link", + "id": "LIonCore_M3_Concept_implements", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Link-multiple" }, "value": "true" }, @@ -1174,61 +1168,57 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "Link" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "Link" - } - ], - "children": [ + "value": "LIonCore.M3-Concept-implements" + }, { - "containment": { + "property": { "language": "LIonCore_M3", "version": "1", - "key": "features" + "key": "LIonCore.M3-INamed-name" }, - "children": [ - "LIonCore_M3_Link_multiple", - "LIonCore_M3_Link_type" - ] + "value": "implements" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_Feature" + "reference": "LIonCore_M3_ConceptInterface" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Concept" }, { - "id": "LIonCore_M3_Link_multiple", + "id": "LIonCore_M3_ConceptInterface", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -1236,75 +1226,86 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "multiple" + "value": "LIonCore.M3-ConceptInterface" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "multiple" + "value": "ConceptInterface" + } + ], + "children": [ + { + "containment": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-Classifier-features" + }, + "children": [ + "LIonCore_M3_ConceptInterface_extends" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_builtins_Boolean" + "reference": "LIonCore_M3_Classifier" } ] } ], - "parent": "LIonCore_M3_Link" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Link_type", + "id": "LIonCore_M3_ConceptInterface_extends", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "type" + "value": "LIonCore.M3-ConceptInterface-extends" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Link_type" + "value": "extends" } ], "children": [], @@ -1313,48 +1314,48 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_FeaturesContainer" + "reference": "LIonCore_M3_ConceptInterface" } ] } ], - "parent": "LIonCore_M3_Link" + "parent": "LIonCore_M3_ConceptInterface" }, { - "id": "LIonCore_M3_Reference", + "id": "LIonCore_M3_DataType", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Reference" + "value": "LIonCore.M3-DataType" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Reference" + "value": "DataType" } ], "children": [], @@ -1363,11 +1364,11 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_Link" + "reference": "LIonCore_M3_LanguageEntity" } ] } @@ -1375,18 +1376,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Property", + "id": "LIonCore_M3_PrimitiveType", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -1394,41 +1395,30 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Property" + "value": "LIonCore.M3-PrimitiveType" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" - }, - "value": "Property" - } - ], - "children": [ - { - "containment": { - "language": "LIonCore_M3", - "version": "1", - "key": "features" + "key": "LIonCore.M3-INamed-name" }, - "children": [ - "LIonCore_M3_Property_type" - ] + "value": "PrimitiveType" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { - "reference": "LIonCore_M3_Feature" + "reference": "LIonCore_M3_DataType" } ] } @@ -1436,18 +1426,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Property_type", + "id": "LIonCore_M3_Enumeration", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -1455,34 +1445,37 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-INamed-key" }, - "value": "false" + "value": "LIonCore.M3-Enumeration" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-name" }, - "value": "type" - }, + "value": "Enumeration" + } + ], + "children": [ { - "property": { + "containment": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-Classifier-features" }, - "value": "type" + "children": [ + "LIonCore_M3_Enumeration_literals" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Concept-extends" }, "targets": [ { @@ -1491,21 +1484,21 @@ ] } ], - "parent": "LIonCore_M3_Property" + "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_DataType", + "id": "LIonCore_M3_Enumeration_literals", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Containment" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Link-multiple" }, "value": "true" }, @@ -1513,17 +1506,25 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "DataType" + "value": "false" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "DataType" + "value": "LIonCore.M3-Enumeration-literals" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "literals" } ], "children": [], @@ -1532,30 +1533,30 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_LanguageElement" + "reference": "LIonCore_M3_EnumerationLiteral" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Enumeration" }, { - "id": "LIonCore_M3_PrimitiveType", + "id": "LIonCore_M3_EnumerationLiteral", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -1563,17 +1564,17 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "PrimitiveType" + "value": "LIonCore.M3-EnumerationLiteral" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "PrimitiveType" + "value": "EnumerationLiteral" } ], "children": [], @@ -1582,11 +1583,11 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-implements" }, "targets": [ { - "reference": "LIonCore_M3_DataType" + "reference": "LIonCore_M3_IKeyed" } ] } @@ -1594,18 +1595,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Containment", + "id": "LIonCore_M3_Language", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Concept" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Concept-abstract" }, "value": "false" }, @@ -1613,30 +1614,43 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Containment" + "value": "LIonCore.M3-Language" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "Containment" + "value": "Language" + } + ], + "children": [ + { + "containment": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-Classifier-features" + }, + "children": [ + "LIonCore_M3_Language_version", + "LIonCore_M3_Language_entities", + "LIonCore_M3_Language_dependsOn" + ] } ], - "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Concept-implements" }, "targets": [ { - "reference": "LIonCore_M3_Link" + "reference": "LIonCore_M3_IKeyed" } ] } @@ -1644,18 +1658,18 @@ "parent": "LIonCore_M3" }, { - "id": "LIonCore_M3_Enumeration", + "id": "LIonCore_M3_Language_version", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Property" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Feature-optional" }, "value": "false" }, @@ -1663,72 +1677,49 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "Enumeration" + "value": "LIonCore.M3-Language-version" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" - }, - "value": "Enumeration" - } - ], - "children": [ - { - "containment": { - "language": "LIonCore_M3", - "version": "1", - "key": "features" + "key": "LIonCore.M3-INamed-name" }, - "children": [ - "LIonCore_M3_Enumeration_literals" - ] + "value": "version" } ], + "children": [], "references": [ { "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" - }, - "targets": [ - { - "reference": "LIonCore_M3_DataType" - } - ] - }, - { - "reference": { - "language": "LIonCore_M3", - "version": "1", - "key": "implements" + "key": "LIonCore.M3-Property-type" }, "targets": [ { - "reference": "LIonCore_M3_NamespaceProvider" + "reference": "LIonCore_builtins_String" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Language" }, { - "id": "LIonCore_M3_Enumeration_literals", + "id": "LIonCore_M3_Language_entities", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Containment" + "key": "LIonCore.M3-Containment" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "multiple" + "key": "LIonCore.M3-Link-multiple" }, "value": "true" }, @@ -1736,25 +1727,25 @@ "property": { "language": "LIonCore_M3", "version": "1", - "key": "optional" + "key": "LIonCore.M3-Feature-optional" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-INamed-key" }, - "value": "literals" + "value": "LIonCore.M3-Language-entities" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-name" }, - "value": "literals" + "value": "entities" } ], "children": [], @@ -1763,48 +1754,56 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Link_type" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_EnumerationLiteral" + "reference": "LIonCore_M3_LanguageEntity" } ] } ], - "parent": "LIonCore_M3_Enumeration" + "parent": "LIonCore_M3_Language" }, { - "id": "LIonCore_M3_EnumerationLiteral", + "id": "LIonCore_M3_Language_dependsOn", "concept": { "language": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Reference" }, "properties": [ { "property": { "language": "LIonCore_M3", "version": "1", - "key": "abstract" + "key": "LIonCore.M3-Link-multiple" }, - "value": "false" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_name" + "key": "LIonCore.M3-Feature-optional" }, - "value": "EnumerationLiteral" + "value": "true" }, { "property": { "language": "LIonCore_M3", "version": "1", - "key": "NamespacedEntity_key" + "key": "LIonCore.M3-INamed-key" }, - "value": "EnumerationLiteral" + "value": "LIonCore.M3-Language-dependsOn" + }, + { + "property": { + "language": "LIonCore_M3", + "version": "1", + "key": "LIonCore.M3-INamed-name" + }, + "value": "dependsOn" } ], "children": [], @@ -1813,16 +1812,16 @@ "reference": { "language": "LIonCore_M3", "version": "1", - "key": "Concept_extends" + "key": "LIonCore.M3-Link-type" }, "targets": [ { - "reference": "LIonCore_M3_NamespacedEntity" + "reference": "LIonCore_M3_Language" } ] } ], - "parent": "LIonCore_M3" + "parent": "LIonCore_M3_Language" } ] } \ No newline at end of file diff --git a/schemas/lioncore.m3.serialization.schema.json b/schemas/lioncore.m3.serialization.schema.json index f7d2317b..53a6ff05 100644 --- a/schemas/lioncore.m3.serialization.schema.json +++ b/schemas/lioncore.m3.serialization.schema.json @@ -58,7 +58,7 @@ ], "additionalProperties": false }, - "Language": { + "Property": { "type": "object", "properties": { "id": { @@ -68,41 +68,41 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Language" + "key": "LIonCore.M3-Property" } }, "properties": { "type": "array", "items": {}, "properties": { - "Language_name": { + "LIonCore.M3-Feature-optional": { + "type": "string" + }, + "LIonCore.M3-INamed-key": { "type": "string" }, - "version": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "Language_name", - "version" + "LIonCore.M3-Feature-optional", + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": { - "elements": { - "$ref": "#/$defs/Ids" - } - }, + "properties": {}, "additionalProperties": false }, "references": { "type": "array", "items": {}, "properties": { - "dependsOn": { + "LIonCore.M3-Property-type": { "$ref": "#/$defs/Ids" } }, @@ -121,7 +121,7 @@ ], "additionalProperties": false }, - "Concept": { + "Containment": { "type": "object", "properties": { "id": { @@ -131,48 +131,45 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Concept" + "key": "LIonCore.M3-Containment" } }, "properties": { "type": "array", "items": {}, "properties": { - "abstract": { + "LIonCore.M3-Link-multiple": { "type": "string" }, - "NamespacedEntity_name": { + "LIonCore.M3-Feature-optional": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-key": { + "type": "string" + }, + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "abstract", - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-Link-multiple", + "LIonCore.M3-Feature-optional", + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": { - "features": { - "$ref": "#/$defs/Ids" - } - }, + "properties": {}, "additionalProperties": false }, "references": { "type": "array", "items": {}, "properties": { - "Concept_extends": { - "$ref": "#/$defs/Ids" - }, - "implements": { + "LIonCore.M3-Link-type": { "$ref": "#/$defs/Ids" } }, @@ -191,7 +188,7 @@ ], "additionalProperties": false }, - "ConceptInterface": { + "Reference": { "type": "object", "properties": { "id": { @@ -201,41 +198,45 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "ConceptInterface" + "key": "LIonCore.M3-Reference" } }, "properties": { "type": "array", "items": {}, "properties": { - "NamespacedEntity_name": { + "LIonCore.M3-Link-multiple": { + "type": "string" + }, + "LIonCore.M3-Feature-optional": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-key": { + "type": "string" + }, + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-Link-multiple", + "LIonCore.M3-Feature-optional", + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": { - "features": { - "$ref": "#/$defs/Ids" - } - }, + "properties": {}, "additionalProperties": false }, "references": { "type": "array", "items": {}, "properties": { - "ConceptInterface_extends": { + "LIonCore.M3-Link-type": { "$ref": "#/$defs/Ids" } }, @@ -254,7 +255,7 @@ ], "additionalProperties": false }, - "Reference": { + "Concept": { "type": "object", "properties": { "id": { @@ -264,45 +265,52 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Reference" + "key": "LIonCore.M3-Concept" } }, "properties": { "type": "array", "items": {}, "properties": { - "multiple": { + "LIonCore.M3-Concept-abstract": { "type": "string" }, - "optional": { + "LIonCore.M3-Concept-partition": { "type": "string" }, - "NamespacedEntity_name": { + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "multiple", - "optional", - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-Concept-abstract", + "LIonCore.M3-Concept-partition", + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": {}, + "properties": { + "LIonCore.M3-Classifier-features": { + "$ref": "#/$defs/Ids" + } + }, "additionalProperties": false }, "references": { "type": "array", "items": {}, "properties": { - "Link_type": { + "LIonCore.M3-Concept-extends": { + "$ref": "#/$defs/Ids" + }, + "LIonCore.M3-Concept-implements": { "$ref": "#/$defs/Ids" } }, @@ -321,7 +329,7 @@ ], "additionalProperties": false }, - "Property": { + "ConceptInterface": { "type": "object", "properties": { "id": { @@ -331,41 +339,41 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Property" + "key": "LIonCore.M3-ConceptInterface" } }, "properties": { "type": "array", "items": {}, "properties": { - "optional": { - "type": "string" - }, - "NamespacedEntity_name": { + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "optional", - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": {}, + "properties": { + "LIonCore.M3-Classifier-features": { + "$ref": "#/$defs/Ids" + } + }, "additionalProperties": false }, "references": { "type": "array", "items": {}, "properties": { - "type": { + "LIonCore.M3-ConceptInterface-extends": { "$ref": "#/$defs/Ids" } }, @@ -394,23 +402,23 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "PrimitiveType" + "key": "LIonCore.M3-PrimitiveType" } }, "properties": { "type": "array", "items": {}, "properties": { - "NamespacedEntity_name": { + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, @@ -439,7 +447,7 @@ ], "additionalProperties": false }, - "Containment": { + "Enumeration": { "type": "object", "properties": { "id": { @@ -449,48 +457,43 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Containment" + "key": "LIonCore.M3-Enumeration" } }, "properties": { "type": "array", "items": {}, "properties": { - "multiple": { - "type": "string" - }, - "optional": { + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_name": { - "type": "string" - }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "multiple", - "optional", - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": {}, + "properties": { + "LIonCore.M3-Enumeration-literals": { + "$ref": "#/$defs/Ids" + } + }, + "required": [ + "LIonCore.M3-Enumeration-literals" + ], "additionalProperties": false }, "references": { "type": "array", "items": {}, - "properties": { - "Link_type": { - "$ref": "#/$defs/Ids" - } - }, + "properties": {}, "additionalProperties": false }, "parent": { @@ -506,7 +509,7 @@ ], "additionalProperties": false }, - "Enumeration": { + "EnumerationLiteral": { "type": "object", "properties": { "id": { @@ -516,37 +519,30 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "Enumeration" + "key": "LIonCore.M3-EnumerationLiteral" } }, "properties": { "type": "array", "items": {}, "properties": { - "NamespacedEntity_name": { + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": { - "literals": { - "$ref": "#/$defs/Ids" - } - }, - "required": [ - "literals" - ], + "properties": {}, "additionalProperties": false }, "references": { @@ -568,7 +564,7 @@ ], "additionalProperties": false }, - "EnumerationLiteral": { + "Language": { "type": "object", "properties": { "id": { @@ -578,36 +574,48 @@ "const": { "metamodel": "LIonCore_M3", "version": "1", - "key": "EnumerationLiteral" + "key": "LIonCore.M3-Language" } }, "properties": { "type": "array", "items": {}, "properties": { - "NamespacedEntity_name": { + "LIonCore.M3-Language-version": { + "type": "string" + }, + "LIonCore.M3-INamed-key": { "type": "string" }, - "NamespacedEntity_key": { + "LIonCore.M3-INamed-name": { "type": "string" } }, "required": [ - "NamespacedEntity_name", - "NamespacedEntity_key" + "LIonCore.M3-Language-version", + "LIonCore.M3-INamed-key", + "LIonCore.M3-INamed-name" ], "additionalProperties": false }, "children": { "type": "array", "items": {}, - "properties": {}, + "properties": { + "LIonCore.M3-Language-entities": { + "$ref": "#/$defs/Ids" + } + }, "additionalProperties": false }, "references": { "type": "array", "items": {}, - "properties": {}, + "properties": { + "LIonCore.M3-Language-dependsOn": { + "$ref": "#/$defs/Ids" + } + }, "additionalProperties": false }, "parent": { @@ -626,31 +634,31 @@ "SerializedNode": { "oneOf": [ { - "$ref": "#/$defs/Language" - }, - { - "$ref": "#/$defs/Concept" + "$ref": "#/$defs/Property" }, { - "$ref": "#/$defs/ConceptInterface" + "$ref": "#/$defs/Containment" }, { "$ref": "#/$defs/Reference" }, { - "$ref": "#/$defs/Property" + "$ref": "#/$defs/Concept" }, { - "$ref": "#/$defs/PrimitiveType" + "$ref": "#/$defs/ConceptInterface" }, { - "$ref": "#/$defs/Containment" + "$ref": "#/$defs/PrimitiveType" }, { "$ref": "#/$defs/Enumeration" }, { "$ref": "#/$defs/EnumerationLiteral" + }, + { + "$ref": "#/$defs/Language" } ] } diff --git a/src-test/deps.ts b/src-test/deps.ts index b7586d72..c3e4105b 100644 --- a/src-test/deps.ts +++ b/src-test/deps.ts @@ -1,8 +1,5 @@ // for all unit tests: -import { - assertEquals, - assertThrows -} from "https://deno.land/std@0.168.0/testing/asserts.ts" +import {assertEquals, assertThrows} from "https://deno.land/std@0.168.0/testing/asserts.ts" // for src-test/m3/ecore/importer.test.ts: import {parse} from "https://deno.land/x/xml@2.1.1/mod.ts" diff --git a/src-test/functions.test.ts b/src-test/functions.test.ts new file mode 100644 index 00000000..553d9783 --- /dev/null +++ b/src-test/functions.test.ts @@ -0,0 +1,20 @@ +import {assertEquals} from "https://deno.land/std@0.168.0/testing/asserts.ts" +import {Node} from "../src/types.ts" +import {containmentChain} from "../src/functions.ts" + + +Deno.test("functions", async (tctx) => { + + await tctx.step("containmentChain", () => { + const node1: Node = { id: "1" } + const node2: Node = { id: "2", parent: node1 } + const node3: Node = { id: "3", parent: node1 } + const node4: Node = { id: "4", parent: node2 } + assertEquals(containmentChain(node1), [node1]) + assertEquals(containmentChain(node2), [node2, node1]) + assertEquals(containmentChain(node3), [node3, node1]) + assertEquals(containmentChain(node4), [node4, node2, node1]) + }) + +}) + diff --git a/src-test/m3/constraints.test.ts b/src-test/m3/constraints.test.ts index 813dd8da..f8a822d7 100644 --- a/src-test/m3/constraints.test.ts +++ b/src-test/m3/constraints.test.ts @@ -13,7 +13,7 @@ Deno.test("constraints (LIonCore)", async (tctx) => { cis[2].extends.push(cis[1]) cis[1].extends.push(cis[0]) cis[0].extends.push(cis[2]) - language.elements.push(...cis) + language.entities.push(...cis) const issues = issuesLanguage(language) assertEquals(issues.length, 3) @@ -26,7 +26,7 @@ Deno.test("constraints (LIonCore)", async (tctx) => { const {language} = factory const ci = factory.conceptInterface(`foo`) ci.extends.push(ci) - language.elements.push(ci) + language.entities.push(ci) const issues = issuesLanguage(language) assertEquals(issues.length, 1) @@ -36,9 +36,9 @@ Deno.test("constraints (LIonCore)", async (tctx) => { }) await tctx.step("check that things have names", () => { - const language = new Language("", "x", "x") + const language = new Language("", "0", "x", "x") const concept = new Concept(language, " ", "y", "y", false) - language.havingElements(concept) + language.havingEntities(concept) const issues = issuesLanguage(language) assertEquals(issues.length, 2) assertEquals(issues[0], { diff --git a/src-test/m3/ecore/importer.test.ts b/src-test/m3/ecore/importer.test.ts index 574dc158..272b1763 100644 --- a/src-test/m3/ecore/importer.test.ts +++ b/src-test/m3/ecore/importer.test.ts @@ -4,17 +4,9 @@ import {serializeLanguage} from "../../../src/m3/serializer.ts" import {EcoreXml} from "../../../src/m3/ecore/types.ts" import {issuesLanguage} from "../../../src/m3/constraints.ts" import {checkReferences} from "../../../src/m3/reference-checker.ts" -import { - generatePlantUmlForMetamodel -} from "../../../src/m3/diagrams/PlantUML-generator.ts" -import { - generateMermaidForMetamodel -} from "../../../src/m3/diagrams/Mermaid-generator.ts" -import { - logIssues, - logUnresolvedReferences, - undefinedValuesDeletedFrom -} from "../../utils/test-helpers.ts" +import {generatePlantUmlForMetamodel} from "../../../src/m3/diagrams/PlantUML-generator.ts" +import {generateMermaidForMetamodel} from "../../../src/m3/diagrams/Mermaid-generator.ts" +import {logIssues, logUnresolvedReferences, undefinedValuesDeletedFrom} from "../../utils/test-helpers.ts" import {libraryLanguage} from "../library-meta.ts" diff --git a/src-test/m3/key-generation.ts b/src-test/m3/key-generation.test.ts similarity index 94% rename from src-test/m3/key-generation.ts rename to src-test/m3/key-generation.test.ts index d80f6d0e..707f2fc2 100644 --- a/src-test/m3/key-generation.ts +++ b/src-test/m3/key-generation.test.ts @@ -11,7 +11,7 @@ Deno.test("key generation", async (tctx) => { const factory = new LanguageFactory("FormLanguage", "1", hashingIdGen(), qualifiedNameBasedKeyGenerator("-")) const form = factory.concept("Form", false) - factory.language.havingElements(form) + factory.language.havingEntities(form) assertEquals(form.key, "FormLanguage-Form") diff --git a/src-test/m3/library-meta.ts b/src-test/m3/library-meta.ts index a9117b73..a2ee7636 100644 --- a/src-test/m3/library-meta.ts +++ b/src-test/m3/library-meta.ts @@ -33,7 +33,7 @@ const specialistBookWriter_subject = factory.property(specialistBookWriter, "sub specialistBookWriter.havingFeatures(specialistBookWriter_subject) -libraryLanguage.havingElements( +libraryLanguage.havingEntities( book, library, writer, diff --git a/src-test/m3/library.test.ts b/src-test/m3/library.test.ts index 87dc05c8..da2674ad 100644 --- a/src-test/m3/library.test.ts +++ b/src-test/m3/library.test.ts @@ -1,11 +1,7 @@ import {assertEquals} from "../deps.ts" import {libraryLanguage} from "./library-meta.ts" -import { - generatePlantUmlForMetamodel -} from "../../src/m3/diagrams/PlantUML-generator.ts" -import { - generateMermaidForMetamodel -} from "../../src/m3/diagrams/Mermaid-generator.ts" +import {generatePlantUmlForMetamodel} from "../../src/m3/diagrams/PlantUML-generator.ts" +import {generateMermaidForMetamodel} from "../../src/m3/diagrams/Mermaid-generator.ts" import {serializeLanguage} from "../../src/m3/serializer.ts" import {deserializeLanguage} from "../../src/m3/deserializer.ts" import {lioncoreBuiltins} from "../../src/m3/builtins.ts" diff --git a/src-test/m3/meta-circularity.test.ts b/src-test/m3/meta-circularity.test.ts index bad500db..472fb415 100644 --- a/src-test/m3/meta-circularity.test.ts +++ b/src-test/m3/meta-circularity.test.ts @@ -1,22 +1,14 @@ import {assertEquals} from "../deps.ts" import {lioncore} from "../../src/m3/self-definition.ts" -import { - generateMermaidForMetamodel -} from "../../src/m3/diagrams/Mermaid-generator.ts" -import { - generatePlantUmlForMetamodel -} from "../../src/m3/diagrams/PlantUML-generator.ts" +import {generateMermaidForMetamodel} from "../../src/m3/diagrams/Mermaid-generator.ts" +import {generatePlantUmlForMetamodel} from "../../src/m3/diagrams/PlantUML-generator.ts" import {checkReferences} from "../../src/m3/reference-checker.ts" import {issuesLanguage} from "../../src/m3/constraints.ts" import {serializeLanguage} from "../../src/m3/serializer.ts" import {deserializeLanguage} from "../../src/m3/deserializer.ts" import {readFileAsJson, writeJsonAsFile} from "../utils/json.ts" import {SerializedModel} from "../../src/serialization.ts" -import { - logIssues, - logUnresolvedReferences, - undefinedValuesDeletedFrom -} from "../utils/test-helpers.ts" +import {logIssues, logUnresolvedReferences, undefinedValuesDeletedFrom} from "../utils/test-helpers.ts" Deno.test("meta-circularity (LIonCore)", async (tctx) => { diff --git a/src-test/m3/types.test.ts b/src-test/m3/types.test.ts index 1f7537b6..20958123 100644 --- a/src-test/m3/types.test.ts +++ b/src-test/m3/types.test.ts @@ -24,9 +24,9 @@ Deno.test("M3 types", async (tctx) => { const {language} = factory const concept = factory.concept("Concept", false) const property = factory.property(concept, "property").ofType(intDatatype) - factory.language.havingElements(concept) + factory.language.havingEntities(concept) assertThrows(() => { - language.havingElements(property), + language.havingEntities(property), Error, `trying to add non-LanguageElements to Language: "property"` }) diff --git a/src-test/utils/test-helpers.ts b/src-test/utils/test-helpers.ts index d65ed0ff..37520b1b 100644 --- a/src-test/utils/test-helpers.ts +++ b/src-test/utils/test-helpers.ts @@ -1,5 +1,5 @@ import {Issue} from "../../src/m3/constraints.ts" -import {asIds} from "../../src/types.ts" +import {asIds} from "../../src/functions.ts" /** diff --git a/src/api.ts b/src/api.ts index c23dbcd6..05586ba8 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,9 +1,6 @@ import {Node} from "./types.ts" import {Concept, Feature, Link} from "./m3/types.ts" -import { - flatMapNonCyclingFollowing, - trivialFlatMapper -} from "./utils/recursion.ts" +import {flatMapNonCyclingFollowing, trivialFlatMapper} from "./utils/recursion.ts" import {allFeaturesOf, isContainment} from "./m3/functions.ts" diff --git a/src/deps.ts b/src/deps.ts index 5bedfefa..255ff20c 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -4,11 +4,7 @@ import {createHash} from "https://deno.land/std@0.177.0/node/crypto.ts" import {nanoid} from "npm:nanoid@4.0.2" // for src/m3/diagrams/*-generator.ts: -import { - asString, - indentWith, - NestedString -} from "npm:littoral-templates@0.2.2" +import {asString, indentWith, NestedString} from "npm:littoral-templates@0.2.2" export { diff --git a/src/deserializer.ts b/src/deserializer.ts index 4ef0f4d5..e8a56861 100644 --- a/src/deserializer.ts +++ b/src/deserializer.ts @@ -1,13 +1,7 @@ import {Id, Node} from "./types.ts" import {SerializedModel, SerializedNode} from "./serialization.ts" import {ModelAPI} from "./api.ts" -import { - Concept, - Containment, - Language, - Property, - Reference -} from "./m3/types.ts" +import {Concept, Containment, Language, Property, Reference} from "./m3/types.ts" import {allFeaturesOf} from "./m3/functions.ts" import {deserializeBuiltin} from "./m3/builtins.ts" import {groupBy} from "./utils/grouping.ts" @@ -78,7 +72,7 @@ export const deserializeModel = ( */ const instantiate = ({concept: conceptMetaPointer, id, properties, children, references}: SerializedNode, parent?: NT): NT => { - const concept = language.elements + const concept = language.entities .find((element) => element instanceof Concept && element.key === conceptMetaPointer.key ) as (Concept | undefined) diff --git a/src/functions.ts b/src/functions.ts new file mode 100644 index 00000000..64c61858 --- /dev/null +++ b/src/functions.ts @@ -0,0 +1,19 @@ +import {Id, Node} from "./types.ts" +import {flatMapNonCyclingFollowing, trivialFlatMapper} from "./utils/recursion.ts" + + +/** + * @return a list of itself and the ancestors of the given {@link Node node}, in anti-chronological order. + */ +export const containmentChain = (node: Node): Node[] => { + const getParent = (t: Node): Node[] => t.parent === undefined ? [] : [t.parent] + return flatMapNonCyclingFollowing(trivialFlatMapper, getParent)(node) +} + + +/** + * Maps an array of {@link Node AST nodes} to their IDs. + */ +export const asIds = (nodes: Node[]): Id[] => + nodes.map(({id}) => id) + diff --git a/src/m3/api.ts b/src/m3/api.ts index df8d726d..c19cf832 100644 --- a/src/m3/api.ts +++ b/src/m3/api.ts @@ -1,11 +1,11 @@ import {ModelAPI, updateSettings} from "../api.ts" import { + Classifier, Concept, ConceptInterface, Containment, Enumeration, EnumerationLiteral, - FeaturesContainer, Language, M3Concept, PrimitiveType, @@ -13,8 +13,8 @@ import { Reference } from "./types.ts" import {lioncore, metaConcepts, metaFeatures} from "./self-definition.ts" -import {classBasedConceptDeducerFor} from "./functions.ts" -import {KeyGenerator, simpleNameIsKeyGenerator} from "./key-generation.ts" +import {classBasedConceptDeducerFor, qualifiedNameOf} from "./functions.ts" +import {KeyGenerator, nameIsKeyGenerator} from "./key-generation.ts" /** @@ -28,25 +28,25 @@ export const lioncoreAPIWithKeyGen = (keyGen: KeyGenerator): ModelAPI nodeFor: (parent, concept, id, settings) => { switch (concept.id) { case metaConcepts.concept.id: - return new Concept(parent as Language, settings[metaFeatures.namespacedEntity_name.id] as string, "", id, settings[metaFeatures.concept_abstract.id] as boolean).keyed(keyGen) + return new Concept(parent as Language, settings[metaFeatures.inamed_name.id] as string, "", id, settings[metaFeatures.concept_abstract.id] as boolean).keyed(keyGen) case metaConcepts.conceptInterface.id: - return new ConceptInterface(parent as Language, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new ConceptInterface(parent as Language, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.containment.id: - return new Containment(parent as FeaturesContainer, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new Containment(parent as Classifier, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.enumeration.id: - return new Enumeration(parent as Language, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new Enumeration(parent as Language, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.enumerationLiteral.id: - return new EnumerationLiteral(parent as Enumeration, settings[metaFeatures.language_elements.id] as string, "", id).keyed(keyGen) + return new EnumerationLiteral(parent as Enumeration, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.language.id: - return new Language(settings[metaFeatures.language_elements.id] as string, settings[metaFeatures.language_version.id] as string, id) + return new Language(settings[metaFeatures.inamed_name.id] as string, settings[metaFeatures.language_version.id] as string, id, settings[metaFeatures.ikeyed_key.id] as string) case metaConcepts.primitiveType.id: - return new PrimitiveType(parent as Language, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new PrimitiveType(parent as Language, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.property.id: - return new Property(parent as FeaturesContainer, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new Property(parent as Classifier, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) case metaConcepts.reference.id: - return new Reference(parent as FeaturesContainer, settings[metaFeatures.namespacedEntity_name.id] as string, "", id).keyed(keyGen) + return new Reference(parent as Classifier, settings[metaFeatures.inamed_name.id] as string, "", id).keyed(keyGen) default: - throw new Error(`can't deserialize a node of concept "${concept.qualifiedName()}" with ID "${concept.id}"`) + throw new Error(`can't deserialize a node of concept "${qualifiedNameOf(concept)}" with ID "${concept.id}"`) } }, setFeatureValue: (node, feature, value) => { @@ -60,5 +60,5 @@ export const lioncoreAPIWithKeyGen = (keyGen: KeyGenerator): ModelAPI * * TODO deprecate this: [de-]serialization of metamodels should be parametrized with key generation throughout */ -export const lioncoreAPI: ModelAPI = lioncoreAPIWithKeyGen(simpleNameIsKeyGenerator) +export const lioncoreAPI: ModelAPI = lioncoreAPIWithKeyGen(nameIsKeyGenerator) diff --git a/src/m3/builtins.ts b/src/m3/builtins.ts index c56a1e10..f2633f17 100644 --- a/src/m3/builtins.ts +++ b/src/m3/builtins.ts @@ -15,7 +15,7 @@ export const booleanDatatype = factory.primitiveType("Boolean") export const intDatatype = factory.primitiveType("Integer") export const jsonDatatype = factory.primitiveType("JSON") -lioncoreBuiltins.havingElements( +lioncoreBuiltins.havingEntities( stringDatatype, booleanDatatype, intDatatype, diff --git a/src/m3/constraints.ts b/src/m3/constraints.ts index 303234bc..e22f6f2b 100644 --- a/src/m3/constraints.ts +++ b/src/m3/constraints.ts @@ -1,17 +1,5 @@ -import { - Concept, - ConceptInterface, - Language, - M3Concept, - NamespacedEntity -} from "./types.ts" -import { - flatMap, - inheritedCycleWith, - keyOf, - namedsOf, - qualifiedNameOf -} from "./functions.ts" +import {Concept, ConceptInterface, isINamed, Language, M3Concept} from "./types.ts" +import {flatMap, inheritedCycleWith, keyOf, namedsOf, qualifiedNameOf} from "./functions.ts" import {duplicatesAmong} from "../utils/grouping.ts" @@ -49,11 +37,11 @@ export const issuesLanguage = (language: Language): Issue[] => if (t instanceof Concept || t instanceof ConceptInterface) { const cycle = inheritedCycleWith(t) if (cycle.length > 0) { - issue(`A ${t.constructor.name} can't inherit (directly or indirectly) from itself, but ${t.qualifiedName()} does so through the following cycle: ${cycle.map((t) => t.qualifiedName()).join(" -> ")}`) + issue(`A ${t.constructor.name} can't inherit (directly or indirectly) from itself, but ${qualifiedNameOf(t)} does so through the following cycle: ${cycle.map((t) => qualifiedNameOf(t)).join(" -> ")}`) } } - if (t instanceof Language || t instanceof NamespacedEntity) { + if (isINamed(t)) { if (t.name.trim().length === 0) { issue(`A ${t.constructor.name} must have a non-whitespace name`) } diff --git a/src/m3/diagrams/Mermaid-generator.ts b/src/m3/diagrams/Mermaid-generator.ts index 243fdc1e..02d23893 100644 --- a/src/m3/diagrams/Mermaid-generator.ts +++ b/src/m3/diagrams/Mermaid-generator.ts @@ -6,16 +6,11 @@ import { Enumeration, Feature, Language, - LanguageElement, + LanguageEntity, Link, PrimitiveType } from "../types.ts" -import { - elementsSortedByName, - nonRelationalFeatures, - relationsOf, - type -} from "../functions.ts" +import {elementsSortedByName, nonRelationalFeatures, relationsOf, type} from "../functions.ts" import {isRef, unresolved} from "../../references.ts" @@ -43,15 +38,15 @@ const withNewLine = (content: NestedString): NestedString => * Generates a string with a Mermaid class diagram * representing the given {@link Language LIonCore/M3 instance}. */ -export const generateMermaidForMetamodel = ({elements}: Language) => +export const generateMermaidForMetamodel = ({entities}: Language) => asString([ "```mermaid", `classDiagram `, - indented(elementsSortedByName(elements).map(generateForElement)), + indented(elementsSortedByName(entities).map(generateForElement)), ``, - indented(elementsSortedByName(elements).map(generateForRelationsOf)), + indented(elementsSortedByName(entities).map(generateForRelationsOf)), ``, "```" ]) @@ -107,7 +102,7 @@ const generateForPrimitiveType = ({name}: PrimitiveType) => // Note: No construct for PrimitiveType exists in PlantUML. -const generateForElement = (element: LanguageElement) => { +const generateForElement = (element: LanguageEntity) => { if (element instanceof Concept) { return generateForConcept(element) } @@ -124,7 +119,7 @@ const generateForElement = (element: LanguageElement) => { } -const generateForRelationsOf = (element: LanguageElement) => { +const generateForRelationsOf = (element: LanguageEntity) => { const relations = relationsOf(element) return relations.length === 0 ? `` @@ -133,7 +128,7 @@ const generateForRelationsOf = (element: LanguageElement) => { } -const generateForRelation = ({name: leftName}: LanguageElement, relation: Link) => { +const generateForRelation = ({name: leftName}: LanguageEntity, relation: Link) => { const {name: relationName, optional, multiple, type} = relation const rightName = isRef(type) ? type.name : (type === unresolved ? `` : ``) const isContainment = relation instanceof Containment diff --git a/src/m3/diagrams/PlantUML-generator.ts b/src/m3/diagrams/PlantUML-generator.ts index 0d4fc14e..adefeaa5 100644 --- a/src/m3/diagrams/PlantUML-generator.ts +++ b/src/m3/diagrams/PlantUML-generator.ts @@ -6,16 +6,11 @@ import { Enumeration, Feature, Language, - LanguageElement, + LanguageEntity, Link, PrimitiveType } from "../types.ts" -import { - elementsSortedByName, - nonRelationalFeatures, - relationsOf, - type -} from "../functions.ts" +import {elementsSortedByName, nonRelationalFeatures, relationsOf, type} from "../functions.ts" import {isRef, unresolved} from "../../references.ts" @@ -26,7 +21,7 @@ const indented = indentWith(` `)(1) * Generates a string with a PlantUML class diagram * representing the given {@link Language LIonCore/M3 instance}. */ -export const generatePlantUmlForMetamodel = ({name, elements}: Language) => +export const generatePlantUmlForMetamodel = ({name, entities}: Language) => asString([ `@startuml hide empty members @@ -35,13 +30,13 @@ hide empty members `, - elementsSortedByName(elements).map(generateForElement), + elementsSortedByName(entities).map(generateForElement), ` ' relations: `, - elementsSortedByName(elements).map(generateForRelationsOf), + elementsSortedByName(entities).map(generateForRelationsOf), ` @enduml ` @@ -116,7 +111,7 @@ const generateForPrimitiveType = ({name}: PrimitiveType) => // Note: No construct for PrimitiveType exists in PlantUML. -const generateForElement = (element: LanguageElement) => { +const generateForElement = (element: LanguageEntity) => { if (element instanceof Enumeration) { return generateForEnumeration(element) } @@ -134,7 +129,7 @@ const generateForElement = (element: LanguageElement) => { } -const generateForRelationsOf = (element: LanguageElement) => { +const generateForRelationsOf = (element: LanguageEntity) => { const relations = relationsOf(element) return relations.length === 0 ? `` @@ -143,7 +138,7 @@ const generateForRelationsOf = (element: LanguageElement) => { } -const generateForRelation = ({name: leftName}: LanguageElement, relation: Link) => { +const generateForRelation = ({name: leftName}: LanguageEntity, relation: Link) => { const {name: relationName, type, optional, multiple} = relation const rightName = isRef(type) ? type.name : (type === unresolved ? `` : ``) const isContainment = relation instanceof Containment diff --git a/src/m3/ecore/importer.ts b/src/m3/ecore/importer.ts index 473728d7..e9090b56 100644 --- a/src/m3/ecore/importer.ts +++ b/src/m3/ecore/importer.ts @@ -1,11 +1,4 @@ -import { - Concept, - Feature, - FeaturesContainer, - Language, - LanguageElement, - PrimitiveType -} from "../types.ts" +import {Classifier, Concept, Feature, Language, LanguageEntity, PrimitiveType} from "../types.ts" import {LanguageFactory} from "../factory.ts" import { checkDefinedData, @@ -15,15 +8,11 @@ import { hashingIdGen, wrapIdGen } from "../../id-generation.ts" -import { - asArray, - EClassifier, - EcoreXml, - EStructuralFeature -} from "./types.ts" -import {ConceptType, keyOf, namedsOf} from "../functions.ts" +import {EClassifier, EcoreXml, EStructuralFeature} from "./types.ts" +import {ConceptType, keyOf, namedsOf, qualifiedNameOf} from "../functions.ts" import {booleanDatatype, intDatatype, stringDatatype} from "../builtins.ts" import {duplicatesAmong} from "../../utils/grouping.ts" +import {asArray} from "../../utils/array-helpers.ts" const localRefPrefix = "#//" @@ -59,13 +48,13 @@ export const asLIonCoreLanguage = (ecoreXml: EcoreXml, version: string): Languag factory.concept(eClassifier["@name"], false) // TODO (#10) ConceptInterface, Enumeration - const convertedEClassifiers: [eClassifier: EClassifier, element: LanguageElement][] = + const convertedEClassifiers: [eClassifier: EClassifier, element: LanguageEntity][] = ePackage["eClassifiers"] .map((eClassifier) => [eClassifier, convertEClassifier(eClassifier)] ) - const eClassifierConversionFor = (eClassifierName: string): LanguageElement => + const eClassifierConversionFor = (eClassifierName: string): LanguageEntity => convertedEClassifiers .find(([source, _]) => source["@name"] === eClassifierName)![1] @@ -86,7 +75,7 @@ export const asLIonCoreLanguage = (ecoreXml: EcoreXml, version: string): Languag } } - const convertEStructuralFeature = (container: FeaturesContainer, feature: EStructuralFeature): Feature => { + const convertEStructuralFeature = (container: Classifier, feature: EStructuralFeature): Feature => { const metaType = feature["@xsi:type"] const name = feature["@name"] switch (metaType) { @@ -104,7 +93,7 @@ export const asLIonCoreLanguage = (ecoreXml: EcoreXml, version: string): Languag ? factory.containment(container, name) : factory.reference(container, name) ) - .ofType(eClassifierConversionFor(deref(feature["@eType"])) as FeaturesContainer) + .ofType(eClassifierConversionFor(deref(feature["@eType"])) as Classifier) if (feature["@lowerBound"] === "0") { link.isOptional() } @@ -121,7 +110,7 @@ export const asLIonCoreLanguage = (ecoreXml: EcoreXml, version: string): Languag convertedEClassifiers.forEach(([source, target]) => { if (source["@xsi:type"] === "ecore:EClass") { const eClass = source - const container = target as FeaturesContainer + const container = target as Classifier container .havingFeatures( ...asArray(source.eStructuralFeatures) @@ -139,13 +128,13 @@ export const asLIonCoreLanguage = (ecoreXml: EcoreXml, version: string): Languag // phase 3: put all converted things into the metamodel factory.language - .havingElements(...convertedEClassifiers.map(([_, mmElement]) => mmElement)) + .havingEntities(...convertedEClassifiers.map(([_, mmElement]) => mmElement)) // phase 4: dedup keys (crudely, using the qualified name) where necessary Object.entries(duplicatesAmong(namedsOf(factory.language), keyOf)) .forEach(([_, mmElements]) => { - mmElements.forEach((mmElement) => mmElement.havingKey(mmElement.qualifiedName().replaceAll(/\./g, "_"))) + mmElements.forEach((mmElement) => mmElement.havingKey(qualifiedNameOf(mmElement, "_"))) }) return factory.language diff --git a/src/m3/ecore/types.ts b/src/m3/ecore/types.ts index aef578af..6287e643 100644 --- a/src/m3/ecore/types.ts +++ b/src/m3/ecore/types.ts @@ -1,3 +1,6 @@ +import {AnyNumberOf} from "../../utils/array-helpers.ts" + + /** * Type definitions that correspond to an Ecore XML metamodel (file), * parsed using the XML parser built-in to Deno (see {@link https://deno.land/x/xml@2.1.0/mod.ts}), @@ -49,26 +52,3 @@ export type EReference = ENamed & { "@containment": boolean } - -/** - * Feature values that are parsed from an Ecore XML metamodel file - * can be either `undefined`, a single object, or an array of objects, - * regardless of the actual cardinality of that feature. - */ -export type AnyNumberOf = undefined | T | T[] - -/** - * Turns a {@link AnyNumberOf feature's value} into an array of objects - * (possibly empty), regardless of the feature's cardinality and how its - * value happened to be parsed. - */ -export const asArray = (thing: AnyNumberOf): T[] => { - if (thing === undefined) { - return [] - } - if (Array.isArray(thing)) { - return thing - } - return [thing] -} - diff --git a/src/m3/factory.ts b/src/m3/factory.ts index b3153b9c..49fcf460 100644 --- a/src/m3/factory.ts +++ b/src/m3/factory.ts @@ -1,21 +1,25 @@ import { + Classifier, Concept, ConceptInterface, Containment, Enumeration, EnumerationLiteral, - FeaturesContainer, Language, + lioncoreQNameSeparator, PrimitiveType, Property, - qualify, Reference } from "./types.ts" import {SingleRef} from "../references.ts" import {IdGenerator, nanoIdGen} from "../id-generation.ts" -import {KeyGenerator, simpleNameIsKeyGenerator} from "./key-generation.ts" +import {qualifiedNameOf} from "./functions.ts" +import {KeyGenerator, nameIsKeyGenerator} from "./key-generation.ts" +const concat = (...names: string[]): string => + names.join(lioncoreQNameSeparator) + /** * A factory that produces a {@link Language} instance, * as well as elements contained by that instance. @@ -28,47 +32,48 @@ export class LanguageFactory { readonly key: KeyGenerator readonly language: Language - constructor(name: string, version: string, id: IdGenerator = nanoIdGen(), key: KeyGenerator = simpleNameIsKeyGenerator) { + constructor(name: string, version: string, id: IdGenerator = nanoIdGen(), key: KeyGenerator = nameIsKeyGenerator) { this.id = id this.key = key - this.language = new Language(name, version, this.id(name)) + const idAndKey = this.id(name) // need to call this.id just once + this.language = new Language(name, version, idAndKey, idAndKey) } // TODO this pattern (post-re-setting the key) is not nice: improve... concept(name: string, abstract: boolean, extends_?: SingleRef) { - return new Concept(this.language, name, "", this.id(qualify(this.language.name, name)), abstract, extends_).keyed(this.key) + return new Concept(this.language, name, "", this.id(concat(this.language.name, name)), abstract, extends_).keyed(this.key) } conceptInterface(name: string) { - return new ConceptInterface(this.language, name, "", this.id(qualify(this.language.name, name))).keyed(this.key) + return new ConceptInterface(this.language, name, "", this.id(concat(this.language.name, name))).keyed(this.key) } enumeration(name: string) { - return new Enumeration(this.language, name, "", this.id(qualify(this.language.name, name))).keyed(this.key) + return new Enumeration(this.language, name, "", this.id(concat(this.language.name, name))).keyed(this.key) } primitiveType(name: string) { - return new PrimitiveType(this.language, name, "", this.id(qualify(this.language.name, name))).keyed(this.key) + return new PrimitiveType(this.language, name, "", this.id(concat(this.language.name, name))).keyed(this.key) } - containment(featuresContainer: FeaturesContainer, name: string) { - return new Containment(featuresContainer, name, "", this.id(qualify(featuresContainer.qualifiedName(), name))).keyed(this.key) + containment(classifier: Classifier, name: string) { + return new Containment(classifier, name, "", this.id(concat(qualifiedNameOf(classifier, lioncoreQNameSeparator), name))).keyed(this.key) } - property(featuresContainer: FeaturesContainer, name: string) { - return new Property(featuresContainer, name, "", this.id(qualify(featuresContainer.qualifiedName(), name))).keyed(this.key) + property(classifier: Classifier, name: string) { + return new Property(classifier, name, "", this.id(concat(qualifiedNameOf(classifier, lioncoreQNameSeparator), name))).keyed(this.key) } - reference(featuresContainer: FeaturesContainer, name: string) { - return new Reference(featuresContainer, name, "", this.id(qualify(featuresContainer.qualifiedName(), name))).keyed(this.key) + reference(classifier: Classifier, name: string) { + return new Reference(classifier, name, "", this.id(concat(qualifiedNameOf(classifier, lioncoreQNameSeparator), name))).keyed(this.key) } enumerationLiteral(enumeration: Enumeration, name: string) { - return new EnumerationLiteral(enumeration, name, "", this.id(qualify(enumeration.qualifiedName(), name))).keyed(this.key) + return new EnumerationLiteral(enumeration, name, "", this.id(concat(qualifiedNameOf(enumeration, lioncoreQNameSeparator), name))).keyed(this.key) } } diff --git a/src/m3/functions.ts b/src/m3/functions.ts index 82927891..c105bb60 100644 --- a/src/m3/functions.ts +++ b/src/m3/functions.ts @@ -4,18 +4,20 @@ import { + Classifier, Concept, ConceptInterface, Containment, Datatype, Enumeration, Feature, - FeaturesContainer, + IKeyed, + INamed, + isINamed, Language, - LanguageElement, + LanguageEntity, Link, M3Concept, - NamespacedEntity, Property, Reference } from "./types.ts" @@ -25,22 +27,23 @@ import {cycleWith} from "../utils/cycles.ts" import {flatMapNonCyclingFollowing} from "../utils/recursion.ts" import {Id, Node} from "../types.ts" import {ConceptDeducer} from "../api.ts" +import {containmentChain} from "../functions.ts" /** * @return The type of the given {@link Feature} */ -export const type = (feature: Feature): FeaturesContainer | Datatype | typeof unresolved => +const type = (feature: Feature): Classifier | Datatype | typeof unresolved => (feature as (Link | Property)).type -export const isProperty = (feature: Feature): feature is Property => +const isProperty = (feature: Feature): feature is Property => feature instanceof Property -export const isContainment = (feature: Feature): feature is Containment => +const isContainment = (feature: Feature): feature is Containment => feature instanceof Containment -export const isReference = (feature: Feature): feature is Reference => +const isReference = (feature: Feature): feature is Reference => feature instanceof Reference @@ -54,35 +57,35 @@ const isRelational = (feature: Feature): feature is Link => /** * @return the relations among the given {@link Feature features}. */ -export const relations = (features: Feature[]): Link[] => +const relations = (features: Feature[]): Link[] => features.filter(isRelational) /** * @return the non-relations among the given {@link Feature features}. */ -export const nonRelationalFeatures = (features: Feature[]): Feature[] => +const nonRelationalFeatures = (features: Feature[]): Feature[] => features.filter((feature) => !isRelational(feature)) /** - * @return the relations of the given {@link LanguageElement language element}. + * @return the relations of the given {@link LanguageEntity language element}. */ -export const relationsOf = (element: LanguageElement): Link[] => - element instanceof FeaturesContainer +const relationsOf = (element: LanguageEntity): Link[] => + element instanceof Classifier ? relations(element.features) : [] /** * @return The "things", i.e. {@link M3Concept}s, contained by the given "thing". - * These can be: {@link LanguageElement}s, {@link Feature}s, {@link EnumerationLiteral} + * These can be: {@link LanguageEntity}s, {@link Feature}s, {@link EnumerationLiteral} * (and all their sub types). */ -export const containeds = (thing: M3Concept): M3Concept[] => { +const containeds = (thing: M3Concept): M3Concept[] => { if (thing instanceof Language) { - return thing.elements + return thing.entities } - if (thing instanceof FeaturesContainer) { + if (thing instanceof Classifier) { return thing.features } if (thing instanceof Enumeration) { @@ -96,62 +99,72 @@ export const containeds = (thing: M3Concept): M3Concept[] => { * Performs a depth-first tree traversal of a language, "flatMapping" the `map` function on every node. * It avoids visiting nodes twice (to avoid potential infinite loops), but doesn't report cycles. */ -export const flatMap = (language: Language, map: (t: M3Concept) => T[]): T[] => +const flatMap = (language: Language, map: (t: M3Concept) => T[]): T[] => flatMapNonCyclingFollowing(map, containeds)(language) /** - * @return the name of the given {@link NamespacedEntity named thing}. + * @return the name of the given {@link INamed named thing}. */ -export const nameOf = ({name}: T): string => +const nameOf = ({name}: T): string => name /** - * @return the qualified name of the given {@link NamespacedEntity named thing}. + * @return the concatenation of the names of the given nodes using the given separator. */ -export const qualifiedNameOf = (t: T): string => - t.qualifiedName() +const concatenateNamesOf = (separator: string, nodes: M3Concept[]): string => + nodes + .filter(isINamed) + .map(nameOf) + .join(separator) + // !! slight overkill: every node in an M2 is an M3Concept, so IKeyed and INamed + +/** + * @return the qualified name of the given {@link INamed named thing}. + */ +const qualifiedNameOf = (node: T, separator = "."): string => + concatenateNamesOf(separator, containmentChain(node).reverse() as M3Concept[]) /** - * @return the {@link NamespacedEntity named things} in this {@link Language language} + * @return the {@link INamed named things} in this {@link Language language} * (excluding the language itself) */ -export const namedsOf = (language: Language): NamespacedEntity[] => - flatMap(language, (t) => t instanceof NamespacedEntity ? [t] : []) +const namedsOf = (language: Language): M3Concept[] => + flatMap(language, (t) => isINamed(t) ? [t] : []) /** - * @return the key of the given {@link NamespacedEntity named thing}. + * @return the key of the given {@link INamed named thing}. */ -export const keyOf = ({key}: T): string => +const keyOf = ({key}: T): string => key /** * @return the id of the given {@link M3Concept}. */ -export const idOf = ({id}: T): string => +const idOf = ({id}: T): string => id /** - * Sorts the given {@link LanguageElement metamodel elements} by name. + * Sorts the given {@link LanguageEntity metamodel elements} by name. */ -export const elementsSortedByName = (elements: LanguageElement[]) => +const elementsSortedByName = (elements: LanguageEntity[]) => sortByStringKey(elements, nameOf) /** * A sum type of {@link Concept} and {@link ConceptInterface}. */ -export type ConceptType = Concept | ConceptInterface +type ConceptType = Concept | ConceptInterface /** - * Determines whether the given {@link LanguageElement metamodel element} is + * Determines whether the given {@link LanguageEntity metamodel element} is * *concrete*, i.e. is instantiable. */ -export const isConcrete = (thing: LanguageElement): thing is Concept => +const isConcrete = (thing: LanguageEntity): thing is Concept => thing instanceof Concept && !thing.abstract const inheritsFrom = (conceptType: ConceptType): ConceptType[] => { @@ -174,7 +187,7 @@ const inheritsFrom = (conceptType: ConceptType): ConceptType[] => { /** * @return an array that's either an inheritance cycle, or empty (meaning: no inheritance cycle). */ -export const inheritedCycleWith = (conceptType: ConceptType) => +const inheritedCycleWith = (conceptType: ConceptType) => cycleWith(conceptType, inheritsFrom) @@ -182,7 +195,7 @@ export const inheritedCycleWith = (conceptType: ConceptType) => * @return *all* super types (through `extends` or `implements`) of the given * {@link Concept concept} or {@link ConceptInterface concept interface}. */ -export const allSuperTypesOf = (conceptType: ConceptType): ConceptType[] => +const allSuperTypesOf = (conceptType: ConceptType): ConceptType[] => flatMapNonCyclingFollowing(inheritsFrom, inheritsFrom)(conceptType) @@ -190,38 +203,71 @@ export const allSuperTypesOf = (conceptType: ConceptType): ConceptType[] => * @return *all* {@link Feature features} of the given {@link Concept concept} or {@link ConceptInterface concept interface}, * including the inherited ones. */ -export const allFeaturesOf = (conceptType: ConceptType): Feature[] => +const allFeaturesOf = (conceptType: ConceptType): Feature[] => flatMapNonCyclingFollowing((ci) => ci.features, inheritsFrom)(conceptType) /** - * Determines whether the given {@link LanguageElement language element} is an {@link Enumeration enumeration}. + * Determines whether the given {@link LanguageEntity language element} is an {@link Enumeration enumeration}. */ -export const isEnumeration = (element: LanguageElement): element is Enumeration => +const isEnumeration = (element: LanguageEntity): element is Enumeration => element instanceof Enumeration /** * @return a function that looks up a concept from the given {@link Language language} by its ID. */ -export const idBasedConceptDeducerFor = (language: Language) => +const idBasedConceptDeducerFor = (language: Language) => (id: Id) => - language.elements.find((element) => element instanceof Concept && element.id === id) as Concept + language.entities.find((element) => element instanceof Concept && element.id === id) as Concept /** * @return a function that looks up a concept from the given {@link Language language} by its name. */ -export const nameBasedConceptDeducerFor = (language: Language) => +const nameBasedConceptDeducerFor = (language: Language) => (name: string) => - language.elements.find((element) => element instanceof Concept && element.name === name) as Concept + language.entities.find((element) => element instanceof Concept && element.name === name) as Concept /** * @return a {@link ConceptDeducer concept deducer} that deduces the concept of nodes by looking up * the concept in the given {@link Language language} by matching the node object's class name to the concept's name. */ -export const classBasedConceptDeducerFor = (language: Language): ConceptDeducer => { +const classBasedConceptDeducerFor = (language: Language): ConceptDeducer => { const deducer = nameBasedConceptDeducerFor(language) return (node: NT) => deducer(node.constructor.name) } + +export { + allFeaturesOf, + allSuperTypesOf, + classBasedConceptDeducerFor, + concatenateNamesOf, + containeds, + containmentChain, + elementsSortedByName, + flatMap, + idBasedConceptDeducerFor, + idOf, + inheritedCycleWith, + isConcrete, + isContainment, + isEnumeration, + isProperty, + isReference, + keyOf, + nameBasedConceptDeducerFor, + nameOf, + namedsOf, + nonRelationalFeatures, + relations, + relationsOf, + type, + qualifiedNameOf +} + +export type { + ConceptType +} + diff --git a/src/m3/id-generation.ts b/src/m3/id-generation.ts index 36474932..ae179726 100644 --- a/src/m3/id-generation.ts +++ b/src/m3/id-generation.ts @@ -1,10 +1,4 @@ -import { - checkDefinedData, - checkUniqueData, - checkUniqueId, - checkValidId, - wrapIdGen -} from "../id-generation.ts" +import {checkDefinedData, checkUniqueData, checkUniqueId, checkValidId, wrapIdGen} from "../id-generation.ts" /** diff --git a/src/m3/key-generation.ts b/src/m3/key-generation.ts index ae62370a..0bf06492 100644 --- a/src/m3/key-generation.ts +++ b/src/m3/key-generation.ts @@ -1,4 +1,5 @@ -import {Language, M3Concept} from "./types.ts" +import {M3Concept} from "./types.ts" +import {qualifiedNameOf} from "./functions.ts" /** @@ -6,13 +7,12 @@ import {Language, M3Concept} from "./types.ts" * Note that, in theory, key generation doesn't need to be idempotent: f(node) != f(node.havingKey(f(node)), with f of type KeyGenerator. */ export type KeyGenerator = (node: M3Concept) => string - // TODO should have as type NamespacedEntity, but don't want to do that until propagating recent-recent changes /** * A {@link KeyGenerator key generator} for which: key = name */ -export const simpleNameIsKeyGenerator = (node: M3Concept) => +export const nameIsKeyGenerator = (node: M3Concept) => node.name @@ -20,8 +20,5 @@ export const simpleNameIsKeyGenerator = (node: M3Concept) => * @return A {@link KeyGenerator key generator} that generates a key with the qualified name using the given separator. */ export const qualifiedNameBasedKeyGenerator = (separator: string): KeyGenerator => - (node) => - (node instanceof Language) - ? node.name - : node.qualifiedName(separator) + (node) => qualifiedNameOf(node, separator) diff --git a/src/m3/reference-checker.ts b/src/m3/reference-checker.ts index 9b544898..bb58e4fe 100644 --- a/src/m3/reference-checker.ts +++ b/src/m3/reference-checker.ts @@ -1,11 +1,5 @@ -import { - Concept, - Containment, - Language, - Property, - Reference -} from "./types.ts" -import {flatMap} from "./functions.ts" +import {Concept, Containment, Language, Property, Reference} from "./types.ts" +import {flatMap, qualifiedNameOf} from "./functions.ts" import {SingleRef, unresolved} from "../references.ts" @@ -25,16 +19,16 @@ export const checkReferences = (language: Language): string[] => } if (thing instanceof Concept) { - check(thing.extends, `${thing.qualifiedName()}#extends`) + check(thing.extends, `${qualifiedNameOf(thing)}#extends`) } if (thing instanceof Containment) { - check(thing.type, `${thing.qualifiedName()}#type`) + check(thing.type, `${qualifiedNameOf(thing)}#type`) } if (thing instanceof Property) { - check(thing.type, `${thing.qualifiedName()}#type`) + check(thing.type, `${qualifiedNameOf(thing)}#type`) } if (thing instanceof Reference) { - check(thing.type, `${thing.qualifiedName()}#type`) + check(thing.type, `${qualifiedNameOf(thing)}#type`) } return locations diff --git a/src/m3/schema-generator.ts b/src/m3/schema-generator.ts index 9aaf4147..c6b123fe 100644 --- a/src/m3/schema-generator.ts +++ b/src/m3/schema-generator.ts @@ -1,20 +1,5 @@ -import { - Concept, - Datatype, - Enumeration, - Feature, - Language, - PrimitiveType, - Property -} from "./types.ts" -import { - allFeaturesOf, - isConcrete, - isContainment, - isEnumeration, - isProperty, - isReference -} from "./functions.ts" +import {Concept, Datatype, Enumeration, Feature, Language, PrimitiveType, Property} from "./types.ts" +import {allFeaturesOf, isConcrete, isContainment, isEnumeration, isProperty, isReference} from "./functions.ts" import {isRef} from "../references.ts" // TODO import types for JSON Schema for added type-safety? @@ -109,8 +94,8 @@ const schemaForEnumeration = ({literals}: Enumeration): unknown => * specific to the (metamodel in/of the) given language. */ export const schemaFor = (language: Language): unknown /* <=> JSON Schema */ => { - const concreteConcepts = language.elements.filter(isConcrete) - const enumerations = language.elements.filter(isEnumeration) + const concreteConcepts = language.entities.filter(isConcrete) + const enumerations = language.entities.filter(isEnumeration) return { $schema: "https://json-schema.org/draft/2020-12/schema", $id: `${language.name}-serialization`, // TODO let caller specify URL instead? diff --git a/src/m3/self-definition.ts b/src/m3/self-definition.ts index 3ce94617..79259034 100644 --- a/src/m3/self-definition.ts +++ b/src/m3/self-definition.ts @@ -1,9 +1,21 @@ import {LanguageFactory} from "./factory.ts" import {lioncoreIdGen} from "./id-generation.ts" import {booleanDatatype, stringDatatype} from "./builtins.ts" +import {qualifiedNameBasedKeyGenerator} from "./key-generation.ts" -const factory = new LanguageFactory("LIonCore.M3", "1", lioncoreIdGen) +const factory = new LanguageFactory("LIonCore.M3", "2", lioncoreIdGen, qualifiedNameBasedKeyGenerator("-")) + +/** + * TODO: + * * ✓ Add the missing builtins Node and INamed + * * Use the id of a node as the default key instead of the name + * * Remove NamespaceProvider and NamespacedEntity from the self definition, let a number of concepts implement INamed instead (and I'm missing IKeyed in this definition) + * * Change underscores to dashes in the havingKey keys of the self defintiion and add some more specified keys + * * Change the separator from a dot to a dash + * + * Source of definition: https://lionweb-org.github.io/organization/lioncore/metametamodel/metametamodel.html + */ /** @@ -12,176 +24,173 @@ const factory = new LanguageFactory("LIonCore.M3", "1", lioncoreIdGen) export const lioncore = factory.language -const namespaceProvider = factory.conceptInterface("NamespaceProvider") +const inamed = factory.conceptInterface("INamed") +const inamed_name = factory.property(inamed, "name") + .ofType(stringDatatype) -const namespacedEntity = factory.concept("NamespacedEntity", true) +inamed.havingFeatures(inamed_name) -const namespacedEntity_name = factory.property(namespacedEntity, "name") - .ofType(stringDatatype) - .havingKey("NamespacedEntity_name") -const namespacedEntity_key = factory.property(namespacedEntity, "key") +const ikeyed = factory.conceptInterface("IKeyed") + .extending(inamed) + +const ikeyed_key = factory.property(inamed, "key") .ofType(stringDatatype) - .havingKey("NamespacedEntity_key") -namespacedEntity.havingFeatures( - namespacedEntity_name, - namespacedEntity_key - ) +ikeyed.havingFeatures(ikeyed_key) -const language = factory.concept("Language", false) - .implementing(namespaceProvider) +const feature = factory.concept("Feature", true).implementing(ikeyed) -const language_name = factory.property(language, "name") - .ofType(stringDatatype) - .havingKey("Language_name") +const feature_optional = factory.property(feature, "optional") + .ofType(booleanDatatype) -const language_version = factory.property(language, "version") - .ofType(stringDatatype) +feature.havingFeatures( + feature_optional +) -const language_elements = factory.containment(language, "elements") - .isOptional() - .isMultiple() -const language_dependsOn = factory.reference(language, "dependsOn") - .isOptional() - .isMultiple() - .ofType(language) +const property = factory.concept("Property", false, feature) + +const property_type = factory.reference(property, "type") + +property.havingFeatures( + property_type +) -language.havingFeatures(language_name, language_version, language_elements, language_dependsOn) +const link = factory.concept("Link", true, feature) + +const link_multiple = factory.property(link, "multiple") + .ofType(booleanDatatype) + +const link_type = factory.reference(link, "type") + +link.havingFeatures( + link_multiple, + link_type +) + + +const containment = factory.concept("Containment", false, link) -const languageElement = factory.concept("LanguageElement", true, namespacedEntity) -language_elements.ofType(languageElement) +const reference = factory.concept("Reference", false, link) + +const languageEntity = factory.concept("LanguageEntity", true) + .implementing(ikeyed) -const featuresContainer = factory.concept("FeaturesContainer", true, languageElement) - .implementing(namespaceProvider) -const featuresContainer_features = factory.containment(featuresContainer, "features") +const classifier = factory.concept("Classifier", true, languageEntity) + +const classifier_features = factory.containment(classifier, "features") .isOptional() .isMultiple() + .ofType(feature) -featuresContainer.havingFeatures( - featuresContainer_features +classifier.havingFeatures( + classifier_features ) +link_type.ofType(classifier) + -const concept = factory.concept("Concept", false, featuresContainer) +const concept = factory.concept("Concept", false, classifier) const concept_abstract = factory.property(concept, "abstract") .ofType(booleanDatatype) +const concept_partition = factory.property(concept, "partition") + .ofType(booleanDatatype) + const concept_extends = factory.reference(concept, "extends") .isOptional() .ofType(concept) - .havingKey("Concept_extends") const concept_implements = factory.reference(concept, "implements") .isOptional() .isMultiple() - concept.havingFeatures( concept_abstract, + concept_partition, concept_extends, concept_implements ) -const conceptInterface = factory.concept("ConceptInterface", false, featuresContainer) +const conceptInterface = factory.concept("ConceptInterface", false, classifier) const conceptInterface_extends = factory.reference(conceptInterface, "extends") .isOptional() .isMultiple() .ofType(conceptInterface) - .havingKey("ConceptInterface_extends") -concept_implements.ofType(conceptInterface) conceptInterface.havingFeatures(conceptInterface_extends) +concept_implements.ofType(conceptInterface) -const feature = factory.concept("Feature", true, namespacedEntity) - -const feature_optional = factory.property(feature, "optional") - .ofType(booleanDatatype) - -feature.havingFeatures( - feature_optional -) - -featuresContainer_features.type = feature - - -const link = factory.concept("Link", true, feature) - -const link_multiple = factory.property(link, "multiple") - .ofType(booleanDatatype) - -const link_type = factory.reference(link, "type") - .ofType(featuresContainer) - .havingKey("Link_type") - -link.havingFeatures( - link_multiple, - link_type -) +const dataType = factory.concept("DataType", true, languageEntity) -const reference = factory.concept("Reference", false, link) +property_type.ofType(dataType) -const property = factory.concept("Property", false, feature) +const primitiveType = factory.concept("PrimitiveType", false, dataType) -const property_type = factory.reference(property, "type") -property.havingFeatures( - property_type -) +const enumeration = factory.concept("Enumeration", false, dataType) +const enumeration_literals = factory.containment(enumeration, "literals") + .isMultiple() -const dataType = factory.concept("DataType", true, languageElement) -property_type.ofType(dataType) +enumeration.havingFeatures(enumeration_literals) -const primitiveType = factory.concept("PrimitiveType", false, dataType) +const enumerationLiteral = factory.concept("EnumerationLiteral", false) + .implementing(ikeyed) +enumeration_literals.ofType(enumerationLiteral) -const containment = factory.concept("Containment", false, link) +const language = factory.concept("Language", false) + .implementing(ikeyed) -const enumeration = factory.concept("Enumeration", false, dataType) - .implementing(namespaceProvider) +const language_version = factory.property(language, "version") + .ofType(stringDatatype) -const enumeration_literals = factory.containment(enumeration, "literals") +const language_entities = factory.containment(language, "entities") + .isOptional() .isMultiple() + .ofType(languageEntity) -const enumerationLiteral = factory.concept("EnumerationLiteral", false, namespacedEntity) +const language_dependsOn = factory.reference(language, "dependsOn") + .isOptional() + .isMultiple() + .ofType(language) -enumeration_literals.ofType(enumerationLiteral) -enumeration.havingFeatures(enumeration_literals) +language.havingFeatures(language_version, language_entities, language_dependsOn) -lioncore.havingElements( - namespacedEntity, - namespaceProvider, - language, - languageElement, - featuresContainer, - concept, - conceptInterface, +lioncore.havingEntities( + inamed, + ikeyed, feature, + property, link, + containment, reference, - property, + languageEntity, + classifier, + concept, + conceptInterface, dataType, primitiveType, - containment, enumeration, - enumerationLiteral + enumerationLiteral, + language ) @@ -198,20 +207,21 @@ export const metaConcepts = { } export const metaFeatures = { + inamed_name, + ikeyed_key, concept_abstract, + concept_partition, concept_extends, concept_implements, conceptInterface_extends, enumeration_literals, feature_optional, - featuresContainer_features, link_multiple, link_type, - language_dependsOn, - language_elements, - language_name, + classifier_features, language_version, - namespacedEntity_name, + language_dependsOn, + language_entities, property_type } diff --git a/src/m3/types.ts b/src/m3/types.ts index cee8386c..1e3435ee 100644 --- a/src/m3/types.ts +++ b/src/m3/types.ts @@ -5,24 +5,10 @@ import {MultiRef, SingleRef, unresolved} from "../references.ts" import {Id, Node} from "../types.ts" -import {allFeaturesOf} from "./functions.ts" import {KeyGenerator} from "./key-generation.ts" -/** - * @return A function that combines fragments of a qualified name using the given separator string. - */ -const combiner = (separator: string) => - (...names: (string|undefined)[]): string => - names - .filter((name) => typeof name === "string") - .join(separator) - -/** - * @return The combination of fragments of a qualified name using the `.` character. - */ -const qualify = combiner(".") - +const lioncoreQNameSeparator = "." /** * The qualified name of the LIonCore language containing the built-in {@link PrimitiveType primitive types}. @@ -31,24 +17,42 @@ const qualify = combiner(".") const lioncoreBuiltinsQName = "LIonCore.builtins" +interface INamed extends Node { + name: string +} + +const isINamed = (node: Node): node is INamed => + "name" in node && typeof node.name === "string" + + +interface IKeyed extends INamed { + key: Id +} + +const isIKeyed = (node: Node): node is IKeyed => + isINamed(node) && "key" in node && typeof node.key === "string" + + /** * Abstract base class for nodes in an LIonCore/M3-instance, - * providing an ID and the containment hierarchy. + * providing an ID, a key, and the containment hierarchy. */ -abstract class M3Node implements Node { - parent?: NamespaceProvider +abstract class M3Node implements IKeyed { + parent?: M3Node /* - * Note: every parent in an M2 (i.e., a Metamodel, Concept, ConceptInterface, Enumeration) also happens to be a namespace. - * This is why we can give `parent` the narrower type `NamespaceProvider` instead of `M3Node`. + * Note: every parent in an M2 (i.e., a Language, Concept, ConceptInterface, Enumeration) implements IKeyed. + * Because that's just an interface and is implemented by {@link M3Node} */ readonly id: Id - key: string // TODO make this a specific type? - protected constructor(id: Id, key: string, parent?: NamespaceProvider) { + name: string + key: Id + protected constructor(id: Id, name: string, key: Id, parent?: M3Node) { this.id = id + this.name = name this.key = key this.parent = parent } - havingKey(key: string) { + havingKey(key: Id) { this.key = key return this } @@ -59,80 +63,66 @@ abstract class M3Node implements Node { */ keyed(keyGenerator: KeyGenerator) { this.key = keyGenerator(this as unknown as M3Concept) - // FIXME the cast smells like a hack... + // FIXME the cast smells like a hack... return this } } - -interface NamespaceProvider extends Node { - namespaceQualifier(): string -} - -abstract class NamespacedEntity extends M3Node { - name: string - protected constructor(parent: NamespaceProvider, name: string, key: string, id: Id) { - super(id, key, parent) - this.name = name +abstract class Feature extends M3Node { + optional /*: boolean */ = false + // TODO look at order of constructors' arguments! + constructor(featuresContainer: Classifier, name: string, key: string, id: Id) { + super(id, name, key, featuresContainer) } - qualifiedName(separator = ".") { - return combiner(separator)(this.parent?.namespaceQualifier(), this.name) + isOptional() { + this.optional = true + return this } } -class Language implements NamespaceProvider, Node { - readonly id: string - name: string - version: string - elements: LanguageElement[] = [] // (containment) - dependsOn: MultiRef = [] // special (!) reference - // (!) special because deserializer needs to be aware of where to get the instance from - constructor(name: string, version: string, id: Id) { - this.id = id - this.name = name - this.version = version - } - namespaceQualifier(): string { - return this.name +class Property extends Feature { + type: SingleRef = unresolved // (reference) + ofType(type: Datatype): Property { + this.type = type + return this } - havingElements(...elements: LanguageElement[]): Language { - const nonLanguageElements = elements.filter((element) => !(element instanceof LanguageElement)) - if (nonLanguageElements.length > 0) { - throw Error(`trying to add non-LanguageElements to Language: ${nonLanguageElements.map((node) => `<${node.constructor.name}>"${node.name}"`).join(", ")}`) - } - this.elements.push(...elements) +} + +abstract class Link extends Feature { + multiple /*: boolean */ = false + type: SingleRef = unresolved // (reference) + isMultiple() { + this.multiple = true return this } - dependingOn(...metamodels: Language[]): Language { - // TODO check actual types of metamodels, or use type shapes/interfaces - this.dependsOn.push( - ...metamodels - .filter((metamodel) => metamodel.name !== lioncoreBuiltinsQName) - ) + ofType(type: Classifier) { + this.type = type return this } } -abstract class LanguageElement extends NamespacedEntity { - constructor(language: Language, name: string, key: string, id: Id) { - super(language, name, key, id) +class Containment extends Link { +} + +class Reference extends Link { +} + +abstract class LanguageEntity extends M3Node { + constructor(language: Language, name: string, key: Id, id: Id) { + super(id, name, key, language) } } -abstract class FeaturesContainer extends LanguageElement implements NamespaceProvider { +abstract class Classifier extends LanguageEntity { features: Feature[] = [] // (containment) havingFeatures(...features: Feature[]) { // TODO check actual types of features, or use type shapes/interfaces this.features.push(...features) return this } - abstract allFeatures(): Feature[] - namespaceQualifier(): string { - return this.qualifiedName() - } } -class Concept extends FeaturesContainer { +class Concept extends Classifier { abstract: boolean extends?: SingleRef // (reference) implements: MultiRef = [] // (reference) @@ -146,84 +136,70 @@ class Concept extends FeaturesContainer { this.implements.push(...conceptInterfaces) return this } - allFeatures(): Feature[] { - return allFeaturesOf(this) - } } -class ConceptInterface extends FeaturesContainer { +class ConceptInterface extends Classifier { extends: MultiRef = [] // (reference) - allFeatures(): Feature[] { - return allFeaturesOf(this) - } -} - -abstract class Feature extends NamespacedEntity { - optional /*: boolean */ = false - constructor(featuresContainer: FeaturesContainer, name: string, key: string, id: Id) { - super(featuresContainer, name, key, id) - } - isOptional() { - this.optional = true + extending(...conceptInterfaces: ConceptInterface[]): ConceptInterface { + // TODO check actual types of concept interfaces, or use type shapes/interfaces + this.extends.push(...conceptInterfaces) return this } } -abstract class Link extends Feature { - multiple /*: boolean */ = false - type: SingleRef = unresolved // (reference) - ofType(type: FeaturesContainer) { - this.type = type - return this - } - isMultiple() { - this.multiple = true - return this - } -} +abstract class Datatype extends LanguageEntity {} -class Reference extends Link { -} +class PrimitiveType extends Datatype {} -class Containment extends Link { +class Enumeration extends Datatype { + literals: EnumerationLiteral[] = [] // (containment) } -class Property extends Feature { - type: SingleRef = unresolved // (reference) - ofType(type: Datatype): Property { - this.type = type - return this +class EnumerationLiteral extends M3Node { + constructor(enumeration: Enumeration, name: string, key: string, id: Id) { + super(id, name, key, enumeration) } } -abstract class Datatype extends LanguageElement {} - -class PrimitiveType extends Datatype {} - -class Enumeration extends Datatype implements NamespaceProvider { - literals: EnumerationLiteral[] = [] // (containment) - namespaceQualifier(separator = "."): string { - return combiner(separator)(this.parent?.namespaceQualifier(), this.name) +class Language extends M3Node { + version: string + entities: LanguageEntity[] = [] // (containment) + dependsOn: MultiRef = [] // special (!) reference + // (!) special because deserializer needs to be aware of where to get the instance from + constructor(name: string, version: string, id: Id, key: Id) { + super(id, name, key) + this.version = version } -} - -class EnumerationLiteral extends NamespacedEntity { - constructor(enumeration: Enumeration, name: string, key: string, id: Id) { - super(enumeration, name, key, id) + havingEntities(...elements: LanguageEntity[]): Language { + const nonLanguageElements = elements.filter((element) => !(element instanceof LanguageEntity)) + if (nonLanguageElements.length > 0) { + throw Error(`trying to add non-LanguageElements to Language: ${nonLanguageElements.map((node) => `<${node.constructor.name}>"${node.name}"`).join(", ")}`) + } + this.entities.push(...elements) + return this + } + dependingOn(...metamodels: Language[]): Language { + // TODO check actual types of metamodels, or use type shapes/interfaces + this.dependsOn.push( + ...metamodels + .filter((metamodel) => metamodel.name !== lioncoreBuiltinsQName) + ) + return this } } +// TODO can we add the `<>` tag on it programmatically (to make it truly meta-circular)? /** * Sum type of all LIonCore type definitions whose meta-type is a concrete (thus: instantiable) Concept. + * All the classes in this sum type extend (from) {@link M3Node}, + * so they also implement {@link INamed} and {@link IKeyed}. */ type M3Concept = | Language - // ▼▼▼ all NamespacedEntity-s | Concept | ConceptInterface | Enumeration - // ▲▲▲ all NamespaceProvider-s | EnumerationLiteral | PrimitiveType | Containment @@ -232,6 +208,7 @@ type M3Concept = export { + Classifier, Concept, ConceptInterface, Containment, @@ -239,18 +216,21 @@ export { Enumeration, EnumerationLiteral, Feature, - FeaturesContainer, Language, - LanguageElement, + LanguageEntity, Link, - NamespacedEntity, PrimitiveType, Property, Reference, + isINamed, + isIKeyed, lioncoreBuiltinsQName, - qualify + lioncoreQNameSeparator } + export type { + IKeyed, + INamed, M3Concept } diff --git a/src/serializer.ts b/src/serializer.ts index d8ee7751..d7fe828b 100644 --- a/src/serializer.ts +++ b/src/serializer.ts @@ -1,9 +1,10 @@ -import {Containment, Property, Reference} from "./m3/types.ts" +import {ConceptDeducer as _ConceptDeducer, ModelAPI} from "./api.ts" import {SerializedModel, SerializedNode} from "./serialization.ts" -import {asIds, Node} from "./types.ts" +import {asIds} from "./functions.ts" +import {Node} from "./types.ts" +import {Containment, Property, Reference} from "./m3/types.ts" import {allFeaturesOf} from "./m3/functions.ts" -import {asArray} from "./m3/ecore/types.ts" -import {ConceptDeducer as _ConceptDeducer, ModelAPI} from "./api.ts" +import {asArray} from "./utils/array-helpers.ts" import {BuiltinPrimitive, serializeBuiltin} from "./m3/builtins.ts" diff --git a/src/types.ts b/src/types.ts index 2559bf0f..e2533322 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,11 +8,6 @@ export type Id = string */ export type Node = { id: Id + parent?: Node } -/** - * Maps an array of {@link Node AST nodes} to their IDs. - */ -export const asIds = (nodes: Node[]): Id[] => - nodes.map(({id}) => id) - diff --git a/src/utils/array-helpers.ts b/src/utils/array-helpers.ts new file mode 100644 index 00000000..9269a837 --- /dev/null +++ b/src/utils/array-helpers.ts @@ -0,0 +1,23 @@ +/** + * Feature's values are often persisted as either `undefined`, a single object, or an array of objects, + * regardless of the actual cardinality of that feature. + * This is e.g. the case when parsing an Ecore XML metamodel file. + * This type definition captures that phenomenon. + */ +export type AnyNumberOf = undefined | T | T[] + +/** + * Turns a {@link AnyNumberOf feature's value} into an array of objects + * (possibly empty), regardless of the feature's cardinality and how its + * value happened to be parsed. + */ +export const asArray = (thing: AnyNumberOf): T[] => { + if (thing === undefined) { + return [] + } + if (Array.isArray(thing)) { + return thing + } + return [thing] +} + diff --git a/src/utils/recursion.ts b/src/utils/recursion.ts index f4a405fa..a70eb4b6 100644 --- a/src/utils/recursion.ts +++ b/src/utils/recursion.ts @@ -4,7 +4,10 @@ export type FlatMapper = (t: T) => R[] * Performs a "flatMap" on a graph that's specified as a start vertex and a function that computes (outgoing) edges. * The "flatMap" is performed depth-first, and doesn't loop on cycles. */ -export const flatMapNonCyclingFollowing = (mapper: FlatMapper, edges: (t: T) => T[]): FlatMapper => +const flatMapNonCyclingFollowing = ( + mapper: FlatMapper, + edges: (t: T) => T[] +): FlatMapper => (startVertex: T): R[] => { const visited: T[] = [] const rs: R[] = [] @@ -21,5 +24,11 @@ export const flatMapNonCyclingFollowing = (mapper: FlatMapper, edges } -export const trivialFlatMapper = (t: T) => [t] +const trivialFlatMapper = (t: T) => [t] + + +export { + flatMapNonCyclingFollowing, + trivialFlatMapper +}