ManageIQ/manageiq-gems-pending

View on GitHub
lib/gems/pending/util/xml/xml_patch.rb

Summary

Maintainability
C
1 day
Test Coverage
B
83%
module MiqXmlPatch
unless defined?(XML_DIFF_ADD)
XML_DIFF_ADD = 1
XML_DIFF_DEL = -1
XML_DIFF_FOUND_ATTR = 'miqcomparefound'
end
 
def xmlPatch(patch_xml, direction = 1)
raise "Invalid XML Diff document [#{patch_xml.root.name}]. Expected root name [xmlDiff]" unless patch_xml.root.name.to_s == "xmlDiff"
 
st = Time.now
stats = {:deletes => 0, :adds => 0, :updates => 0, :errors => 0}
 
# Apply path
miq_apply_patch(self, patch_xml, direction, stats)
stats[:_xmlpatchtime_] = Time.now - st
 
miq_patch_check(patch_xml, stats, direction)
 
stats
end
 
private
 
def miq_apply_patch(xml, patch, direction, stats)
nodes = [:deletes, :adds]
 
# Depending on the direction we are applying the
# changes adds and deletes will be switched
nodes.reverse! if direction < 0
 
# Process Deletes first
miq_patch_elements(xml, patch, nodes[0], XML_DIFF_DEL, stats)
 
# Process Adds
miq_patch_elements(xml, patch, nodes[1], XML_DIFF_ADD, stats)
 
# Process Modified elements
miq_patch_elements(xml, patch, :updates, direction, stats)
end
 
Method `miq_patch_elements` has a Cognitive Complexity of 33 (exceeds 5 allowed). Consider refactoring.
Cyclomatic complexity for miq_patch_elements is too high. [12/11]
Method `miq_patch_elements` has 37 lines of code (exceeds 25 allowed). Consider refactoring.
Method `miq_patch_elements` has 5 arguments (exceeds 4 allowed). Consider refactoring.
def miq_patch_elements(xml, patch, node, direction, stats)
miq_patch_element_logging(node, direction)
patch.root.elements[node.to_s].each_element do |e|
path = e.elements['path'].elements[1]
data = e.elements['data'].elements[1]
 
parent_node = nil
 
compare_roots = true if path.nil? && e.elements['path'].attributes['root'] == "true"
unless compare_roots
# If the data should already exist add the first data element we are
# searching for to the search path.
if node == :updates || direction == XML_DIFF_DEL
# Set lastElement to the path element in case it has no children
# and the recursive block below does not execute.
lastElement = path
# Find the last element of the search path
path.each_recursive { |lastE| lastElement = lastE }
# Add a child element to search for so we ensure we find the
# proper node
lastElement << data.shallow_copy
end
 
# If the search path is only one level then we are looking
# for the root element. No need to search.
if path.elements[1].nil?
compare_roots = true
ele = xml.root
else
ele = miq_find_diff_element(path.elements[1], xml.root)
 
if ele.nil?
stats[:errors] += 1
miq_patch_logging("Unable to find XML element to update during XML Patching. Search Path:[#{path}]", :warn)
next
end
 
parent_node = ele.parent
end
 
if ele.nil?
stats[:errors] += 1
miq_patch_logging("XML node not found", :warn)
end
end
 
miq_patch_process_element(ele, data, path, compare_roots, direction, parent_node, node, xml, stats)
 
data_elements = e.attributes['data_count'].to_i
e.each_element do |de|
data = de.elements['data']
data = data.elements[1] if data
miq_patch_process_element(ele, data, path, compare_roots, direction, parent_node, node, xml, stats) if data
end unless data_elements.zero?
end
end
 
Method `miq_patch_process_element` has 9 arguments (exceeds 4 allowed). Consider refactoring.
Method `miq_patch_process_element` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.
Avoid parameter lists longer than 5 parameters. [9/5]
def miq_patch_process_element(ele, data, path, compare_roots, direction, parent_node, node, xml, stats)
if compare_roots == true
ele = xml.root
else
if node == :updates || direction == XML_DIFF_DEL
ele = miq_find_diff_element(data.shallow_copy, parent_node)
end
end
 
if node == :updates
miq_patch_update_element(ele, data, compare_roots, direction, stats)
else
miq_patch_add_element(ele, data, path, stats) if direction > 0
miq_patch_delete_element(ele, data, path, stats) if direction < 0
end
end
 
Method `miq_patch_update_element` has 5 arguments (exceeds 4 allowed). Consider refactoring.
def miq_patch_update_element(element, data, compare_roots, direction, stats)
data = data.parent.parent.elements['data_old'].elements[1] if direction < 0
e2 = compare_roots ? element.root : element
 
# Delete all existing attrbutes for this element
e2.attributes.clear
# Add new attributes
e2.add_attributes(data.attributes.to_h)
# Replace the element text
e2.text = data.text
 
stats[:updates] += 1
end
 
def miq_patch_add_element(element, data, _path, stats)
element.add(data)
stats[:adds] += 1
end
 
def miq_patch_delete_element(element, _data, path, stats)
if element.nil?
# We should not get to this point, since the element we want to
# delete should always exists. But if we do log a warning.
stats[:errors] += 1
miq_patch_logging("Unable to find XML element to delete during XML Patching. Search Path:[#{path}]", :warn)
else
element.remove!
stats[:deletes] += 1
end
end
 
def miq_find_diff_element(searchNode, xml)
data = miq_find_diff_element2(searchNode, xml)
# If the data is not found miq_find_diff_element2 returns an array
data = nil if data.kind_of?(Array)
data
end
 
Method `miq_find_diff_element2` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.
def miq_find_diff_element2(searchNode, xml)
# Loop over each element to find matching elements at the current level
xml.each_element do |dataNode|
comp_rc = miq_same_element(searchNode, dataNode)
if comp_rc.zero?
# If there are no search elements left and we match on
# and element we found what we are looking for.
if searchNode.elements[1].nil?
break(dataNode)
end
ret_val = miq_find_diff_element2(searchNode.elements[1], dataNode)
if ret_val && !ret_val.kind_of?(Array)
break(ret_val)
end
end
end
end
 
def miq_patch_element_logging(node, direction)
patch_mode = direction >= XML_DIFF_ADD ? "adds" : "deletes"
patch_mode = "udpates" if node == :updates
miq_patch_logging("Processing xml patches for [#{patch_mode}] from node [#{node}]. Direction flag:[#{direction}]")
end
 
def miq_patch_logging(message, level = :debug)
return $log.send(level, message) if $log
# puts "#{level}: #{message}"
end
 
def miq_patch_check(patch_xml, stats, direction)
expected = patch_xml.root.attributes.to_h
expected[:adds], expected[:deletes] = expected[:deletes], expected[:adds] if direction < 0
 
miq_patch_logging("Errors detected during Xml Patching for document:[#{root.name}]. Error count:[#{stats[:errors]}]", :warn) unless stats[:errors].zero?
miq_patch_logging("XML patching results for document:[#{root.name}]: Adds-Applied:[#{stats[:adds]}] Expected:[#{expected[:adds]}] -- Deletes-Applied:[#{stats[:deletes]}] Expected:[#{expected[:deletes]}] -- Updates-Applied:[#{stats[:updates]}] Expected:[#{expected[:updates]}] Errors:[#{stats[:errors]}]")
end
end