archimate 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +47 -0
  3. data/TODOs.org +219 -0
  4. data/archimate.gemspec +2 -1
  5. data/exe/archidiff +7 -0
  6. data/exe/archidiff-summary +7 -0
  7. data/exe/archimerge +7 -0
  8. data/exe/fmtxml +7 -0
  9. data/lib/archimate.rb +10 -21
  10. data/lib/archimate/cli/archi.rb +2 -1
  11. data/lib/archimate/cli/cleanup.rb +8 -9
  12. data/lib/archimate/cli/convert.rb +3 -1
  13. data/lib/archimate/cli/mapper.rb +1 -1
  14. data/lib/archimate/cli/stats.rb +1 -1
  15. data/lib/archimate/config.rb +4 -1
  16. data/lib/archimate/data_model.rb +11 -24
  17. data/lib/archimate/data_model/any_attribute.rb +18 -5
  18. data/lib/archimate/data_model/any_element.rb +30 -7
  19. data/lib/archimate/data_model/bounds.rb +34 -7
  20. data/lib/archimate/data_model/color.rb +32 -7
  21. data/lib/archimate/data_model/comparison.rb +87 -0
  22. data/lib/archimate/data_model/concern.rb +20 -7
  23. data/lib/archimate/data_model/connection.rb +71 -51
  24. data/lib/archimate/data_model/connector_type.rb +23 -0
  25. data/lib/archimate/data_model/diagram.rb +72 -10
  26. data/lib/archimate/data_model/diagram_type.rb +17 -0
  27. data/lib/archimate/data_model/differentiable.rb +142 -0
  28. data/lib/archimate/data_model/element.rb +39 -45
  29. data/lib/archimate/data_model/element_type.rb +89 -0
  30. data/lib/archimate/data_model/font.rb +30 -12
  31. data/lib/archimate/data_model/lang_string.rb +89 -16
  32. data/lib/archimate/data_model/layer.rb +55 -0
  33. data/lib/archimate/data_model/layers.rb +62 -0
  34. data/lib/archimate/data_model/location.rb +27 -11
  35. data/lib/archimate/data_model/metadata.rb +10 -3
  36. data/lib/archimate/data_model/model.rb +188 -121
  37. data/lib/archimate/data_model/modeling_note.rb +14 -3
  38. data/lib/archimate/data_model/organization.rb +44 -13
  39. data/lib/archimate/data_model/{documentation.rb → preserved_lang_string.rb} +1 -5
  40. data/lib/archimate/data_model/property.rb +17 -11
  41. data/lib/archimate/data_model/property_definition.rb +34 -4
  42. data/lib/archimate/data_model/referenceable.rb +0 -9
  43. data/lib/archimate/data_model/referenceable_collection.rb +201 -0
  44. data/lib/archimate/data_model/relationship.rb +52 -33
  45. data/lib/archimate/data_model/relationship_type.rb +43 -0
  46. data/lib/archimate/data_model/schema_info.rb +17 -6
  47. data/lib/archimate/data_model/style.rb +41 -11
  48. data/lib/archimate/data_model/view_node.rb +153 -59
  49. data/lib/archimate/data_model/viewpoint.rb +56 -80
  50. data/lib/archimate/data_model/viewpoint_type.rb +429 -0
  51. data/lib/archimate/export/csv_export.rb +2 -2
  52. data/lib/archimate/export/cypher.rb +2 -2
  53. data/lib/archimate/export/graph_ml.rb +7 -5
  54. data/lib/archimate/export/jsonl.rb +166 -0
  55. data/lib/archimate/export/n_quads.rb +8 -5
  56. data/lib/archimate/file_format.rb +4 -5
  57. data/lib/archimate/file_formats/archi_file_reader.rb +7 -240
  58. data/lib/archimate/file_formats/archi_file_writer.rb +16 -188
  59. data/lib/archimate/file_formats/model_exchange_file_reader.rb +7 -225
  60. data/lib/archimate/file_formats/model_exchange_file_writer_21.rb +22 -114
  61. data/lib/archimate/file_formats/model_exchange_file_writer_30.rb +22 -122
  62. data/lib/archimate/file_formats/sax.rb +55 -0
  63. data/lib/archimate/file_formats/sax/any_element.rb +64 -0
  64. data/lib/archimate/file_formats/sax/archi/archi_handler_factory.rb +48 -0
  65. data/lib/archimate/file_formats/sax/archi/bounds.rb +25 -0
  66. data/lib/archimate/file_formats/sax/archi/connection.rb +47 -0
  67. data/lib/archimate/file_formats/sax/archi/content.rb +28 -0
  68. data/lib/archimate/file_formats/sax/archi/diagram.rb +66 -0
  69. data/lib/archimate/file_formats/sax/archi/element.rb +36 -0
  70. data/lib/archimate/file_formats/sax/archi/location.rb +25 -0
  71. data/lib/archimate/file_formats/sax/archi/model.rb +109 -0
  72. data/lib/archimate/file_formats/sax/archi/organization.rb +60 -0
  73. data/lib/archimate/file_formats/sax/archi/property.rb +54 -0
  74. data/lib/archimate/file_formats/sax/archi/relationship.rb +50 -0
  75. data/lib/archimate/file_formats/sax/archi/style.rb +35 -0
  76. data/lib/archimate/file_formats/sax/archi/view_node.rb +76 -0
  77. data/lib/archimate/file_formats/sax/capture_content.rb +20 -0
  78. data/lib/archimate/file_formats/sax/capture_documentation.rb +19 -0
  79. data/lib/archimate/file_formats/sax/capture_properties.rb +20 -0
  80. data/lib/archimate/file_formats/sax/content_element.rb +19 -0
  81. data/lib/archimate/file_formats/sax/document.rb +80 -0
  82. data/lib/archimate/file_formats/sax/handler.rb +54 -0
  83. data/lib/archimate/file_formats/sax/lang_string.rb +28 -0
  84. data/lib/archimate/file_formats/sax/model_exchange_file/color.rb +36 -0
  85. data/lib/archimate/file_formats/sax/model_exchange_file/connection.rb +67 -0
  86. data/lib/archimate/file_formats/sax/model_exchange_file/diagram.rb +60 -0
  87. data/lib/archimate/file_formats/sax/model_exchange_file/element.rb +43 -0
  88. data/lib/archimate/file_formats/sax/model_exchange_file/font.rb +44 -0
  89. data/lib/archimate/file_formats/sax/model_exchange_file/item.rb +64 -0
  90. data/lib/archimate/file_formats/sax/model_exchange_file/location.rb +23 -0
  91. data/lib/archimate/file_formats/sax/model_exchange_file/metadata.rb +66 -0
  92. data/lib/archimate/file_formats/sax/model_exchange_file/model.rb +124 -0
  93. data/lib/archimate/file_formats/sax/model_exchange_file/model_exchange_handler_factory.rb +53 -0
  94. data/lib/archimate/file_formats/sax/model_exchange_file/property.rb +32 -0
  95. data/lib/archimate/file_formats/sax/model_exchange_file/property_definition.rb +36 -0
  96. data/lib/archimate/file_formats/sax/model_exchange_file/relationship.rb +49 -0
  97. data/lib/archimate/file_formats/sax/model_exchange_file/schema_info.rb +47 -0
  98. data/lib/archimate/file_formats/sax/model_exchange_file/style.rb +66 -0
  99. data/lib/archimate/file_formats/sax/model_exchange_file/view_node.rb +86 -0
  100. data/lib/archimate/file_formats/sax/no_op.rb +17 -0
  101. data/lib/archimate/file_formats/sax/preserved_lang_string.rb +28 -0
  102. data/lib/archimate/file_formats/serializer.rb +57 -0
  103. data/lib/archimate/file_formats/serializer/archi/bounds.rb +23 -0
  104. data/lib/archimate/file_formats/serializer/archi/connection.rb +33 -0
  105. data/lib/archimate/file_formats/serializer/archi/diagram.rb +28 -0
  106. data/lib/archimate/file_formats/serializer/archi/documentation.rb +16 -0
  107. data/lib/archimate/file_formats/serializer/archi/element.rb +24 -0
  108. data/lib/archimate/file_formats/serializer/archi/location.rb +26 -0
  109. data/lib/archimate/file_formats/serializer/archi/model.rb +25 -0
  110. data/lib/archimate/file_formats/serializer/archi/organization.rb +21 -0
  111. data/lib/archimate/file_formats/serializer/archi/property.rb +15 -0
  112. data/lib/archimate/file_formats/serializer/archi/relationship.rb +36 -0
  113. data/lib/archimate/file_formats/serializer/archi/view_node.rb +52 -0
  114. data/lib/archimate/file_formats/serializer/archi/viewpoint_type.rb +45 -0
  115. data/lib/archimate/file_formats/serializer/model_exchange_file/element.rb +25 -0
  116. data/lib/archimate/file_formats/serializer/model_exchange_file/location.rb +15 -0
  117. data/lib/archimate/file_formats/serializer/model_exchange_file/model_exchange_file_writer.rb +32 -0
  118. data/lib/archimate/file_formats/serializer/model_exchange_file/organization.rb +23 -0
  119. data/lib/archimate/file_formats/serializer/model_exchange_file/properties.rb +15 -0
  120. data/lib/archimate/file_formats/serializer/model_exchange_file/relationship.rb +19 -0
  121. data/lib/archimate/file_formats/serializer/model_exchange_file/style.rb +48 -0
  122. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/connection.rb +25 -0
  123. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/diagram.rb +27 -0
  124. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/item.rb +17 -0
  125. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/label.rb +17 -0
  126. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/model.rb +36 -0
  127. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/organization_body.rb +25 -0
  128. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/property.rb +19 -0
  129. data/lib/archimate/file_formats/serializer/model_exchange_file/v21/view_node.rb +44 -0
  130. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/connection.rb +26 -0
  131. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/diagram.rb +27 -0
  132. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/item.rb +17 -0
  133. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/label.rb +17 -0
  134. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/model.rb +41 -0
  135. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/organization_body.rb +25 -0
  136. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/property.rb +19 -0
  137. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/property_definitions.rb +34 -0
  138. data/lib/archimate/file_formats/serializer/model_exchange_file/v30/view_node.rb +45 -0
  139. data/lib/archimate/file_formats/serializer/named_collection.rb +21 -0
  140. data/lib/archimate/file_formats/serializer/writer.rb +56 -0
  141. data/lib/archimate/file_formats/serializer/xml_lang_string.rb +30 -0
  142. data/lib/archimate/file_formats/serializer/xml_metadata.rb +64 -0
  143. data/lib/archimate/file_formats/{model_exchange_file → serializer}/xml_property_defs.rb +2 -2
  144. data/lib/archimate/lint/duplicate_entities.rb +3 -3
  145. data/lib/archimate/lint/linter.rb +24 -29
  146. data/lib/archimate/svg/connection.rb +13 -103
  147. data/lib/archimate/svg/diagram.rb +1 -1
  148. data/lib/archimate/svg/entity/base_entity.rb +12 -8
  149. data/lib/archimate/svg/entity/data_entity.rb +2 -2
  150. data/lib/archimate/svg/entity/diagram_model_reference.rb +1 -1
  151. data/lib/archimate/svg/entity/event_entity.rb +2 -2
  152. data/lib/archimate/svg/entity/gap.rb +1 -1
  153. data/lib/archimate/svg/entity/group.rb +1 -1
  154. data/lib/archimate/svg/entity/motivation_entity.rb +1 -1
  155. data/lib/archimate/svg/entity/node.rb +1 -1
  156. data/lib/archimate/svg/entity/rect_entity.rb +1 -1
  157. data/lib/archimate/svg/entity/rounded_rect_entity.rb +1 -1
  158. data/lib/archimate/svg/entity/service_entity.rb +2 -2
  159. data/lib/archimate/svg/entity/value.rb +2 -2
  160. data/lib/archimate/svg/path.rb +153 -0
  161. data/lib/archimate/svg/point.rb +8 -1
  162. data/lib/archimate/version.rb +1 -1
  163. metadata +118 -36
  164. data/lib/archimate/data_model/archimate_node.rb +0 -181
  165. data/lib/archimate/data_model/concept.rb +0 -14
  166. data/lib/archimate/data_model/constants.rb +0 -82
  167. data/lib/archimate/data_model/container.rb +0 -17
  168. data/lib/archimate/data_model/diffable_array.rb +0 -213
  169. data/lib/archimate/data_model/diffable_primitive.rb +0 -83
  170. data/lib/archimate/data_model/label.rb +0 -19
  171. data/lib/archimate/data_model/named_referenceable.rb +0 -14
  172. data/lib/archimate/data_model/view.rb +0 -12
  173. data/lib/archimate/data_model/view_concept.rb +0 -18
  174. data/lib/archimate/file_formats/archi_file_format.rb +0 -151
  175. data/lib/archimate/file_formats/archimate_v2.rb +0 -461
  176. data/lib/archimate/file_formats/model_exchange_file/xml_lang_string.rb +0 -35
  177. data/lib/archimate/file_formats/model_exchange_file/xml_metadata.rb +0 -115
  178. data/lib/archimate/file_formats/model_exchange_file/xml_property_definitions.rb +0 -28
  179. data/lib/archimate/file_formats/model_exchange_file_reader_21.rb +0 -73
  180. data/lib/archimate/file_formats/model_exchange_file_reader_30.rb +0 -134
  181. data/lib/archimate/file_formats/model_exchange_file_writer.rb +0 -157
  182. data/lib/archimate/file_formats/writer.rb +0 -56
