@lionweb/validation 0.6.0-beta.3 → 0.6.0-beta.5

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.
Files changed (54) hide show
  1. package/dist/diff/LionWebJsonDiff.d.ts +1 -1
  2. package/dist/diff/LionWebJsonDiff.d.ts.map +1 -1
  3. package/dist/diff/LionWebJsonDiff.js +70 -21
  4. package/dist/diff/LionWebJsonDiff.js.map +1 -1
  5. package/dist/diff/changes/Change.d.ts +21 -3
  6. package/dist/diff/changes/Change.d.ts.map +1 -1
  7. package/dist/diff/changes/Change.js +21 -2
  8. package/dist/diff/changes/Change.js.map +1 -1
  9. package/dist/diff/changes/ChunkChange.d.ts +5 -5
  10. package/dist/diff/changes/ChunkChange.d.ts.map +1 -1
  11. package/dist/diff/changes/ChunkChange.js +5 -5
  12. package/dist/diff/changes/ChunkChange.js.map +1 -1
  13. package/dist/diff/changes/ContainmentChange.d.ts +9 -10
  14. package/dist/diff/changes/ContainmentChange.d.ts.map +1 -1
  15. package/dist/diff/changes/ContainmentChange.js +12 -12
  16. package/dist/diff/changes/ContainmentChange.js.map +1 -1
  17. package/dist/diff/changes/NodeChange.d.ts +21 -2
  18. package/dist/diff/changes/NodeChange.d.ts.map +1 -1
  19. package/dist/diff/changes/NodeChange.js +32 -2
  20. package/dist/diff/changes/NodeChange.js.map +1 -1
  21. package/dist/diff/changes/PropertyChange.d.ts +7 -6
  22. package/dist/diff/changes/PropertyChange.d.ts.map +1 -1
  23. package/dist/diff/changes/PropertyChange.js +5 -4
  24. package/dist/diff/changes/PropertyChange.js.map +1 -1
  25. package/dist/diff/changes/ReferenceChange.d.ts +13 -7
  26. package/dist/diff/changes/ReferenceChange.d.ts.map +1 -1
  27. package/dist/diff/changes/ReferenceChange.js +17 -8
  28. package/dist/diff/changes/ReferenceChange.js.map +1 -1
  29. package/dist/json/LionWebJson.d.ts +6 -0
  30. package/dist/json/LionWebJson.d.ts.map +1 -1
  31. package/dist/json/LionWebJson.js +8 -0
  32. package/dist/json/LionWebJson.js.map +1 -1
  33. package/dist/json/LionWebJsonChunkWrapper.d.ts +2 -3
  34. package/dist/json/LionWebJsonChunkWrapper.d.ts.map +1 -1
  35. package/dist/json/LionWebJsonChunkWrapper.js +16 -16
  36. package/dist/json/LionWebJsonChunkWrapper.js.map +1 -1
  37. package/dist/json/LionWebLanguageDefinition.d.ts.map +1 -1
  38. package/dist/json/LionWebLanguageDefinition.js.map +1 -1
  39. package/dist/json/NodeUtils.d.ts +3 -1
  40. package/dist/json/NodeUtils.d.ts.map +1 -1
  41. package/dist/json/NodeUtils.js +8 -1
  42. package/dist/json/NodeUtils.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/diff/LionWebJsonDiff.ts +81 -26
  45. package/src/diff/changes/Change.ts +27 -3
  46. package/src/diff/changes/ChunkChange.ts +5 -5
  47. package/src/diff/changes/ContainmentChange.ts +10 -12
  48. package/src/diff/changes/NodeChange.ts +33 -2
  49. package/src/diff/changes/PropertyChange.ts +8 -6
  50. package/src/diff/changes/ReferenceChange.ts +18 -8
  51. package/src/json/LionWebJson.ts +9 -0
  52. package/src/json/LionWebJsonChunkWrapper.ts +17 -24
  53. package/src/json/LionWebLanguageDefinition.ts +1 -0
  54. package/src/json/NodeUtils.ts +19 -4
@@ -1,22 +1,23 @@
1
1
  import { JsonContext } from "../issues/index.js"
2
2
  import {
3
3
  ChunkUtils,
4
- isEqualMetaPointer,
5
- LionWebJsonContainment,
4
+ isEqualMetaPointer, isEqualReferenceTarget,
6
5
  LionWebJsonChunk,
6
+ LionWebJsonContainment,
7
7
  LionWebJsonNode,
8
8
  LionWebJsonProperty,
9
9
  LionWebJsonReference,
10
+ LionWebJsonReferenceTarget,
10
11
  LwJsonUsedLanguage,
11
- NodeUtils, LionWebJsonReferenceTarget
12
+ NodeUtils
12
13
  } from "../json/index.js"
