/* Author: Jeff Dalton <J.Dalton@ed.ac.uk>
 * Updated: Mon Jul  2 15:02:36 2001 by Jeff Dalton
 * Copyright: (c) 2001, AIAI, University of Edinburgh
 */

package ix.iface.domain;

import java.io.*;
import java.util.*;

import ix.icore.domain.*;
import ix.util.*;
import ix.util.lisp.*;
import ix.util.match.*;

// Imports for using JDOM
// import java.io.IOException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;


/**
 * A writer for domains described in a simple XML syntax.
 */
public class XMLTF_Writer extends DomainWriter {

    File domainName;

    public XMLTF_Writer(File domainName) {
	this.domainName = domainName;
    }

    //
    // Writing a domain description using JDOM
    //

    public void writeDomain(Domain domain) 
    throws IOException {
	Document domainDoc = makeDomainDocument(domain);
	// Get a stream to write to
	OutputStream out = 
	    new BufferedOutputStream(
                new FileOutputStream(domainName));
	// Create an outputter with 3 space indent and newlines=true
	XMLOutputter outputter = new XMLOutputter("   ", true);
	outputter.setTrimText(true);
	outputter.output(domainDoc, out);
	out.flush();
    }

    public Document makeDomainDocument(Domain domain) {
	Element domainElt = new Element("domain");
	domainElt.addContent(makeActivitiesElt(domain.getAllSchemas()));
	Document doc = new Document(domainElt);
	return doc;
    }

    protected Element makeActivitiesElt(LList schemas) {
	Element activitiesElt = new Element("activities");
	for (Iterator i = schemas.iterator(); i.hasNext();) {
	    activitiesElt.addContent(makeActivityElt((Schema)i.next()));
	}
	return activitiesElt;
    }

    protected Element makeActivityElt(Schema s) {
	Element activityElt = new Element("activity");
	// Name
	activityElt.addAttribute("name", s.name);
	// Expands
	activityElt.addContent(
	    new Element("expands")
	        .addContent(Lisp.printToString(s.pattern)));
	// Nodes
	if (!s.nodes.isEmpty()) {
	    activityElt.addContent(makeNodesElt(s.nodes));
	}
	// Orderings
	if (!s.orderings.isEmpty()) {
	    activityElt.addContent(makeConstrainsElt(s.orderings));
	}
	return activityElt;
    }

    protected Element makeNodesElt(LList nodes) {
	Element nodesElt = new Element("nodes");
	for (Iterator i = nodes.iterator(); i.hasNext();) {
	    nodesElt.addContent(makeNodeElt((LList)i.next()));
	}
	return nodesElt;
    }

    protected Element makeNodeElt(LList nodeSpec) {
	Long n = (Long)nodeSpec.get(0);
	LList pattern = (LList)nodeSpec.get(1);
	Element nodeElt = new Element("node");
	nodeElt.addAttribute("id", n.toString());
	nodeElt.addContent(Lisp.printToString(pattern));
	return nodeElt;
    }

    protected Element makeConstrainsElt(LList orderings) {
	Element constraintsElt = new Element("constraints");
	for (Iterator i = orderings.iterator(); i.hasNext();) {
	    constraintsElt.addContent(makeOrderingElt((LList)i.next()));
	}
	return constraintsElt;
    }

    protected Element makeOrderingElt(LList ordering) {
	Long from = (Long)ordering.get(0);
	Long to = (Long)ordering.get(1);
	Element ordElt = new Element("constraint");
	MatchEnv env = new MatchEnv();
	env.put(XMLTF_Parser.Q_FROM, from);
	env.put(XMLTF_Parser.Q_TO, to);
	LList ordSpec = (LList)env.instantiateTree(
	                    XMLTF_Parser.temporalSyntax);
	ordElt.addContent(Lisp.printToString(ordSpec));
	return ordElt;
    }


}
