/*******************************************************************************
 * Copyright (c) 2010, 2016 Ericsson
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License 2.0 which
 * accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Patrick Tasse - Initial API and implementation
 *   Matthew Khouzam - Add support for default xml parsers
 *******************************************************************************/

package org.eclipse.tracecompass.tmf.core.parsers.custom;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.common.core.xml.XmlUtils;
import org.eclipse.tracecompass.internal.tmf.core.Activator;
import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * Trace definition for custom XML traces.
 *
 * @author Patrick Tassé
 */
public class CustomXmlTraceDefinition extends CustomTraceDefinition {

    /**
     * Custom XML label used internally and therefore should not be externalized
     */
    public static final String CUSTOM_XML_CATEGORY = "Custom XML"; //$NON-NLS-1$


    /** Name of the default XML definitions file */
    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME = "custom_xml_default_parsers.xml"; //$NON-NLS-1$

    /** Name of the XML definitions file */
    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml"; //$NON-NLS-1$

    /** Path to the XML definitions file */
    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME =
            Platform.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
                    CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_FILE_NAME;

    /** Path to the XML definitions file */
    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME =
            Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();

    /**
     * Legacy path to the XML definitions file (in the UI plug-in of linux tools) TODO Remove
     * once we feel the transition phase is over.
     */
    private static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI =
            Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
                    .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
                    .append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();

    /**
     * Legacy path to the XML definitions file (in the core plug-in of linux tools) TODO Remove
     * once we feel the transition phase is over.
     */
    private static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE =
            Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
                    .append("org.eclipse.linuxtools.tmf.core") //$NON-NLS-1$
                    .append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();

    // TODO: These strings should not be externalized
    private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomXmlTraceDefinition_definitionRootElement;
    private static final String DEFINITION_ELEMENT = Messages.CustomXmlTraceDefinition_definition;
    private static final String CATEGORY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_category;
    private static final String TAG_ATTRIBUTE = Messages.CustomXmlTraceDefinition_tag;
    private static final String NAME_ATTRIBUTE = Messages.CustomXmlTraceDefinition_name;
    private static final String LOG_ENTRY_ATTRIBUTE = Messages.CustomXmlTraceDefinition_logEntry;
    private static final String EVENT_TYPE_ATTRIBUTE = Messages.CustomXmlTraceDefinition_eventType;
    private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomXmlTraceDefinition_timestampOutputFormat;
    private static final String INPUT_ELEMENT_ELEMENT = Messages.CustomXmlTraceDefinition_inputElement;
    private static final String ATTRIBUTE_ELEMENT = Messages.CustomXmlTraceDefinition_attribute;
    private static final String INPUT_DATA_ELEMENT = Messages.CustomXmlTraceDefinition_inputData;
    private static final String ACTION_ATTRIBUTE = Messages.CustomXmlTraceDefinition_action;
    private static final String FORMAT_ATTRIBUTE = Messages.CustomXmlTraceDefinition_format;
    private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomXmlTraceDefinition_outputColumn;

    /**
     * This is the value that the extension sets for traceContentType to be able
     * to load an XML parser
     **/
    private static final String TRACE_CONTENT_TYPE_ATTRIBUTE_VALUE = "xml"; //$NON-NLS-1$

    /** Top-level input element */
    public CustomXmlInputElement rootInputElement;

    /**
     * Default constructor
     */
    public CustomXmlTraceDefinition() {
        this(CUSTOM_XML_CATEGORY, "", null, new ArrayList<OutputColumn>(), ""); //$NON-NLS-1$ //$NON-NLS-2$
    }

    /**
     * Full constructor
     *
     * @param category
     *            Category of the trace type
     * @param traceType
     *            Name of the trace type
     * @param rootElement
     *            The top-level XML element
     * @param outputs
     *            The list of output columns
     * @param timeStampOutputFormat
     *            The timestamp format to use
     */
    public CustomXmlTraceDefinition(String category, String traceType, CustomXmlInputElement rootElement,
            List<OutputColumn> outputs, String timeStampOutputFormat) {
        this.categoryName = category;
        this.definitionName = traceType;
        this.rootInputElement = rootElement;
        this.outputs = outputs;
        this.timeStampOutputFormat = timeStampOutputFormat;
    }

