#!/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)

    errors = []
    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

        patch_num = patch_num + 1

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

        print("Patch " + str(patch_num) + ":")

        try:
            if xpath is None:
                raise Exception("  E>  No XPath attribute found")

            target = tree.find(xpath)

            if target is None:
                raise Exception("  E>  Could not find XPath target " + xpath)

            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:
                    raise Exception("  E>  Could not find parent of " + xpath +
                                    " so can't remove this element")
                parent.remove(target)

            elif patch_type == "replace":

                print("  Replacing element " + xpath)
                parent = target.find("..")
                if parent is None:
                    raise Exception("  E>  Could not find parent of " + xpath +
                                    " so can't replace this element")
                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 None:
                    raise Exception("  E>  Patch type is replace-child, but"
                                    " 'key' attribute isn't set")
                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:
                raise Exception("  E>  Unknown patch type attribute found:  " +
                                patch_type)

        except Exception as e:
            print e
            errors.append(e)

    tree.write(args.output_xml)

    if errors:
        print("Exiting with " + str(len(errors)) + " total errors")
        sys.exit(-1)
