archimate 2.0.1 → 2.0.2

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/archimate.gemspec +2 -1
  3. data/lib/archimate/color.rb +2 -2
  4. data/lib/archimate/data_model/any_attribute.rb +4 -10
  5. data/lib/archimate/data_model/any_element.rb +9 -17
  6. data/lib/archimate/data_model/bounds.rb +6 -6
  7. data/lib/archimate/data_model/color.rb +6 -6
  8. data/lib/archimate/data_model/comparison.rb +101 -5
  9. data/lib/archimate/data_model/concern.rb +5 -13
  10. data/lib/archimate/data_model/connection.rb +39 -48
  11. data/lib/archimate/data_model/connector_type.rb +1 -0
  12. data/lib/archimate/data_model/diagram.rb +27 -42
  13. data/lib/archimate/data_model/diagram_type.rb +1 -0
  14. data/lib/archimate/data_model/element.rb +14 -35
  15. data/lib/archimate/data_model/elements.rb +681 -0
  16. data/lib/archimate/data_model/font.rb +8 -8
  17. data/lib/archimate/data_model/lang_string.rb +10 -36
  18. data/lib/archimate/data_model/layer.rb +4 -5
  19. data/lib/archimate/data_model/layers.rb +45 -49
  20. data/lib/archimate/data_model/location.rb +6 -6
  21. data/lib/archimate/data_model/metadata.rb +2 -6
  22. data/lib/archimate/data_model/model.rb +50 -62
  23. data/lib/archimate/data_model/modeling_note.rb +3 -8
  24. data/lib/archimate/data_model/organization.rb +18 -27
  25. data/lib/archimate/data_model/property.rb +9 -8
  26. data/lib/archimate/data_model/property_definition.rb +15 -21
  27. data/lib/archimate/data_model/referenceable.rb +14 -9
  28. data/lib/archimate/data_model/referenceable_list.rb +82 -0
  29. data/lib/archimate/data_model/relationship.rb +41 -152
  30. data/lib/archimate/data_model/relationship_references.rb +29 -0
  31. data/lib/archimate/data_model/relationships.rb +214 -0
  32. data/lib/archimate/data_model/schema_info.rb +6 -12
  33. data/lib/archimate/data_model/style.rb +14 -25
  34. data/lib/archimate/data_model/view_node.rb +38 -66
  35. data/lib/archimate/data_model/viewpoint.rb +23 -38
  36. data/lib/archimate/data_model/viewpoint_type.rb +347 -387
  37. data/lib/archimate/data_model.rb +7 -6
  38. data/lib/archimate/derived_relations.rb +106 -31
  39. data/lib/archimate/export/cypher.rb +0 -18
  40. data/lib/archimate/export/jsonl.rb +16 -45
  41. data/lib/archimate/export/n_quads.rb +1 -24
  42. data/lib/archimate/file_formats/archi_file_reader.rb +2 -1
  43. data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +9 -1
  44. data/lib/archimate/file_formats/sax/archi/archi_handler_factory.rb +2 -2
  45. data/lib/archimate/file_formats/sax/archi/connection.rb +2 -1
  46. data/lib/archimate/file_formats/sax/archi/element.rb +7 -5
  47. data/lib/archimate/file_formats/sax/archi/relationship.rb +1 -1
  48. data/lib/archimate/file_formats/sax/model_exchange_file/connection.rb +2 -1
  49. data/lib/archimate/file_formats/sax/model_exchange_file/element.rb +1 -1
  50. data/lib/archimate/file_formats/sax/model_exchange_file/relationship.rb +1 -1
  51. data/lib/archimate/file_formats/sax/model_exchange_file/view_node.rb +0 -1
  52. data/lib/archimate/file_formats/serializer/archi/relationship.rb +1 -1
  53. data/lib/archimate/lint/duplicate_entities.rb +46 -42
  54. data/lib/archimate/svg/archimate.css +12 -2
  55. data/lib/archimate/svg/entity/base_entity.rb +6 -29
  56. data/lib/archimate/svg/entity/location.rb +1 -0
  57. data/lib/archimate/svg/entity_factory.rb +3 -3
  58. data/lib/archimate/svg/point.rb +3 -3
  59. data/lib/archimate/svg/svg_template.svg.erb +5 -5
  60. data/lib/archimate/version.rb +2 -1
  61. metadata +20 -6
  62. data/TODOs.org +0 -505
  63. data/lib/archimate/data_model/differentiable.rb +0 -142
  64. data/lib/archimate/data_model/element_type.rb +0 -89
  65. data/lib/archimate/data_model/relationship_type.rb +0 -45