    @Override
    public void save() {
        save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
    }

    @Override
    public void save(String path) {
        try {
            DocumentBuilder db = XmlUtils.newSafeDocumentBuilderFactory().newDocumentBuilder();
            // The following allows xml parsing without access to the dtd
            db.setEntityResolver(createEmptyEntityResolver());

            // The following catches xml parsing exceptions
            db.setErrorHandler(createErrorHandler());

            Document doc = null;
            File file = new File(path);
            if (file.canRead()) {
                doc = db.parse(file);
                if (!doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
                    Activator.logError(String.format("Error saving CustomXmlTraceDefinition: path=%s is not a valid custom parser file", path)); //$NON-NLS-1$
                    return;
                }
            } else {
                doc = db.newDocument();
                Node node = doc.createElement(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT);
                doc.appendChild(node);
            }

            Element root = doc.getDocumentElement();

            Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
            if (oldDefinitionElement != null) {
                root.removeChild(oldDefinitionElement);
            }
            Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
            root.appendChild(definitionElement);
            definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
            definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);

            if (timeStampOutputFormat != null && !timeStampOutputFormat.isEmpty()) {
                Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
                definitionElement.appendChild(formatElement);
                formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
            }

            if (rootInputElement != null) {
                definitionElement.appendChild(createInputElementElement(rootInputElement, doc));
            }

            if (outputs != null) {
                for (OutputColumn output : outputs) {
                    Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);
                    definitionElement.appendChild(outputColumnElement);
                    outputColumnElement.setAttribute(TAG_ATTRIBUTE, output.tag.name());
                    outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);
                }
            }

            Transformer transformer = XmlUtils.newSecureTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$

            // initialize StreamResult with File object to save to file
            StreamResult result = new StreamResult(new StringWriter());
            DOMSource source = new DOMSource(doc);
            transformer.transform(source, result);
            String xmlString = result.getWriter().toString();

            try (FileWriter writer = new FileWriter(file);) {
                writer.write(xmlString);
            }

            TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);

        } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException | IOException | SAXException e) {
            Activator.logError("Error saving CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
        }
    }

    private Element createInputElementElement(CustomXmlInputElement inputElement, Document doc) {
        Element inputElementElement = doc.createElement(INPUT_ELEMENT_ELEMENT);
        inputElementElement.setAttribute(NAME_ATTRIBUTE, inputElement.getElementName());

        if (inputElement.isLogEntry()) {
            inputElementElement.setAttribute(LOG_ENTRY_ATTRIBUTE, Boolean.toString(inputElement.isLogEntry()));
        }

        if (inputElement.getEventType() != null) {
            inputElementElement.setAttribute(EVENT_TYPE_ATTRIBUTE, inputElement.getEventType());
        }

        if (inputElement.getParentElement() != null) {
            Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
            inputElementElement.appendChild(inputDataElement);
            inputDataElement.setAttribute(TAG_ATTRIBUTE, inputElement.getInputTag().name());
            inputDataElement.setAttribute(NAME_ATTRIBUTE, inputElement.getInputName());
            inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputElement.getInputAction()));
            String inputFormat = inputElement.getInputFormat();
            if (inputFormat != null && !inputFormat.isEmpty()) {
                inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputFormat);
            }
        }

        if (inputElement.getAttributes() != null) {
            for (CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
                Element inputAttributeElement = doc.createElement(ATTRIBUTE_ELEMENT);
                inputElementElement.appendChild(inputAttributeElement);
                inputAttributeElement.setAttribute(NAME_ATTRIBUTE, attribute.getAttributeName());
                Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
                inputAttributeElement.appendChild(inputDataElement);
                inputDataElement.setAttribute(TAG_ATTRIBUTE, attribute.getInputTag().name());
                inputDataElement.setAttribute(NAME_ATTRIBUTE, attribute.getInputName());
                inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(attribute.getInputAction()));
                String inputFormat = attribute.getInputFormat();
                if (inputFormat != null && !inputFormat.isEmpty()) {
                    inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputFormat);
                }
            }
        }

        if (inputElement.getChildElements() != null) {
            for (CustomXmlInputElement childInputElement : inputElement.getChildElements()) {
                inputElementElement.appendChild(createInputElementElement(childInputElement, doc));
            }
        }

        return inputElementElement;
    }

    /**
     * Load all custom XML trace definitions, including the user-defined and
     * default (built-in) parsers.
     *
     * @return The loaded trace definitions
     */
    public static CustomXmlTraceDefinition[] loadAll() {
        return loadAll(true);
    }

    /**
     * Load all custom XML trace definitions, including the user-defined and,
     * optionally, the default (built-in) parsers.
     *
     * @param includeDefaults
     *            if true, the default (built-in) parsers are included
     *
     * @return The loaded trace definitions
     */
    public static CustomXmlTraceDefinition[] loadAll(boolean includeDefaults) {
        File defaultFile = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
        File legacyFileUI = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
        File legacyFileCore = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);

        /*
         * If there is no file at the expected location, check the legacy
         * locations instead.
         */
        if (!defaultFile.exists()) {
            if (legacyFileCore.exists()) {
                transferDefinitions(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);
            } else if (legacyFileUI.exists()) {
                transferDefinitions(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
            }
        }

        Set<CustomXmlTraceDefinition> defs = new TreeSet<>(Comparator.comparing(CustomXmlTraceDefinition::getCategoryName).thenComparing(CustomXmlTraceDefinition::getDefinitionName));
        defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME)));
        if (includeDefaults) {
            defs.addAll(Arrays.asList(loadAll(CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME)));

            // Also load definitions contributed by extensions
            Collection<String> paths = getExtensionDefinitionsPaths(TRACE_CONTENT_TYPE_ATTRIBUTE_VALUE);
            for (String customTraceDefinitionPath : paths) {
                defs.addAll(Arrays.asList(loadAll(customTraceDefinitionPath)));
            }
        }
        return defs.toArray(new CustomXmlTraceDefinition[0]);
    }

    private static void transferDefinitions(String defFile) {
        CustomXmlTraceDefinition[] oldDefs = loadAll(defFile);
        for (CustomXmlTraceDefinition def : oldDefs) {
            /* Save in the new location */
            def.save();
        }
    }


    /**
     * Load all the XML trace definitions in the given definitions file.
     *
     * @param path
     *            Path to the definitions file to load
     * @return The loaded trace definitions
     */
    public static CustomXmlTraceDefinition[] loadAll(String path) {
        File file = new File(path);
        if (!file.canRead()) {
            return new CustomXmlTraceDefinition[0];
        }
        try (FileInputStream fis = new FileInputStream(file);) {
            return loadAll(fis);
        } catch (IOException e) {
            Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + path, e); //$NON-NLS-1$
        }
        return new CustomXmlTraceDefinition[0];
    }

    /**
     * Load all the XML trace definitions from the given stream
     *
     * @param stream
     *            An input stream from which to read the definitions
     * @return The loaded trace definitions
     */
    public static CustomXmlTraceDefinition[] loadAll(InputStream stream) {
        try {
            DocumentBuilder db = XmlUtils.newSafeDocumentBuilderFactory().newDocumentBuilder();

            // The following allows xml parsing without access to the dtd
            db.setEntityResolver(createEmptyEntityResolver());

            // The following catches xml parsing exceptions
            db.setErrorHandler(createErrorHandler());

            Document doc = db.parse(stream);
            Element root = doc.getDocumentElement();
            if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
                return new CustomXmlTraceDefinition[0];
            }

            ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<>();
            NodeList nodeList = root.getChildNodes();
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
                    CustomXmlTraceDefinition def = extractDefinition((Element) node);
                    if (def != null) {
                        defList.add(def);
                    }
                }
            }
            return defList.toArray(new CustomXmlTraceDefinition[0]);
        } catch (ParserConfigurationException | SAXException | IOException e) {
            Activator.logError("Error loading all in CustomXmlTraceDefinition: path=" + stream, e); //$NON-NLS-1$
        }
        return new CustomXmlTraceDefinition[0];
    }

    /**
     * Load the given trace definition.
     *
     * @param categoryName
     *            Category of the definition to load
     * @param definitionName
     *            Name of the XML trace definition to load
     * @return The loaded trace definition
     */
    public static CustomXmlTraceDefinition load(String categoryName, String definitionName) {
        try {
            DocumentBuilder db = XmlUtils.newSafeDocumentBuilderFactory().newDocumentBuilder();

            // The following allows xml parsing without access to the dtd
            EntityResolver resolver = (publicId, systemId) -> {
                String empty = ""; //$NON-NLS-1$
                ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
                return new InputSource(bais);
            };
            db.setEntityResolver(resolver);

            // The following catches xml parsing exceptions
            db.setErrorHandler(new ErrorHandler() {
                @Override
                public void error(SAXParseException saxparseexception) throws SAXException {
                    // Do nothing
                }

                @Override
                public void warning(SAXParseException saxparseexception) throws SAXException {
                    // Do nothing
                }

                @Override
                public void fatalError(SAXParseException saxparseexception) throws SAXException {
                    throw saxparseexception;
                }
            });

            CustomXmlTraceDefinition value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
            if (value == null) {
                value = lookupXmlDefinition(categoryName, definitionName, db, CUSTOM_XML_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
            }
            return value;
        } catch (ParserConfigurationException | SAXException | IOException e) {
            Activator.logError("Error loading CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
        }
        return null;
    }

    private static CustomXmlTraceDefinition lookupXmlDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
        File file = new File(source);
        if (!file.exists()) {
            return null;
        }

        Document doc = db.parse(file);

        Element root = doc.getDocumentElement();
        if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
            return null;
        }

        Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
        if (definitionElement != null) {
            return extractDefinition(definitionElement);
        }
        return null;
    }

    private static Element findDefinitionElement(Element root, String categoryName, String definitionName) {
        NodeList nodeList = root.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
                Element element = (Element) node;
                String categoryAttribute = element.getAttribute(CATEGORY_ATTRIBUTE);
                if (categoryAttribute.isEmpty()) {
                    categoryAttribute = CUSTOM_XML_CATEGORY;
                }
                String nameAttribute = element.getAttribute(NAME_ATTRIBUTE);
                if (categoryName.equals(categoryAttribute) &&
                        definitionName.equals(nameAttribute)) {
                    return element;
                }
            }
        }
        return null;
    }

    /**
     * Extract a trace definition from an XML element.
     *
     * @param definitionElement
     *            Definition element
     * @return The extracted trace definition
     */
    public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) {
        CustomXmlTraceDefinition def = new CustomXmlTraceDefinition();

        def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
        if (def.categoryName.isEmpty()) {
            def.categoryName = CUSTOM_XML_CATEGORY;
        }
        def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
        if (def.definitionName.isEmpty()) {
            return null;
        }

        NodeList nodeList = definitionElement.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            String nodeName = node.getNodeName();
            if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
                Element formatElement = (Element) node;
                def.timeStampOutputFormat = formatElement.getTextContent();
            } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
                CustomXmlInputElement inputElement = extractInputElement((Element) node);
                if (inputElement != null) {
                    if (def.rootInputElement == null) {
                        def.rootInputElement = inputElement;
                    } else {
                        return null;
                    }
                }
            } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
                Element outputColumnElement = (Element) node;
                Entry<@NonNull Tag, @NonNull String> entry = extractTagAndName(outputColumnElement, TAG_ATTRIBUTE, NAME_ATTRIBUTE);
                OutputColumn outputColumn = new OutputColumn(entry.getKey(), entry.getValue());
                def.outputs.add(outputColumn);
            }
        }
        return def;
    }

    private static CustomXmlInputElement extractInputElement(Element inputElementElement) {
        CustomXmlInputElement inputElement = new CustomXmlInputElement();
        inputElement.setElementName(inputElementElement.getAttribute(NAME_ATTRIBUTE));
        inputElement.setLogEntry((Boolean.toString(true).equals(inputElementElement.getAttribute(LOG_ENTRY_ATTRIBUTE))) ? true : false);
        String eventType = inputElementElement.getAttribute(EVENT_TYPE_ATTRIBUTE);
        inputElement.setEventType(eventType.isEmpty() ? null : eventType);
        NodeList nodeList = inputElementElement.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            String nodeName = node.getNodeName();
            if (nodeName.equals(INPUT_DATA_ELEMENT)) {
                Element inputDataElement = (Element) node;
                Entry<@NonNull Tag, @NonNull String> entry = extractTagAndName(inputDataElement, TAG_ATTRIBUTE, NAME_ATTRIBUTE);
                inputElement.setInputTag(entry.getKey());
                inputElement.setInputName(entry.getValue());
                inputElement.setInputAction(Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE)));
                inputElement.setInputFormat(inputDataElement.getAttribute(FORMAT_ATTRIBUTE));
            } else if (nodeName.equals(ATTRIBUTE_ELEMENT)) {
                Element attributeElement = (Element) node;

                String attributeName = attributeElement.getAttribute(NAME_ATTRIBUTE);
                NodeList attributeNodeList = attributeElement.getChildNodes();
                for (int j = 0; j < attributeNodeList.getLength(); j++) {
                    Node attributeNode = attributeNodeList.item(j);
                    String attributeNodeName = attributeNode.getNodeName();
                    if (attributeNodeName.equals(INPUT_DATA_ELEMENT)) {
                        Element inputDataElement = (Element) attributeNode;
                        Entry<@NonNull Tag, @NonNull String> entry = extractTagAndName(inputDataElement, TAG_ATTRIBUTE, NAME_ATTRIBUTE);
                        int action = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
                        String format = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
                        inputElement.addAttribute(new CustomXmlInputAttribute(attributeName, entry.getKey(), entry.getValue(), action, format));
                        break;
                    }
                }
            } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {
                Element childInputElementElement = (Element) node;
                CustomXmlInputElement childInputElement = extractInputElement(childInputElementElement);
                if (childInputElement != null) {
                    inputElement.addChild(childInputElement);
                }
            }
        }
        return inputElement;
    }

    /**
     * Delete a definition from the currently loaded ones.
     *
     * @param categoryName
     *            The category of the definition to delete
     * @param definitionName
     *            The name of the definition to delete
     */
    public static void delete(String categoryName, String definitionName) {
        try {
            DocumentBuilder db = XmlUtils.newSafeDocumentBuilderFactory().newDocumentBuilder();

            // The following allows xml parsing without access to the dtd
            EntityResolver resolver = (publicId, systemId) -> {
                String empty = ""; //$NON-NLS-1$
                ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
                return new InputSource(bais);
            };
            db.setEntityResolver(resolver);

            // The following catches xml parsing exceptions
            db.setErrorHandler(new ErrorHandler() {
                @Override
                public void error(SAXParseException saxparseexception) throws SAXException {
                    // Do nothing
                }

                @Override
                public void warning(SAXParseException saxparseexception) throws SAXException {
                    // Do nothing
                }

                @Override
                public void fatalError(SAXParseException saxparseexception) throws SAXException {
                    throw saxparseexception;
                }
            });

            File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);
            Document doc = db.parse(file);

            Element root = doc.getDocumentElement();
            if (!root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {
                return;
            }

            Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
            if (definitionElement != null) {
                root.removeChild(definitionElement);
            }

            Transformer transformer = XmlUtils.newSecureTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$

            // initialize StreamResult with File object to save to file
            StreamResult result = new StreamResult(new StringWriter());
            DOMSource source = new DOMSource(doc);
            transformer.transform(source, result);
            String xmlString = result.getWriter().toString();

            try (FileWriter writer = new FileWriter(file);) {
                writer.write(xmlString);
            }

            TmfTraceType.removeCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);
            // Check if default definition needs to be reloaded
            TmfTraceType.addCustomTraceType(CustomXmlTrace.class, categoryName, definitionName);

        } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
            Activator.logError("Error deleteing CustomXmlTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
        }
    }

}
