SoilXMLWriter.java [src/java/d/util] Revision: default  Date:
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API, and application suite.
 *
 * 2012-2017, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package d.util;

import csip.api.server.ServiceException;
import d.dataNodes.R2StaticData;
import d.dataNodes.XMLData;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import soils.Component;
import soils.Horizon;
import soils.MapUnit;

/**
 *
 * @author brad
 */
public class SoilXMLWriter {
    
    public File writeXMLfile(MapUnit mapUnit,Component component,Horizon horizon,String dir) throws ParserConfigurationException, TransformerException, FileNotFoundException, ServiceException{
        Document dom;
        Transformer tr;
        String fileName;
        Element rootElement;
        File soilFile;
        String sTiledHydrologicClass;
        String sHydrologicClass;
        String drained;
        String undrained;

        fileName = mapUnit.areaname() + "/" + mapUnit.musym() + "/" + mapUnit.muname()+ "/"+ component.compname() + ".xml";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        
        DocumentBuilder db = dbf.newDocumentBuilder();
        
        dom = db.newDocument();
        
        rootElement = dom.createElement("Obj");
        
        //Header data
        rootElement.appendChild(createTypeElement(dom,"SOIL"));
        rootElement.appendChild(createFilenameElement(dom,fileName));
        rootElement.appendChild(createScienceElement(dom,"20051219")); // was hard coded in the original c++ but not sure it should be
        
        //component data
        rootElement.appendChild(createFloatElement(dom,"TYPICAL_LENGTH",(float)component.slopelenusle_r(),"U_METER"));
        rootElement.appendChild(createFloatElement(dom,"TYPICAL_STEEPNESS",(float) component.slope_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"SOIL_T_VALUE",(float) component.tfact(),"U_TON_P_AC_YR"));
        
        sTiledHydrologicClass = sHydrologicClass = "Nan";
        if(component.hydgrp().length() > 0){
            if(component.hydgrp().length() == 3){
                drained = component.hydgrp().substring(0, 1);
                undrained = component.hydgrp().substring(2, 3);
            }else
                /* drained is undefined, so set same as undrained */
                undrained = drained = component.hydgrp().substring(0,1);
            
            sTiledHydrologicClass = R2StaticData.Rusle2Hydrologic.getOrDefault(drained, "HYDROLOGIC_CLASS_HIGH_RO");
            sHydrologicClass = R2StaticData.Rusle2Hydrologic.getOrDefault(undrained, "HYDROLOGIC_CLASS_HIGH_RO");
        }
        
        rootElement.appendChild(createLstElement(dom,"TILED_HYDROLOGIC_CLASS",sTiledHydrologicClass));
        rootElement.appendChild(createLstElement(dom,"HYDROLOGIC_CLASS",sHydrologicClass));
        
        //horizon data
        rootElement.appendChild(createFloatElement(dom,"NASIS_OM_REP_HOR_1",(float)horizon.om_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"ORGANIC_MATTER",(float)horizon.om_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"NASIS_PH_1TO1_H20_REP_HOR_1",(float)horizon.ph1to1h2o_r(),"U_PH_UNITS"));
        rootElement.appendChild(createFloatElement(dom,"ERODIBILITY",(float)component.calculated_kffact(),"U_ENGLISH_EROD"));
        rootElement.appendChild(createFloatElement(dom,"ERODIBILITY_HAND",(float)component.calculated_kffact(),"U_ENGLISH_EROD"));
        rootElement.appendChild(createSubElement(dom,"ERODIBILITY_OPTION_PTR","ERODIBILITY_OPTION_SET_BY_USER"));
        rootElement.appendChild(createFloatElement(dom,"SAND",(float)component.calculated_sandtotal_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"SILT",(float)component.calculated_silttotal_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"CLAY",(float)component.calculated_claytotal_r(),"U_PERCENT"));
        
        //NASIS data
        rootElement.appendChild(createStringElement(dom,"NASIS_MUSYM",mapUnit.musym(),"1"));
        rootElement.appendChild(createStringElement(dom,"NASIS_SASYM",mapUnit.muname(),"1"));
        rootElement.appendChild(createFloatElement(dom,"NASIS_CEC_7",(float)horizon.cec7_r(),"U_MEQ_P_100_ML"));
        rootElement.appendChild(createFloatElement(dom,"NASIS_WATER_CONTENT_THIRD_BAR",(float)horizon.wthirdbar_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"NASIS_WATER_CONTENT_15_BAR",(float)horizon.wfifteenbar_r(),"U_PERCENT"));
        rootElement.appendChild(createFloatElement(dom,"NASIS_BULK_DENSITY_THIRD_BAR",(float)horizon.dbthirdbar_r(),"U_PERCENT"));
        
        
        dom.appendChild(rootElement);
        
        
        tr = TransformerFactory.newInstance().newTransformer();

        fileName = dir + "/" + fileName;
        soilFile = new File(fileName);
        soilFile.getParentFile().mkdirs();
        // send DOM to file
        tr.transform(new DOMSource(dom), 
                             new StreamResult(new FileOutputStream(fileName)));
        
        return new File(fileName);
    }
    
