/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package domsample;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
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 javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 *
 * @author blackpanther
 */
public class Main {

    private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
    private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
    private static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
    private static final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    private static DocumentBuilder db;
    private static String nsUri = "http://ing2.eisti.fr/BDD-XML-II";

    static {
        dbFactory.setIgnoringComments(true);
        dbFactory.setNamespaceAware(true);

        /* Validation against a XSD*/
        dbFactory.setValidating(true);
        dbFactory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
        dbFactory.setAttribute(JAXP_SCHEMA_SOURCE, new File("sample-schema.xsd"));
    }

//    private static NamespaceContext ns = 
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        String xmlfile = "sample.xml";
        String schemafile = "sample-schema.xsd";
        Document dom = loadXML(xmlfile, schemafile);

        System.out.println("\n Display 1");
        displayStudents(dom);

        System.out.println("Test " + dom.getDocumentElement().lookupPrefix("exo"));

        modifyStudent(
                (Element) dom.getElementsByTagName("etudiant").item(0),
                "Coquio",
                "Guillaume");

        System.out.println("\n Display 2");
        displayStudents(dom);

        addStudent(dom, "Prayer", "Tom");

        System.out.println("\n Display 3");
        displayStudents(dom);

        saveXML(dom, "sample-new.xml");
    }

    private static Document loadXML(String xmlFilpath, String schemaFilepath) {

        //singleton
        if (db == null) {
            try {
                db = dbFactory.newDocumentBuilder();
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Couldn't load a document builder", ex);
                System.exit(-1);
            }
        }

        try {
            // 1. Lookup a factory for the W3C XML Schema language
            // 2. Compile the schema.
            // Here the schema is loaded from a java.io.File, but you could use
            // a java.net.URL or a javax.xml.transform.Source instead.
//            SchemaFactory sf = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
//            System.out.println("SchemaFactory :  " + sf);
//            File schemaLocation = new File(schemaFilepath);
//            System.out.println(schemaLocation.getAbsolutePath() + " exists ? " + schemaLocation.exists());
//            Schema schema = schema = sf.newSchema(schemaLocation);
//            // 3. Get a validator from the schema.
//            Validator validator = schema.newValidator();
//            // 4. Parse the document you want to check.
//            Source source = new StreamSource(xmlFilpath);
//            // 5. Check the document
//            validator.validate(source);
//            System.out.println(xmlFilpath + " is valid.");

            Document dom = db.parse(new File(xmlFilpath));

            System.out.println("Document parsed and validated.");

            return dom;
        } catch (SAXParseException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Document is not valid against given schema : \n\t" + ex.getMessage());
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }


        //Error exit
        return null;

    }

    private static void saveXML(Document dom, String filename) {
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

            BufferedWriter bw = new BufferedWriter(
                    new FileWriter(filename));
            //initialize StreamResult with File object to save to file
            StreamResult result = new StreamResult(bw);
            DOMSource source = new DOMSource(dom);
            transformer.transform(source, result);

            bw.close();






        } catch (TransformerException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }




    }

    private static void displayStudents(Document dom) {
        Element rootElement = dom.getDocumentElement();

        NodeList list = rootElement.getChildNodes();

        for (int i = 0; i
                < list.getLength(); i++) {
            Node node = list.item(i);
            //clear the empty text node
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element el = (Element) node;

                System.out.println("Etudiant "
                        + el.getAttribute("nom").toUpperCase()
                        + " "
                        + el.getAttribute("prenom"));
                System.out.println("\tNamespace : " + el.getNodeName());
            }
        }
    }

    private static void modifyStudent(Element student, String lastname, String firstname) {
        if (student.getNodeName().equals("etudiant")) {
            student.getAttributeNode("nom").setValue(lastname);
            student.getAttributeNode("prenom").setValue(firstname);
        } else {
            Logger.getLogger(Main.class.getName()).log(Level.WARNING, "Given node is not a student node");
        }
    }

    private static void addStudent(Document dom, String lastname, String firstname) {
        Element el = dom.createElement("etudiant");

        el.setAttribute("nom", lastname);
        el.setAttribute("prenom", firstname);

        dom.getDocumentElement().appendChild(el);










    }

    class StudentNamespace implements NamespaceContext {

        public String getNamespaceURI(String prefix) {
            return prefix.equals("exo")
                    ? "http://ing2.eisti.fr/BDD-XML-II"
                    : "";
        }

        public String getPrefix(String namespaceURI) {
            return namespaceURI.equals("http://ing2.eisti.fr/BDD-XML-II")
                    ? "exo"
                    : "";
        }

        public Iterator getPrefixes(String namespaceURI) {
            List l = new ArrayList();

            if (namespaceURI.equals("http://ing2.eisti.fr/BDD-XML-II")) {
                l.add("exo");
            }

            return l.iterator();
        }
    }
}