data/TODOs.org DELETED
@@ -1,505 +0,0 @@
1
- * ArchiMate Tools TODO
2
-
3
- ** SVG Rendering
4
-
5
- *** DONE skip bendpoints inside source or target
6
- CLOSED: [2017-02-01 Wed 12:41]
7
- *** DONE badges for device, node, service (cosmetic)
8
- CLOSED: [2017-02-01 Wed 12:41]
9
- *** DONE trim space around diagram names (cosmetic)
10
- CLOSED: [2017-02-01 Wed 12:42]
11
- *** DONE badge position updates (cosmetic, legibility)
12
- CLOSED: [2017-02-01 Wed 12:42]
13
- *** DONE badge updates (cosmetic)
14
- CLOSED: [2017-02-01 Wed 12:42]
15
- *** DONE verify junctions
16
- CLOSED: [2017-02-01 Wed 12:42]
17
- *** DONE alternate figures (curved vs box & badge) selected by type="1" on Child (legibility)
18
- CLOSED: [2017-02-01 Wed 12:42]
19
- *** DONE text bounds in entities (cosmetic, legibility)
20
- CLOSED: [2017-02-01 Wed 12:42]
21
- *** DONE badge spacer settings (cosmetic, legibility) - artifact needs work.
22
- CLOSED: [2017-02-01 Wed 12:42]
23
- *** TODO text on lines (cosmetic, legibility)
24
- *** TODO bendpoint curves (cosmetic)
25
- *** TODO line crossing hops (cosmetic)
26
- *** DONE refactor
27
- CLOSED: [2017-02-01 Wed 12:42]
28
-
29
- ** Performance
30
-
31
- *** TODO Look into using Celluloid and/or jruby to improve performance
32
- Thinking about concurrency for performance improvements
33
-
34
- read base
35
- read local
36
- read remote
37
-
38
- base + local -> diff l
39
- base + remote -> diff b
40
-
41
- diff l + diff b -> conflict detection
42
-
43
- cd -> each conflict type
44
-
45
- conflicts -> conflict resolution
46
-
47
- cr (user response)
48
-
49
- serialize result (single)
50
-
51
-
52
- ** Diff/Merge
53
-
54
- *** Conflicts can happen on the same diff 2x. How to handle this?
55
- *** DONE In `Change.to_s` - deref args that point to other elements (like archimate_element)
56
- CLOSED: [2017-02-01 Wed 12:48]
57
- *** In Diagram children diffs - make to_s reference the parent diagram
58
- *** DONE Array diffs on non-id'd diffable elements should detect changes rather than delete/insert
59
- CLOSED: [2017-02-01 Wed 12:48]
60
- *** Archi file could have ids that conflict (i.e. 2 relationships with same id - this is bad!!! Was it a bad merge or something worse)
61
- *** Implement check for de-duplicated merges
62
- *** DONE Add a summary diff - elements added/changed/deleted, diagrams
63
- CLOSED: [2017-02-01 Wed 12:48]
64
-
65
- ** Lint
66
-
67
- *** DONE Basic Lint features (matching Archi)
68
- CLOSED: [2017-02-01 Wed 12:49]
69
- *** TODO Scorecard lint
70
-
71
- ** File Formats & Exports
72
-
73
- *** TODO Convert support for
74
- **** TODO Rdf
75
- **** TODO Gremlin
76
- **** DONE Neo4j CSV
77
- CLOSED: [2017-02-01 Wed 13:04]
78
- **** DONE Cypher
79
- CLOSED: [2017-02-01 Wed 13:04]
80
- **** DONE N-Quad
81
- CLOSED: [2017-02-01 Wed 13:04]
82
- **** DONE GraphML
83
- CLOSED: [2017-02-01 Wed 13:04]
84
-
85
- ** DSL
86
-
87
- *** TODO CLI DSL
88
- *** TODO DSL for relationships
89
- # type from to
90
- "AssociationRelationship", "associated_with", "associated_with"
91
- "AccessRelationship", "accesses", "accessed_by"
92
- "UsedByRelationship", "used_by", "uses"
93
- "RealisationRelationship", "realizes", "realized_by"
94
- "AssignmentRelationship", ""
95
- "AggregationRelationship"
96
- "CompositionRelationship"
97
- "FlowRelationship"
98
- "TriggeringRelationship"
99
- "GroupingRelationship"
100
- "SpecialisationRelationship"
101
- "InfluenceRelationship"
102
-
103
- # attributes that are references to other nodes in the model
104
-
105
- For any of these inserted or changed...
106
-
107
- * Property.key (only after PropertyDefs is introduced)
108
- - Property referenced deleted key
109
- * Child.target_connections -> Array of Connection ids
110
- - Connection.id deleted
111
- * Child.archimate_element -> Element.id
112
- - Element.id deleted
113
- * Folder.items -> Array of IdentifiedNode
114
- - *.id deleted
115
- * Relationship.source -> Element.id
116
- - Element.id deleted
117
- * Relationship.target -> Element.id
118
- - Element.id deleted
119
- * Connection.source -> Child.id
120
- - Child.id deleted
121
- * Connection.target -> Child.id
122
- - Child.id deleted
123
- * Connection.relationship -> Relationship.id
124
- - Relationship.id deleted
125
-
126
-
127
- ** Additional Features
128
-
129
- *** TODO Add Split file feature (extract say a diagram or set of elements)
130
- *** TODO Merge unrelated files (this is the intent of Merger)
131
- *** TODO Add a super strict mode to note when reader finds unexpected content
132
- *** DONE Stats (elements, relationships, diagrams)
133
- CLOSED: [2017-02-01 Wed 12:45]
134
- *** TODO Tool to query for dependencies
135
- *** TODO Tool to assign/validate/enforce metadata
136
-
137
- ** Code Quality/Refactoring
138
-
139
- *** TODO Consider breaking this into a number of gems (for example: base lib, diff/merge, other cmdline tools)
140
- *** TODO Consider making classes for each element and relationship type?
141
- *** DONE Figure out how to make rmagick optional and/or remove rmagick dependency
142
- CLOSED: [2017-02-01 Wed 12:45]
143
- *** TODO Data model items that reference something else by id should have the actual object available - not just the id
144
- *** DONE Convert all CLIs to use AIO - merge with OutputIO and MaybeIO (maybe)
145
- CLOSED: [2017-02-01 Wed 12:45]
146
- *** DONE figure out a better parent mechanism - it's really not fully cooked
147
- CLOSED: [2017-02-01 Wed 12:45]
148
- *** DONE remove parent_id from dry::struct objects - then can use class schema instead of comparison attributes
149
- CLOSED: [2017-02-01 Wed 12:45]
150
- *** TODO Not handling sketch diagram model in archi
151
- *** DONE Use one color method - currently using HighLine and Colorize
152
- CLOSED: [2017-02-01 Wed 12:45]
153
- *** TODO Refactor merge to pull conflict detection out
154
- *** DONE Clean up the way that the describe is done on data model
155
- CLOSED: [2017-02-01 Wed 12:45]
156
- *** DONE Permit model items to link back to their parent
157
- CLOSED: [2017-02-01 Wed 12:45]
158
- *** DONE Should be a master hash index of id to object in Model
159
- CLOSED: [2017-02-01 Wed 12:45]
160
- *** DONE Improve description of diffs for conflict display
161
- CLOSED: [2017-02-01 Wed 12:45]
162
- *** DONE Eliminate use of Document in favor of Model
163
- CLOSED: [2017-02-01 Wed 12:45]
164
- - [X] cli/archi.rb
165
- - [X] cli/cleanup.rb
166
- - [X] cli/convert.rb
167
- - [X] cli/svger.rb
168
- *** TODO Experiment with Ox, Oga, Sax-Machine for better performance on convert
169
- *** TODO Map conversion between archi and archimate diagram formats
170
- *** DONE Write a common clone for dry-struct classes
171
- CLOSED: [2017-02-01 Wed 12:45]
172
- *** DONE Make a format agnostic file reader (which delegates to appropriate file type readers)
173
- CLOSED: [2017-02-01 Wed 12:45]
174
- *** DONE Decide between ox and nokogiri and eliminate the alternate
175
- CLOSED: [2017-02-01 Wed 12:45]
176
- *** DONE See what can be done about performance
177
- CLOSED: [2017-02-01 Wed 12:46]
178
- - Reading file 11-12 secs
179
- - deleted relationships referenced in diagrams is slow
180
- *** DONE Refactor to better OO design where necessary (see all about names below)
181
- CLOSED: [2017-02-01 Wed 12:46]
182
- *** DONE Refactor merge to pull apply diffs out
183
- CLOSED: [2017-02-01 Wed 12:46]
184
- *** TODO Refactor Bendpoint to use a point (rather than Archi start/end points).
185
- *** TODO Refactor DataModel classes to use enumeration classes for appropriate values
186
- *** TODO Add a test to produce SVG output for the "everything.archimate" file
187
- *** TODO Add a test to produce a badges diagram
188
-
189
-
190
- * Refactor of data model for diff/merge purposes
191
-
192
- ** Validation
193
- *** Identifiable objects exist one place in model
194
- ***
195
- ** Join:
196
- - Organizable Id (An Organizable is an Identifiable that can be contained in a Folder
197
- - Folder
198
- - Position in Folder - index isn't good here ... should that position really be a linked list?
199
- * Introduce the idea of archimate modules
200
- - Allow creation of a focused model by including archimate modules - which are self-contained packages of elements and relationships
201
- - Allow inheritance of a module to permit showing changes to an existing model.
202
- ** How to implement?
203
- - Break things down automatically?
204
- - By Layer?
205
- - How to Deal with relationships across module boundaries?
206
- * Need to have model merge capability
207
- * TODO Refactor to use a Decorator approach using SimpleDelegator
208
- * TODO Remove Dry-Types dependency
209
- * TODO Scan git history and inject metadata for concepts created by git author
210
- * Changes for v3 have borked the model
211
- ** TODO Push through fixes focusing on the issues from factories to see if that works
212
- ** TODO Refactor model to eliminate a lot of cruft by removing things like in_model= and populating model with objects instead of ID refs
213
- ** TODO Refactor model to improve the diffing of arrays and by writing explicit diff decorators rather than domain model magic
214
- Both of the last two options risk breaking diffing/merging by making and becoming a long slog
215
-
216
- * TODO In mergetool - show diagrams that reference elements and relationships in diff conflicts
217
-
218
- * Notes
219
-
220
- Generic type - not used directly
221
- ReferenceType <xs:attribute name="ref" type="xs:IDREF
222
-
223
- ElementRefGroup <xs:attribute name="elementRef" type="xs:IDREF
224
- RelationshipRefGroup <xs:attribute name="relationshipRef" type="xs:IDREF
225
- ConceptRefGroup <xs:attribute name="ConceptRef" type="xs:IDREF
226
- PropertyDefinitionRefGroup <xs:attribute name="propertyDefinitionRef" type="xs:IDREF
227
- StereotypeRefGroup <xs:attribute name="stereotypeRef" type="xs:IDREF
228
- PropertyDefinitionRefAttributeGroup <xs:attribute name="propertyDefinitionRef" type="xs:IDREF
229
-
230
- RelationshipType <xs:attribute name="source" type="xs:IDREF
231
- RelationshipType <xs:attribute name="target" type="xs:IDREF
232
-
233
- OrganizationType <xs:attribute name="identifierRef" type="xs:IDREF
234
-
235
-
236
- RelationshipType.source -> ConceptType?
237
- RelationshipType.target -> ConceptType?
238
- ViewType.viewpointRef -> Viewpoint
239
-
240
- Label.conceptRef -> ConceptType
241
- Element (Diagram).elementRef -> ElementType
242
- ConnectionType.source -> ConceptType
243
- ConnectionType.target -> ConceptType
244
- Relationship (Diagram).relationshipRef -> RelationshipType
245
-
246
-
247
- ModelType
248
- PropertyDefinitionType
249
- ConceptType > [RelationshipType > Access, Influence], ElementType > RealElementType, RelationshipConnectorType, CompositeType
250
- ViewType > Diagram
251
-
252
-
253
- ViewConceptType > [ViewNodeType > Label, Container], [ConnectionType > Line, SourcedConnectionType > Relationship > NestingRelationship]
254
- Child is a ViewNodeType
255
-
256
-
257
-
258
- ViewpointType
259
-
260
- * More Notes
261
-
262
- background_class -> used by entity_shape
263
- badge -> entity_badge -> to_svg
264
- entity_shape
265
-
266
-
267
- text_bounds (I think this is only set in entity_shape)
268
- DiagramModelReference assigns the entity from the child.model_element
269
- badge_bounds in Gap, MotivationEntity, RectEntity, RoundedRectEntity
270
- text_align in Note
271
-
272
- some shapes are dependent on child.child_type
273
-
274
- badge should be controlled by the entity_shape method
275
- check that badge_bounds is set by shape (I think it is)
276
-
277
- text_bounds is controlled by entity_shape
278
-
279
- background_class : string (default: layer_background_class)
280
- badge : string option
281
- entity_shape : (child -> element_name_type -> bounds -> Svg.elt wrap)
282
- effective_entity : (child -> element_name_type)
283
-
284
- get effective entity
285
-
286
- that's used to match the rest:
287
-
288
- Intermittent Failure with test --seed 11297
289
-
290
- ---
291
-
292
- Remove Id references in preference to object references
293
-
294
- Done:
295
-
296
- Property (PropertyDefinitionId)
297
-
298
- TODO:
299
-
300
- Relationship (Source & Target)
301
- View (Viewpoint)
302
-
303
- Connection (For Source & Targets)
304
- Label (Not Currently Used)
305
- ViewConcept (View {Concept} list)
306
- ViewNode (model, targetConnections, archimateNode)
307
-
308
- ---
309
-
310
- Part of Better Diff/Merge redux
311
-
312
- What about the path? Need a way to describe diffs & conflicts back to meaningful user world terms. (not id oriented)
313
-
314
- Eliminate the use of DiffableArray by making a class for collections
315
- Eliminate the use of Diffable Primitive with a smarter context diff
316
-
317
- Referenceable Object Instance Classes
318
-
319
- Archimate::DataModel::Model < Archimate::DataModel::NamedReferenceable
320
- Archimate::DataModel::PropertyDefinition < Archimate::DataModel::NamedReferenceable,
321
- Archimate::DataModel::Element < Archimate::DataModel::Concept,
322
- Archimate::DataModel::Relationship < Archimate::DataModel::Concept,
323
- Archimate::DataModel::Diagram < Archimate::DataModel::View,
324
- Archimate::DataModel::ViewNode < Archimate::DataModel::Referenceable,
325
- Archimate::DataModel::Connection < Archimate::DataModel::Referenceable,
326
-
327
- What are the non-referenceable things that might be included by a less automated diff?
328
-
329
- Model
330
- (from Referenceable)
331
- id
332
- name
333
- documentation: Array of LangString - really should be a LangString type (I believe)
334
- type: String - TODO: need to handle US/UK spelling differences and naming differences between Archi/ArchiMate2.1/ArchiMate3
335
- properties
336
- metadata
337
- elements
338
- relationships
339
- organizations
340
- property_definitions
341
- version
342
- diagrams
343
- viewpoints
344
- filename
345
- file_format
346
- archimate_version
347
- namespaces
348
- schema_locations
349
-
350
- PropertyDefinition
351
- (from Referenceable)
352
- id
353
- name
354
- documentation: Array of LangString - really should be a LangString type (I believe)
355
- type: String
356
- (from PropertyDefinition)
357
- value_type (DataType)
358
-
359
- Element
360
- (from Referenceable)
361
- id
362
- name
363
- documentation: Array of LangString - really should be a LangString type (I believe)
364
- type: String
365
- properties (from Concept)
366
-
367
- Relationship
368
- (from Referenceable)
369
- id
370
- name
371
- documentation: Array of LangString - really should be a LangString type (I believe)
372
- type: String
373
- source
374
- target
375
- access_type
376
-
377
- Diagram
378
- (from Referenceable)
379
- id
380
- name
381
- documentation: Array of LangString - really should be a LangString type (I believe)
382
- type: String
383
- (from View)
384
- properties
385
- viewpoint_type
386
- viewpoint
387
- (from Diagram)
388
- nodes (ViewNode collection)
389
- connection_router_type (int - enum, Archi only)
390
- background (int Archi only)
391
- connections (Connection Collection)
392
-
393
- ViewNode
394
- (from Referenceable)
395
- id
396
- name
397
- documentation: Array of LangString - really should be a LangString type (I believe)
398
- type: String
399
- model: (identifier - what is this? Archi Only)
400
- content: string
401
- target_connections: (Archi only, identifiers, collection of ids of targets, TODO, probably not needed)
402
- archimate_element (Element)
403
- bounds
404
- nodes: (ViewNode collection)
405
- connections (Connection collection)
406
- style
407
- type
408
- child_type: (TODO: int this selects the shape of the object)
409
- properties
410
-
411
- There are some sub-classes here that might be valuable to implement?
412
- Connection
413
- (from Referenceable)
414
- id
415
- name
416
- documentation: Array of LangString - really should be a LangString type (I believe)
417
- type: String
418
- source_attachment (Location)
419
- bendpoints
420
- target_attachment (Location)
421
- source
422
- target
423
- relationship
424
- style
425
- properties
426
-
427
- What about Organizations - they are horrifically defined in ArchiMate 3. Need an internal model that isn't so insane and is diffable/mergable.
428
-
429
- ---
430
-
431
- Diff implementation
432
-
433
- The refinements implementation is hokey. A lot of code and makes thing fragile.
434
-
435
- Diff calculation
436
-
437
- In most collections (except ones under diagram), the order of items doesn't matter - except it helps make textual diffs of models smaller.
438
-
439
- insert and delete are probably only useful for collections
440
-
441
- change is typical
442
-
443
- how would move be implemented (i.e. move between collections)
444
- What's the best data structure for collections to make diffs and merges easier? Diff lcs?
445
-
446
- validation on demand rather than at creation of data model in absence of dry-struct? Switchable by global setting?
447
-
448
- How would we add archimate modules (new concept)? privacy? Timeline? Transitional architectures?
449
-
450
- ---
451
-
452
- Diff
453
-
454
- - [ ] User friendly text description
455
- - [ ] User friendly description includes location information in the model (I.e diagram it's located in, elements describing relationship, and so on)
456
- - [ ] Diffs can be compared to see if they are in conflict
457
- - [ ] Diff can be applied to a model to patch model
458
-
459
- * TODO Eliminate Documentation class - it's a LangString
460
- * TODO Make LangString be like a Hash with lang as key and string as value
461
- * TODO Make LangString use a default lang (stored in Archimate module)
462
-
463
- ---
464
-
465
- Strict::Array.member(AnyAttribute).default([])
466
- Strict::Array.member(AnyElement).default([])
467
- Strict::Array.member(Concern).default([])
468
- Strict::Array.member(Connection).default([])
469
- Strict::Array.member(Diagram).default([])
470
- Strict::Array.member(Element).default([])
471
- Strict::Array.member(ElementType).default([])
472
- Strict::Array.member(LangString)
473
- Strict::Array.member(Location).default([])
474
- Strict::Array.member(ModelingNote).default([])
475
- Strict::Array.member(Organization).default([])
476
- Strict::Array.member(Property).default([])
477
- Strict::Array.member(PropertyDefinition).default([])
478
- Strict::Array.member(Referenceable).default([])
479
- Strict::Array.member(Relationship).default([])
480
- Strict::Array.member(RelationshipType).default([])
481
- Strict::Array.member(SchemaInfo).default([])
482
- Strict::Array.member(Strict::String).default([])
483
- Strict::Array.member(ViewNode).default([])
484
- Strict::Array.member(Viewpoint).default([])
485
- Strict::Array.member(ViewpointContentEnum).default([])
486
- Strict::Array.member(ViewpointPurposeEnum).default([])
487
-
488
- ---
489
-
490
- Use locale for LangString
491
- IRB::Locale.new.lang
492
-
493
- ---
494
-
495
- referenced_identified_nodes
496
- Model->
497
-
498
- Diagram
499
- ViewNode
500
- Container
501
- Connection
502
- Element (Property->PropertyDefinition)
503
- Organization
504
- Relationship
505
-
@@ -1,142 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Archimate
4
- module DataModel
5
- # Let's talk about diff...
6
- #
7
- # Here are my expectations of diff:
8
- #
9
- # = Preconditions:
10
- #
11
- # 1. self is non-nil
12
- # 2. self is a class that includes Comparison
13
- #
14
- # = Requirements for other
15
- #
16
- # Not matching one of these is a programming error.
17
- #
18
- # 1. Other is nil
19
- # 2. Other is an instance of the same class as self
20
- #
21
- # = Diff results
22
- #
23
- # * Diffing results in a list of Diff instances between +self+ and +other+
24
- # * Patching the list of diffs against self results in an instance that == +other+
25
- #
26
- # = Diff Container
27
- #
28
- # A diff container is a top level entity that is meaningful in the user domain
29
- # for example: [Element], [Relationship], [Diagram]. It collects and groups
30
- # the smaller diffs into the things that changed by an entity tha makes sense
31
- # to the user.
32
- #
33
- # = Diff structure
34
- #
35
- # A diff contains a change to be applied in a particular context.
36
- #
37
- # Use cases:
38
- #
39
- # 1. Delete a value that is a member of this class. Example: Delete the
40
- # +a+ member of a [Color] instance.
41
- # 2. A non-reference value replacing a value in a class. Example:
42
- # Changing the +r+ value of a [Color] with a different value.
43
- # 3. Updating the value of an attribute of a child. (or child's child)
44
- # 4. Deleting the value of an attribute of a child. (or child's child)
45
- # 5. For Array attributes with non-referenceable contents
46
- # 1. Deleting a value from an array attribute
47
- # 2. Inserting a value into an array attribute
48
- # 3. Changing a value in an array attribute
49
- # 6. For Array attributes with referenceable contents
50
- # 1. Deleting a value from an array attribute (has an implication on
51
- # if the entity is deleted from the model entirely)
52
- # 2. Inserting a value into an array attribute (may need addtion to the
53
- # model)
54
- # 3. Changing a value in an array attribute (changing the entity id may
55
- # require the implications of deletion and insertion as above)
56
- #
57
- # When to stop?
58
- #
59
- # When digging down into a diff operation, there are some natural stopping
60
- # points:
61
- #
62
- # 1. When there is no more depth to dig
63
- # 2. When the objects being compared are references to other entities, but
64
- # do not belong to the current object being diffed.
65
- # 3. When the object being diffed is a Diff container unto itself. For
66
- # example: When diffing a model, the diff should include the order
67
- # of elements referenced in the +elements+ attribute, but shouldn't
68
- # continue with the diff of each element itself.
69
- #
70
- # = Complications
71
- #
72
- # == Object references
73
- #
74
- # Since a patch operation produces an new replacement object, object
75
- # references need to be handled. For example, given an +Element+ with +id=3+
76
- # if a patch changes this +Element+'s name, then the +Element+ in
77
- # the model under +Model#elements+ is replaced with a different instance,
78
- # but a +Relationship+ that references the +Element+ is still pointing at
79
- # a different instance and needs to be updated.
80
- Insert = Struct.new(:path, :value)
81
- Delete = Struct.new(:path)
82
- Change = Struct.new(:path, :from, :to)
83
-
84
- module Differentiable
85
- # Computes the diffs between this object and another object of the same type
86
- #
87
- # @param other [self.class] another object to compare
88
- # @return [Array<Diff::Difference>]
89
- # @raise
90
- def diff(other)
91
- return [] if other.nil?
92
- raise TypeError, "Expected other <#{other.class} to be of type #{self.class}" unless other.is_a?(self.class)
93
-
94
- self.class.attr_names.each_with_object([]) do |k, a|
95
- val = send(k)
96
- case val
97
- when NilClass
98
- a << Insert.new(k, other[k]) unless other[k].nil?
99
- when Integer, Float, Hash, String, Symbol
100
- a.concat(Differentiable.diff_primitive(val, other[k], self, other, k))
101
- when Differentiable
102
- a.concat(val.diff(other[k]))
103
- else
104
- raise "Unexpected Type for Diff don't know how to diff a #{val.class}"
105
- end
106
- end
107
- end
108
-
109
- def patch(diffs)
110
- ary = diffs.is_a?(Array) ? diffs : [diffs]
111
- self.class.new(
112
- ary.each_with_object(to_h) do |diff, args|
113
- case diff
114
- when Delete
115
- args[diff.path] = nil
116
- when Insert
117
- args[diff.path] = diff.value
118
- when Change
119
- args[diff.path] = diff.to
120
- else
121
- raise "Unexpected diff type #{diff.class} #{diff.inspect}"
122
- end
123
- end
124
- )
125
- end
126
-
127
- private
128
-
129
- def self.diff_primitive(val, other, from_parent, to_parent, attribute, from_attribute = nil)
130
- from_attribute = attribute if from_attribute.nil?
131
- if other.nil?
132
- return [Delete.new(attribute)]
133
- end
134
- raise TypeError, "Expected other #{other.class} to be of type #{val.class}" unless other.is_a?(val.class)
135
- unless val == other
136
- return [Change.new(attribute, val, other)]
137
- end
138
- []
139
- end
140
- end
141
- end
142
- end