Class: Archimate::Diff::Cli::Merger

Inherits:
Object
  • Object
show all
Defined in:
lib/archimate/diff/cli/merger.rb

Overview

Merger is a class that is a decorator on Archimate::DataModel::Model to provide the capability to merge another model into itself

TODO: provide for a conflict resolver instance TODO: provide an option to determine if potential matches are merged

or if the conflict resolver should be asked.

Instance Method Summary collapse

Instance Method Details

#conflicting_ids(doc1, doc2) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/archimate/diff/cli/merger.rb', line 92

def conflicting_ids(doc1, doc2)
  doc_id_hash1 = id_hash_for(doc1)
  doc_id_hash2 = id_hash_for(doc2)
  cids = Set.new(doc_id_hash1.keys) & doc_id_hash2.keys
  # puts "ID Conflicts:"
  # puts cids.to_a.join(",")
  cids
end

#e_to_s(e) ⇒ Object



49
50
51
# File 'lib/archimate/diff/cli/merger.rb', line 49

def e_to_s(e)
  "#{e.name} #{hash_to_attr(e.attributes)}"
end

#hash_to_attr(h) ⇒ Object

TODO: handle inner text of elements TODO: handle merging by element type



45
46
47
# File 'lib/archimate/diff/cli/merger.rb', line 45

def hash_to_attr(h)
  h.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")
end

#id_hash_for(doc) ⇒ Object



85
86
87
88
89
90
# File 'lib/archimate/diff/cli/merger.rb', line 85

def id_hash_for(doc)
  doc.css("[id]").each_with_object({}) do |obj, memo|
    memo[obj["id"]] = obj
    memo
  end
end

#merge(doc1, doc2) ⇒ Object

Merge node1, node2 For node

For each child
  If has a matching child


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/archimate/diff/cli/merger.rb', line 57

def merge(doc1, doc2)
  doc2.children.each do |e|
    next if e.name == "text" && e.text.strip.empty?
    # p = e.path
    # if p =~ /\[\d+\]$/
    #   p = p.gsub(/\[\d+\]$/, "[@name=\"#{e.attr("name")}\"]")
    # end
    # puts "Looking for #{p}"``
    # matches = doc1.xpath(p)
    css = ">#{e.name}"
    # puts css
    css += "[name=\"#{e.attr('name')}\"]" if e.attributes.include?("name")
    css += "[xsi|type=\"#{e.attr('xsi:type')}\"]" if e.attributes.include?("xsi:type")
    matches = doc1.css(css)
    if !matches.empty? # We have a potential match
      # puts "Match?"
      # puts "  Doc2: #{e_to_s(e)}"
      # matches.each do |e1|
      #   puts "  Doc1: #{e_to_s(e1)}"
      # end
      merge(matches[0], e) unless matches.size > 1
    else # No match insert the node into the tree TODO: handle id conflicts
      doc1.add_child(e)
    end
  end
  doc1
end

#merge_files(file1, file2) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/archimate/diff/cli/merger.rb', line 101

def merge_files(file1, file2)
  doc1 = Nokogiri::XML(File.open(file1))
  doc2 = Nokogiri::XML(File.open(file2))

  # cids = conflicting_ids(doc1, doc2)
  merge(doc1.root, doc2.root).document
end