1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
require 'rgen/ecore/ecore'
module RGen
module Util
module ModelComparator
# This method compares to models regarding equality
# For this the identity of a model element is defined based on identity
# of all attributes and referenced elements.
# Arrays are sorted before comparison if possible (if <=> is provided).
#
def modelEqual?(a, b, featureIgnoreList=[])
@modelEqual_visited = {}
_modelEqual_internal(a, b, featureIgnoreList, [])
end
def _modelEqual_internal(a, b, featureIgnoreList, path)
return true if @modelEqual_visited[[a,b]]
@modelEqual_visited[[a,b]] = true
return true if a.nil? && b.nil?
unless a.class == b.class
puts "#{path.inspect}\n Classes differ: #{a} vs. #{b}"
return false
end
if a.is_a?(Array)
unless a.size == b.size
puts "#{path.inspect}\n Array size differs: #{a.size} vs. #{b.size}"
return false
end
begin
# in Ruby 1.9 every object has the <=> operator but the default one returns
# nil and thus sorting won't work (ArgumentError)
as = a.sort
rescue ArgumentError, NoMethodError
as = a
end
begin
bs = b.sort
rescue ArgumentError, NoMethodError
bs = b
end
a.each_index do |i|
return false unless _modelEqual_internal(as[i], bs[i], featureIgnoreList, path+[i])
end
else
a.class.ecore.eAllStructuralFeatures.reject{|f| f.derived}.each do |feat|
next if featureIgnoreList.include?(feat.name)
if feat.eType.is_a?(RGen::ECore::EDataType)
unless a.getGeneric(feat.name) == b.getGeneric(feat.name)
puts "#{path.inspect}\n Value '#{feat.name}' differs: #{a.getGeneric(feat.name)} vs. #{b.getGeneric(feat.name)}"
return false
end
else
return false unless _modelEqual_internal(a.getGeneric(feat.name), b.getGeneric(feat.name), featureIgnoreList, path+["#{a.respond_to?(:name) && a.name}:#{feat.name}"])
end
end
end
return true
end
end
end
end
|