Class: Archimate::DerivedRelations

Inherits:
Object
  • Object
show all
Defined in:
lib/archimate/derived_relations.rb

Overview

5.6.1 Derivation Rule for Structural and Dependency Relationships

The structural and dependency relationships can be ordered by ‘strength’. Structural relationships are ‘stronger’ than dependency relationships, and the relationships within these categories can also be ordered by strength:

  • Influence (weakest)

  • Access

  • Serving

  • Realization

  • Assignment

  • Aggregation

  • Composition (strongest)

Part of the language definition is an abstraction rule that states that two relationships that join at an intermediate element can be combined and replaced by the weaker of the two.

5.6.2 Derivation Rules for Dynamic Relationships

For the two dynamic relationships, the following rules apply:

  • If there is a flow relationship r from element a to element b, and a structural relationship from element c to element a, a flow relationship r can be derived from element c to element b.

  • If there is a flow relationship r from element a to element b, and a structural relationship from element d to element b, a flow relationship r can be derived from element a to element d.

These rules can be applied repeatedly. Informally, this means that the begin and/or endpoint of a flow relationship can be transferred ‘backward’ in a chain of elements connected by structural relationships. Example 16 shows two of the possible flow relationships that can be derived with these rules, given a flow relationship between the two services.

This rule also applies for a triggering relationship, but only in combination with an assignment relationship (not with other structural relationships):

  • If there is a triggering relationship r from element a to element b, and an assignment relationship from element c to element a, a triggering relationship r can be derived from element c to element b.

  • If there is a triggering relationship r from element a to element b, and an assignment relationship from element d to element b, a triggering relationship r can be derived from element a to element d.

Moreover, triggering relationships are transitive:

  • If there is a triggering relationship from element a to element b, and a triggering relationship from element b to element c, a triggering relationship can be derived from element a to element c.

Constant Summary collapse

PASS_ALL =
->(_item) { true }
FAIL_ALL =
->(_item) { false }

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ DerivedRelations

Returns a new instance of DerivedRelations.



59
60
61
# File 'lib/archimate/derived_relations.rb', line 59

def initialize(model)
  @model = model
end

Instance Method Details

#derived_relations(start_elements, relationship_filter, target_filter, stop_filter = FAIL_ALL) ⇒ Object

This returns a set of derived relationships in this model between the elements in the ‘start_elements` argument, including relationships that pass the `relationship_filter` recursively until either a target_filter is matched and/or the stop_filter is matched.

TODO: Rules for derived relations

Assumptions:

  1. If an existing relation exists for found “derived” relation, it shouldn’t be included in the results.

  2. Any path of length 1 inherently identifies an instance of #1 so they can be skipped.

Parameters:

  • start_elements (Array<Element>)

    collection of starting nodes

  • relationship_filter (Boolean, lambda(Relationship) => Boolean)

    filter for the kinds of relationships to follow.

  • target_filter (lambda(Element) => Boolean)

    if true, then a derived relationship is added to the results

  • stop_filter (lambda(Element) => Boolean) (defaults to: FAIL_ALL)

    if true, then relationships below this element are not followed



84
85
86
87
88
89
90
# File 'lib/archimate/derived_relations.rb', line 84

def derived_relations(start_elements, relationship_filter, target_filter, stop_filter = FAIL_ALL)
  traverse(start_elements, relationship_filter, stop_filter)
    .reject(&single_relation_paths) # See #2 above
    .select(&target_relations(target_filter))
    .map(&create_relationship_for_path)
    .uniq { |rel| [rel.type, rel.source, rel.target] }
end

#derived_relationship_type(path) ⇒ Object



92
93
94
95
96
# File 'lib/archimate/derived_relations.rb', line 92

def derived_relationship_type(path)
  path
    .min_by(&:weight)
    .class
end

#traverse(start_elements, relation_filter, stop_filter, from_path = []) ⇒ Object

traverse returns an Array of paths (Array<Relationship>) between each of the start elements and elements that pass the relation_filter.

Parameters:

  • start_elements (Array<Element>)

    initial elements to start the model traversal

  • relation_filter (Proc(Relationship) => Boolean)

    only relationships that pass the relation_filter will be followed

  • stop_filter (Proc(Element) => Boolean)

    the traversal will not proceed further than relationship targets that the stop_filter returns true for.



109
110
111
112
113
114
115
116
117
118
# File 'lib/archimate/derived_relations.rb', line 109

def traverse(start_elements, relation_filter, stop_filter, from_path = [])
  return [] if from_path.size > 100
  start_elements.each_with_object([]) do |el, relations|
    concrete_rels = concrete_relationships(el, relation_filter, from_path)
    relations.concat(
      concrete_rels,
      *derived_relationship_paths(concrete_rels, relation_filter, stop_filter, from_path)
    )
  end
end