#!/usr/bin/env python

"""
This script applies patches to an XML file.

The patch file is itself an XML file.  It can have any root element name,
and uses XML attributes to specify if the elements in the file should replace
existing elements or add new ones.  An XPath attribute is used to specify
where the fix should be applied.  A <targetFile> element is required in the
patch file to specify the base name of the XML file the patches should be
applied to, though the targetFile element is handled outside of this script.

The only restriction is that since the type, xpath, and key attributes are
used to specify the patch placement the target XML cannot use those at a
top level element.

 It can apply patches in 5 ways:

 1) Add an element:
    Put in the element to add, along with the type='add' attribute
    and an xpath attribute specifying where the new element should go.

     <enumerationType type='add' xpath="./">
       <id>MY_TYPE</id>
     </enumerationType>

     This will add a new enumerationType element child to the root element.

 2) Replace an element:
    Put in the new element, with the type='replace' attribute
    and the XPath of the element you want to replace.

     <enumerator type='replace'
               xpath="enumerationType/[id='TYPE']/enumerator[name='XBUS']">
       <name>XBUS</name>
       <value>the new XBUS value</value>
     </enumerator>

    This will replace the enumerator element with name XBUS under the
    enumerationType element with ID TYPE.

 3) Remove an element:
    Put in the element to remove, with the type='remove' attribute and
    the XPath of the element you want to remove. The full element contents
    don't need to be specified, as the XPath is what locates the element.

    <enumerator type='remove'
                xpath='enumerationType[id='TYPE]/enumerator[name='DIMM']>
    </enumerator>

    This will remove the enumerator element with name DIMM under the
    enumerationType element with ID TYPE.

 4) Add child elements to a specific element.  Useful when adding several
    child elements at once.

    Use a type attribute of 'add-child' and specify the target parent with
    the xpath attribute.

     <enumerationType type="add-child" xpath="enumerationType/[id='TYPE']">
       <enumerator>
         <name>MY_NEW_ENUMERATOR</name>
         <value>23</value>
       </enumerator>
       <enumerator>
         <name>ANOTHER_NEW_ENUMERATOR</name>
         <value>99</value>
       </enumerator>
     </enumerationType>

     This will add 2 new <enumerator> elements to the enumerationType
     element with ID TYPE.

 5) Replace a child element inside another element, useful when replacing
    several child elements of the same parent at once.

    Use a type attribute of 'replace-child' and the xpath attribute
    as described above, and also use the key attribute to specify which
    element should be used to match on so the replace can be done.

     <enumerationType type="replace-child"
                      key="name"
                      xpath="enumerationType/[id='TYPE']">
       <enumerator>
         <name>OLD_ENUMERATOR</name>
         <value>newvalue</value>
       </enumerator>
       <enumerator>
         <name>ANOTHER_OLD_ENUMERATOR</name>
         <value>anothernewvalue</value>
       </enumerator>
     </enumerationType>

     This will replace the <enumerator> elements with the names of
     OLD_ENUMERATOR and ANOTHER_OLD_ENUMERATOR with the <enumerator>
     elements specified, inside of the enumerationType element with
     ID TYPE.
"""


from lxml import etree
import sys
import argparse


def delete_attrs(element, attrs):
    for a in attrs:
        try:
            del element.attrib[a]
        except:
            pass

if __name__ == '__main__':

    parser = argparse.ArgumentParser("Applies fixes to XML files")
    parser.add_argument("-x", dest='xml', help='The input XML file')
    parser.add_argument("-p", dest='patch_xml', help='The patch XML file')
    parser.add_argument("-o", dest='output_xml', help='The output XML file')
    args = parser.parse_args()

    if not all([args.xml, args.patch_xml, args.output_xml]):
        parser.print_usage()
        sys.exit(-1)

    rc = 0
    patch_num = 0
    patch_tree = etree.parse(args.patch_xml)
    patch_root = patch_tree.getroot()
    tree = etree.parse(args.xml)
    root = tree.getroot()

    for node in patch_root:
        if (node.tag is etree.PI) or (node.tag is etree.Comment) or \
           (node.tag == "targetFile"):
            continue

        xpath = node.get('xpath', None)
        patch_type = node.get('type', 'add')
        patch_key = node.get('key', None)
        delete_attrs(node, ['xpath', 'type', 'key'])

        if xpath is None:
            print("No XPath attribute found for patch " + str(patch_num))
            rc = -1
        else:
            target = tree.find(xpath)

            if target is None:
                print("Patch " + str(patch_num) + ": Could not find XPath "
                      "target " + xpath)
                rc = -1
            else:
                print("Patch " + str(patch_num) + ":")

                if patch_type == "add":

                    print("  Adding element " + target.tag + " to " + xpath)

                    #The ServerWiz API is dependent on ordering for the
                    #elements at the root node, so make sure they get appended
                    #at the end.
                    if (xpath == "./") or (xpath == "/"):
                        root.append(node)
                    else:
                        target.append(node)

                elif patch_type == "remove":

                    print("  Removing element " + xpath)
                    parent = target.find("..")
                    if parent is None:
                        print("Could not find parent of " + xpath +
                              " so can't remove this element")
                        rc = -1
                    else:
                        parent.remove(target)

                elif patch_type == "replace":

                    print("  Replacing element " + xpath)
                    parent = target.find("..")
                    if parent is None:
                        print("Could not find parent of " + xpath +
                              " so can't replace this element")
                        rc = -1
                    else:
                        parent.remove(target)
                        parent.append(node)

                elif patch_type == "add-child":

                    for child in node:
                        print("  Adding a '" + child.tag + "' child element "
                              "to " + xpath)
                        target.append(child)

                elif patch_type == "replace-child":

                    if patch_key is not None:
                        updates = []
                        for child in node:
                            #Use the key to figure out which element to replace
                            key_element = child.find(patch_key)
                            for target_child in target:
                                for grandchild in target_child:
                                    if (grandchild.tag == patch_key) and \
                                       (grandchild.text == key_element.text):
                                        update = {}
                                        update['remove'] = target_child
                                        update['add'] = child
                                        updates.append(update)

                        for update in updates:
                            print("  Replacing a '" + update['remove'].tag +
                                  "' element in path " + xpath)
                            target.remove(update['remove'])
                            target.append(update['add'])

                    else:
                        print("Patch type is replace-child, but 'key' "
                              "attribute isn't set")
                        rc = -1

                else:
                    print("Unknown patch type attribute found:  " + patch_type)
                    rc = -1

        patch_num = patch_num + 1

    tree.write(args.output_xml)
    sys.exit(rc)