@@ -5,7 +5,7 @@ module Archimate
5
5
  class Convert
6
6
  include Archimate::Logging
7
7
 
8
- SUPPORTED_FORMATS = %w[meff2.1 meff3.0 archi nquads graphml csv cypher].freeze
8
+ SUPPORTED_FORMATS = %w[meff2.1 meff3.0 archi nquads graphml csv cypher jsonl].freeze
9
9
 
10
10
  attr_reader :model
11
11
 
@@ -30,6 +30,8 @@ module Archimate
30
30
  Archimate::Export::CSVExport.new(model).to_csv(output_dir: output_dir)
31
31
  when "cypher"
32
32
  Archimate::Export::Cypher.new(output_io).to_cypher(model)
33
+ when "jsonl"
34
+ Archimate::Export::Jsonl.new(output_io).to_jsonl(model)
33
35
  else
34
36
  error { "Export to '#{export_format}' is not supported yet." }
35
37
  end
@@ -28,7 +28,7 @@ module Archimate
28
28
  when "archimate:SketchModel"
29
29
  "Sketch"
30
30
  when "archimate:ArchimateDiagramModel"
31
- DataModel::Constants::VIEWPOINTS[(row[2] || 0).to_i]
31
+ DataModel::ViewpointType.values[(row[2] || 0).to_i].to_s
32
32
  else
