/*
 * ProActive Parallel Suite(TM): The Java(TM) library for
 *    Parallel, Distributed, Multi-Core Computing for
 *    Enterprise Grids & Clouds
 *
 * Copyright (C) 1997-2016 INRIA/University of
 *                 Nice-Sophia Antipolis/ActiveEon
 * Contact: proactive@ow2.org or contact@activeeon.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; version 3 of
 * the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * If needed, contact us to obtain a release under GPL Version 2 or 3
 * or a different license than the AGPL.
 *
 * Initial developer(s):               The ProActive Team
 *                         http://proactive.inria.fr/team_members.htm
 */

package org.ow2.proactive.workflow_catalog.rest.util;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.function.BiConsumer;

/**
 * @author ActiveEon Team
 */
public final class WorkflowParser {

    private static final String ATTRIBUTE_JOB_NAME = "name";

    private static final String ATTRIBUTE_JOB_PROJECT_NAME = "projectName";

    private static final String ATTRIBUTE_GENERIC_INFORMATION_NAME = "name";

    private static final String ATTRIBUTE_GENERIC_INFORMATION_VALUE = "value";

    private static final String ATTRIBUTE_VARIABLE_NAME = "name";

    private static final String ATTRIBUTE_VARIABLE_VALUE = "value";

    private static final String ELEMENT_GENERIC_INFORMATION = "genericInformation";

    private static final String ELEMENT_GENERIC_INFORMATION_INFO = "info";

    private static final String ELEMENT_JOB = "job";

    private static final String ELEMENT_VARIABLE = "variable";

    private static final String ELEMENT_VARIABLES = "variables";

    private final XMLStreamReader xmlStreamReader;

    /*
     * Variables indicating which parts of the document have been parsed.
     * Thanks to these information, parsing can be stopped once required
     * information have been extracted.
     */

    private boolean jobHandled = false;

    private boolean variablesHandled = false;

    private boolean genericInformationHandled = false;

    /* Below are instance variables containing values which are extracted */

    private String jobName;

    private String projectName;

    private ImmutableMap<String, String> genericInformation;

    private ImmutableMap<String, String> variables;

    private static final class XmlInputFactoryLazyHolder {

        private static final XMLInputFactory INSTANCE = XMLInputFactory.newInstance();

    }

    public WorkflowParser(InputStream inputStream) throws XMLStreamException {
        this.xmlStreamReader = XmlInputFactoryLazyHolder.INSTANCE.createXMLStreamReader(inputStream);
    }

    public void parse() throws XMLStreamException {
        int eventType;

        ImmutableMap.Builder<String, String> genericInformation = ImmutableMap.builder();
        ImmutableMap.Builder<String, String> variables = ImmutableMap.builder();

        try {
            while (xmlStreamReader.hasNext() && !allElementHandled()) {
                eventType = xmlStreamReader.next();

                switch (eventType) {
                    case XMLEvent.START_ELEMENT:
                        String elementLocalPart = xmlStreamReader.getName().getLocalPart();

                        switch (elementLocalPart) {
                            case ELEMENT_JOB:
                                handleJobElement();
                                break;
                            case ELEMENT_GENERIC_INFORMATION_INFO:
                                handleGenericInformationElement(genericInformation);
                                break;
                            case ELEMENT_VARIABLE:
                                handleVariableElement(variables);
                                break;
                        }

                        break;
                    case XMLEvent.END_ELEMENT:
                        elementLocalPart = xmlStreamReader.getName().getLocalPart();

                        if (elementLocalPart.equals(ELEMENT_GENERIC_INFORMATION)) {
                            this.genericInformationHandled = true;
                        } else if (elementLocalPart.equals(ELEMENT_VARIABLES)) {
                            this.variablesHandled = true;
                        }

                        break;
                    default:
                        break;
                }
            }
        } finally {
            this.xmlStreamReader.close();
            this.genericInformation = genericInformation.build();
            this.variables = variables.build();
        }
    }

    private void handleGenericInformationElement(ImmutableMap.Builder<String, String> genericInformation) {
        handleElementWithMultipleValues(
                genericInformation,
                ATTRIBUTE_GENERIC_INFORMATION_NAME,
                ATTRIBUTE_GENERIC_INFORMATION_VALUE);
    }

    private void handleJobElement() {
        iterateOverAttributes(
                (attributeName, attributeValue) -> {
                    if (attributeName.equals(ATTRIBUTE_JOB_NAME)) {
                        this.jobName = attributeValue;
                    } else if (attributeName.equals(ATTRIBUTE_JOB_PROJECT_NAME)) {
                        this.projectName = attributeValue;
                    }
                }
        );

        jobHandled = true;
    }

    private void handleVariableElement(ImmutableMap.Builder<String, String> variables) {
        handleElementWithMultipleValues(
                variables,
                ATTRIBUTE_VARIABLE_NAME,
                ATTRIBUTE_VARIABLE_VALUE);
    }

    private void handleElementWithMultipleValues(ImmutableMap.Builder<String, String> store, String attributeNameForKey, String attributeNameForValue) {
        String[] key = new String[1];
        String[] value = new String[1];

        iterateOverAttributes(
                (attributeName, attributeValue) -> {
                    if (attributeName.equals(attributeNameForKey)) {
                        key[0] = attributeValue;
                    } else if (attributeName.equals(attributeNameForValue)) {
                        value[0] = attributeValue;
                    }
                }
        );

        store.put(key[0], value[0]);
    }

    private void iterateOverAttributes(BiConsumer<String, String> attribute) {
        for (int i = 0; i < xmlStreamReader.getAttributeCount(); i++) {
            String attributeName = xmlStreamReader.getAttributeName(i).getLocalPart();
            String attributeValue = xmlStreamReader.getAttributeValue(i);

            attribute.accept(attributeName, attributeValue);
        }
    }

    private boolean allElementHandled() {
        return this.jobHandled && this.genericInformationHandled && this.variablesHandled;
    }

    public Optional<String> getJobName() {
        return Optional.fromNullable(jobName);
    }

    public Optional<String> getProjectName() {
        return Optional.fromNullable(projectName);
    }

    public ImmutableMap<String, String> getGenericInformation() {
        return genericInformation;
    }

    public ImmutableMap<String, String> getVariables() {
        return variables;
    }

}

@@ -1553,99 +1553,8 @@
 nt;%0A
-import java.io.File;%0Aimport java.io.FileInputStream;%0Aimport java.io.FileNotFoundException;%0A
 impo

Remove unused imports