import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.*;

import java.io.*;
import java.util.*;

/**
	Cet ensemble de classe permet de gérer dans un fichier un arbre xml d'un ensemble de session de programme.c
	La racine de cet arbre est sessionsProgrammes<br/>
	Une session de programme est un arbre XML dont la racine est sessionProgramme et est composée<br/>
		1) d'un identifiant en attribut. Le nom de l'attribut est idSession<br/>
		2) d'un noeud de type programme contenant le nom du programme enseigné<br/>
		3) d'un noeud de type inscrits contenant une liste de noeuds de type inscrit<br/>
			un noeud inscrit est composé de deux noeuds nom et prenom. Il peut avoir un attribut auditeurLibre qui vaut "yes" ou "no".<br/>
			Si cet attribut n'exsite pas alors l'inscrit n'est pas un auditeur libre.<br/>
	On utilise la technologie DOM fournie par le jdk de Java.<br/>
	@version 1.0<br/> 
	@author Hervé de Milleville<br/>
*/
class GererSessionsProgrammes {
	/** Pour gérer l'arbre xml en mémoire vive et créer les différents éléments de l'arbre */
	private Document d;
	
	public static void main(String [] args) {
		GererSessionsProgrammes ge = new GererSessionsProgrammes();
		ge.chargerSessionsProgrammes("data/sessionsProgrammes.xml");
		ge.nouvelleSession();
		ge.SauverArbre("data/sessionsProgrammes.xml");
	}
	
	/**
		On lit dans l'entrée standard les informations d'une nouvelle session et on la stocke dans un objet Element
		<br>puis on ajoute cet élément dans l'arbre de toutes les sessions de programme
	*/
	public void nouvelleSession() {
		// On récupère le flot de l'entrée standard (par défaut le clavier) dans un objet Scanner
		Scanner sc = new Scanner(System.in);
		
		String idSession = sc.nextLine();
						
		Element sessionProgramme = d.createElement("sessionProgramme");
		sessionProgramme.setAttribute("idSession",idSession);
		Element programme = d.createElement("programme");
		Text nomProgramme = d.	createTextNode(sc.nextLine());
		programme.appendChild(nomProgramme);
		sessionProgramme.appendChild(programme);
		lireInscrits(sc,sessionProgramme);
		
				
		// on accroche cette racine e au document d
		d.getDocumentElement().appendChild(sessionProgramme);
	}
	
	/**
	On ajoute les inscrits dans l'arbre xml en les lisant dans l'entrée standard
		@param sessionProgramme Arbre xml qui contient la nouvelle session
	*/
	public void lireInscrits(Scanner sc,Element sessionProgramme) {
		String nom, prenom,auditeurLibre;
		Element enom, eprenom, einscrit;
		String inscrit;
		Element einscrits = d.createElement("inscrits");
		
		inscrit = sc.nextLine();
		while(! inscrit.equals("Fin") && !inscrit.equals("")) {
			StringTokenizer st = new StringTokenizer(inscrit);
			nom = new String("");
			prenom = new String("");
			auditeurLibre = new String("");						
			if(st.hasMoreTokens()) {
				nom = st.nextToken();
				if(st.hasMoreTokens()) {
					prenom = st.nextToken();
					if(st.hasMoreTokens()) {
						auditeurLibre = st.nextToken();
						if(!auditeurLibre.equals("yes") && !auditeurLibre.equals("no")) {
							auditeurLibre = new String("");
						}	
					}
				}
			}
			if(! nom.equals("")) {
				einscrit = d.createElement("inscrit");
				enom = d.createElement("nom");
				enom.appendChild(d.	createTextNode(nom));
				eprenom = d.createElement("prenom");
				eprenom.appendChild(d.	createTextNode(prenom));
				einscrit.appendChild(enom);
				einscrit.appendChild(eprenom);				
				if(!auditeurLibre.equals("")) {
					einscrit.setAttribute("auditeurLibre",auditeurLibre);
				}
				einscrits.appendChild(einscrit);
			}
		inscrit = sc.nextLine();	
		}
		sessionProgramme.appendChild(einscrits);
	}
	
	/**
		On charge dans un objet Document l'arbre xml des sessions de programmes
		@param fileName : nom du fichier xml contenant l'ensemble des sessions de programmes
	*/
	public void chargerSessionsProgrammes(String fileName) {
		try {
			// On alloue l'objet qui permet de fabriquer l'objet document
			DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = fabrique.newDocumentBuilder();
			
			File f = new File(fileName);
			if (!f.exists()) {
				// Le fichier des sessions n'existe pas. On crée un arbre toutesLesSessions avec aucune session
				// On crée en mémoire vive un document qui est donc un arbre vide
				d = db.newDocument();
			
				// On crée un élément en précisant le nom de la balise
				Element e = d.createElement("sessionsProgrammes");
				// On l'accroche au document. Il devient donc la racine de l'arbre xml
				d.appendChild(e);
				}
			else {
				// On charge en mémoire vive l'arbre de l'ensemble des sessions
				d =  db.parse(f);
				}

		}
		catch(Exception e) {
			System.out.println("Erreur de création ou de chargement de l'arbre xml des sessions de programmes "+e+ "  : Fin du message d'erreur");
		}
				
		
	}

	/**
	On sauvegarde l'objet d dans un fichier xml 
	@param fileName : nom du fichier xml contenant l'ensemble des sessions de programmes 
	*/	
	public void SauverArbre(String fileName) {
		try {
		
			// allocation et préparation de l'objet qui va permettre de créer le fichier xml
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			
			// On précise que la sauvegarde doit être un fichier xml
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			
			// On demande pour la présentation du fichier xml de mettre des indentations pour chaque nouveau noeud
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			
			// On précise l'encodage du fichier xml à générer
			transformer.setOutputProperty(OutputKeys.ENCODING, "iso-8859-1");
			
			// Pour mettre la ligne de déclaration <?xml ... ?>
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			
			// Création et ouverture du fichier xml de sauvegarde
			File f = new File(fileName);
			if (f.exists()) {
				f.delete();
				}
			// l'objet transformer ne travaille pas avec un fichier mais avec un flot de type StreamResult
			StreamResult nvFichier = new StreamResult(f);
			
			// On fait la sauvegarde
			transformer.transform(new DOMSource(d), nvFichier);
		}
		catch(Exception e) {
			System.out.println("Erreur de sauvegarde d'un objet Document "+e+ "  : Fin du message d'erreur");			
		}
	}
	
	/**
	méthode non terminée
	On affiche les différents noeuds de notre arbre XML
	*/
	public void afficherXML() {
		try {
		Element e = d.getDocumentElement();
		
		NodeList nl = e.getChildNodes();
		
		int i, j;
		for(i = 0; i < nl.getLength() ; i++) {
			Node n = nl.item(i);
			
			
			switch(n.getNodeType()) {
				case Node.TEXT_NODE :
				System.out.println("Noeud texte "+ n.getNodeValue());
				break;
				case Node.ELEMENT_NODE :
				System.out.println("Noeud "+ n.getNodeName() + " Liste des attributs");
					for(j = 0; j < n.getAttributes().getLength() ; j++) {
						Node nf = n.getAttributes().item(j);
						System.out.println(nf.getNodeName()+ " : " +nf.getNodeValue());
					}
				System.out.println();
				break;
				}
			}
		}
		catch(Exception e) {
			System.out.println("Erreur de lecture de l'arbre XML "+e+ "  : Fin du message d'erreur");			
		}
	}
}