33
33
  row[3]
34
34
  end
@@ -28,7 +28,7 @@ module Archimate
28
28
  end
29
29
 
30
30
  def title_width
31
- @title_width ||= (elements_by_layer.keys + ["Total Elements"]).map(&:size).max
31
+ @title_width ||= (elements_by_layer.keys + ["Total Elements"]).map(&:to_s).map(&:size).max
32
32
  end
33
33
 
34
34
  def row(title, size, color)
@@ -3,6 +3,7 @@
3
3
  require "logger"
4
4
  require "singleton"
5
5
  require "observer"
6
+ require "irb"
6
7
 
7
8
  module Archimate
8
9
  # This is the singleton class that contains application configuration.
@@ -12,10 +13,12 @@ module Archimate
12
13
 
13
14
  attr_reader :interactive
14
15
  attr_reader :logger
16
+ attr_reader :default_lang
15
17
 
16
18
  def initialize
17
19
  @interactive = true
18
- @logger ||= Logger.new(STDERR, progname: "archimate")
20
+ @logger = Logger.new(STDERR, progname: "archimate")
21
+ @default_lang = IRB::Locale.new.lang
19
22
  end
20
23
 
21
24
  def interactive=(interactive)
@@ -2,53 +2,40 @@
2
2
 
3
3
  module Archimate
