package org.objectweb.proactive.extra.gcmdeployment.environment;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import org.objectweb.proactive.core.xml.VariableContractImpl;
import org.objectweb.proactive.core.xml.VariableContractType;
import org.objectweb.proactive.extra.gcmdeployment.GCMDeploymentLoggers;
import org.objectweb.proactive.extra.gcmdeployment.GCMParserConstants;
import org.objectweb.proactive.extra.gcmdeployment.GCMParserHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


class EnvironmentParser {
    private Document document;
    private XPath xpath;

    protected List<String> schemas = null;
    protected VariableContractImpl variableContract;
    protected String namespace;
    protected boolean alreadyParsed;

    protected EnvironmentParser(File descriptor, VariableContractImpl vContract,
            DocumentBuilderFactory domFactory, XPath xpath, String namespace) throws IOException,
            SAXException {
        this(descriptor, vContract, domFactory, xpath, namespace, null);
    }

    protected EnvironmentParser(File descriptor, VariableContractImpl vContract,
            DocumentBuilderFactory domFactory, XPath xpath, String namespace, List<String> userSchemas)
            throws IOException, SAXException {
        this.xpath = xpath;
        this.namespace = namespace;
        if (vContract == null) {
            vContract = new VariableContractImpl();
        }
        this.variableContract = vContract;

        InputSource inputSource = new InputSource(new FileInputStream(descriptor));
        try {
            DocumentBuilder documentBuilder = GCMParserHelper.getNewDocumentBuilder(domFactory);
            document = documentBuilder.parse(inputSource);
        } catch (SAXException e) {
            GCMDeploymentLoggers.GCMD_LOGGER.fatal(e.getMessage());
            throw e;
        }
    }

    protected VariableContractImpl getVariableContract() throws XPathExpressionException, SAXException {
        if (!alreadyParsed) {
            parseEnvironment();
        }

        return variableContract;
    }

    protected Map<String, String> getVariableMap() throws XPathExpressionException, SAXException {
        return getVariableContract().toMap();
    }

    private void parseEnvironment() throws XPathExpressionException, SAXException {
        alreadyParsed = true;

        NodeList environmentNodes = (NodeList) xpath.evaluate("/*/" +
            GCMParserHelper.elementInNS(namespace, "environment"), document, XPathConstants.NODESET);

        if (environmentNodes.getLength() == 1) {
            for (int i = 0; i < GCMParserConstants.VARIABLES_TAGS.length; i++) {
                VariableContractType varContractType = VariableContractType
                        .getType(GCMParserConstants.VARIABLES_TAGS[i]);
                String expr = GCMParserHelper.elementInNS(namespace, GCMParserConstants.VARIABLES_TAGS[i]);
                processVariables(environmentNodes.item(0), expr, varContractType);
            }
        }
    }

    private void processVariables(Node environmentNode, String expr, VariableContractType varContractType)
            throws XPathExpressionException, SAXException {
        Object result = xpath.evaluate(expr, environmentNode, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;
        for (int i = 0; i < nodes.getLength(); ++i) {
            Node node = nodes.item(i);

            String varName = GCMParserHelper.getAttributeValue(node, "name");

            String varValue = variableContract.transform(GCMParserHelper.getAttributeValue(node, "value"));
            if (varValue == null) {
                varValue = "";
            }
            variableContract.setDescriptorVariable(varName, varValue, varContractType);
        }
    }

}

@@ -597,79 +597,8 @@
 rs;%0A
-import org.objectweb.proactive.extra.gcmdeployment.GCMParserConstants;%0A
 impo
@@ -2879,24 +2879,25 @@
 h() == 1) %7B%0A
+%0A
             
@@ -2900,333 +2900,271 @@
     
-for (int i = 0; i %3C GCMParserConstants.VARIABLES_TAGS.length; i++) %7B%0A                VariableContractType varContractType = VariableContractType%0A                        .getType(GCMParserConstants.VARIABLES_TAGS%5Bi%5D);%0A                String expr = GCMParserHelper.elementInNS(namespace, GCMParserConstants.VARIABLES_TAGS%5Bi%5D
+Node envNode = environmentNodes.item(0);%0A%0A            NodeList variableDeclarationNodes = envNode.getChildNodes();%0A%0A            for (int i = 0; i %3C variableDeclarationNodes.getLength(); ++i) %7B%0A                Node varDeclNode = variableDeclarationNodes.item(i
 );%0A
+%0A
     
@@ -3179,88 +3179,90 @@
     
-processVariables(environmentNodes.item(0), expr, varContractType);%0A            %7D
+if (varDeclNode.getNodeType() != Node.ELEMENT_NODE)%0A                    continue;%0A
 %0A   
@@ -3270,85 +3270,126 @@
     
-%7D%0A
     
-%7D%0A%0A
     
-private void processVariables(Node environmentNode, String expr,
+String varContractTypeName = varDeclNode.getNodeName();%0A                VariableContractType varContractType =
  Var
@@ -3397,33 +3397,41 @@
 ableContractType
- 
+.getType(
 varContractType)
@@ -3429,17 +3429,22 @@
 ractType
-)
+Name);
 %0A       
@@ -3452,53 +3452,40 @@
     
-throws XPathExpressionException, SAXException
+    if (varContractType == null)
  %7B%0A 
@@ -3495,225 +3495,198 @@
     
+  
-Object result = xpath.evaluate(expr, environmentNode, XPathConstants.NODESET);%0A        NodeList nodes = (NodeList) result;%0A        for (int i = 0; i %3C nodes.getLength(); ++i) %7B%0A            Node node = nodes.item(i);%0A%0A
+          GCMDeploymentLoggers.GCMD_LOGGER.warn(%22unknown variable declaration type : %22 +%0A                        varContractTypeName);%0A                    continue;%0A                %7D%0A%0A    
     
@@ -3740,25 +3740,32 @@
 ributeValue(
-n
+varDeclN
 ode, %22name%22)
@@ -3763,24 +3763,28 @@
 , %22name%22);%0A%0A
+    
             
@@ -3866,13 +3866,44 @@
 lue(
-node,
+varDeclNode,%0A                       
  %22va
@@ -3918,24 +3918,28 @@
             
+ 
+   
 if (varValue
@@ -3942,32 +3942,36 @@
 alue == null) %7B%0A
+    
                 
@@ -3989,34 +3989,42 @@
 %22%22;%0A            
-%7D%0A
+    %7D%0A    
             vari
@@ -4094,16 +4094,31 @@
 ctType);
+%0A%0A            %7D
 %0A       
@@ -4126,11 +4126,10 @@
 %7D%0A    %7D%0A
-%0A
 %7D%0A

Fix for PROACTIVE-286. Parse var declaration nodes in the same order as they are declared.