import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;

class LoadAndValidConfigHandler extends DefaultHandler {

	private enum TypeSgbd { Oracle, MicrosoftSQLServer, Teradata, Ingres,
			Sybase, MySQL, PostgreSQL 
	}

	private TypeSgbd typeSgbd;
	private String serverAddress;
	private String databaseName;
	private int serverPort;
	private String userLogin;
	private String userPasswd;

	private void initConnection() {
		// TODO : ici initialiser la connexion à la BDD
		// en attendant simple affichage
		// NB : on lance l'appli uniquement si le fichier de config est correct
		// et le XSD impose la présence de chaque paramètre
		System.out.println("Initialisation de la connection avec les paramètres suivants : ");
		System.out.println("\tType SGBD :\t" + typeSgbd); 
		System.out.println("\tadresse :\t" + serverAddress); 
		System.out.println("\tnom base :\t" + databaseName); 
		System.out.println("\tport :\t\t" + serverPort); 
		System.out.println("\tlogin :\t\t" + userLogin); 
		System.out.println("\tpasswd :\t" + userPasswd); 
	} 
	

	// partie traitement du fichier XML (sans namespace)
	String currentElement;

	public void startDocument() throws SAXException {
		currentElement = null;
	}

	public void startElement(String uri, String localName, String qName, 
			Attributes attributes) throws SAXException {
		if (qName.equals("databaseAccessConfig")) {
			// traitement des éléments avec attributs

			// récupère la valeur contenant le type de SGBD
			// NB : la validation détecte l'absence de l'attribut obligatoire
			// mais on n'arrête pas le parcours du fichier XML
			if (attributes.getIndex("sgbd") != -1) {
				typeSgbd = TypeSgbd.valueOf(attributes.getValue("sgbd"));
			}

		} else { 
			// traitement des éléments avec 1 chaîne de caractères

			// mémorisation du nom de l'élément pour traitement ultérieur
			// de la chaîne de caractères
			currentElement = qName;
		}
	}

	public void characters(char[] ch, int start, int length) throws SAXException {
		if (currentElement != null) {
			if (currentElement.equals("serverAddress")) {
				serverAddress = new String(ch, start, length);	
			} else if (currentElement.equals("serverPort")) {
				serverPort = Integer.parseInt(new String(ch, start, length));	
			} else if (currentElement.equals("databaseName")) {
				databaseName = new String(ch, start, length);	
			} else if (currentElement.equals("userLogin")) {
				userLogin = new String(ch, start, length);	
			} else if (currentElement.equals("userPasswd")) {
				userPasswd = new String(ch, start, length);	
			}
		}
	}
	
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// important pour éviter d'écraser des champs déjà remplis
		currentElement = null;	
	}

	public void endDocument() throws SAXException {
		// si tous les paramètres ont été lu, on lance la connexion
		if (isValid()) {initConnection();}
	}


	// partie validation XML/XSD
	private boolean bool_isValid = true;

	public void reportState() {
		if (isValid()) {
			System.out.println("Configuration valide chargée avec succès");
		} else {
			System.out.println("Configuration non valide");
		}
	}

	public boolean isValid() {
		return bool_isValid;
	}

	private void reportProblem(String generalMessage, SAXParseException e) {
		System.err.println(generalMessage);
		System.err.println("   Ligne   : "+e.getLineNumber());	
      	System.err.println("   Colonne : "+e.getColumnNumber());
		System.err.println("   Message : "+e.getMessage());
	}

	public void fatalError(SAXParseException e) {
		reportProblem("Erreur de validation - Erreur fatal",e);
		bool_isValid = false;
	}

	public void error(SAXParseException e) {
		reportProblem("Erreur de validation - Erreur",e);
		bool_isValid = false;
	}

	public void warning(SAXParseException e) {
		reportProblem("Erreur de validation - Warning",e);
		bool_isValid = false;
	} 
}

public class LoadConfig {

	static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
	static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
	static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";

	public static void saxParseWithXsd(String xmlFileName, String xsdFileName) {
		saxParseWithXsd(xmlFileName, xsdFileName, false);
	}

	public static void saxParseWithXsd(String xmlFileName, String xsdFileName, boolean isNameSpaceAware) {
		try {
			SAXParserFactory spf = SAXParserFactory.newInstance();
			spf.setNamespaceAware(isNameSpaceAware);
			spf.setValidating(true);
			SAXParser sp = spf.newSAXParser();
			sp.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
			sp.setProperty(JAXP_SCHEMA_SOURCE, new File(xsdFileName)); 
			LoadAndValidConfigHandler saxHandler = new LoadAndValidConfigHandler();
			sp.parse(new File(xmlFileName), saxHandler);
			saxHandler.reportState();
		} catch (ParserConfigurationException e) {
			System.err.println(e.getMessage());
		} catch (SAXException e) {
			System.err.println(e.getMessage());
		} catch (java.io.IOException e) {
			System.err.println(e.getMessage());
		}
	}

	public static void main(String[] args) {
		if (args.length > 1) {
			// args[0] : XML
			// args[1] : XSD
			saxParseWithXsd(args[0], args[1]);
		}
	}
}
	
