Class: Archsight::Resources::Base
- Inherits:
-
Object
- Object
- Archsight::Resources::Base
- Defined in:
- lib/archsight/resources/base.rb
Overview
Base is the base for all assets, should not be used directly, only by inheritance
Direct Known Subclasses
Analysis, ApplicationComponent, ApplicationInterface, ApplicationService, BusinessActor, BusinessConstraint, BusinessProcess, BusinessProduct, BusinessRequirement, ComplianceEvidence, DataObject, Import, MotivationGoal, MotivationOutcome, MotivationStakeholder, StrategyCapability, TechnologyArtifact, TechnologyInterface, TechnologyNode, TechnologyService, TechnologySystemSoftware, View
Instance Attribute Summary collapse
-
#path_ref ⇒ Object
Returns the value of attribute path_ref.
-
#raw ⇒ Object
Returns the value of attribute raw.
-
#references ⇒ Object
Returns the value of attribute references.
Class Method Summary collapse
-
.annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: true, type: nil, list: false, editor: true, validator: nil) ⇒ Object
Define an annotation using the Annotation class.
- .annotation_enum(key) ⇒ Object
- .annotation_format(key) ⇒ Object
-
.annotation_matching(key) ⇒ Object
Find annotation definition matching a key (handles patterns).
- .annotation_title(key) ⇒ Object
-
.annotations ⇒ Object
Get all annotation definitions.
-
.computed_annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: false, type: nil, list: false, editor: true) { ... } ⇒ Object
Define a computed annotation using a block Computed annotations are calculated from related resources after the database is loaded.
-
.computed_annotations ⇒ Object
Get all computed annotation definitions.
- .description(text = nil) ⇒ Object
- .discovered_annotations ⇒ Object
-
.filterable_annotations ⇒ Object
Get filterable annotations as array of Annotation objects.
- .icon(icon_name = nil) ⇒ Object
-
.include_annotations(*names) ⇒ Object
Include annotation modules by symbol name.
- .inherited(subclass) ⇒ Object
- .layer(layer_name = nil) ⇒ Object
-
.list_annotations ⇒ Object
Get annotations marked for list display.
-
.matches_annotation_pattern?(key) ⇒ Boolean
Check if key matches any pattern annotation.
- .relation(verb, kind, klass_name) ⇒ Object
- .relations ⇒ Object
Instance Method Summary collapse
- #abandoned? ⇒ Boolean
- #annotations ⇒ Object
-
#computed_annotation_value(key) ⇒ Object?
Get a computed annotation value from the cache.
- #has_relations? ⇒ Boolean
-
#initialize(raw, path_ref) ⇒ Base
constructor
A new instance of Base.
- #kind ⇒ Object
- #klass ⇒ Object
- #merge!(inst) ⇒ Object
- #metadata ⇒ Object
- #name ⇒ Object
-
#raise(msg) ⇒ Object
raise provides a helper for better error messages including current path and line no.
- #referenced_by(inst, verb = nil) ⇒ Object
-
#references_grouped ⇒ Object
Get references grouped by kind and verb for display (incoming) Returns: { “Kind” => { “verb” => [instances…] } }.
- #relations(verb, kind) ⇒ Object
-
#relations_grouped ⇒ Object
Get outgoing relations grouped by verb and kind for display Returns: { “verb” => { “Kind” => [instances…] } }.
-
#set_computed_annotation(key, value) ⇒ Object
Set a computed annotation value This writes to both the computed values cache and the annotations hash so computed values are accessible via the normal annotations interface.
- #set_relations(verb, kind, rels) ⇒ Object
- #spec ⇒ Object
- #to_s ⇒ Object
- #verb_allowed?(verb) ⇒ Boolean
- #verb_kind_allowed?(verb, kind) ⇒ Boolean
- #verify! ⇒ Object
Constructor Details
#initialize(raw, path_ref) ⇒ Base
Returns a new instance of Base.
149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/archsight/resources/base.rb', line 149 def initialize(raw, path_ref) @raw = raw @path_ref = path_ref @references = [] # Auto-discover annotation keys return unless annotations annotations.each_key do |key| self.class.discovered_annotations.add(key) end end |
Instance Attribute Details
#path_ref ⇒ Object
Returns the value of attribute path_ref.
9 10 11 |
# File 'lib/archsight/resources/base.rb', line 9 def path_ref @path_ref end |
#raw ⇒ Object
Returns the value of attribute raw.
9 10 11 |
# File 'lib/archsight/resources/base.rb', line 9 def raw @raw end |
#references ⇒ Object
Returns the value of attribute references.
9 10 11 |
# File 'lib/archsight/resources/base.rb', line 9 def references @references end |
Class Method Details
.annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: true, type: nil, list: false, editor: true, validator: nil) ⇒ Object
Define an annotation using the Annotation class
27 28 29 30 31 32 33 |
# File 'lib/archsight/resources/base.rb', line 27 def self.annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: true, type: nil, list: false, editor: true, validator: nil) @annotations ||= [] #: Array[Archsight::Annotations::Annotation] = { description: description, filter: filter, title: title, format: format, enum: enum, sidebar: , type: type, list: list, editor: editor, validator: validator } @annotations << Archsight::Annotations::Annotation.new(key, ) end |
.annotation_enum(key) ⇒ Object
99 100 101 |
# File 'lib/archsight/resources/base.rb', line 99 def self.annotation_enum(key) annotation_matching(key)&.enum end |
.annotation_format(key) ⇒ Object
95 96 97 |
# File 'lib/archsight/resources/base.rb', line 95 def self.annotation_format(key) annotation_matching(key)&.format end |
.annotation_matching(key) ⇒ Object
Find annotation definition matching a key (handles patterns)
72 73 74 |
# File 'lib/archsight/resources/base.rb', line 72 def self.annotation_matching(key) annotations.find { |a| a.matches?(key) } end |
.annotation_title(key) ⇒ Object
91 92 93 |
# File 'lib/archsight/resources/base.rb', line 91 def self.annotation_title(key) annotation_matching(key)&.title || key.split("/").last.capitalize end |
.annotations ⇒ Object
Get all annotation definitions
36 37 38 |
# File 'lib/archsight/resources/base.rb', line 36 def self.annotations @annotations || [] end |
.computed_annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: false, type: nil, list: false, editor: true) { ... } ⇒ Object
Define a computed annotation using a block Computed annotations are calculated from related resources after the database is loaded. Supports all the same options as regular annotations.
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/archsight/resources/base.rb', line 53 def self.computed_annotation(key, description: nil, filter: nil, title: nil, format: nil, enum: nil, sidebar: false, type: nil, list: false, editor: true, &) require_relative "../annotations/computed" @computed_annotations ||= [] #: Array[Archsight::Annotations::Computed] @computed_annotations << Archsight::Annotations::Computed.new(key, description: description, type: type, &) # Also register as a regular annotation so it passes validation and is recognized @annotations ||= [] #: Array[Archsight::Annotations::Annotation] = { description: description, filter: filter, title: title, format: format, enum: enum, sidebar: , type: type, list: list, editor: editor } @annotations << Archsight::Annotations::Annotation.new(key, ) end |
.computed_annotations ⇒ Object
Get all computed annotation definitions
67 68 69 |
# File 'lib/archsight/resources/base.rb', line 67 def self.computed_annotations @computed_annotations || [] end |
.description(text = nil) ⇒ Object
119 120 121 122 123 124 125 |
# File 'lib/archsight/resources/base.rb', line 119 def self.description(text = nil) if text @description = text else @description end end |
.discovered_annotations ⇒ Object
145 146 147 |
# File 'lib/archsight/resources/base.rb', line 145 def self.discovered_annotations @discovered_annotations ||= Set.new end |
.filterable_annotations ⇒ Object
Get filterable annotations as array of Annotation objects
82 83 84 |
# File 'lib/archsight/resources/base.rb', line 82 def self.filterable_annotations annotations.select(&:filterable?).reject(&:pattern?) end |
.icon(icon_name = nil) ⇒ Object
103 104 105 106 107 108 109 |
# File 'lib/archsight/resources/base.rb', line 103 def self.icon(icon_name = nil) if icon_name @icon = icon_name else @icon || "page" # default icon end end |
.include_annotations(*names) ⇒ Object
Include annotation modules by symbol name
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/archsight/resources/base.rb', line 130 def self.include_annotations(*names) names.each do |name| # Convert snake_case to CamelCase (e.g., :git -> 'Git', :my_module -> 'MyModule') module_name = name.to_s.split("_").map(&:capitalize).join mod = Archsight::Annotations.const_get(module_name) include mod rescue NameError available = Archsight::Annotations.constants .select { |c| Archsight::Annotations.const_get(c).is_a?(Module) && Archsight::Annotations.const_get(c).respond_to?(:included) } .map { |c| ":#{c.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase}" } .sort Kernel.raise "Unknown annotation module :#{name}. Available: #{available.join(", ")}" end end |
.inherited(subclass) ⇒ Object
11 12 13 14 15 |
# File 'lib/archsight/resources/base.rb', line 11 def self.inherited(subclass) super # Auto-register when class is defined Archsight::Resources.register(subclass) end |
.layer(layer_name = nil) ⇒ Object
111 112 113 114 115 116 117 |
# File 'lib/archsight/resources/base.rb', line 111 def self.layer(layer_name = nil) if layer_name @layer = layer_name else @layer || "other" # default layer end end |
.list_annotations ⇒ Object
Get annotations marked for list display
87 88 89 |
# File 'lib/archsight/resources/base.rb', line 87 def self.list_annotations annotations.select(&:list_display?).reject(&:pattern?) end |
.matches_annotation_pattern?(key) ⇒ Boolean
Check if key matches any pattern annotation
77 78 79 |
# File 'lib/archsight/resources/base.rb', line 77 def self.matches_annotation_pattern?(key) annotations.any? { |a| a.pattern? && a.matches?(key) } end |
.relation(verb, kind, klass_name) ⇒ Object
17 18 19 20 |
# File 'lib/archsight/resources/base.rb', line 17 def self.relation(verb, kind, klass_name) @relations ||= [] #: Array[[Symbol, Symbol, String]] @relations << [verb, kind, klass_name] end |
.relations ⇒ Object
22 23 24 |
# File 'lib/archsight/resources/base.rb', line 22 def self.relations @relations || [] end |
Instance Method Details
#abandoned? ⇒ Boolean
210 211 212 |
# File 'lib/archsight/resources/base.rb', line 210 def abandoned? annotations["activity/status"] == "abandoned" end |
#annotations ⇒ Object
173 174 175 |
# File 'lib/archsight/resources/base.rb', line 173 def annotations ["annotations"] || {} end |
#computed_annotation_value(key) ⇒ Object?
Get a computed annotation value from the cache
194 195 196 |
# File 'lib/archsight/resources/base.rb', line 194 def computed_annotation_value(key) @computed_values&.[](key) end |
#has_relations? ⇒ Boolean
214 215 216 |
# File 'lib/archsight/resources/base.rb', line 214 def has_relations? spec.any? { |_verb, kinds| kinds.is_a?(Hash) && kinds.values.any? { |v| v.is_a?(Array) && v.any? } } end |
#kind ⇒ Object
165 166 167 |
# File 'lib/archsight/resources/base.rb', line 165 def kind @raw["kind"] end |
#klass ⇒ Object
161 162 163 |
# File 'lib/archsight/resources/base.rb', line 161 def klass self.class.name.split("::").last end |
#merge!(inst) ⇒ Object
289 290 291 292 |
# File 'lib/archsight/resources/base.rb', line 289 def merge!(inst) # NOTE: path reference is preserved from the original instance @raw = Archsight::Helpers.deep_merge(@raw, inst.raw) end |
#metadata ⇒ Object
198 199 200 |
# File 'lib/archsight/resources/base.rb', line 198 def @raw["metadata"] || {} end |
#name ⇒ Object
169 170 171 |
# File 'lib/archsight/resources/base.rb', line 169 def name ["name"] end |
#raise(msg) ⇒ Object
raise provides a helper for better error messages including current path and line no
295 296 297 |
# File 'lib/archsight/resources/base.rb', line 295 def raise(msg) Kernel.raise(Archsight::ResourceError.new(msg, @path_ref)) end |
#referenced_by(inst, verb = nil) ⇒ Object
235 236 237 238 239 |
# File 'lib/archsight/resources/base.rb', line 235 def referenced_by(inst, verb = nil) # Store reference with verb information for grouped display existing = @references.find { |r| r[:instance] == inst && r[:verb] == verb } @references << { instance: inst, verb: verb } unless existing end |
#references_grouped ⇒ Object
Get references grouped by kind and verb for display (incoming) Returns: { “Kind” => { “verb” => [instances…] } }
243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/archsight/resources/base.rb', line 243 def references_grouped grouped = {} #: Hash[String, Hash[untyped, Array[Base]]] @references.each do |ref| inst = ref[:instance] verb = ref[:verb] kind = inst.klass grouped[kind] ||= {} grouped[kind][verb] ||= [] #: Array[Base] grouped[kind][verb] << inst end # Sort by kind name, then by verb name grouped.sort.to_h.transform_values { |verbs| verbs.sort.to_h } end |
#relations(verb, kind) ⇒ Object
226 227 228 |
# File 'lib/archsight/resources/base.rb', line 226 def relations(verb, kind) (spec[verb.to_s] || {})[kind.to_s] || [] end |
#relations_grouped ⇒ Object
Get outgoing relations grouped by verb and kind for display Returns: { “verb” => { “Kind” => [instances…] } }
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/archsight/resources/base.rb', line 259 def relations_grouped grouped = {} #: Hash[String, Hash[String, Array[Base]]] spec.each do |verb, kinds| next unless kinds.is_a?(Hash) kinds.each_value do |instances| next unless instances.is_a?(Array) && instances.any? instances.each do |inst| kind = inst.klass grouped[verb] ||= {} grouped[verb][kind] ||= [] #: Array[Base] grouped[verb][kind] << inst end end end # Sort by verb name, then by kind name grouped.sort.to_h.transform_values { |kinds| kinds.sort.to_h } end |
#set_computed_annotation(key, value) ⇒ Object
Set a computed annotation value This writes to both the computed values cache and the annotations hash so computed values are accessible via the normal annotations interface.
182 183 184 185 186 187 188 189 |
# File 'lib/archsight/resources/base.rb', line 182 def set_computed_annotation(key, value) @computed_values ||= {} #: Hash[String, untyped] @computed_values[key] = value # Write to annotations hash for query compatibility @raw["metadata"] ||= {} @raw["metadata"]["annotations"] = @raw["metadata"]["annotations"] || {} #: Hash[String, String] @raw["metadata"]["annotations"][key] = value end |
#set_relations(verb, kind, rels) ⇒ Object
230 231 232 233 |
# File 'lib/archsight/resources/base.rb', line 230 def set_relations(verb, kind, rels) spec[verb.to_s][kind.to_s] = rels rels.each { |rel| rel.referenced_by(self, verb) } end |
#spec ⇒ Object
202 203 204 |
# File 'lib/archsight/resources/base.rb', line 202 def spec @raw["spec"] || {} end |
#to_s ⇒ Object
206 207 208 |
# File 'lib/archsight/resources/base.rb', line 206 def to_s "#<#{self.class} name=#{name}>" end |
#verb_allowed?(verb) ⇒ Boolean
218 219 220 |
# File 'lib/archsight/resources/base.rb', line 218 def verb_allowed?(verb) self.class.relations.any? { |v, _, _| v.to_s == verb.to_s } end |
#verb_kind_allowed?(verb, kind) ⇒ Boolean
222 223 224 |
# File 'lib/archsight/resources/base.rb', line 222 def verb_kind_allowed?(verb, kind) self.class.relations.any? { |v, k, _| v.to_s == verb.to_s && k.to_s == kind.to_s } end |
#verify! ⇒ Object
279 280 281 282 283 284 285 286 287 |
# File 'lib/archsight/resources/base.rb', line 279 def verify! spec.each do |verb, kinds| raise "unknown verb #{verb}" unless verb_allowed?(verb) kinds.each_key do |kind, _| raise "unknown verb #{verb} / kind #{kind} combination" unless verb_kind_allowed?(verb, kind) end end end |