4
4
  module DataModel
5
- include Dry::Types.module
6
-
7
- Coercible = Archimate::DataModel::Coercible
8
- Strict = Archimate::DataModel::Strict
9
-
10
- # Identifiers in the ArchiMate exchange format standard are of
11
- Identifier = Strict::String # .constrained(format: /[[[:alpha:]]_][\w\-\.]*/)
12
-
13
- # An enumeration of data types.
14
- DataType = Strict::String.default("string").enum("string", "boolean", "currency", "date", "time", "number")
15
-
16
5
  # Enumeration of Influence Strength types. These are suggestions.
17
- InfluenceStrengthEnum = Strict::String.enum(%w[+ ++ - -- 0 1 2 3 4 5 6 7 8 9 10])
6
+ # InfluenceStrengthEnum = String # Strict::String.enum(%w[+ ++ - -- 0 1 2 3 4 5 6 7 8 9 10])
18
7
 
19
- require 'archimate/data_model/diffable_primitive'
20
- require 'archimate/data_model/diffable_array'
21
- require 'archimate/data_model/constants'
22
- require 'archimate/data_model/archimate_node'
8
+ require 'archimate/data_model/connector_type'
9
+ require 'archimate/data_model/diagram_type'
10
+ require 'archimate/data_model/element_type'
11
+ require 'archimate/data_model/relationship_type'
12
+ require 'archimate/data_model/comparison'
13
+ require 'archimate/data_model/differentiable'
14
+ require 'archimate/data_model/layer'
15
+ require 'archimate/data_model/layers'
16
+ require 'archimate/data_model/viewpoint_type'
23
17
  require 'archimate/data_model/any_attribute'