13
- import { Change, GenericChange } from "./changes/Change.js"
14
+ import { Change, GenericChange, Missing } from "./changes/Change.js"
14
15
  import { LanguageAdded, LanguageRemoved, NodeAdded, NodeRemoved, SerializationFormatChange } from "./changes/ChunkChange.js"
15
- import { ChildAdded, ChildRemoved } from "./changes/ContainmentChange.js"
16
- import { TargetAdded, TargetRemoved } from "./changes/index.js"
17
- import { DiffResult } from "./DiffResult.js"
16
+ import { ChildAdded, ChildRemoved, ChildOrderChanged } from "./changes/ContainmentChange.js"
17
+ import { AnnotationAdded, AnnotationOrderChanged, AnnotationRemoved, TargetAdded, TargetOrderChanged, TargetRemoved } from "./changes/index.js"
18
18
  import { NodeClassifierChanged, ParentChanged } from "./changes/NodeChange.js"
19
19
  import { PropertyValueChanged } from "./changes/PropertyChange.js"
20
+ import { DiffResult } from "./DiffResult.js"
20
21
 
21
22
  /**
22
23
  * Comparing LionWeb JSON chunks and find all differences
@@ -42,9 +43,7 @@ export class LionWebJsonDiff {
42
43
  */
43
44
  diffLwNode(ctx: JsonContext, beforeNode: LionWebJsonNode, afterNode: LionWebJsonNode): void {
44
45
  if (!isEqualMetaPointer(beforeNode.classifier, afterNode.classifier)) {
45
- this.change(
46
- new NodeClassifierChanged(ctx.concat("classifier"), beforeNode, beforeNode.classifier, afterNode.classifier),
47
- )
46
+ this.change(new NodeClassifierChanged(ctx.concat("classifier"), beforeNode, beforeNode.classifier, afterNode.classifier))
48
47
  }
49
48
  if (beforeNode.parent !== afterNode.parent) {
50
49
  this.change(new ParentChanged(ctx, beforeNode, beforeNode.parent, afterNode.parent))
@@ -60,7 +59,8 @@ export class LionWebJsonDiff {
60
59
  beforeNode.id,
61
60
  beforeProperty.property,
62
61
  beforeProperty.value,
63
- undefined,
62
+ null,
63
+ Missing.MissingAfter
64
64
  ),
65
65
  )
66
66
  } else {
@@ -76,8 +76,9 @@ export class LionWebJsonDiff {
76
76
  ctx.concat("properties", index),
77
77
  beforeNode.id,
78
78
  afterProperty.property,
79
- undefined,
79
+ null,
80
80
  afterProperty.value,
81
+ Missing.MissingBefore
81
82
  ),
82
83
  )
83
84
  }
