@lionweb/json-utils 0.7.0-beta.17 → 0.7.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lionweb/json-utils",
3
- "version": "0.7.0-beta.17",
3
+ "version": "0.7.0-beta.19",
4
4
  "description": "Utilities for LionWeb JSON",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  "release": "npm publish"
28
28
  },
29
29
  "dependencies": {
30
- "@lionweb/json": "0.7.0-beta.17",
31
- "@lionweb/ts-utils": "0.7.0-beta.17"
30
+ "@lionweb/json": "0.7.0-beta.19",
31
+ "@lionweb/ts-utils": "0.7.0-beta.19"
32
32
  }
33
33
  }
@@ -0,0 +1,49 @@
1
+ import { LionWebId, LionWebJsonChunk, LionWebJsonNode, LionWebJsonUsedLanguage, LionWebKey } from "@lionweb/json"
2
+
3
+ /**
4
+ * Utility functions for LionWeb chunks
5
+ */
6
+ export class ChunkUtils {
7
+ /**
8
+ * Find a used language in `chunk` with `key`.
9
+ * @param chunk
10
+ * @param key
11
+ */
12
+ static findLwUsedLanguage(chunk: LionWebJsonChunk, key: LionWebKey): LionWebJsonUsedLanguage | null {
13
+ for (const language of chunk.languages) {
14
+ if (language.key === key) {
15
+ return language
16
+ }
17
+ }
18
+ return null
19
+ }
20
+
21
+ /**
22
+ * Find a used language in `chunk` with `key` and 'version'.
23
+ * @param chunk
24
+ * @param key
25
+ * @param version
26
+ */
27
+ static findLwUsedLanguageWithVersion(chunk: LionWebJsonChunk, key: LionWebKey, version: string): LionWebJsonUsedLanguage | null {
28
+ for (const language of chunk.languages) {
29
+ if (language.key === key && language.version === version) {
30
+ return language
31
+ }
32
+ }
33
+ return null
34
+ }
35
+
36
+ /**
37
+ * Find node with id equals `id` in `chunk`.
38
+ * @param chunk
39
+ * @param id
40
+ */
41
+ static findNode(chunk: LionWebJsonChunk, id: LionWebId): LionWebJsonNode | null {
42
+ for (const node of chunk.nodes) {
43
+ if (node.id === id) {
44
+ return node
45
+ }
46
+ }
47
+ return null
48
+ }
49
+ }
@@ -0,0 +1,31 @@
1
+ type JsonPath = (string | number)[]
2
+
3
+ export class JsonContext {
4
+ private parent: JsonContext | null
5
+ private local_path: JsonPath
6
+
7
+ concat(...items: JsonPath): JsonContext {
8
+ return new JsonContext(this, items)
9
+ }
10
+
11
+ path(): JsonPath {
12
+ return this.parent === null ? this.local_path : this.parent.path().concat(this.local_path)
13
+ }
14
+
15
+ constructor(parent: JsonContext | null, path: JsonPath) {
16
+ this.parent = parent
17
+ this.local_path = path
18
+ }
19
+
20
+ toString(): string {
21
+ let result = ""
22
+ this.path().forEach((part, index) => {
23
+ if (typeof part === "string") {
24
+ result += (index === 0 ? "" : ".") + part
25
+ } else if (typeof part === "number") {
26
+ result += "[" + part + "]"
27
+ }
28
+ })
29
+ return result
30
+ }
31
+ }
@@ -0,0 +1,13 @@
1
+ import { LionWebJsonUsedLanguage } from "@lionweb/json"
2
+ import { LION_CORE_M3_KEY, LION_CORE_M3_VERSION } from "./M3definitions.js"
3
+
4
+ /**
5
+ * The types defining the structure of the LionWeb JSON format.
6
+ * @see https://lionweb-io.github.io/specification/serialization/serialization.html
7
+ * We use types instead of classes, because the purpose is to define the Lionweb JSON to be sent over the line.
8
+ */
9
+
10
+
11
+ export function isLionWebM3Language(language: LionWebJsonUsedLanguage): boolean {
12
+ return language.key === LION_CORE_M3_KEY && language.version === LION_CORE_M3_VERSION
13
+ }
@@ -0,0 +1,137 @@
1
+ import {
2
+ isEqualMetaPointer,
3
+ LionWebId,
4
+ LionWebJsonChunk,
5
+ LionWebJsonContainment,
6
+ LionWebJsonMetaPointer,
7
+ LionWebJsonNode,
8
+ LionWebJsonReference
9
+ } from "@lionweb/json"
10
+ import { asMinimalJsonString } from "@lionweb/ts-utils"
11
+ import { MetaPointers } from "./M3definitions.js"
12
+ import { NodeUtils } from "./NodeUtils.js"
13
+
14
+ /**
15
+ * Wraps around a LionWebJsonChunk, providing access to information inside, might be using caches to improve performance.
16
+ * NB Make sure that the contents of the chunk are not changed after creating the wrapper!
17
+ * NB BE aware that with `pushChunk(...)` the original chunk will be changed.
18
+ */
19
+ export class LionWebJsonChunkWrapper {
20
+ jsonChunk: LionWebJsonChunk
21
+ /**
22
+ * Map to get quick access to nodes by id.
23
+ * @protected
24
+ */
25
+ protected nodesIdMap: Map<LionWebId, LionWebJsonNode> = new Map<LionWebId, LionWebJsonNode>()
26
+
27
+ /**
28
+ * Create a wrapper with `chunk` as its chunk
29
+ * @param chunk
30
+ */
31
+ constructor(chunk: LionWebJsonChunk) {
32
+ this.jsonChunk = chunk
33
+ this.prepareNodeIds(chunk)
34
+ }
35
+
36
+ /** Put all nodes in a map, validate that there are no two nodes with the same id.
37
+ * The check should logically be in LionWebReferenceValidator, but the created map is needed here.
38
+ */
39
+ prepareNodeIds(chunk: LionWebJsonChunk) {
40
+ chunk.nodes.forEach(node => {
41
+ this.nodesIdMap.set(node.id, node)
42
+ })
43
+ }
44
+
45
+ getNode(id: LionWebId): LionWebJsonNode | undefined {
46
+ return this.nodesIdMap.get(id)
47
+ }
48
+
49
+ findNodesOfClassifier(concept: LionWebJsonMetaPointer): LionWebJsonNode[] {
50
+ return this.jsonChunk.nodes.filter(node => isEqualMetaPointer(node.classifier, concept))
51
+ }
52
+
53
+ /**
54
+ * Return the target nodes inside `reference` as a list of actual nodes (LionWebJsonNode[])
55
+ * @param reference
56
+ */
57
+ getReferredNodes(reference: LionWebJsonReference | undefined) {
58
+ if (reference === undefined) {
59
+ return []
60
+ }
61
+ const result = reference.targets.flatMap(target => {
62
+ if (target.reference === null) {
63
+ return []
64
+ } else {
65
+ const referredNode = this.getNode(target.reference)
66
+ return referredNode === undefined ? [] : [referredNode]
67
+ }
68
+ })
69
+ return result
70
+ }
71
+
72
+ /**
73
+ * Return the target nodes inside `reference` as a list of actual nodes (LionWebJsonNode[])
74
+ * @param reference
75
+ */
76
+ getChildrenAsNodes(containment: LionWebJsonContainment | undefined) {
77
+ if (containment === undefined) {
78
+ return []
79
+ }
80
+ const result: LionWebJsonNode[] = []
81
+ containment.children.forEach(ch => {
82
+ const childNode = this.getNode(ch)
83
+ if (childNode !== undefined) {
84
+ result.push(childNode)
85
+ }
86
+ })
87
+ return result
88
+ }
89
+
90
+ asString(): string {
91
+ let result = ""
92
+ const partitions = this.jsonChunk.nodes.filter(n => n.parent === null)
93
+ partitions.forEach(partition => {
94
+ const pString = this.recursiveToString(partition, 1)
95
+ result += pString
96
+ })
97
+ return result
98
+ }
99
+
100
+ private recursiveToString(node: LionWebJsonNode | undefined, depth: number): string {
101
+ if (node === undefined) {
102
+ return ""
103
+ }
104
+ let result: string = ""
105
+ const nameProperty = NodeUtils.findProperty(node, MetaPointers.INamedName)
106
+ const name = nameProperty === undefined ? "" : " " + nameProperty.value
107
+ result += this.indent(depth) + "(" + node.id + ")" + name + "\n"
108
+ if (node.annotations !== undefined && node.annotations.length !== 0) {
109
+ result += this.indent(depth + 1) + "*Annotations*" + "\n"
110
+ node.annotations.forEach(ann => {
111
+ result += this.recursiveToString(this.getNode(ann), depth + 1)
112
+ // result += this.indent(depth) + "[[" + asMinimalJsonString(ann) + "]]\n"
113
+ })
114
+ }
115
+ node.properties
116
+ .filter(p => p !== nameProperty)
117
+ .forEach(property => {
118
+ result += this.indent(depth + 1) + "*property* " + property.property.key + ": " + property.value + "\n"
119
+ })
120
+ node.references.forEach(ref => {
121
+ result += this.indent(depth + 1) + "*" + ref.reference.key + "*: " + asMinimalJsonString(ref.targets) + "\n"
122
+ })
123
+ node.containments.forEach(cont => {
124
+ if (cont.children.length !== 0) {
125
+ result += this.indent(depth + 1) + "*" + cont.containment.key + "*" + "\n"
126
+ cont.children.forEach(ch => {
127
+ result += this.recursiveToString(this.getNode(ch), depth + 1)
128
+ })
129
+ }
130
+ })
131
+ return result
132
+ }
133
+
134
+ private indent(depth: number): string {
135
+ return Array(depth).join(" ")
136
+ }
137
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * This file contains LionWeb defined M3 keys and identifications.
3
+ */
4
+ export const LION_CORE_BUILTINS_INAMED_NAME = "LionCore-builtins-INamed-name"
5
+ export const LION_CORE_BUILTINS_KEY = "LionCore-builtins"
6
+
7
+ export const LION_CORE_M3_KEY = "LionCore-M3"
8
+ export const LION_CORE_M3_NAME = "LionCore_M3"
9
+
10
+ export const LION_CORE_M3_VERSION = "2023.1"
11
+
12
+ // built-in data types:
13
+ export const LIONWEB_BOOLEAN_TYPE = "LionCore-builtins-Boolean"
14
+ export const LIONWEB_JSON_TYPE = "LionCore-builtins-JSON"
15
+ export const LIONWEB_INTEGER_TYPE = "LionCore-builtins-Integer"
16
+ export const LIONWEB_STRING_TYPE = "LionCore-builtins-String"
17
+
18
+ export const M3_Keys = {
19
+ Property: "Property",
20
+ Reference: "Reference",
21
+ Concept: "Concept",
22
+ conceptExtends: "Concept-extends",
23
+ conceptImplements: "Concept-implements",
24
+ concept2: {
25
+ key: "Concept",
26
+ extends: { key: "Concept-extends" },
27
+ implements: { key: "Concept-implements" }
28
+ },
29
+ conceptAbstract: "Concept-abstract",
30
+ conceptPartition: "Concept-partition",
31
+ classifierFeatures: "Classifier-features",
32
+ Interface: "Interface",
33
+ InterfaceExtends: "Interface-extends",
34
+ Containment: "Containment",
35
+ Language: "Language",
36
+ languageVersion: "Language-version",
37
+ IKeyedKey: "IKeyed-key",
38
+ PropertyType: "Property-type",
39
+ Enumeration: "Enumeration",
40
+ EnumerationLiterals: "Enumeration-literals",
41
+ EnumerationLiteral: "EnumerationLiteral",
42
+ INamed: "LionCore-builtins-INamed",
43
+ INamedName: "LionCore-builtins-INamed-name",
44
+ Annotation: "Annotation",
45
+ AnnotationAnnotates: "Annotation-annotates",
46
+ AnnotationExtends: "Annotation-extends",
47
+ AnnotationImplements: "Annotation-implements",
48
+ Node: "LionCore-builtins-Node"
49
+ }
50
+
51
+ export const MetaPointers = {
52
+ Language: {
53
+ version: LION_CORE_M3_VERSION,
54
+ language: LION_CORE_M3_KEY,
55
+ key: M3_Keys.Language
56
+ },
57
+ LanguageVersion: {
58
+ version: LION_CORE_M3_VERSION,
59
+ language: LION_CORE_M3_KEY,
60
+ key: M3_Keys.languageVersion
61
+ },
62
+ ClassifierFeatures: {
63
+ version: LION_CORE_M3_VERSION,
64
+ language: LION_CORE_M3_KEY,
65
+ key: M3_Keys.classifierFeatures
66
+ },
67
+ Concept: {
68
+ version: LION_CORE_M3_VERSION,
69
+ language: LION_CORE_M3_KEY,
70
+ key: M3_Keys.concept2.key
71
+ },
72
+ ConceptAbstract: {
73
+ version: LION_CORE_M3_VERSION,
74
+ language: LION_CORE_M3_KEY,
75
+ key: M3_Keys.conceptAbstract
76
+ },
77
+ ConceptPartition: {
78
+ version: LION_CORE_M3_VERSION,
79
+ language: LION_CORE_M3_KEY,
80
+ key: M3_Keys.conceptPartition
81
+ },
82
+ ConceptExtends: {
83
+ version: LION_CORE_M3_VERSION,
84
+ language: LION_CORE_M3_KEY,
85
+ key: M3_Keys.concept2.extends.key
86
+ },
87
+ ConceptImplements: {
88
+ version: LION_CORE_M3_VERSION,
89
+ language: LION_CORE_M3_KEY,
90
+ key: M3_Keys.concept2.implements.key
91
+ },
92
+ Annotation: {
93
+ version: LION_CORE_M3_VERSION,
94
+ language: LION_CORE_M3_KEY,
95
+ key: M3_Keys.Annotation
96
+ },
97
+ AnnotationAnnotates: {
98
+ version: LION_CORE_M3_VERSION,
99
+ language: LION_CORE_M3_KEY,
100
+ key: M3_Keys.AnnotationAnnotates
101
+ },
102
+ AnnotationExtends: {
103
+ version: LION_CORE_M3_VERSION,
104
+ language: LION_CORE_M3_KEY,
105
+ key: M3_Keys.AnnotationExtends
106
+ },
107
+ AnnotationImplements: {
108
+ version: LION_CORE_M3_VERSION,
109
+ language: LION_CORE_M3_KEY,
110
+ key: M3_Keys.AnnotationImplements
111
+ },
112
+ Interface: {
113
+ version: LION_CORE_M3_VERSION,
114
+ language: LION_CORE_M3_KEY,
115
+ key: M3_Keys.Interface
116
+ },
117
+ InterfaceExtends: {
118
+ version: LION_CORE_M3_VERSION,
119
+ language: LION_CORE_M3_KEY,
120
+ key: M3_Keys.InterfaceExtends
121
+ },
122
+ Enumeration: {
123
+ version: LION_CORE_M3_VERSION,
124
+ language: LION_CORE_M3_KEY,
125
+ key: M3_Keys.Enumeration
126
+ },
127
+ EnumerationLiteral: {
128
+ version: LION_CORE_M3_VERSION,
129
+ language: LION_CORE_M3_KEY,
130
+ key: M3_Keys.EnumerationLiteral
131
+ },
132
+ EnumerationLiterals: {
133
+ version: LION_CORE_M3_VERSION,
134
+ language: LION_CORE_M3_KEY,
135
+ key: M3_Keys.EnumerationLiterals
136
+ },
137
+ Containment: {
138
+ version: LION_CORE_M3_VERSION,
139
+ language: LION_CORE_M3_KEY,
140
+ key: M3_Keys.Containment
141
+ },
142
+ Property: {
143
+ version: LION_CORE_M3_VERSION,
144
+ language: LION_CORE_M3_KEY,
145
+ key: M3_Keys.Property
146
+ },
147
+ PropertyType: {
148
+ version: LION_CORE_M3_VERSION,
149
+ language: LION_CORE_M3_KEY,
150
+ key: M3_Keys.PropertyType
151
+ },
152
+ Reference: {
153
+ version: LION_CORE_M3_VERSION,
154
+ language: LION_CORE_M3_KEY,
155
+ key: M3_Keys.Reference
156
+ },
157
+ IKeyedKey: {
158
+ language: LION_CORE_M3_KEY,
159
+ version: LION_CORE_M3_VERSION,
160
+ key: M3_Keys.IKeyedKey
161
+ },
162
+ // Builtins:
163
+ Node: {
164
+ language: LION_CORE_BUILTINS_KEY,
165
+ version: LION_CORE_M3_VERSION,
166
+ key: M3_Keys.Node
167
+ },
168
+ INamed: {
169
+ language: LION_CORE_BUILTINS_KEY,
170
+ version: LION_CORE_M3_VERSION,
171
+ key: M3_Keys.INamed
172
+ },
173
+ INamedName: {
174
+ language: LION_CORE_BUILTINS_KEY,
175
+ version: LION_CORE_M3_VERSION,
176
+ key: M3_Keys.INamedName
177
+ }
178
+ }
@@ -0,0 +1,76 @@
1
+ import {
2
+ isEqualMetaPointer,
3
+ isEqualReferenceTarget, LionWebId,
4
+ LionWebJsonContainment,
5
+ LionWebJsonMetaPointer,
6
+ LionWebJsonNode,
7
+ LionWebJsonProperty,
8
+ LionWebJsonReference,
9
+ LionWebJsonReferenceTarget, LionWebKey
10
+ } from "@lionweb/json"
11
+
12
+ /**
13
+ * Utility functions for LionWebJsonNode's
14
+ */
15
+ export class NodeUtils {
16
+ /**
17
+ * Find property with key equals `key` in `node`.
18
+ * @param node
19
+ * @param key
20
+ */
21
+ static findProperty(node: LionWebJsonNode, property: LionWebJsonMetaPointer): LionWebJsonProperty | undefined {
22
+ if (node === undefined) {
23
+ return undefined
24
+ }
25
+ return node.properties.find(
26
+ prop => isEqualMetaPointer(prop.property, property)
27
+ )
28
+ }
29
+
30
+ /**
31
+ * Find containment child with key equals `key` in `node`.
32
+ * @param node
33
+ * @param key
34
+ */
35
+ static findChild(node: LionWebJsonNode, key: LionWebKey): LionWebJsonContainment | undefined {
36
+ if (node === undefined) {
37
+ return undefined
38
+ }
39
+ for (const containment of node.containments) {
40
+ if (containment.containment.key === key) {
41
+ return containment
42
+ }
43
+ }
44
+ return undefined
45
+ }
46
+
47
+ static findContainment(node: LionWebJsonNode, containment: LionWebJsonMetaPointer): LionWebJsonContainment | undefined {
48
+ if (node === undefined) {
49
+ return undefined
50
+ }
51
+ return node.containments.find(cont => isEqualMetaPointer(cont.containment, containment))
52
+ }
53
+
54
+ static findReference(node: LionWebJsonNode, reference: LionWebJsonMetaPointer): LionWebJsonReference | undefined {
55
+ if (node === undefined) {
56
+ return undefined
57
+ }
58
+ return node.references.find(ref => isEqualMetaPointer(ref.reference, reference))
59
+ }
60
+
61
+ static findReferenceTarget(
62
+ referenceTargets: LionWebJsonReferenceTarget[],
63
+ target: LionWebJsonReferenceTarget,
64
+ ): LionWebJsonReferenceTarget | undefined {
65
+ for (const refTarget of referenceTargets) {
66
+ if (isEqualReferenceTarget(refTarget, target)) {
67
+ return refTarget
68
+ }
69
+ }
70
+ return undefined
71
+ }
72
+
73
+ static findContainmentContainingChild(containments: LionWebJsonContainment[], childId: LionWebId): LionWebJsonContainment | undefined {
74
+ return containments.find(cont => cont.children.includes(childId))
75
+ }
76
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./JsonContext.js"
2
+ export * from "./NodeUtils.js"
3
+ export * from "./ChunkUtils.js"
4
+ export * from "./LionWebJson.js"
5
+ export * from "./LionWebJsonChunkWrapper.js"
6
+ export * from "./M3definitions.js"