module XamplGenerator class GraphMLOut def initialize(elements_map) @elements_map = elements_map end def generate_class_nodes(element, include_mixins) node = @element_to_node_map[element.nstag] class_name = "#{ element.package }::#{ element.class_name }" mixin_name = "#{ element.package }::#{ element.class_name }" if element.persisted then write_entity_node(node, class_name, element.kind) else write_internal_node(node, class_name, element.kind) end if include_mixins then mixin_node = @mixed_in[element.nstag] #puts "#{ element.nstag } => #{ node }, mixin: [#{ mixin_node }]" if mixin_node then write_mixin_node(mixin_node, class_name) end end # puts "NODE #{ node } #{ class_name }" # puts "NODE #{ mixin_node } #{ mixin_name }" end def generate_edges(element, include_mixins) # for each child, generate an entity-ref or internal-ref edge # for each child, generate a mixin-ref edge return if ignore_package(element.package) element.child_element_child.each do | celement | next if ignore_package(celement.package) cnstag = "{{#{ celement.namespace }}}#{ celement.element_name }" referenced_element = @ns_to_element_map[ cnstag ] next unless referenced_element this_node = @element_to_node_map[ element.nstag ] other_node = @element_to_node_map[ cnstag ] other_mixin = @mixed_in[ cnstag ] if referenced_element.persisted then @current_edge += 1 write_entity_ref_edge(@current_edge, this_node, other_node) # puts "ER EDGE #{ @current_edge }, #{ this_node } --> #{ other_node } :: #{ element.class_name } --> #{ referenced_element.class_name }" else @current_edge += 1 write_internal_ref_edge(@current_edge, this_node, other_node) # puts "IR EDGE #{ @current_edge }, #{ this_node } --> #{ other_node } :: #{ element.class_name } --> #{ referenced_element.class_name }" end if include_mixins then @current_edge += 1 write_mixin_ref_edge(@current_edge, this_node, other_mixin) # puts "MI EDGE #{ @current_edge }, #{ this_node } --> #{ other_mixin } :: #{ element.class_name } --> #{ referenced_element.class_name }" end end end def ignore_package(package) return true if @excluded_packages.member?(package) return false if @included_packages.nil? return true unless @included_packages.member?(package) return false end def write_graph_ml(base_filename, excluded_packages=[ ], included_packages=nil, include_mixins=true) filename = "#{base_filename}.graphml" @excluded_packages = Set.new(excluded_packages) @included_packages = included_packages ? Set.new(included_packages) : nil @element_to_node_map = {} @ns_to_element_map = {} @element_to_child_element_map = {} @mixed_in = {} nodes = 0 edges = 0 mixins = 0 @elements_map.each_value do |elements| elements.element_child.each do |element| next if ignore_package(element.package) nodes += 1 @element_to_node_map[element.nstag] = nodes @ns_to_element_map[element.nstag] = element @element_to_child_element_map[element.nstag] = map = {} element.child_element_child.each do | celement | edges += 1 cnstag = "{{#{ celement.namespace }}}#{ celement.element_name }" map[cnstag] = edges unless @mixed_in.include?(cnstag) then mixins += 1 @mixed_in[cnstag] = mixins end end end end @mixed_in.each do | k, v | @mixed_in[k] = v + nodes end # puts "#{File.basename(__FILE__)}:#{__LINE__} #{ @element_to_node_map.inspect }" @reference_edges = edges File.open(filename, "w") do | out | @out = out if include_mixins then write_graphml_start(nodes + mixins, 2 * edges) else write_graphml_start(nodes, edges) end @elements_map.each_value do |elements| elements.element_child.each do |element| generate_class_nodes(element, include_mixins) end end @current_edge = 0 @elements_map.each_value do |elements| elements.element_child.each do |element| generate_edges(element, include_mixins) end end write_graphml_end # puts "#{File.basename(__FILE__)}:#{__LINE__} EDGES:: predicted: #{ 2 * edges }, actual: #{ @current_edge }" end return nil end def write_entity_node(node, class_name, kind) @out << < #{ class_name } UMLClass EOS end def write_internal_node(node, class_name, kind) @out << < #{ class_name } UMLClass EOS end def write_mixin_node(node, class_name) @out << < #{ class_name } UMLClass EOS end def write_entity_ref_edge(edge, class_node, external_node) @out << < UMLuses EOS end def write_internal_ref_edge(edge, class_node, internal_node) @out << < UMLuses EOS end def write_mixin_ref_edge(edge, class_node, mixin_node) @out << < UMLinherits EOS end def write_graphml_start(nodes, edges) @out << < EOS end def write_graphml_end @out << < EOS end end end