    private Element createFloatElement(Document dom,String name,float value,String unit){
        Element floatElement = dom.createElement("Flt");
        Element nameElement = dom.createElement("Name");
        Element dataElement = dom.createElement("Data");
        Element unitElement = dom.createElement("Unit");
        
        nameElement.setTextContent(name);
        dataElement.setTextContent(String.valueOf(value));
        unitElement.setTextContent(unit);

        floatElement.appendChild(nameElement);
        floatElement.appendChild(dataElement);
        floatElement.appendChild(unitElement);
        
        return floatElement;
    }
    
    private Element createTypeElement(Document dom,String type){
        Element typeElement = dom.createElement("Type");
        
        typeElement.setTextContent(type);
        
        return typeElement;
    }
    
    private Element createFilenameElement(Document dom,String filename){
        Element filenameElement = dom.createElement("Filename");
        
        filenameElement.setTextContent("soils\\"+filename.replace("/", "\\"));
        
        return filenameElement;
    }
    
    private Element createScienceElement(Document dom,String value){
        Element scienceElement = dom.createElement("Science");
        
        scienceElement.setTextContent(value);
        
        return scienceElement;
    }
    
    private Element createLstElement(Document dom,String name, String data){ // I think this is a list element but I have not seen a list longer than 1 yet
        Element listElement = dom.createElement("Lst");
        Element nameElement = dom.createElement("Name");
        Element dataElement = dom.createElement("Data");
        
        nameElement.setTextContent(name);
        dataElement.setTextContent(data);
        
        listElement.appendChild(nameElement);
        listElement.appendChild(dataElement);
        
        return listElement;
    }
    
    private Element createStringElement(Document dom, String name, String data,String dims){
        Element stringElement = dom.createElement("Str");
        Element nameElement = dom.createElement("Name");
        Element dataElement = dom.createElement("Data"); 
        Element dimsElement = dom.createElement("Dims");
        
        nameElement.setTextContent(name);
        dataElement.setTextContent(data);
        dimsElement.setTextContent(dims);
        
        stringElement.appendChild(nameElement);
        stringElement.appendChild(dataElement);
        stringElement.appendChild(dimsElement);
        
        return stringElement;
    }
    
    private Element createSubElement(Document dom,String name,String sub){
        Element subElement = dom.createElement("SbR");
        Element nameElement = dom.createElement("Name");
        Element dataElement = dom.createElement("Data"); 
        
        nameElement.setTextContent(name);
        dataElement.setTextContent(sub);
        
        subElement.appendChild(nameElement);
        subElement.appendChild(dataElement);
        
        return subElement;
    }
}