/*
 * DataFileParser.java
 *
 * This file contains functions to parser the data XML file for WEPS crops and operations.
 * The parsing is done with the SAX parser and the important information is saved
 * in internal data structures. 
 *
 * Created on July 27, 2004, 3:24 PM
 */
package ex1;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;

/**
 * This class contains functions to parse the data XML file for WEPS crops and operations.
 * The parsing is done with the SAX parser and the important information is saved
 * in internal data structures. 
 *
 * @author  jrf
 */
public class DataFileParser extends DefaultHandler {

    DefnFileParser pListing;    // link to main parameter listing

    private boolean grabName;   // true if we are getting a parameter name
    private boolean grabValue;  // true if we are getting a parameter value
    private boolean grabObjectName;
    private String name;        // current parameter name read
    private String theVal;      // current parameter value read (as string)

    /**
     *
     */
    public String objectName;
    private boolean grabId;
    private boolean grabCode;
    private boolean inIdSection;
    private String theCode, theId;

    private final String mcrew_cfg;   // directory where DTD files can be found
    private final boolean isCropXml;  // true if we are parsing a crop files
    private WepsDBFile currentFile; // link to file info we are parsing

    /** 
     * Creates a new instance to handle parsing detail CROP or OPRN files
     * 
     *
     * @param listing  parameter dictionary constructed from mcrew config files
     * @param topdir directory of mcrew files
     * @param isCrop true if we are parsing a crop xml file (simpler structure), false for operations
     *
     */
    public DataFileParser(DefnFileParser listing, String topdir, boolean isCrop) {
        pListing = listing;

        isCropXml = isCrop;

        //actionStores = new ArrayList();
        if (topdir.endsWith("/") || topdir.endsWith("\\")) {
        } else {
            topdir += "/";
        }
        mcrew_cfg = topdir;
    }

    /**
     * Parses the weps file contained in the structure.
     *
     * @param xfile File to load as a WepsDBFile class
     */
    public void addXmlFile(WepsDBFile xfile) {
        SAXParserFactory factory;
        SAXParser saxParser;
        factory = SAXParserFactory.newInstance();
        TFile wf = new TFile(xfile.getPathName());
        //actionSeq = new ArrayList();
        //actionStores.add(actionSeq);
        currentFile = xfile;

        try {
            // Parse the input
            saxParser = factory.newSAXParser();
            saxParser.parse(new TFileInputStream(wf), this);
        } catch (IOException | ParserConfigurationException | SAXException t) {
            t.printStackTrace();
        }
    }

    /**
     * Called automatically by the SAX parser.
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void startDocument()
            throws SAXException {
        inIdSection = false;
    }

    /**
     * Called automatically by the SAX parser.
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void endDocument()
            throws SAXException {
        //At the end of the document, we want to make sure it has devnotes.
//        if(isCropXml) currentFile.updateCropNotes();
//        else currentFile.updateOpNotes();
    }

    /**
     * This translates the external DTD references to the file location in the 
     * main mcrew_cfg directory. This is called automatically by the SAX parser.
     * @param publicID
     * @param sysID
     * @return 
     */
    @Override
    public InputSource resolveEntity(String publicID, String sysID) {
        TFile base = new TFile(sysID);
        String n = "file:" + mcrew_cfg + base.getName();
        return new InputSource(n);
    }

    /**
     * Called automatically by the SAX parser when a beginning <> tag is seen.
     * @param namespaceURI
     * @param attrs
     * @param lName
     * @param qName
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void startElement(String namespaceURI,
            String lName, // local name
            String qName, // qualified name
            Attributes attrs)
            throws SAXException {

        String eName = lName; // element name
        if ("".equals(eName)) {
            eName = qName;
        }
        switch (eName) {
            case "operationname":
                objectName = "";
                grabObjectName = true;
                break;
            case "cropname":
                objectName = "";
                grabObjectName = true;
                break;
            case "name":
                name = "";
                grabName = true;
                break;
            case "value":
                theVal = "";
                grabValue = true;
                break;
            case "actionvalue":
                currentFile.startActionNode();
                break;
            case "identity":
                inIdSection = true;
                break;
            case "code":
                if (inIdSection) {
                    grabCode = true;
                    theCode = "";
                }
                break;
            case "id":
                if (inIdSection) {
                    grabId = true;
                    theId = "";
                }
                break;
        }

    }

    /**
     * Called automatically by the SAX parser when an ending <> is seen.
     * This causes the information to be added to the internal viewer classes
     * @param namespaceURI
     * @param qName
     * @param sName
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void endElement(String namespaceURI,
            String sName, // simple name
            String qName // qualified name
    )
            throws SAXException {
        String eName = sName; // element name
        if ("".equals(eName)) {
            eName = qName;
        }

        if (eName.equals("operationname")) {
            grabObjectName = false;
            currentFile.objectName = objectName;
        } else if (eName.equals("cropname")) {
            grabObjectName = false;
            currentFile.objectName = objectName;
        } else if (eName.equals("param")) {
            String parmName2 = name;
            if (!isCropXml) {
                int intId = Integer.parseInt(theId);
                parmName2 = parmName2.concat(Integer.toString(intId));
            }
            if (currentFile.addParm(parmName2, theVal) == false) {
                String estr = "";
                if (!isCropXml) {
                    estr = "Could not set parameter: '" + name + "' to " + theVal + " in process/group "
                            + theId + ". Source file: '" + currentFile.getFileName() + "'";
                    estr = estr.concat("\nReason: Parameter not in defn file/not necessary.\n");
                    //System.out.println(lastBuf + " " + Integer.toString(lastlen) + "  " + Integer.toString(lastoff));
                } else {
                    estr = "Could not set parm value: '" + parmName2 + "' to " + theVal
                            + " source file: " + currentFile.getFileName();
                }
                //System.out.println(estr);
                ErrorSink.add(estr);
            }
        } else if (eName.equals("identity")) {
            inIdSection = false;
        } else if (eName.equals("actionvalue")) {
            OpAction a = pListing.findOpAction(theCode, theId);
            if (a == null) {
                String estr = "Could not find process/group: " + theCode + " " + theId
                        + " source file: " + currentFile.getFileName();
                ErrorSink.add(estr);
                //System.out.println(estr);
            } else {
                //actionSeq.add(a);
                currentFile.endActionNode(a);
            }
        } else if (eName.equals("name")) {
            grabName = false;
            name = name.trim();
        } else if (eName.equals("value")) {
            grabValue = false;
            theVal = theVal.trim();
        } else if (eName.equals("code") && inIdSection) {
            theCode = theCode.trim();
            grabCode = false;
        } else if (eName.equals("id") && inIdSection) {
            grabId = false;
            theId = theId.trim();
        }
    }

    /**
     * 
     * Called automatically by the SAX parser to get the string inside the tags
     * This may require several calls to piece together the data.
     *
     * @param buf
     * @param len
     * @param offset
     * @throws org.xml.sax.SAXException
     */
    @Override
    public void characters(char buf[], int offset, int len)
            throws SAXException {

        String s = new String(buf, offset, len);
        if (grabName) {
            name = name.concat(s);
        } else if (grabValue) {
            theVal = theVal.concat(s);
        } else if (grabCode) {
            theCode = theCode.concat(s);
        } else if (grabId) {
            theId = theId.concat(s);
        } else if (grabObjectName) {
            objectName = objectName.concat(s);
        }

    }

}