24
18
  require 'archimate/data_model/any_element'
25
19
  require 'archimate/data_model/lang_string'
20
+ require 'archimate/data_model/preserved_lang_string'
26
21
  require 'archimate/data_model/schema_info'
27
22
  require 'archimate/data_model/metadata'
28
23
  require 'archimate/data_model/color'
29
24
  require 'archimate/data_model/font'
30
25
  require 'archimate/data_model/style'
31
26
  require 'archimate/data_model/bounds'
32
- require 'archimate/data_model/documentation'
33
27
  require 'archimate/data_model/modeling_note'
34
- require 'archimate/data_model/referenceable'
35
- require 'archimate/data_model/named_referenceable'
36
28
  require 'archimate/data_model/property_definition'
37
29
  require 'archimate/data_model/property'
38
- require 'archimate/data_model/concept'
39
30
  require 'archimate/data_model/organization'
40
31
  require 'archimate/data_model/element'
41
32
  require 'archimate/data_model/relationship'
42
33
  require 'archimate/data_model/concern'
43
34
  require 'archimate/data_model/viewpoint'
44
- require 'archimate/data_model/view'
45
- require 'archimate/data_model/view_concept'
46
35
  require 'archimate/data_model/location'
47
36
  require 'archimate/data_model/connection'
48
37
  require 'archimate/data_model/view_node'
49
- require 'archimate/data_model/container'
50
38
  require 'archimate/data_model/diagram'
