archimate 1.1.1 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -47
- data/lib/archimate.rb +0 -11
- data/lib/archimate/cli/archi.rb +0 -8
- data/lib/archimate/data_model/diffable_array.rb +64 -64
- data/lib/archimate/version.rb +1 -1
- metadata +2 -32
- data/exe/archidiff +0 -7
- data/exe/archidiff-summary +0 -7
- data/exe/archimerge +0 -7
- data/exe/fmtxml +0 -7
- data/lib/archimate/cli/conflict_resolver.rb +0 -39
- data/lib/archimate/cli/diff.rb +0 -31
- data/lib/archimate/cli/diff_summary.rb +0 -101
- data/lib/archimate/cli/merge.rb +0 -49
- data/lib/archimate/cli/merger.rb +0 -109
- data/lib/archimate/diff.rb +0 -17
- data/lib/archimate/diff/archimate_array_reference.rb +0 -113
- data/lib/archimate/diff/archimate_identified_node_reference.rb +0 -41
- data/lib/archimate/diff/archimate_node_attribute_reference.rb +0 -70
- data/lib/archimate/diff/archimate_node_reference.rb +0 -80
- data/lib/archimate/diff/change.rb +0 -49
- data/lib/archimate/diff/conflict.rb +0 -31
- data/lib/archimate/diff/conflicts.rb +0 -89
- data/lib/archimate/diff/conflicts/base_conflict.rb +0 -53
- data/lib/archimate/diff/conflicts/deleted_items_child_updated_conflict.rb +0 -30
- data/lib/archimate/diff/conflicts/deleted_items_referenced_conflict.rb +0 -63
- data/lib/archimate/diff/conflicts/path_conflict.rb +0 -51
- data/lib/archimate/diff/delete.rb +0 -41
- data/lib/archimate/diff/difference.rb +0 -113
- data/lib/archimate/diff/insert.rb +0 -43
- data/lib/archimate/diff/merge.rb +0 -70
- data/lib/archimate/diff/move.rb +0 -51
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Change < Difference
|
5
|
-
using DataModel::DiffableArray
|
6
|
-
|
7
|
-
# Create a new Change difference
|
8
|
-
#
|
9
|
-
# @param target [Archimate::Diff::ArchimateNodeReference] reference to
|
10
|
-
# ArchimateNode that was changed
|
11
|
-
# @param changed_from [Archimate::Diff::ArchimateNodeReference] Element
|
12
|
-
# that was changed
|
13
|
-
def initialize(target, changed_from)
|
14
|
-
super(target, changed_from)
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
# Note - the explicit to_s is required to access the DiffableArray
|
19
|
-
# implementation if the parent is an Array.
|
20
|
-
"#{diff_type} #{changed_from.parent&.to_s} #{Color.color(target.to_s, :change)} changed to #{target.value}"
|
21
|
-
end
|
22
|
-
|
23
|
-
def apply(to_model)
|
24
|
-
unless to_model.is_a?(DataModel::Model)
|
25
|
-
throw(
|
26
|
-
TypeError,
|
27
|
-
"Expected a Archimate::DataModel::Model, was a #{to_model.class}"
|
28
|
-
)
|
29
|
-
end
|
30
|
-
target.change(to_model, changed_from.value)
|
31
|
-
to_model
|
32
|
-
end
|
33
|
-
|
34
|
-
def change?
|
35
|
-
true
|
36
|
-
end
|
37
|
-
|
38
|
-
def kind
|
39
|
-
"Change"
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def diff_type
|
45
|
-
Color.color('CHANGE:', :change)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Conflict
|
5
|
-
attr_reader :base_local_diffs
|
6
|
-
attr_reader :base_remote_diffs
|
7
|
-
attr_reader :reason
|
8
|
-
attr_reader :diffs
|
9
|
-
|
10
|
-
def initialize(base_local_diffs, base_remote_diffs, reason)
|
11
|
-
@base_local_diffs = Array(base_local_diffs)
|
12
|
-
@base_remote_diffs = Array(base_remote_diffs)
|
13
|
-
@diffs = @base_local_diffs + @base_remote_diffs
|
14
|
-
@reason = reason
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
"#{Color.color('CONFLICT:', [:black, :on_red])} #{reason}\n" \
|
19
|
-
"\tBase->Local Diff(s):\n\t\t#{base_local_diffs.map(&:to_s).join("\n\t\t")}" \
|
20
|
-
"\n\tBase->Remote Diffs(s):\n\t\t#{base_remote_diffs.map(&:to_s).join("\n\t\t")}"
|
21
|
-
end
|
22
|
-
|
23
|
-
def ==(other)
|
24
|
-
other.is_a?(self.class) &&
|
25
|
-
base_local_diffs == other.base_local_diffs &&
|
26
|
-
base_remote_diffs == other.base_remote_diffs &&
|
27
|
-
reason == other.reason
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'forwardable'
|
4
|
-
require 'parallel'
|
5
|
-
require 'archimate/diff/conflicts/base_conflict'
|
6
|
-
require 'archimate/diff/conflicts/deleted_items_child_updated_conflict'
|
7
|
-
require 'archimate/diff/conflicts/deleted_items_referenced_conflict'
|
8
|
-
require 'archimate/diff/conflicts/path_conflict'
|
9
|
-
|
10
|
-
module Archimate
|
11
|
-
module Diff
|
12
|
-
class Conflicts
|
13
|
-
extend Forwardable
|
14
|
-
|
15
|
-
attr_reader :base_local_diffs
|
16
|
-
attr_reader :base_remote_diffs
|
17
|
-
|
18
|
-
def_delegator :@conflicts, :empty?
|
19
|
-
def_delegator :@conflicts, :size
|
20
|
-
def_delegator :@conflicts, :first
|
21
|
-
def_delegator :@conflicts, :map
|
22
|
-
def_delegator :@conflicts, :each
|
23
|
-
|
24
|
-
include Archimate::Logging
|
25
|
-
|
26
|
-
def initialize(base_local_diffs, base_remote_diffs)
|
27
|
-
@base_local_diffs = base_local_diffs
|
28
|
-
@base_remote_diffs = base_remote_diffs
|
29
|
-
@conflict_finders = [PathConflict, DeletedItemsChildUpdatedConflict, DeletedItemsReferencedConflict]
|
30
|
-
@conflicts = nil
|
31
|
-
@conflicting_diffs = nil
|
32
|
-
@unconflicted_diffs = nil
|
33
|
-
# TODO: consider making this an argument
|
34
|
-
@conflict_resolver = Cli::ConflictResolver.new
|
35
|
-
end
|
36
|
-
|
37
|
-
# TODO: refactor this method elsewhere
|
38
|
-
# resolve iterates through the set of conflicting diffs asking the user
|
39
|
-
# (if running interactively) and return the set of diffs that can be applied.
|
40
|
-
#
|
41
|
-
# To keep diffs reasonably human readable in logs, the local diffs should
|
42
|
-
# be applied first followed by the remote diffs.
|
43
|
-
def resolve
|
44
|
-
debug do
|
45
|
-
<<~MSG
|
46
|
-
Filtering out #{conflicts.size} conflicts from #{base_local_diffs.size + base_remote_diffs.size} diffs
|
47
|
-
Remaining diffs #{unconflicted_diffs.size}
|
48
|
-
MSG
|
49
|
-
end
|
50
|
-
|
51
|
-
conflicts.each_with_object(unconflicted_diffs) do |conflict, diffs|
|
52
|
-
# TODO: this will result in diffs being out of order from their
|
53
|
-
# original order. diffs should be flagged as conflicted and
|
54
|
-
# this method should instead remove the conflicted flag.
|
55
|
-
diffs.concat(@conflict_resolver.resolve(conflict))
|
56
|
-
# TODO: if the conflict is resolved, it should be removed from the
|
57
|
-
# @conflicts array.
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def conflicts
|
62
|
-
@conflicts ||= find_conflicts
|
63
|
-
end
|
64
|
-
|
65
|
-
def conflicting_diffs
|
66
|
-
@conflicting_diffs ||= conflicts.map(&:diffs).flatten
|
67
|
-
end
|
68
|
-
|
69
|
-
def unconflicted_diffs
|
70
|
-
@unconflicted_diffs ||=
|
71
|
-
(base_local_diffs + base_remote_diffs) - conflicting_diffs
|
72
|
-
end
|
73
|
-
|
74
|
-
def to_s
|
75
|
-
"Conflicts:\n\n#{conflicts.map(&:to_s).join("\n\n")}\n"
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def find_conflicts
|
81
|
-
# TODO: Running this in parallel breaks currently.
|
82
|
-
# @conflicts = Parallel.map(@conflict_finders, in_processes: 3) { |cf_class|
|
83
|
-
@conflicts = @conflict_finders.map { |cf_class|
|
84
|
-
cf_class.new(base_local_diffs, base_remote_diffs).conflicts
|
85
|
-
}.flatten
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Conflicts
|
5
|
-
# BaseConflict
|
6
|
-
# @abstract
|
7
|
-
class BaseConflict
|
8
|
-
def initialize(base_local_diffs, base_remote_diffs)
|
9
|
-
@base_local_diffs = base_local_diffs
|
10
|
-
@base_remote_diffs = base_remote_diffs
|
11
|
-
@associative = false
|
12
|
-
@diff_iterations = nil
|
13
|
-
end
|
14
|
-
|
15
|
-
def filter1
|
16
|
-
->(_diff) { true }
|
17
|
-
end
|
18
|
-
|
19
|
-
def filter2
|
20
|
-
->(_diff) { true }
|
21
|
-
end
|
22
|
-
|
23
|
-
def conflicts
|
24
|
-
progressbar = ProgressIndicator.new(total: diff_iterations.size, title: "Analyzing Conflicts")
|
25
|
-
diff_iterations.each_with_object([]) do |(md1, md2), conflicts|
|
26
|
-
progressbar.increment
|
27
|
-
conflicts.concat(
|
28
|
-
md1.map { |diff1| [diff1, md2.select(&method(:diff_conflicts).curry[diff1])] }
|
29
|
-
.reject { |_diff1, diff2| diff2.empty? }
|
30
|
-
.map { |diff1, diff2_ary| Conflict.new(diff1, diff2_ary, describe) }
|
31
|
-
)
|
32
|
-
end
|
33
|
-
ensure
|
34
|
-
progressbar.finish
|
35
|
-
end
|
36
|
-
|
37
|
-
def diff_combinations
|
38
|
-
combos = [@base_local_diffs, @base_remote_diffs]
|
39
|
-
@associative ? [combos] : combos.permutation(2)
|
40
|
-
end
|
41
|
-
|
42
|
-
# By default our conflict tests are not associative to we need to run
|
43
|
-
# [local, remote] and [remote, local] through the tests.
|
44
|
-
def diff_iterations
|
45
|
-
@diff_iterations ||=
|
46
|
-
diff_combinations.map do |local_diffs, remote_diffs|
|
47
|
-
[local_diffs.select(&filter1), remote_diffs.select(&filter2)]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Conflicts
|
5
|
-
class DeletedItemsChildUpdatedConflict < BaseConflict
|
6
|
-
def describe
|
7
|
-
"Checking for Deleted items in one change set have children that are inserted or changed in the other change set"
|
8
|
-
end
|
9
|
-
|
10
|
-
def filter1
|
11
|
-
->(diff) { diff.delete? }
|
12
|
-
end
|
13
|
-
|
14
|
-
def filter2
|
15
|
-
->(diff) { !diff.delete? }
|
16
|
-
end
|
17
|
-
|
18
|
-
# TODO: This is simple, but might be slow.
|
19
|
-
def diff_conflicts(diff1, diff2)
|
20
|
-
da1 = diff1.path.split("/")
|
21
|
-
da2 = diff2.path.split("/")
|
22
|
-
|
23
|
-
cmp_size = [da1, da2].map(&:size).min - 1
|
24
|
-
return false if da2.size == cmp_size + 1
|
25
|
-
da1[0..cmp_size] == da2[0..cmp_size]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Conflicts
|
5
|
-
# DeletedItemsReferencedConflict
|
6
|
-
#
|
7
|
-
# This sort of conflict occurs when one change set has deleted an element
|
8
|
-
# that is referenced by id in the other change set.
|
9
|
-
#
|
10
|
-
# For example:
|
11
|
-
#
|
12
|
-
# In the local change set, an element with id "abc123" is deleted.
|
13
|
-
# In the remote change set, a child is inserted into a diagram with
|
14
|
-
# archimate_element = "abc123". These two changes are in conflict.
|
15
|
-
class DeletedItemsReferencedConflict < BaseConflict
|
16
|
-
using DataModel::DiffableArray
|
17
|
-
using DataModel::DiffablePrimitive
|
18
|
-
|
19
|
-
def describe
|
20
|
-
"Checking for Deleted items in one change set are referenced in the other change set"
|
21
|
-
end
|
22
|
-
|
23
|
-
# Filters a changeset to potentially conflicting diffs (making the set
|
24
|
-
# of combinations to check smaller)
|
25
|
-
#
|
26
|
-
# @return [lambda] a filter to limit diffs to Delete type
|
27
|
-
def filter1
|
28
|
-
->(diff) { diff.delete? && diff.target.value.is_a?(DataModel::Referenceable) }
|
29
|
-
end
|
30
|
-
|
31
|
-
# Filters a changeset to potentially conflicting diffs (making the set
|
32
|
-
# of combinations to check smaller)
|
33
|
-
#
|
34
|
-
# @return [lambda] a filter to limit diffs to other
|
35
|
-
# than Delete type
|
36
|
-
def filter2
|
37
|
-
->(diff) { !diff.delete? }
|
38
|
-
end
|
39
|
-
|
40
|
-
# Determine the set of conflicts between the given diffs
|
41
|
-
# def conflicts
|
42
|
-
# progressbar = ProgressIndicator.new(total: diff_iterations.size)
|
43
|
-
# diff_iterations.each_with_object([]) do |(md1, md2), a|
|
44
|
-
# progressbar.increment
|
45
|
-
# a.concat(
|
46
|
-
# md1.map { |diff1| [diff1, md2.select(&method(:diff_conflicts).curry[diff1])] }
|
47
|
-
# .reject { |_diff1, diff2| diff2.empty? }
|
48
|
-
# .map { |diff1, diff2_ary| Conflict.new(diff1, diff2_ary, describe) }
|
49
|
-
# )
|
50
|
-
# end
|
51
|
-
# ensure
|
52
|
-
# progressbar&.finish
|
53
|
-
# end
|
54
|
-
|
55
|
-
# TODO: This is simple, but might be slow. If it is, then override
|
56
|
-
# the conflicts method to prevent calculating referenced_identified_nodes methods
|
57
|
-
def diff_conflicts(diff1, diff2)
|
58
|
-
diff2.target.value.referenced_identified_nodes.include?(diff1.target.value.id)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Conflicts
|
5
|
-
class PathConflict < BaseConflict
|
6
|
-
def initialize(base_local_diffs, base_remote_diffs)
|
7
|
-
super
|
8
|
-
@associative = true
|
9
|
-
end
|
10
|
-
|
11
|
-
def describe
|
12
|
-
"Checking for Differences in one change set that conflict with changes in other change set at the same path"
|
13
|
-
end
|
14
|
-
|
15
|
-
def diff_conflicts(diff1, diff2)
|
16
|
-
same_path_but_diff(diff1, diff2) && in_conflict?(diff1, diff2)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def same_path_but_diff(a, b)
|
22
|
-
a.path == b.path && a != b
|
23
|
-
end
|
24
|
-
|
25
|
-
# I'm in conflict if:
|
26
|
-
# 1. ld and rd are both changes to the same path (but not the same change)
|
27
|
-
# 2. one is a change, the other a delete and changed_from is the same
|
28
|
-
# 3. both are inserts of the different identifyable nodes with the same id
|
29
|
-
#
|
30
|
-
# If I'm not an identifyable node and my parent is an array, then two inserts are ok
|
31
|
-
def in_conflict?(local_diff, remote_diff)
|
32
|
-
return true if
|
33
|
-
local_diff.target.parent.is_a?(Array) &&
|
34
|
-
local_diff.target.value.is_a?(DataModel::Referenceable) &&
|
35
|
-
local_diff.target.value.id == remote_diff.target.value.id &&
|
36
|
-
local_diff != remote_diff
|
37
|
-
|
38
|
-
case [local_diff, remote_diff].map { |d| d.class.name.split('::').last }.sort
|
39
|
-
when %w(Change Change)
|
40
|
-
local_diff.changed_from.value == remote_diff.changed_from.value &&
|
41
|
-
local_diff.target.value != remote_diff.target.value
|
42
|
-
when %w(Change Delete)
|
43
|
-
true
|
44
|
-
else
|
45
|
-
false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Archimate
|
3
|
-
module Diff
|
4
|
-
class Delete < Difference
|
5
|
-
using DataModel::DiffablePrimitive
|
6
|
-
using DataModel::DiffableArray
|
7
|
-
|
8
|
-
# Create a new Delete difference
|
9
|
-
#
|
10
|
-
# @param target [ArchimateNodeReference] Element that was deleted
|
11
|
-
def initialize(target)
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
# Note - the explicit to_s is required to access the DiffableArray
|
17
|
-
# implementation if the parent is an Array.
|
18
|
-
"#{diff_type} #{target} from #{target.parent.to_s}"
|
19
|
-
end
|
20
|
-
|
21
|
-
def apply(el)
|
22
|
-
target.delete(el)
|
23
|
-
el
|
24
|
-
end
|
25
|
-
|
26
|
-
def delete?
|
27
|
-
true
|
28
|
-
end
|
29
|
-
|
30
|
-
def kind
|
31
|
-
"Delete"
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def diff_type
|
37
|
-
Color.color('DELETE:', :delete)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
|
5
|
-
module Archimate
|
6
|
-
module Diff
|
7
|
-
class Difference
|
8
|
-
using DataModel::DiffableArray
|
9
|
-
using DataModel::DiffablePrimitive
|
10
|
-
extend Forwardable
|
11
|
-
|
12
|
-
ARRAY_RE = Regexp.compile(/\[(\d+)\]/)
|
13
|
-
PATH_ROOT_SORT_ORDER = %w[elements relationships diagrams organizations].freeze
|
14
|
-
|
15
|
-
# delete: something responds to parent, child attribute (which is thing deleted - and could be sym for archimate nodes or index for array), value
|
16
|
-
# insert: something responds to parent, child attribute (or index), value, after value (to help with inserts)
|
17
|
-
# change: something responds to parent, child attribute (or index), value, changed from value
|
18
|
-
# move: something responds to parent, child index, value, after value) move after a particular value
|
19
|
-
attr_reader :target
|
20
|
-
attr_reader :changed_from
|
21
|
-
|
22
|
-
def_delegator :@target, :path
|
23
|
-
|
24
|
-
# Re-thinking.
|
25
|
-
#
|
26
|
-
# Requirements:
|
27
|
-
#
|
28
|
-
# 1. User friendly display of what is different in context
|
29
|
-
# 2. Able to apply the diff to another model (which was based on the "base" of the diff)
|
30
|
-
#
|
31
|
-
# Delete: example
|
32
|
-
# ArchimateNode child.bounds
|
33
|
-
# ArchimateNode, attribute model, "name"
|
34
|
-
# DiffableArray, ArchimateNode model.elements, element
|
35
|
-
# bendpoint attributes under connection
|
36
|
-
# documentation
|
37
|
-
# properties
|
38
|
-
# child/style/fill_color
|
39
|
-
# child/style/font/name
|
40
|
-
#
|
41
|
-
# @param target [Dry::Struct with id attribute] the element operated on (why is array treated as a special case?)
|
42
|
-
# @param changed_from [same class as target] (optional) for change this is the previous value
|
43
|
-
# def initialize(changed_from, target)
|
44
|
-
def initialize(target, changed_from = nil)
|
45
|
-
# raise TypeError, "Expected target to be an ArchimateNodeReference" unless target.is_a?(ArchimateNodeReference)
|
46
|
-
@target = target
|
47
|
-
@changed_from = changed_from
|
48
|
-
end
|
49
|
-
|
50
|
-
def ==(other)
|
51
|
-
other.is_a?(self.class) &&
|
52
|
-
@target == other.target &&
|
53
|
-
@changed_from == other.changed_from
|
54
|
-
end
|
55
|
-
|
56
|
-
# Difference sorting is based on the path.
|
57
|
-
# Top level components are sorted in this order: (elements, relationships, diagrams, organizations)
|
58
|
-
# Array entries are sorted by numeric order
|
59
|
-
# Others are sorted alphabetically
|
60
|
-
# TODO: this isn't complete
|
61
|
-
def <=>(other)
|
62
|
-
a = path_to_array
|
63
|
-
b = other.path_to_array
|
64
|
-
|
65
|
-
part_a = a.shift
|
66
|
-
part_b = b.shift
|
67
|
-
res = PATH_ROOT_SORT_ORDER.index(part_a) <=> PATH_ROOT_SORT_ORDER.index(part_b)
|
68
|
-
return res unless res.zero?
|
69
|
-
|
70
|
-
until a.empty? || b.empty?
|
71
|
-
part_a = a.shift
|
72
|
-
part_b = b.shift
|
73
|
-
|
74
|
-
return part_a <=> part_b unless (part_a <=> part_b).zero?
|
75
|
-
end
|
76
|
-
|
77
|
-
return -1 if a.empty?
|
78
|
-
return 1 if b.empty?
|
79
|
-
part_a <=> part_b
|
80
|
-
end
|
81
|
-
|
82
|
-
def delete?
|
83
|
-
false
|
84
|
-
end
|
85
|
-
|
86
|
-
def change?
|
87
|
-
false
|
88
|
-
end
|
89
|
-
|
90
|
-
def insert?
|
91
|
-
false
|
92
|
-
end
|
93
|
-
|
94
|
-
def move?
|
95
|
-
false
|
96
|
-
end
|
97
|
-
|
98
|
-
def path_to_array
|
99
|
-
path(force_array_index: :index).split("/").map do |p|
|
100
|
-
md = ARRAY_RE.match(p)
|
101
|
-
md ? md[1].to_i : p
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def summary_element
|
106
|
-
summary_elements = [DataModel::Element, DataModel::Organization, DataModel::Relationship, DataModel::Diagram, DataModel::Model]
|
107
|
-
se = target.value.primitive? ? target.parent : target.value
|
108
|
-
se = se.parent while summary_elements.none? { |c| se.is_a?(c) }
|
109
|
-
se
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|