/**
 * Exemple de parsing d'un fichier XML (graphml).
 * Version 25/11/10
 */

import java.io.FileReader;

import java.util.StringTokenizer;

import org.xml.sax.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.helpers.DefaultHandler;


public class Parser extends DefaultHandler {

    /** Etats de lecture possibles. */
    private static final int LECTURE_RIEN = 0;
    private static final int LECTURE_NOEUD = 1;
    private static final int LECTURE_ARETE = 2;
    private static final int LECTURE_NOM_NOEUD = 3;
    private static final int LECTURE_NOM_LIGNE = 4;
    private static final int LECTURE_LATITUDE_LONGITUDE = 5;
    private static final int LECTURE_DEBUT = 6;
    private static final int LECTURE_FIN = 7;
    private static final int LECTURE_CONNECTION = 8;

    /** Etat de la lecture pour signaler si l'on est en train de lire
     *  un noeud ou une arete. */
    private int etat_lecture;
    
    /** Attributs de lecture des noeuds. */
    private String nom_noeud;
    private String nom_ligne;
    private double latitude;
    private double longitude;
    
    /** Attributs de lecture des aretes. */
    private String debut;
    private String fin;
    private int type_connection;
    
    public Parser() {
        super();
    }
    
     /** Action a realiser en debut de parsing du fichier. */
    public void startDocument () {
        System.out.println("Debut du document");
    }

    /** Action a realiser en fin de parsing du fichier. */
    public void endDocument () {
        System.out.println("Fin du document");
    }
    
    /** Action a realiser, pour chaque balise ouvrante. */
    public void startElement(String uri, String name, String qName, Attributes atts) {
        if (name.equals("node")) {
            this.etat_lecture = LECTURE_NOEUD;
        }
        else if (name.equals("edge")) {
            this.debut = atts.getValue("source");
            this.fin = atts.getValue("target");
            this.etat_lecture = LECTURE_ARETE;
        }
        else if (name.equals("data")) {
            String cle = atts.getValue("key");
            if (cle.equals("name")) {
                this.etat_lecture = LECTURE_NOM_NOEUD;
            }
            else if (cle.equals("line")) {
                this.etat_lecture = LECTURE_NOM_LIGNE;
            }
            else if (cle.equals("coordinates")) {
                this.etat_lecture = LECTURE_LATITUDE_LONGITUDE;
            }
            else if (cle.equals("connection")) {
                this.etat_lecture = LECTURE_CONNECTION;
            }
        }
    }

    /** Action a realiser, pour chaque balise fermante. */
    public void endElement (String uri, String name, String qName) {
        if (name.equals("node")) {
            System.out.println("------- Noeud -------");
            System.out.println("Nom       : " + this.nom_noeud);
            System.out.println("Nom ligne : " + this.nom_ligne);
            System.out.println("Latitude  : " + this.latitude);
            System.out.println("Longitude : " + this.longitude);
            System.out.println();
        
        } else if (name.equals("edge")) {
            System.out.println("------- Arete -------");
            System.out.println("Debut               : " + this.debut);
            System.out.println("Fin                 : " + this.fin);
            System.out.println("Type de connection  : " + this.type_connection);
            System.out.println();
        }
        this.etat_lecture = LECTURE_RIEN;
    }
    
    /** Action a realiser, pour chaque lecture de caracteres hors d'une balise. */
    public void characters (char ch[], int start, int length) {
        String chaine = "";
        boolean lecture_ok = true;
        
        /** Reconstitution de la chaine de caracteres. */
        for (int i = start ; i < start + length ; ++i) {
            if (ch[i] != '\\' && ch[i] != '\n' && ch[i] != '\r' && ch[i] != '\t') {
                chaine += ch[i];
            }
        }
        switch (this.etat_lecture) {
        case LECTURE_NOM_NOEUD : 
            this.nom_noeud = chaine; 
            break;
        case LECTURE_NOM_LIGNE : 
            this.nom_ligne = chaine; 
            break;
        case LECTURE_LATITUDE_LONGITUDE : 
            StringTokenizer st = new StringTokenizer(chaine, ", ", false);
            this.latitude = Double.parseDouble(st.nextToken());
            this.longitude = Double.parseDouble(st.nextToken());
            break;
        case LECTURE_DEBUT : 
            this.debut = chaine; 
            break;
        case LECTURE_FIN : 
            this.fin = chaine; 
            break;
        case LECTURE_CONNECTION : 
            this.type_connection = Integer.parseInt(chaine); 
            break;
        }
    }

    public static void main(String args[]) throws Exception {
        XMLReader xr = XMLReaderFactory.createXMLReader();
        Parser handler = new Parser();
        xr.setContentHandler(handler);
        xr.setErrorHandler(handler);
        FileReader r = new FileReader(args[0]);
        xr.parse(new InputSource(r));
    }

}