51
- require 'archimate/data_model/label'
52
39
  require 'archimate/data_model/model'
53
40
  end
54
41
  end
@@ -3,11 +3,24 @@
3
3
  module Archimate
4
4
  module DataModel
5
5
  # An instance of any XML attribute for arbitrary content like metadata
6
- class AnyAttribute < ArchimateNode
7
- attribute :attribute, Strict::String
8
- attribute :prefix, Strict::String
9
- attribute :value, Strict::String
6
+ class AnyAttribute
7
+ include Comparison
8
+
9
+ # @!attribute [r] attribute
10
+ # @return [String]
11
+ model_attr :attribute
12
+ # @!attribute [r] prefix
13
+ # @return [String]
14
+ model_attr :prefix
15
+ # @!attribute [r] value
16
+ # @return [String]
17
+ model_attr :value
18
+
19
+ def initialize(attribute, value, prefix: "")
20
+ @attribute = attribute
21
+ @prefix = prefix
22
+ @value = value
23
+ end
10
24
  end
11
- Dry::Types.register_class(AnyAttribute)
12
25
  end
13
26
  end
@@ -3,13 +3,36 @@
3
3
  module Archimate
4
4
  module DataModel
5
5
  # An instance of any XML element for arbitrary content like metadata
6
- class AnyElement < ArchimateNode
7
- attribute :element, Strict::String
8
- attribute :prefix, Strict::String.optional
9
- attribute :attributes, Strict::Array.member(AnyAttribute).default([])
10
- attribute :content, Strict::String.optional
11
- attribute :children, Strict::Array.member(AnyElement).default([])
6
+ class AnyElement
7
+ include Comparison
8
+
9
+ # @!attribute [r] element
10
+ # @return [String]
11
+ model_attr :element
12
+ # @!attribute [r] prefix
13
+ # @return [String, NilClass]
14
+ model_attr :prefix
15
+ # @!attribute [r] attributes
16
+ # @return [Array<AnyAttribute>]
17
+ model_attr :attributes
18
+ # @!attribute [r] content
19
+ # @return [String, NilClass]
20
+ model_attr :content
21
+ # @!attribute [r] children
22
+ # @return [Array<AnyElement>]
23
+ model_attr :children
24
+
25
+ def initialize(element:, prefix: "", attributes: [], content: nil, children: [])
26
+ @element = element
27
+ @prefix = prefix
28
+ @attributes = attributes
29
+ @content = content
30
+ @children = children
31
+ end
32
+
33
+ def to_sym
34
+ element&.to_sym
35
+ end
12
36
  end
13
- Dry::Types.register_class(AnyElement)
14
37
  end
15
38
  end
@@ -1,16 +1,36 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Archimate
3
4
  module DataModel
4
- class Bounds < ArchimateNode
5
- attribute :x, Coercible::Float.optional
6
- attribute :y, Coercible::Float.optional
7
- attribute :width, Coercible::Float
8
- attribute :height, Coercible::Float
5
+ class Bounds
6
+ include Comparison
7
+
8
+ # @!attribute [r] x
9
+ # @return [Float, NilClass]
10
+ model_attr :x
11
+ # @!attribute [r] y
12
+ # @return [Float, NilClass]
13
+ model_attr :y
14
+ # @!attribute [r] width
15
+ # @return [Float]
16
+ model_attr :width
17
+ # @!attribute [r] height
18
+ # @return [Float]
19
+ model_attr :height
9
20
 
10
21
  def self.zero
11
22
  Archimate::DataModel::Bounds.new(x: 0, y: 0, width: 0, height: 0)
12
23
  end
13
24
 
25
+ def initialize(x: nil, y: nil, width:, height:)
26
+ raise "Width expected" unless width
27
+ raise "Height expected" unless height
28
+ @x = x.nil? ? nil : x.to_f
29
+ @y = y.nil? ? nil : y.to_f
30
+ @width = width.to_f
31
+ @height = height.to_f
32
+ end
33
+
14
34
  def to_s
