/* $Id: kifOutput.java,v 1.3 2000/08/13 15:50:26 connolly Exp $ */
/* References
 * XT by James Clark http://www.jclark.com/xml/xt.html
 *
 * @@SAX?
 *
 * @@KIF
 *
 * java io
 * http://java.sun.com/j2se/1.3/docs/api/java/io/package-summary.html
 */

/* package org.w3c.util; */

import org.xml.sax.*;
import com.jclark.xsl.sax.OutputDocumentHandler;
import com.jclark.xsl.sax.Destination;
import java.io.OutputStream;
import java.io.IOException;
import java.net.URLDecoder;


public class kifOutput implements OutputDocumentHandler {
  private OutputStream out = null;

  static final String KIFWordNS="http://www.w3.org/2000/07/hs78/KIF?word=";
  static final String KIFNS="http://www.w3.org/2000/07/hs78/KIF#";

  public kifOutput() {
  }

  public kifOutput(OutputStream out) {
    this.out = out;
  }

  public DocumentHandler init(Destination dest, AttributeList atts) throws IOException {
    this.out = dest.getOutputStream("text/plain", null);

    /*if ("yes".equals(atts.getValue("omit-xml-declaration")))
      omitXmlDeclaration = true; */

    return this;
  }

  public void startDocument() throws SAXException {
  }

  public void processingInstruction(String n, String r) throws SAXException {
  }

  public void characters(char cbuf[], int off, int len) throws SAXException {
    throw new SAXException("no data characters in KIF elments");
  }
    
  public void rawCharacters(String chars) throws SAXException {
    throw new SAXException("no data characters in KIF elments");
  }

  public void ignorableWhitespace (char ch[], int start, int length)
    throws SAXException {
      /* nothing */
  }

  public void startElement(String name, AttributeList atts) throws SAXException {

    if(name.equals("paren")){
      write("(");
    }

    else if(name.equals("word")){
      String str = atts.getValue("ref");
      /* @@ handle missing ref */
      write("'");
      writeWord(str, KIFWordNS);
    }


    else if(name.equals("constant")){
      String str = atts.getValue("n");
      /* @@ handle missing n attr */
      if(str.startsWith(KIFWordNS)){
	write("'");
	writeWord(str, KIFWordNS);
      }else{
	writeWord(str, KIFNS);
      }
    }

    else if(name.equals("indvar")){
      String str = atts.getValue("n");
      /* @@ handle missing n attr */
      writeWord("?" + str, KIFNS);
    }


    else if(name.equals("string")){
      String str = atts.getValue("v");
      write("\"");

      try {
	final int n = str.length();
	for (int i = 0; i < n; i++) {
	  char c = str.charAt(i);
	  if (c < 0x80){
	    if(c == '\\' || c == '"') out.write('\\');
	    out.write((byte)c);
	  }
	  else {
	    throw new SAXException("KIF is ascii only@@");
	  }
	}
      }
      catch (java.io.IOException e) {
	throw new SAXException(e);
      }

      write("\" ");
    }

    else if(name.equals("char")){
      String str = atts.getValue("v");
      /* @@check for string length 1 */
      write("#\\");
      write(str);
      write(" ");
    }

    else if(name.equals("indvar")){
      String str = atts.getValue("n");
      write("?");
      write(str); /* @@ check for legal variable characters */
      write(" ");
    }

    else if(name.equals("seqvar")){
      String str = atts.getValue("n");
      write("@");
      write(str); /* @@ check for legal variable characters */
      write(" ");
    }


    /* @@ others */

    else{
      /* @@ check that it's one of the known names */
      write(name + " ");
    }
  }

  private final void writeWord(String str, String pfx) throws SAXException{
    try {
      final int n = str.length();

      if(str.startsWith(pfx, 0)){
	String encw = str.substring(pfx.length());
	try{
	  String w = java.net.URLDecoder.decode(encw);
	  write(w);
	}catch(Exception e){  /* Odd... JDK documentation
http://java.sun.com/j2se/1.3/docs/api/java/net/URLDecoder.html
doesn't document an exception, but it's there in the source
@(#)URLDecoder.java  1.2 98/06/29
 */
	  throw new SAXException(e);
	}
      }else{
	for (int i = 0; i < n; i++) {
	  char c = str.charAt(i);
	  if (c < 0x80){
	    if(false) out.write('\\'); /*@@ add a switch for this */
	    out.write((byte)c);
	  }
	  else {
	    throw new SAXException("KIF is ascii only@@");
	  }
	}
      }
      out.write(' ');
    }
    catch (java.io.IOException e) {
	throw new SAXException(e);
    }
  }


  public void endElement(String name) throws SAXException {
    if(name.equals("paren")){
      write(")\n");
    }
  }

  public void setDocumentLocator(Locator loc) { }

  public void endDocument() throws SAXException {
    try{
      out.flush(); /*@@keepOpen? close */
    }
    catch (java.io.IOException e) {
      throw new SAXException(e);
    }
  }

  /* @@ really should do some buffering */
  private final void write(String str) throws SAXException {
    try {
      final int n = str.length();
      for (int i = 0; i < n; i++) {
	char c = str.charAt(i);
	if (c < 0x80)
	  out.write((byte)c);
	else {
	  throw new SAXException("KIF is ascii only@@");
	}
      }
    }
    catch (java.io.IOException e) {
      throw new SAXException(e);
    }
  }

}
