/**
 * Class DocumentMixte
 * This class offers a representation of an SVG document with metadata
 * (coded in RDF) embedded within.
 * Such a representation is based on the document's DOM :
 * It allows any user to access to the SVG and the RDF roots of the 
 * document's DOM. Moreover, it builds two hashtables: The first one
 * contains all the Element Nodes of the SVG code which have an id attribute,
 * with this id as the key. The second one contains all the Element nodes of
 * the RDF code whose name is rdf:Description, with the content of the about
 * attribute as the key.
 * Such tables allow any user to access quickly to any Element Node with its
 * id as the only data, without exploring the whole DOM tree each time (the
 * exploration is done one time, when the constructor is called).
 * It also points to an object of the class Sentence holding the information
 * relative to the RDF Schema used for namespace axsvg, and offers some
 * features accessible to further defined methods (see the class Sentence).
 **/

package axsvg;

import java.io.*;
import fr.dyade.koala.dom.*;
import fr.dyade.koala.dom.util.*;
import org.w3c.dom.*;
import java.util.Hashtable;


public class DocumentMixte {
    private final Document generator;
    private final Element racineSVG;
    private final Element racineRDF;
    private Hashtable tableSVG;
    private Hashtable tableRDF;
    private final Sentence sentence;


    /**
     * method setRDFRoot
     * @param an Element node of the DOM which is the SVG root of the document.
     * @return an Element node of the DOM which is the RDF root of the
     * document, or creates an empty one if it does not find such a node.
     **/
    private Element setRDFRoot(Element racineSVG) {
	Node elt = racineSVG;
	elt = elt.getFirstChild();
	while(elt != null) {
	    if(elt.getNodeName().equalsIgnoreCase("metadata")) {
		Node child = elt.getFirstChild();
		while(child != null) {
		    if(child.getNodeName().equalsIgnoreCase("rdf:RDF")) {
			return((Element)child);
		    }
		    child = child.getNextSibling();
		}
		GenericElement rdfRDF = new GenericElement(
				       "rdf:RDF", (AbstractDocument)generator);
		elt.appendChild(rdfRDF);
	        return(rdfRDF);
	    }
	    elt = elt.getNextSibling();
	}
	GenericElement metadata = new GenericElement(
			               "metadata",(AbstractDocument)generator);
	GenericElement rdfRDF = new GenericElement(
				       "rdf:RDF", (AbstractDocument)generator);
	metadata.appendChild(rdfRDF);
	racineSVG.appendChild(metadata);
	return(rdfRDF);
    }


    /**
     * method DocumentMixte
     * It's the constructor of the class.
     * @param the implementation of the document's DOM, considered as a
     * standard XML document.
     * It calls some private methods of the class in order to set the
     * attributes of the new DocumentMixte being build: the RDF and SVG roots,
     * the two hashtables (see the comments about the class itself), and an
     * object of class Sentence, which holds the information contained in the
     * RDF Schema associated to the axsvg namespace (the file name must
     * be "axsvg-schema.rdf").
     **/
    public DocumentMixte(Document doc) throws Exception {
	generator = doc;
	racineSVG = setSVGRoot(doc);
	racineRDF = setRDFRoot(racineSVG);
	tableSVG = new Hashtable();
	tableRDF = new Hashtable();
	buildTableSVG(racineSVG);
	buildTableRDF(racineRDF);
	sentence = new Sentence("axsvg-schema.rdf");
    }


    /**
     * method setSVGRoot
     * @param the document's DOM (class Document, see the DOM API on w3.org).
     * @return an Element node of the DOM which is the SVG root of the
     * document.
     * Stops the execution if it does not find such an element.
     **/
    private Element setSVGRoot(Document doc) {
	Node elt = doc.getDocumentElement();
	while(elt != null) {
	    if(elt.getNodeName().equalsIgnoreCase(":svg") ||
	       elt.getNodeName().equalsIgnoreCase("svg")) {
		return((Element)elt);
	    }
	    elt = elt.getNextSibling();
	}
	System.out.println("SVG root element not found in document");
	System.exit(1);
	return(null);
    }


    /**
     * method buildTableSVG
     * @param an Element node which should be the SVG root of the document.
     * It sets the attribute tableSVG of the calling object. This hashtable
     * gathers all the SVG Element nodes of the document which have an id
     * attribute.
     * This id is taken as the key in the table.
     **/
    public void buildTableSVG(Element racine) {
	String id = racine.getAttribute("id");
	if(id != null && !id.equals("")) {
	    tableSVG.put("#"+id, new AElementSVG(racine));
	}
	
	Node node = racine.getFirstChild();
	while(node != null) {
	    if(node.getNodeType() == node.ELEMENT_NODE) {
		buildTableSVG((Element)node);
	    }
	    node = node.getNextSibling();
	}
	return;
    }


    /**
     * method buildTableRDF
     * @param an Element node which should be the RDF root of the document.
     * It sets the attribute tableRDF of the calling object. This hashtable
     * gathers all the RDF Element nodes whom names are rdf:Description.
     * The attribute about is taken as the key in the table.
     * To put it in a nutshell, the set hashtable contains potentially the
     * description of all the SVG entities whom the id corresponds to a key
     * in the table (the element associated with such a key points to the RDF
     * node holding this description).
     * It offers a way to access quickly to the RDF code which desribes an
     * identifed SVG entity.
     **/
    public void buildTableRDF(Element racine) {
	String about;
	Node node = racine.getFirstChild();
	while(node != null) {
	    if((node.getNodeName()).equalsIgnoreCase("rdf:Description")) {
		tableRDF.put(((Element)node).getAttribute("about"),
			     new AElementRDF((Element)node));
	    }
	    node = node.getNextSibling();
	}
	return;
    }
    

    /**
     * method getTableSVG
     * @return the attribute tableSVG of the DocumentMixte.
     * See also method buildTableSVG for further informations about such a
     * table.
     **/
    public Hashtable getTableSVG() {
	return tableSVG;
    }


    /**
     * method getTableRDF
     * @return the attribute tableRDF of the DocumentMixte.
     * See also method buildTableRDF for further informations about such a
     * table.
     **/
    public Hashtable getTableRDF() {
	return tableRDF;
    }


    /**
     * method getSVGRoot
     * @return the attribute racineSVG of the DocumentMixte.
     * Such an element is final.
     **/
    public Element getSVGRoot() {
	return racineSVG;
    }
   

    /**
     * method getRDFRoot
     * @return the attribute racineRDF of the DocumentMixte.
     * Such an element is final.
     **/
    public Element getRDFRoot() {
	return racineRDF;
    }

    /**
     * method getSentence
     * @return the attribute sentence of the DocumentMixte.
     * Such an element is final.
     **/
    public Sentence getSentence() {
	return sentence;
    }
    
    /**
     * method getGenerator
     * @return the attribute generator of the DocumentMixte.
     * Such an element is final.
     **/
    public Document getGenerator() {
	return generator;
    }
}