15
35
  "Bounds(x: #{x}, y: #{y}, width: #{width}, height: #{height})"
16
36
  end
@@ -39,6 +59,15 @@ module Archimate
39
59
  x || 0
40
60
  end
41
61
 
62
+ def center
63
+ DataModel::Bounds.new(
64
+ x: left + width / 2.0,
65
+ y: top + height / 2.0,
66
+ width: 0,
67
+ height: 0
68
+ )
69
+ end
70
+
42
71
  def is_above?(other)
43
72
  bottom < other.top
44
73
  end
@@ -66,7 +95,5 @@ module Archimate
66
95
  bottom < other.bottom
67
96
  end
68
97
  end
69
-
70
- Dry::Types.register_class(Bounds)
71
98
  end
72
99
  end
@@ -1,16 +1,30 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Archimate
3
4
  module DataModel
4
5
  # RGBColorType in the XSD
5
6
  # RGB Color type.
6
7
  # The r, g, b attributes range from 0 - 255.
7
8
  # The a (alpha) transparency attribute is optional. 0 = full transparency, 100 = opaque.
8
- class Color < ArchimateNode
9
- attribute :r, Coercible::Int.constrained(lt: 256, gt: -1)
10
- attribute :g, Coercible::Int.constrained(lt: 256, gt: -1)
11
- attribute :b, Coercible::Int.constrained(lt: 256, gt: -1)
12
- attribute :a, Coercible::Int.constrained(lt: 101, gt: -1).optional
9
+ class Color
10
+ include Comparison
11
+
12
+ # @!attribute [r] r
13
+ # @return [Int] red component, value 0-255
14
+ model_attr :r
15
+ # @!attribute [r] g
16
+ # @return [Int] green component, value 0-255
17
+ model_attr :g
18
+ # @!attribute [r] b
19
+ # @return [Int] blue component, value 0-255
20
+ model_attr :b
21
+ # @!attribute [r] a
22
+ # @return [Int, NilClass] optional alpha component, value 0-100
23
+ model_attr :a
13
24
 
25
+ # Parses a CSS style color string into a color object
26
+ # @param str [String] CSS color string
27
+ # @return [Color]
14
28
  def self.rgba(str)
15
29
  return nil if str.nil?
16
30
  md = str.match(/#([\da-f]{2})([\da-f]{2})([\da-f]{2})([\da-f]{2})?/)
@@ -23,10 +37,22 @@ module Archimate
23
37
  )
24
38
  end
25
39
 
40
+ # Results in a Color instance for the color black
41
+ # @return [Color]
26
42
  def self.black
27
43
  new(r: 0, g: 0, b: 0, a: 100)
28
44
  end
29
45
 
46
+ def initialize(r:, g:, b:, a: nil)
47
+ raise "r, g, b cannot be nil" if [r, g, b].any?(&:nil?)
48
+ raise "r, g, b must be between 0 and 255" if [r, g, b].any? { |v| v < 0 || v > 255 }
49
+ raise "a must be between 0 and 100" if a && (a < 0 || a > 100)
50
+ @r = r
51
+ @g = g
52
+ @b = b
53
+ @a = a
54
+ end
55
+
30
56
  def to_s
31
57
  "Color(r: #{r}, g: #{g}, b: #{b}, a: #{a})"
32
58
  end
@@ -38,10 +64,9 @@ module Archimate
38
64
  private
39
65
 
40
66
  def scaled_alpha(max = 255)
67
+ return max unless a
41
68
  (max * (a / 100.0)).round
42
69
  end
43
70
  end
44
-
45
- Dry::Types.register_class(Color)
46
71
  end