@@ -90,7 +91,7 @@ export class LionWebJsonDiff {
90
91
  // NB No containment is considered equivalent to a containment with empty _children_
91
92
  if (beforeContainment.children.length !== 0) {
92
93
  beforeContainment.children.forEach(childId => {
93
- this.change(new ChildRemoved(ctx.concat("containments", index), beforeNode, beforeContainment.containment, childId))
94
+ this.change(new ChildRemoved(ctx.concat("containments", index), beforeNode, beforeContainment.containment, afterContainment, childId, Missing.MissingAfter))
94
95
  })
95
96
  }
96
97
  } else {
@@ -103,7 +104,7 @@ export class LionWebJsonDiff {
103
104
  if (beforeContainment === null) {
104
105
  if (afterContainment.children.length !== 0) {
105
106
  afterContainment.children.forEach(childId => {
106
- this.change(new ChildAdded(ctx.concat("containments", index), afterNode, afterContainment.containment, childId))
107
+ this.change(new ChildAdded(ctx.concat("containments", index), afterNode, afterContainment.containment, afterContainment, childId, Missing.MissingBefore))
107
108
  })
108
109
  }
109
110
  }
@@ -115,7 +116,7 @@ export class LionWebJsonDiff {
115
116
  if (afterReference === null) {
116
117
  if (beforeReference.targets.length !== 0) {
117
118
  beforeReference.targets.forEach(target => {
118
- this.change(new TargetRemoved(ctx.concat("references", index), afterNode, beforeReference.reference, target.reference))
119
+ this.change(new TargetRemoved(ctx.concat("references", index), afterNode, beforeReference, afterReference, target, Missing.MissingAfter))
119
120
  })
120
121
  }
121
122
  } else {
@@ -128,11 +129,34 @@ export class LionWebJsonDiff {
128
129
  if (beforeReference === null) {
129
130
  if (afterReference.targets.length !== 0) {
130
131
  afterReference.targets.forEach(target => {
131
- this.change(new TargetAdded(ctx.concat("references", index), afterNode, afterReference.reference, target.reference))
132
+ this.change(new TargetAdded(ctx.concat("references", index), afterNode, beforeReference, afterReference, target, Missing.MissingBefore))
132
133
  })
133
134
  }
134
135
  }
135
136
  })
137
+ if (beforeNode.annotations !== undefined && afterNode.annotations !== undefined) {
138
+ let annotationDiffFound = false
139
+ beforeNode.annotations.forEach((beforeAnn: string, index: number) => {
140
+ if (!afterNode.annotations.includes(beforeAnn)) {
141
+ annotationDiffFound = true
142
+ this.change(new AnnotationRemoved(ctx, beforeNode, afterNode, beforeAnn, index))
143
+ }
144
+ })
145
+ afterNode.annotations.forEach((afterAnn: string, index: number) => {
146
+ if (!beforeNode.annotations.includes(afterAnn)) {
147
+ annotationDiffFound = true
148
+ this.change(new AnnotationAdded(ctx, beforeNode, afterNode, afterAnn, index))
149
+ }
150
+ })
151
+ if (!annotationDiffFound) {
152
+ for (let i: number = 0; i < afterNode.annotations.length; i++) {
153
+ if (afterNode.annotations[i] !== beforeNode.annotations[i]) {
154
+ this.change(new AnnotationOrderChanged(ctx.concat("annotations"), beforeNode, afterNode, "", i))
155
+ break
156
+ }
157
+ }
158
+ }
159
+ }
136
160
  }
137
161
 
138
162
  diffLwChunk(beforeChunk: LionWebJsonChunk, afterChunk: LionWebJsonChunk): void {
@@ -197,14 +221,25 @@ export class LionWebJsonDiff {
197
221
  }
198
222
  // Check whether children exist in both objects (two for loops)
199
223
  // TODO Also check for the order that can be changed!!!
224
+ let changeFound = false
200
225
  for (const childId1 of beforeContainment.children) {
201
226
  if (!afterContainment.children.includes(childId1)) {
202
- this.change(new ChildRemoved(ctx, node, beforeContainment.containment, childId1))
227
+ changeFound = true
228
+ this.change(new ChildRemoved(ctx, node, beforeContainment.containment, afterContainment, childId1))
203
229
  }
204
230
  }
205
231
  for (const childId2 of afterContainment.children) {
206
232
  if (!beforeContainment.children.includes(childId2)) {
207
- this.change(new ChildAdded(ctx, node, beforeContainment.containment, childId2))
233
+ changeFound = true
234
+ this.change(new ChildAdded(ctx, node, beforeContainment.containment, afterContainment, childId2))
235
+ }
236
+ }
237
+ if (!changeFound) {
238
+ for (let i: number = 0; i < afterContainment.children.length; i++) {
239
+ if (afterContainment.children[i] !== beforeContainment.children[i]) {
240
+ this.change(new ChildOrderChanged(ctx.concat("children"), node, afterContainment.containment, afterContainment, ""))
241
+ break
242
+ }
208
243
  }
209
244
  }
210
245
  }
@@ -214,21 +249,41 @@ export class LionWebJsonDiff {
214
249
  console.error("diffContainment: MetaPointers of containments should be identical")
215
250
  this.diff(ctx, `Reference has concept ${JSON.stringify(beforeRef.reference)} vs ${JSON.stringify(afterRef.reference)}`)
216
251
  }
252
+ let diffFound = false;
217
253
  beforeRef.targets.forEach((beforeTarget: LionWebJsonReferenceTarget, index: number) => {
218
254
  const afterTarget = NodeUtils.findLwReferenceTarget(afterRef.targets, beforeTarget)
219
255
  if (afterTarget === null) {
220
- // this.change(new TargetRemoved(ctx.concat("targets", index), node, target))
221
- // this.diff(ctx, `REFERENCE Target ${JSON.stringify(beforeTarget)} missing in second `)
222
- this.change(new TargetRemoved(ctx.concat("targets", index), node, beforeRef.reference, beforeTarget.reference))
256
+ this.change(new TargetRemoved(ctx.concat("targets", index), node, beforeRef, afterRef, beforeTarget))
257
+ diffFound = true
223
258
  } else {
224
- if (beforeTarget.reference !== afterTarget.reference || beforeTarget.resolveInfo !== afterTarget.resolveInfo) {
225
- this.diff(ctx.concat("targets", index), `REFERENCE target ${JSON.stringify(beforeTarget)} vs ${JSON.stringify(afterTarget)}`)
259
+ if (!isEqualReferenceTarget(beforeTarget, afterTarget)) {
260
+ this.diff(
261
+ ctx.concat("targets", index),
262
+ `ERROR: reference target ${JSON.stringify(beforeTarget)} vs ${JSON.stringify(afterTarget)}`,
263
+ )
226
264
  }
227
265
  }
228
266
  })
229
- for (const target of afterRef.targets) {
230
- if (NodeUtils.findLwReferenceTarget(beforeRef.targets, target) === null) {
231
- this.diff(ctx, `REFERENCE Target ${JSON.stringify(target)} missing in first `)
267
+ afterRef.targets.forEach((afterTarget: LionWebJsonReferenceTarget, index: number) => {
268
+ const beforeTarget = NodeUtils.findLwReferenceTarget(beforeRef.targets, afterTarget)
269
+ if (beforeTarget === null) {
270
+ this.change(new TargetAdded(ctx.concat("targets", index), node, beforeRef, afterRef, afterTarget))
271
+ diffFound = true
272
+ } else {
273
+ if (!isEqualReferenceTarget(beforeTarget, afterTarget)) {
274
+ this.diff(
275
+ ctx.concat("targets", index),
276
+ `ERROR: reference target ${JSON.stringify(beforeTarget)} vs ${JSON.stringify(afterTarget)}`,
277
+ )
278
+ }
279
+ }
280
+ })
281
+ if (!diffFound) {
282
+ for (let i: number = 0; i < beforeRef.targets.length; i++) {
283
+ if (!isEqualReferenceTarget(beforeRef.targets[i], afterRef.targets[i])) {
284
+ this.change(new TargetOrderChanged(ctx.concat("targets"), node, beforeRef, afterRef, beforeRef.targets[i]))
285
+ break
286
+ }
232
287
  }
233
288
  }
234
289
  }
@@ -20,9 +20,33 @@ export type ChangeType =
20
20
  | "TargetRemoved"
21
21
  | "ReferenceRemoved"
22
22
  | "ReferenceAdded"
23
+ | "AnnotationRemoved"
24
+ | "AnnotationAdded"
25
+ | "ChildOrderChanged"
26
+ | "AnnotationOrderChanged"
27
+ | "TargetOrderChanged"
28
+
29
+ /**
30
+ * Additionbal property in property, contauinment and reference changes to state
31
+ * that the whole property/ containment / reference definition is missing.
32
+ */
33
+ export enum Missing {
34
+ /**
35
+ * Both before and after have a definition for the property / containment / reference
36
+ */
37
+ NotMissing,
38
+ /**
39
+ * The definition is missing _before_ for the property / containment / reference
40
+ */
41
+ MissingBefore,
42
+ /**
43
+ * The definition is missing _after_ for the property / containment / reference
44
+ */
45
+ MissingAfter
46
+ }
23
47
 
24
48
  export abstract class Change {
25
- abstract readonly id: ChangeType
49
+ abstract readonly changeType: ChangeType
26
50
  context: JsonContext
27
51
 
28
52
  constructor(context: JsonContext) {
@@ -32,12 +56,12 @@ export abstract class Change {
32
56
  protected abstract msg(): string
33
57
 
34
58
  public changeMsg(): string {
35
- return `${this.id}: ${this.msg()} at ${this.context.toString()} `
59
+ return `${this.changeType}: ${this.msg()} at ${this.context.toString()} `
36
60
  }
37
61
  }
38
62
 
39
63
  export class GenericChange extends Change {
40
- readonly id = "GenericChange"
64
+ readonly changeType = "GenericChange"
41
65
 
42
66
  constructor(
43
67
  context: JsonContext,
@@ -9,7 +9,7 @@ export abstract class ChunkChange extends Change {
9
9
  }
10
10
 
11
11
  export class SerializationFormatChange extends ChunkChange {
12
- readonly id = "SerializationFormatChange"
12
+ readonly changeType = "SerializationFormatChange"
13
13
 
14
14
  constructor(
15
15
  public context: JsonContext,
@@ -23,7 +23,7 @@ export class SerializationFormatChange extends ChunkChange {
23
23
  }
24
24
 
25
25
  export class NodeRemoved extends ChunkChange {
26
- readonly id = "NodeRemoved"
26
+ readonly changeType = "NodeRemoved"
27
27
 
28
28
  constructor(
29
29
  public context: JsonContext,
@@ -36,7 +36,7 @@ export class NodeRemoved extends ChunkChange {
36
36
  }
37
37
 
38
38
  export class NodeAdded extends ChunkChange {
39
- readonly id = "NodeAdded"
39
+ readonly changeType = "NodeAdded"
40
40
 
41
41
  constructor(
42
42
  public context: JsonContext,
@@ -58,11 +58,11 @@ export abstract class LanguageChange extends ChunkChange {
58
58
  }
59
59
 
60
60
  export class LanguageRemoved extends LanguageChange {
61
- readonly id = "LanguageRemoved"
61
+ readonly changeType = "LanguageRemoved"
62
62
  protected msg = () => `Language with key ${this.language.key} and version ${this.language.version} is removed`
63
63
  }
64
64
 
65
65
  export class LanguageAdded extends LanguageChange {
66
- readonly id = "LanguageAdded"
66
+ readonly changeType = "LanguageAdded"
67
67
  protected msg = () => `Language with key ${this.language.key} and version ${this.language.version} is added`
68
68
  }
@@ -1,34 +1,32 @@
1
1
  import { JsonContext } from "../../issues/index.js"
2
- import { LionWebJsonMetaPointer, LionWebJsonNode } from "../../json/index.js"
3
- import { Change } from "./Change.js"
2
+ import { LionWebJsonContainment, LionWebJsonMetaPointer, LionWebJsonNode } from "../../json/index.js"
3
+ import { Change, Missing } from "./Change.js"
4
4
 
5
5
  export abstract class ContainmentChange extends Change {
6
6
  constructor(
7
7
  public context: JsonContext,
8
8
  public parentNode: LionWebJsonNode,
9
9
  public containment: LionWebJsonMetaPointer,
10
+ public afterContainment: LionWebJsonContainment | null,
10
11
  public childId: string,
12
+ public missing = Missing.NotMissing
11
13
  ) {
12
14
  super(context)
13
15
  }
14
16
  }
15
17
 
16
18
  export class ChildAdded extends ContainmentChange {
17
- readonly id = "ChildAdded"
19
+ readonly changeType = "ChildAdded"
18
20
  protected msg = () => `Node "${this.parentNode.id}" added child "${this.childId}" to containment ${this.containment.key}`
19
21
  }
20
22
 
21
23
  export class ChildRemoved extends ContainmentChange {
22
- readonly id = "ChildRemoved"
23
- protected msg = () => `Node "${this.parentNode.id}" removed child "${this.childId}"`
24
+ readonly changeType = "ChildRemoved"
25
+ protected msg = () => `Node "${this.parentNode.id}" removed child "${this.childId}" from containment "${this.containment.key}"`
24
26
  }
25
27
 
26
- export class ContainmentAdded extends Change {
27
- readonly id = "ContainmentAdded";
28
- constructor(ctx: JsonContext, public node: LionWebJsonNode, public containment: LionWebJsonMetaPointer) {
29
- super(ctx)
30
- }
31
-
32
- protected msg = () => `Node "${this.node.id}" containment added: "${JSON.stringify(this.containment)}"`
28
+ export class ChildOrderChanged extends ContainmentChange {
29
+ readonly changeType = "ChildOrderChanged"
30
+ protected msg = () => `Node "${this.parentNode.id}" changed order of children in containment "${this.containment.key}"`
33
31
  }
34
32
 
@@ -3,7 +3,7 @@ import { LionWebJsonMetaPointer, LionWebJsonNode } from "../../json/index.js"
3
3
  import { Change, ChangeType } from "./Change.js"
4
4
 
5
5
  export class NodeClassifierChanged extends Change {
6
- readonly id: ChangeType = "NodeClassifierChanged"
6
+ readonly changeType: ChangeType = "NodeClassifierChanged"
7
7
 
8
8
  constructor(
9
9
  public context: JsonContext,
@@ -13,11 +13,12 @@ export class NodeClassifierChanged extends Change {
13
13
  ) {
14
14
  super(context)
15
15
  }
16
+
16
17
  protected msg = () => `Object ${this.node.id} has classifier changed from ${this.oldClassifier.key} to ${this.newClassifier.key}`
17
18
  }
18
19
 
19
20
  export class ParentChanged extends Change {
20
- readonly id = "ParentChanged"
21
+ readonly changeType = "ParentChanged"
21
22
 
22
23
  constructor(
23
24
  public context: JsonContext,
@@ -30,3 +31,33 @@ export class ParentChanged extends Change {
30
31
 
31
32
  protected msg = () => `Node "${this.node.id}" changed parent from "${this.beforeParentId}" to "${this.afterParentId}`
32
33
  }
34
+
35
+ export abstract class AnnotationChange extends Change {
36
+ constructor(
37
+ ctx: JsonContext,
38
+ public nodeBefore: LionWebJsonNode,
39
+ public nodeAfter: LionWebJsonNode,
40
+ public annotationId: string,
41
+ public index: number
42
+ ) {
43
+ super(ctx)
44
+ }
45
+ }
46
+
47
+ export class AnnotationRemoved extends AnnotationChange {
48
+ readonly changeType = "AnnotationRemoved"
49
+
50
+ protected msg = () => `Node "${this.nodeBefore.id}" removed annotation "${this.annotationId}"`
51
+ }
52
+
53
+ export class AnnotationAdded extends AnnotationChange {
54
+ readonly changeType = "AnnotationAdded"
55
+
56
+ protected msg = () => `Node "${this.nodeAfter.id}" added annotation "${this.annotationId}"`
57
+ }
58
+
59
+
60
+ export class AnnotationOrderChanged extends AnnotationChange {
61
+ readonly changeType = "AnnotationOrderChanged"
62
+ protected msg = () => `Node "${this.nodeAfter.id}" changed order of annotations`
63
+ }
@@ -1,26 +1,28 @@
1
1
  import { JsonContext } from "../../issues/index.js"
2
2
  import { LionWebJsonMetaPointer, LionWebJsonNode } from "../../json/index.js"
3
- import { Change } from "./Change.js"
3
+ import { Change, Missing } from "./Change.js"
4
+
4
5
 
5
6
  export abstract class PropertyChange extends Change {
6
7
  constructor(
7
8
  public context: JsonContext,
8
9
  public nodeId: string,
9
10
  public property: LionWebJsonMetaPointer,
10
- public oldValue: string | undefined,
11
- public newValue: string | undefined,
11
+ public oldValue: string | null,
12
+ public newValue: string | null,
13
+ public missing: Missing = Missing.NotMissing
12
14
  ) {
13
- super(context)
15
+ super(context)
14
16
  }
15
17
  }
16
18
 
17
19
  export class PropertyValueChanged extends PropertyChange {
18
- readonly id = "PropertyValueChanged"
20
+ readonly changeType = "PropertyValueChanged"
19
21
  protected msg = () => `Node "${this.nodeId} changed value of property "${this.property.key}" from "${this.oldValue}" to "${this.newValue}"`
20
22
  }
21
23
 
22
24
  export class PropertyAdded extends Change {
23
- readonly id = "PropertyAdded";
25
+ readonly changeType = "PropertyAdded";
24
26
  constructor(ctx: JsonContext, public node: LionWebJsonNode, public property: LionWebJsonMetaPointer) {
25
27
  super(ctx)
26
28
  }
@@ -1,24 +1,34 @@
1
1
  import { JsonContext } from "../../issues/index.js"
2
- import { LionWebJsonMetaPointer, LionWebJsonNode } from "../../json/index.js"
3
- import { Change } from "./Change.js"
2
+ import { LionWebJsonNode, LionWebJsonReference, LionWebJsonReferenceTarget } from "../../json/index.js"
3
+ import { Change, Missing } from "./Change.js"
4
4
 
5
5
  export abstract class ReferenceChange extends Change {
6
6
  constructor(
7
7
  public context: JsonContext,
8
8
  public node: LionWebJsonNode,
9
- public reference: LionWebJsonMetaPointer,
10
- public targetId: string,
9
+ public beforeReference: LionWebJsonReference | null,
10
+ public afterReference: LionWebJsonReference | null,
11
+ public target: LionWebJsonReferenceTarget,
12
+ public missing = Missing.NotMissing
11
13
  ) {
12
14
  super(context)
13
15
  }
14
16
  }
15
17
 
16
18
  export class TargetAdded extends ReferenceChange {
17
- readonly id = "TargetAdded"
18
- protected msg = () => `Node "${this.node.id}" added target "${this.targetId}" to reference "${this.reference.key}"`
19
+ readonly changeType = "TargetAdded"
20
+ protected msg = () =>
21
+ `Node "${this.node.id}" added target "${this.target.reference}" to reference "${this?.afterReference?.reference?.key}"`
19
22
  }
20
23
 
21
24
  export class TargetRemoved extends ReferenceChange {
22
- readonly id = "TargetRemoved"
23
- protected msg = () => `Node "${this.node.id}" removed target "${this.targetId}" from reference "${this.reference.key}"`
25
+ readonly changeType = "TargetRemoved"
26
+ protected msg = () =>
27
+ `Node "${this.node.id}" removed target "${this.target.reference}" from reference "${this?.beforeReference?.reference?.key}"`
24
28
  }
29
+
30
+ export class TargetOrderChanged extends ReferenceChange {
31
+ readonly changeType = "TargetOrderChanged"
32
+ protected msg = () => `Node "${this.node.id}" changed order of targets in reference "${this.afterReference?.reference?.key}"`
33
+ }
34
+
@@ -14,6 +14,11 @@ export const LIONWEB_JSON_TYPE = "LionCore-builtins-JSON"
14
14
  export const LIONWEB_INTEGER_TYPE = "LionCore-builtins-Integer"
15
15
  export const LIONWEB_STRING_TYPE = "LionCore-builtins-String"
16
16
 
17
+ export const LIONWEB_M3_INAMED_PROPERTY = {
18
+ language: LION_CORE_BUILTINS_KEY,
19
+ version: LION_CORE_M3_VERSION,
20
+ key: LION_CORE_BUILTINS_INAMED_NAME
21
+ }
17
22
  export type LionWebId = string
18
23
 
19
24
  export type LionWebJsonMetaPointer = {
@@ -26,6 +31,10 @@ export function isEqualMetaPointer(p1: LionWebJsonMetaPointer, p2: LionWebJsonMe
26
31
  return p1.key === p2.key && p1.version === p2.version && p1.language === p2.language
27
32
  }
28
33
 
34
+ export function isEqualReferenceTarget(first: LionWebJsonReferenceTarget, second: LionWebJsonReferenceTarget): boolean {
35
+ return first.reference === second.reference && first.resolveInfo === second.resolveInfo
36
+ }
37
+
29
38
  export type LionWebJsonChunk = {
30
39
  serializationFormatVersion: string
31
40
  languages: LwJsonUsedLanguage[]
@@ -1,9 +1,7 @@
1
1
  import {
2
- isEqualMetaPointer, LION_CORE_BUILTINS_INAMED_NAME, LION_CORE_BUILTINS_KEY, LION_CORE_M3_VERSION,
2
+ LIONWEB_M3_INAMED_PROPERTY,
3
3
  LionWebId,
4
4
  LionWebJsonChunk,
5
- LionWebJsonContainment,
6
- LionWebJsonMetaPointer,
7
5
  LionWebJsonNode,
8
6
  LionWebJsonProperty
9
7
  } from "./LionWebJson.js"
@@ -41,18 +39,6 @@ export class LionWebJsonChunkWrapper {
41
39
  return this.nodesIdMap.get(id)
42
40
  }
43
41
 
44
- findContainment(node: LionWebJsonNode, containment: LionWebJsonMetaPointer): LionWebJsonContainment | undefined {
45
- return node.containments.find(
46
- cont => isEqualMetaPointer(cont.containment, containment)
47
- )
48
- }
49
-
50
- findProperty(node: LionWebJsonNode, property: LionWebJsonMetaPointer): LionWebJsonProperty | undefined {
51
- return node.properties.find(
52
- prop => isEqualMetaPointer(prop.property, property)
53
- )
54
- }
55
-
56
42
  findNodesOfConcept(conceptKey: string): LionWebJsonNode[] {
57
43
  return this.jsonChunk.nodes.filter(node => node.classifier.key === conceptKey)
58
44
  }
@@ -88,22 +74,25 @@ export class LionWebJsonChunkWrapper {
88
74
  return "";
89
75
  }
90
76
  let result: string = ""
91
- const nameProperty = this.findProperty(node, {
92
- language: LION_CORE_BUILTINS_KEY,
93
- version: LION_CORE_M3_VERSION,
94
- key: LION_CORE_BUILTINS_INAMED_NAME,
95
- })
77
+ const nameProperty = NodeUtils.findProperty(node, LIONWEB_M3_INAMED_PROPERTY)
96
78
  const name = nameProperty === undefined ? "" : " " + nameProperty.value
97
- result += Array(depth).join(" ") + "(" + node.id + ")" + name + "\n"
79
+ result += this.indent(depth) + "(" + node.id + ")" + name + "\n"
80
+ if (node.annotations !== undefined && node.annotations.length !== 0) {
81
+ result += this.indent(depth + 1) + "*Annotations*" + "\n"
82
+ node.annotations.forEach(ann => {
83
+ result += this.recursiveToString(this.getNode(ann), depth + 1)
84
+ // result += this.indent(depth) + "[[" + JSON.stringify(ann) + "]]\n"
85
+ })
86
+ }
98
87
  node.properties.filter(p => p !== nameProperty).forEach(property => {
99
- result += Array(depth + 1).join(" ") + "*" + property.property.key + "*: " + property.value + "\n"
88
+ result += this.indent(depth + 1) + "*property* " + property.property.key + ": " + property.value + "\n"
100
89
  })
101
90
  node.references.forEach(ref => {
102
- result += Array(depth + 1).join(" ") + "*" + ref.reference.key + "*: " + JSON.stringify(ref.targets) + "\n"
91
+ result += this.indent(depth + 1) + "*" + ref.reference.key + "*: " + JSON.stringify(ref.targets) + "\n"
103
92
  })
104
93
  node.containments.forEach(cont => {
105
94
  if (cont.children.length !== 0) {
106
- result += Array(depth + 1).join(" ") + "*" + cont.containment.key + "*" + "\n"
95
+ result += this.indent(depth + 1) + "*" + cont.containment.key + "*" + "\n"
107
96
  cont.children.forEach(ch => {
108
97
  result += this.recursiveToString(this.getNode(ch), depth + 1)
109
98
  })
@@ -111,4 +100,8 @@ export class LionWebJsonChunkWrapper {
111
100
  })
112
101
  return result
113
102
  }
103
+
104
+ private indent(depth: number): string {
105
+ return Array(depth).join(" ")
106
+ }
114
107
  }
@@ -17,6 +17,7 @@ export const LIONWEB_M3_LANGUAGE_KEY = "Language"
17
17
  export const LIONWEB_M3_LANGUAGE_VERSION_KEY = "Language-version"
18
18
  export const LIONWEB_M3_IKEYED_KEY_KEY = "IKeyed-key"
19
19
  export const LIONWEB_M3_PROPERTY_TYPE_KEY = "Property-type"
20
+
20
21
  /**
21
22
  * Collection of language definitions
22
23
  */
@@ -1,9 +1,11 @@
1
1
  import {
2
- LionWebJsonContainment,
2
+ isEqualMetaPointer,
3
+ isEqualReferenceTarget,
4
+ LionWebJsonContainment, LionWebJsonMetaPointer,
3
5
  LionWebJsonNode,
4
6
  LionWebJsonProperty,
5
7
  LionWebJsonReference,
6
- LionWebJsonReferenceTarget,
8
+ LionWebJsonReferenceTarget
7
9
  } from "./LionWebJson.js"
8
10
 
9
11
  /**
@@ -24,6 +26,12 @@ export class NodeUtils {
24
26
  return null
25
27
  }
26
28
 
29
+ static findProperty(node: LionWebJsonNode, property: LionWebJsonMetaPointer): LionWebJsonProperty | undefined {
30
+ return node.properties.find(
31
+ prop => isEqualMetaPointer(prop.property, property)
32
+ )
33
+ }
34
+
27
35
  /**
28
36
  * Find containment child with key equals `key` in `node`.
29
37
  * @param node
@@ -38,6 +46,13 @@ export class NodeUtils {
38
46
  return null
39
47
  }
40
48
 
49
+ static findContainment(node: LionWebJsonNode, containment: LionWebJsonMetaPointer): LionWebJsonContainment | undefined {
50
+ return node.containments.find(
51
+ cont => isEqualMetaPointer(cont.containment, containment)
52
+ )
53
+ }
54
+
55
+
41
56
  static findLwReference(node: LionWebJsonNode, key: string): LionWebJsonReference | null {
42
57
  for (const reference of node.references) {
43
58
  if (reference.reference.key === key) {
@@ -52,13 +67,13 @@ export class NodeUtils {
52
67
  target: LionWebJsonReferenceTarget,
53
68
  ): LionWebJsonReferenceTarget | null {
54
69
  for (const refTarget of lwReferenceTargets) {
55
- if (refTarget.reference === target.reference && refTarget.resolveInfo === target.resolveInfo) {
70
+ if (isEqualReferenceTarget(refTarget, target)) {
56
71
  return refTarget
57
72
  }
58
73
  }
59
74
  return null
60
75
  }
61
-
76
+
62
77
  /**
63
78
  * Get all nodes that are children for _node_: both the containment and annotation children
64
79
  * @param node