47
72
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Archimate
4
+ module DataModel
5
+ module Comparison
6
+ def hash
7
+ @hash_key ||=
8
+ self.class.attr_names.reduce(self.class.hash) { |ha, attr| ha ^ send(attr).hash }
9
+ end
10
+
11
+ def ==(other)
12
+ return true if equal?(other)
13
+ other.is_a?(self.class) &&
14
+ self.class.comparison_attr_paths.all? do |attr|
15
+ dig(*attr) == other.dig(*attr)
16
+ end
17
+ end
18
+
19
+ def [](sym)
20
+ send(sym)
21
+ end
22
+
23
+ def dig(*args)
24
+ return self if args.empty?
25
+ val = send(args.shift)
26
+ return val if args.empty?
27
+ val&.dig(*args)
28
+ end
29
+
30
+ def to_h
31
+ self.class.attr_names.each_with_object({}) { |i, a| a[i] = send(i) }
32
+ end
33
+
34
+ def each(&blk)
35
+ self.class.comparison_attr_paths.each(&blk)
36
+ end
37
+
38
+ def pretty_print(pp)
39
+ pp.object_address_group(self) do
40
+ pp.seplist(self.class.comparison_attr_paths, proc { pp.text ',' }) do |attr|
41
+ column_value = dig(*attr)
42
+ pp.breakable ' '
43
+ pp.group(1) do
44
+ pp.text Array(attr).map(&:to_s).join(".")
45
+ pp.text ':'
46
+ pp.breakable
47
+ pp.pp column_value
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.included(base)
54
+ base.extend ClassMethods
55
+ end
56
+
57
+ module ClassMethods
58
+ # Define the reader method (or call model_attr)
59
+ # Append the attr_sym to the @@attrs for the class
60
+ def model_attr(attr_sym, comparison_attr: nil, writable: false)
61
+ send(:attr_reader, attr_sym)
62
+ attrs = attr_names << attr_sym
63
+ class_variable_set(:@@attr_names, attrs.uniq)
64
+
65
+ if comparison_attr != :no_compare
66
+ attrs = comparison_attr_paths << (comparison_attr ? [attr_sym, comparison_attr] : attr_sym)
67
+ class_variable_set(:@@comparison_attr_paths, attrs.uniq)
68
+ end
69
+ if writable
70
+ define_method("#{attr_sym}=".to_sym) do |val|
71
+ instance_variable_set(:@hash_key, nil)
72
+ instance_variable_set("@#{attr_sym}".to_sym, val)
73
+ end
74
+ end
75
+ end
76
+
77
+ def attr_names
78
+ class_variable_defined?(:@@attr_names) ? class_variable_get(:@@attr_names) : []
79
+ end
80
+
81
+ def comparison_attr_paths
82
+ class_variable_defined?(:@@comparison_attr_paths) ? class_variable_get(:@@comparison_attr_paths) : []
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -5,13 +5,26 @@ module Archimate
5
5
  # document attribute holds all the concern information.
6
6
  #
7
7
  # This is ConcernType in the XSD
8
- class Concern < ArchimateNode
9
- attribute :labels, Strict::Array.member(LangString).constrained(min_size: 1)
10
- attribute :documentation, DocumentationGroup
11
- attribute :stakeholders, Strict::Array.member(LangString)
12
- end
8
+ class Concern
9
+ include Comparison
10
+
11
+ # @!attribute [r] label
12
+ # @return [LangString] one label is required
13
+ model_attr :label
14
+ # @!attribute [r] documentation
15
+ # @return [PreservedLangString]
16
+ model_attr :documentation
17
+ # @!attribute [r] stakeholders
18
+ # @return [Array<LangString>]
19
+ model_attr :stakeholders
13
20
 
14
- Dry::Types.register_class(Concern)
15
- ConcernList = Strict::Array.member(Concern).default([])
21
+ def initialize(label:, documentation: nil, stakeholders: [])
22
+ raise "label is required" unless label
23
+ raise "stakeholders is a list" unless stakeholders.is_a?(Array)
24
+ @label = label
25
+ @documentation = documentation
26
+ @stakeholders = stakeholders
27
+ end
28
+ end
16
29
  end
17
30
  end