/*
 * @(#)LMTConverter.java	0.1 2002/04/25
 *
 * Copyright 2002 by Carnegie Mellon, All rights reserved.
 */

package lmt_converter;

import lmt.*;
import java.sql.*;
import java.util.*;
import java.io.*;

public class LMTConverter
{
//   private String databaseURL = "128.2.211.17:1521:lmt2";
  private String databaseURL;

  SQLConnection dbConnection;

  boolean openDBConnection() 
  {
    if ( dbConnection == null ) {
      dbConnection = new SQLConnection(databaseURL);

      Debug.debug("-- openDBConnection server:" + databaseURL );	
      boolean success = dbConnection.connect();
      if ( !success ) closeDBConnection();

      return success;
    }
    return true;
  }

  void closeDBConnection() 
  {
    if ( dbConnection != null ) {
      dbConnection.close();
      dbConnection = null;
    }
  }

  private PrintStream wordsStream, phrasesStream, aedmStream, zwordsStream;

  private void openOutputFiles()
  {
    try
    {
      wordsStream = new PrintStream(new FileOutputStream("words.dmk"));
      phrasesStream = new PrintStream(new FileOutputStream("phrases.dmk"));
      if (!realdmk)
      {
	aedmStream = new PrintStream(new 
				     FileOutputStream("words+phrases.ae-dm"));
	zwordsStream = new PrintStream(new FileOutputStream("zwords.ae-dm"));
      }
    }
    catch (FileNotFoundException e)
    {
      System.err.println("Couldn't open files for writing: " + e.getMessage());
      System.exit(3);
    }
  }

  private String quoted(String s)
  {
    StringBuffer buf = new StringBuffer(s);
    int x = s.lastIndexOf('\"');
    if (x < 0)
      return s;
    while (x >= 0)
    {
      buf.insert(x, '\\');
      x = s.lastIndexOf('\"', x - 1);
    }
    return buf.toString();
  }

  private String standardMorph(String name, String value, 
			       String f, String fo, 
			       String s, String so,
			       String irr,
			       boolean zword)
  {
    if (value.length() == 0 || value.equals(f))
    {
      if (zword)
	return ("    (:" + name + " " + fo + ")\n");
      else
	return "";
    }
    else if (value.equals(s))
      return ("    (:" + name + " " + so + ")\n");
    else if (value.equals("I"))
      return ("    (:" + name + " \"" + irr + "\")\n");
    throw new IllegalStateException("Bad morphology string");
  }
  
  private String standardMorphPlus(String name, String value, 
				   String irr, boolean zword)
  {
    return standardMorph(name, value, "T", "+", "F", "-", irr, zword);
  }

  private String standardMorphMinus(String name, String value, 
				    String irr, boolean zword)
  {
    return standardMorph(name, value, "F", "-", "T", "+", irr, zword);
  }

  private static String[] monthList = 
  {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
   "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

  private static String convert_month(String month)
  {
    for (int i = 0; i < 12; i++)
      if (month.equalsIgnoreCase(monthList[i]))
// 	return (((i + 1) < 10) ? "0" : "") + (i + 1);
	return  new Integer(i + 1).toString();
    return month;
  }

  private static String convert_timestamp(String s)
  {
    StringTokenizer ts = new StringTokenizer(s);
    if (ts.countTokens() != 2)
      return s;
    StringTokenizer date = new StringTokenizer(ts.nextToken(), "-");
    if (date.countTokens() != 3)
      return s;
    StringTokenizer time = new StringTokenizer(ts.nextToken(), ":");
    if (time.countTokens() != 3)
      return s;
    String retval = "(";
    String t0 = time.nextToken();
    String t1 = time.nextToken();
    retval += time.nextToken() + " " + t1 + " " + t0 + " ";
    retval += date.nextToken() + " ";
    retval += convert_month(date.nextToken()) + " ";
    retval += date.nextToken() + ")";
    return retval;
  }

  private static String get_valency(String c)
  {
    boolean trans[] = {false, false, false, false};
    StringTokenizer val = new StringTokenizer(c, "!/");
    while (val.hasMoreTokens())
    {
      StringTokenizer sem = new StringTokenizer(val.nextToken(), "+");
      int i = 0;
      while (sem.hasMoreTokens())
      {
	String semrole = sem.nextToken();
	if (!(semrole.equalsIgnoreCase("attribute") ||
	      semrole.equalsIgnoreCase("complement")))
	  i++;
      }
      if (i > 3)
	i = 3;
      trans[i] = true;
    }
    String valency = new String();
    if (trans[2])
      valency += " TRANS";
    if (trans[1])
      valency += " INTRANS";
    if (trans[3])
      valency += " DITRANS";
    return valency;
  }

  void convertTerm(String id)
  {
//     SQLConnection  dbCon = new SQLConnection(databaseURL);
//     boolean success = dbCon.connect();
//     if ( !success ) {
//         System.err.println("Can't open db connection.");
//         System.exit(2);
//     }

    Term term = new Term(dbConnection);
    term.setTermID(id);
    int succ = term.fetchTerm();

    PrintStream dmk;
    boolean phrase = term.getTermString().indexOf(' ') != -1;
    if (phrase)
      dmk = phrasesStream;
    else
      dmk = wordsStream;
    

    Vector concepts = term.getConcepts();
    for (int x = 0; x < concepts.size(); x++)
    {
      Concept concept = (Concept)concepts.get(x);

      PrintStream aedm;
      boolean zwords = false;
      String conceptSymbol = concept.getConceptSymbol();

      if (conceptSymbol.equals("*ZWORD"))
      {
	aedm = zwordsStream;
	dmk = null;
	zwords = true;
      }
      else
	aedm = aedmStream;

      String pos = Term.changePosForDB(term.getPos());
      Vector ncri = concept.getNCRI();
      Vector definitions = concept.getDefinitions();

      if (aedm == aedmStream)
      {
	boolean actualdef = false;
	// A definition is not enough to add a non-ambiguous noun phrase
	// to the words+phrases.ae-dm file
	if (!phrase || !pos.equals("N") || concepts.size() > 1)
	  for (int i = 0; !actualdef && i < definitions.size(); i++)
	  {
	    Definition definition = (Definition)definitions.get(i);
	    String s = definition.getUsageDefinition();
	    if (s.length() > 0 &&
		!s.equals("No definition yet") &&
		!s.equals("no definition"))
	      actualdef = true;
	  }

	if (!actualdef &&
	    concept.getCapitalization().length() == 0 &&
	    concept.getIrrCapitalization().length() == 0 &&
	    ncri.size() == 0)
	  aedm = null;
      }
      if (realdmk &&
	  (conceptSymbol.equals("*A-BE") ||
	   conceptSymbol.equals("*SP-BE") ||
	   conceptSymbol.startsWith("*CARD-") ||
	   conceptSymbol.startsWith("*ORD-")))
	dmk = null;

      if (dmk != null)
      {
	if (fulldmk || !zwords)
	{
	  dmk.println("((:ROOT \"" + term.getTermString() + "\")");
	  dmk.println(" (:POS " + pos + ")");
	}
	if (!zwords)
	  dmk.println(" (:CONCEPT " + conceptSymbol + ")");
      }
      if (aedm != null)
      {
	aedm.println("((:ROOT \"" + term.getTermString() + "\")");
	aedm.println(" (:POS " + pos + ")");
	if (!zwords)
	  aedm.println(" (:CONCEPT " + conceptSymbol + ")");
      }

      if (dmk != null && smcsclassdata != null && smcscodedata != null)
      {
	EntryKey k = new EntryKey(term.getTermString(), pos, conceptSymbol);
	Object o = smcscodedata.get(k);
	if (o != null)
	{
	  List list = (List) o;
	  dmk.print(" (:SMCS-CODE ");
	  Iterator i = list.iterator();
	  while (i.hasNext())
	    dmk.print((String)i.next() + " ");
	  dmk.println(")");
	}
	o = smcsclassdata.get(k);
	if (o != null)
	{
	  List list = (List) o;
	  dmk.print(" (:SMCS-CLASS ");
	  Iterator i = list.iterator();
	  while (i.hasNext())
	    dmk.print((String)i.next() + " ");
	  dmk.println(")");
	}
      }

      if (concept.getCteEntry().equals("F"))
      {
	if (dmk != null) {
	  if (realdmk || fulldmk)
	    dmk.println(" (:KCE -)");
	  else
	    dmk.println(" (:CTE -)");
	}
	if (aedm != null && zwords)
	  aedm.println(" (:CTE -)");
      }

      if (dmk != null && term.getTypePhrase().equals("T"))
	dmk.println(" (:TYPE :PHRASE)");

      String tmp = "";
      Morphology morph = concept.getMorphology();
      if (pos.equals("V") || pos.equals("ADJ") || pos.equals("ADV"))
      {
	if (zwords && morph.getConDouble().equals("F"))
	  tmp = "-";
	else if (morph.getConDouble().equals("T"))
	  tmp = "+";
	if (tmp.length() != 0)
	{
	  if (dmk != null)
	    dmk.println(" (:SYL-DOUBLE " + tmp + ")");
	  if (aedm != null && zwords)
	    aedm.println(" (:SYL-DOUBLE " + tmp + ")");
	}
      }

      tmp = "";
      if (morph instanceof MorphNoun && 
	  (pos.equals("N") || pos.equals("PROP") || pos.equals("UNIT")))
      {
	MorphNoun m = (MorphNoun)morph;
	tmp += standardMorphPlus("PLURAL", m.getPlural(), 
				 m.getIrrPlural(), zwords);
	tmp += standardMorphPlus("GENSG", m.getGensg(), 
				 m.getIrrGensg(), zwords);
	tmp += standardMorphPlus("GENPL", m.getGenpl(), 
				 m.getIrrGenpl(), zwords);
	
      } 
      else if (morph instanceof MorphVerb &&
	       (pos.equals("V") || pos.equals("AUX")))
      {
	MorphVerb m = (MorphVerb)morph;
	tmp += standardMorphPlus("PRESENT1SG", m.getPresent1sg(),
				 m.getIrrPresent1sg(), zwords);
	tmp += standardMorphPlus("PRESENT3SG", m.getPresent3sg(),
				 m.getIrrPresent3sg(), zwords);
	tmp += standardMorphPlus("PRESENTPL", m.getPresentpl(),
				 m.getIrrPresentpl(), zwords);
	tmp += standardMorphPlus("PRESPART", m.getPrespart(),
				 m.getIrrPrespart(), zwords);
	tmp += standardMorphPlus("PRESPARTPL", m.getPrespartpl(),
				 m.getIrrPrespartpl(), zwords);
	tmp += standardMorphPlus("PAST13SG", m.getPast13sg(),
				 m.getIrrPast13sg(), zwords);
	tmp += standardMorphPlus("PASTPL", m.getPastpl(),
				 m.getIrrPastpl(), zwords);
	tmp += standardMorphPlus("PAST", m.getPast(),
				 m.getIrrPast(), zwords);
	tmp += standardMorphPlus("PASTPART", m.getPastpart(),
				 m.getIrrPastpart(), zwords);
      }
      else if (morph instanceof MorphAdj &&
	       pos.equals("ADJ") || pos.equals("ADV"))
      {
	MorphAdj m = (MorphAdj)morph;
	tmp += standardMorphMinus("COMP", m.getComparative(),
				  m.getIrrComparative(), zwords);
	tmp += standardMorphMinus("SUPER", m.getSuperlative(),
				  m.getIrrSuperlative(), zwords);
      }

      if (dmk != null && tmp.length() != 0)
	dmk.println(" (:MORPH\n" + tmp + " )");

      tmp = term.getPhraseHead();
      if (tmp.length() != 0 && dmk != null)
      {
	int phead = Integer.parseInt(tmp, 10);
	if (phead == 0)
	  tmp = ":NONE";
	else if (phead == 99)
	  tmp = ":LAST";
	else if (phead < 0 || phead > 99)
	  tmp = ":ERROR";
	dmk.println(" (:PHRASE-HEAD " + tmp + ")");
      }

      tmp = "";
      Syntax syntax = concept.getSyntax();
      if (syntax instanceof SyntaxVerb || syntax instanceof SyntaxNoun ||
	  syntax instanceof SyntaxAdv || syntax instanceof SyntaxAdj ||
	  syntax instanceof SyntaxQuant)
      {
	if (syntax.getAbbreviation().equals("T"))
	  tmp += "    (ABB +)\n";
      }
      if (syntax instanceof SyntaxAdj || syntax instanceof SyntaxAdj ||
	  syntax instanceof SyntaxNoun || syntax instanceof SyntaxVerb)
      {
	if (syntax.getAcronym().equals("T"))
	  tmp += "    (ACR +)\n";
      }

      String full_form = "";
      if (syntax instanceof SyntaxAdj)
	full_form = ((SyntaxAdj)syntax).getFullForm();
      else if (syntax instanceof SyntaxNoun)
	full_form = ((SyntaxNoun)syntax).getFullForm();
      if (full_form.equals("T"))
	tmp += "    (FULL-FORM +)\n";

      if (syntax instanceof SyntaxAdj || syntax instanceof SyntaxAdv ||
	  syntax instanceof SyntaxVerb || 
	  (syntax instanceof SyntaxNoun && pos.equals("N")))
      {
	String comp = "";
	if (syntax.getComplementS().equals("T"))
	  comp += " SCOMP";
	if (syntax.getComplementX().equals("T"))
	  comp += " XCOMP";
	if (syntax instanceof SyntaxVerb &&
	    syntax.getComplementAP().equals("T"))
	  comp += " APCOMP";
	if (comp.length() != 0)
	  tmp += "    (COMP" + comp + ")\n";
      }

      if (syntax instanceof SyntaxNoun)
      {
	SyntaxNoun synnoun = (SyntaxNoun)syntax;
	if (synnoun.getCount().equals("M"))
	  tmp += "    (COUNT -)\n";
	else if (synnoun.getCount().equals("B"))
	  tmp += "    (COUNT + -)\n";

	if (synnoun.getNumber().equals("P"))
	  tmp += "    (NUMBER PL)\n";
      }

      String form = "";
      if (syntax instanceof SyntaxAdj)
	form = ((SyntaxAdj)syntax).getForm();
      else if (syntax instanceof SyntaxAdv)
	form = ((SyntaxAdv)syntax).getForm();
      if (form.equals("C"))
	tmp += "    (FORM COMP)\n";
      else if (form.equals("S"))
	tmp += "    (FORM SUPER)\n";

      if (syntax instanceof SyntaxAdv)
      {
	SyntaxAdv synadv = (SyntaxAdv)syntax;

	if (synadv.getDirection().equals("T"))
	  tmp += "    (DIRECTION-ADV +)\n";
	if (synadv.getDegree().equals("T"))
	  tmp += "    (DEGREE-ADV +)\n";
	if (synadv.getFrequency().equals("T"))
	  tmp += "    (FREQUENCY-ADV +)\n";
      }

      String expl_subj = "";
      if (syntax instanceof SyntaxAdj)
	expl_subj = ((SyntaxAdj)syntax).getExplSubj();
      else if (syntax instanceof SyntaxVerb)
	expl_subj = ((SyntaxVerb)syntax).getExplSubj();
      if (expl_subj.equals("T"))
	tmp += "    (EXPL-SUBJ +)\n";

      if (!realdmk && pos.equals("V"))
      {
	String tr = get_valency(concept.getSemanticVerb().getClasses());
	if (tr.length() != 0)
	  tmp += "    (VALENCY" + tr + ")\n";
      }

      if (syntax instanceof SyntaxVerb)
      {
	SyntaxVerb synverb = (SyntaxVerb)syntax;
	
	if (synverb.getPredPassive().equals("F"))
	  tmp += "    (PRED-PASSIVE -)\n";
      }
      if (syntax instanceof SyntaxPronoun)
      {
	SyntaxPronoun synpron = (SyntaxPronoun)syntax;
	
	if (synpron.getGenitive().equals("T"))
	  tmp += "    (GENITIVE +)\n";

	String pnum = "";
	if (synpron.getNumSingular().equals("T"))
	  pnum += " SG";
	if (synpron.getNumPlural().equals("T"))
	  pnum += " PL";
	if (pnum.length() != 0)
	  tmp += "    (NUMBER" + pnum + ")\n";

	if (synpron.getReferential().equals("F"))
	  tmp += "    (referential -)\n";
	else
	  tmp += "    (referential +)\n";

	if (synpron.getGender().equals("M"))
	  tmp += "    (gender masculine)\n";
	else if (synpron.getGender().equals("F"))
	  tmp += "    (gender feminine)\n";

	if (synpron.getPerson().equals("1"))
	  tmp += "    (person first)\n";
	else if (synpron.getPerson().equals("2"))
	  tmp += "    (person second)\n";
	else if (synpron.getPerson().equals("3"))
	  tmp += "    (person third)\n";

	if (synpron.getAnaphor().equals("T"))
	  tmp += "    (anaphor +)";
      }

      if (syntax instanceof SyntaxConj)
      {
	SyntaxConj synconj = (SyntaxConj)syntax;
	
	if (synconj.getClausalCoor().equals("F"))
	  tmp += "    (CLAUSAL-COOR-CONJ -)\n";
	if (synconj.getCoor().equals("T"))
	  tmp += "    (COOR-CONJ +)\n";
      }

      if (syntax instanceof SyntaxSym)
      {
	SyntaxSym synsym = (SyntaxSym)syntax;
	
	if (synsym.getSingleLetter().equals("T"))
	  tmp += "    (SINGLE-LETTER +)\n";
	if (synsym.getRomanNumeral().equals("T"))
	  tmp += "    (ROMAN-NUMERAL +)\n";
      }

      if (dmk != null && tmp.length() != 0)
	dmk.println(" (:SYN-FEATURES\n" + tmp + " )");

      if (dmk != null && pos.equals("V"))
      {
	String c = concept.getSemanticVerb().getClasses();
	if (c.length() != 0)
	{
	  dmk.println(" (:CLASS " + c + ")");
	}
      }

      String caps = "";
      if (concept.getCapitalization().equals("All"))
	caps = ":ALL";
      else if (concept.getCapitalization().equals("First"))
	caps = ":FIRST";
      else if (concept.getCapitalization().equals("Each"))
	caps = ":EACH";
      else if (concept.getCapitalization().equals("Any"))
	caps = ":ANY";
      if (caps.length() != 0)
      {
	if (fulldmk && dmk != null)
	  dmk.println(" (:CAPS " + caps + ")");
	if (aedm != null)
	  aedm.println(" (:CAPS " + caps + ")");
      }
      else if (concept.getCapitalization().equals("Irr"))
      {
	if (fulldmk && dmk != null)
	  dmk.println(" (:IRREG-CAPS \"" + 
		      concept.getIrrCapitalization() + "\")");
	if (aedm != null)
	  aedm.println(" (:IRREG-CAPS \"" + 
		       concept.getIrrCapitalization() + "\")");
      }
      
      if (fulldmk && dmk != null)
      {
	for (int i = 0; i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("T"))
	  {
	    dmk.print(" (:DEFINITION");
	    dmk.print("\n   (:SENSE \"" + definition.getUsageDefinition() +
		      "\")");
	    Vector examples = definition.getExamples();
	    if (examples.size() != 0)
	    {
	      boolean flag = false;
	      for (int j = 0; j < examples.size(); j++) 
	      {
		String example = ((Example)examples.get(j)).getUsageExample();
		if (example.length() == 0)
		  continue;
		if (flag == false)
		{
		  dmk.print("\n   (:USAGE");
		  flag = true;
		}
		dmk.print("\n           \"" + example + "\"");
	      }
	      if (flag == true)
		dmk.print(")");
	    }
	    Vector related = definition.getRelatedTerms();
	    if (related.size() != 0)
	    {
	      dmk.print("\n   (:RELATED");
	      for (int j = 0; j < related.size(); j++)
		dmk.print("\n             \"" +
			  ((RelatedTerm)related.get(j)).getRelatedTerm() + 
			  "\"");
	      dmk.print(")");
	    }
	    dmk.println(")");
	  }
	}
	for (int i = 0; i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("F"))
	  {
	    dmk.print(" (:NEG-DEFINITION");
	    dmk.print("\n   (:SENSE \"" + definition.getUsageDefinition() +
		      "\")");
	    Vector examples = definition.getExamples();
	    if (examples.size() != 0)
	    {
	      boolean flag = false;
	      for (int j = 0; j < examples.size(); j++) 
	      {
		String example = ((Example)examples.get(j)).getUsageExample();
		if (example.length() == 0)
		  continue;
		if (flag == false)
		{
		  dmk.print("\n   (:USAGE");
		  flag = true;
		}
		dmk.print("\n           \"" + quoted(example) + "\"");
	      }
	      if (flag == true)
		dmk.print(")");
	    }
	    Vector related = definition.getRelatedTerms();
	    if (related.size() != 0)
	    {
	      dmk.print("\n   (:RELATED");
	      for (int j = 0; j < related.size(); j++)
		dmk.print("\n             \"" +
			  ((RelatedTerm)related.get(j)).getRelatedTerm() + 
			  "\"");
	      dmk.print(")");
	    }
	    dmk.println(")");
	  }
	}
      }

      if (aedm != null)
      {
	boolean def_flag = false;
	for (int i = 0; !def_flag && i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("T"))
	  {
	    String s = definition.getUsageDefinition();
	    if (!s.equals("No definition yet") &&
		!s.equals("no definition"))
	    {
	      aedm.print(" (:DEFINITION \"" + s);
	      def_flag = true;
	    }
	  }
	}
	for (int i = 0; i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("F"))
	  {
	    String s = definition.getUsageDefinition();
	    if (!s.equals("No definition yet") &&
		!s.equals("no definition"))
	    {
	      if (!def_flag)
	      {
		def_flag = true;
		aedm.print(" (:DEFINITION \"" + s);
	      }
	      else
		aedm.print("\n" + s);
	    }
	  }
	}
	if (def_flag)
	  aedm.println("\")");

	
	boolean flag = false;
	for (int i = 0; !flag && i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("T"))
	  {
	    Vector examples = definition.getExamples();
	    if (examples.size() != 0)
	    {
	      for (int j = 0; j < examples.size(); j++) 
	      {
		String example = ((Example)examples.get(j)).getUsageExample();
		if (example.length() == 0)
		  continue;
		if (flag == false)
		{
		  aedm.print(" (:USAGE ");
		  flag = true;
		}
		aedm.print("\n   \"" + example + "\"");
	      }
	      if (flag == true)
		aedm.println(")");
	    }
	  }
	}
	flag = false;
	for (int i = 0; i < definitions.size(); i++)
	{
	  Definition definition = (Definition)definitions.get(i);
	  if (definition.getCteUsage().equals("F"))
	  {
	    Vector examples = definition.getExamples();
	    if (examples.size() != 0)
	    {
	      for (int j = 0; j < examples.size(); j++) 
	      {
		String example = ((Example)examples.get(j)).getUsageExample();
		if (example.length() == 0)
		  continue;
		if (flag == false)
		{
		  aedm.print(" (:NEG-USAGE ");
		  flag = true;
		}
		aedm.print("\n   \"" + example + "\"");
	      }
	    }
	  }
	}
	if (flag == true)
	  aedm.println(")");

	tmp = "";
	for (int j = 0; j < ncri.size(); j++)
	{
	  NCRI nterm = (NCRI)ncri.get(j);

	  tmp += "          (\"" + nterm.getNcriTermString() + "\" (:POS " +
		 Term.changePosForDB(nterm.getNcriPos()) + ")";
	  
	  if (nterm.getNcriTypePhrase().equals("T"))
	    tmp += " (:TYPE :PHRASE)";
	  String tmp2 = nterm.getNcriPhraseHead();
	  if (tmp2.length() != 0)
	  {
	    int phead = Integer.parseInt(tmp2, 10);
	    if (phead == 0)
	      tmp2 = ":NONE";
	    else if (phead == 99)
	      tmp2 = ":LAST";
	    else if (phead < 0 || phead > 99)
	      tmp2 = ":ERROR";
	    tmp += " (:PHRASE-HEAD " + tmp2 + ")";
	  }
	  tmp += ")\n";
	}
	if (tmp.length() != 0)
	  aedm.println(" (:NON-CTE-RELATED-ITEMS\n" + tmp + " )");
      }
      
      if (dmk != null && concept.getAmbiguity().equals("C"))
	dmk.println(" (:CHECKSENSE + )");
      else if (dmk != null && concept.getAmbiguity().equals("A"))
	dmk.println(" (:AMBIG :AMBIGTRUE )");

      if (!realdmk && concept.getDateUpdated().length() != 0)
      {
	String where = concept.getAuthorUpdating();
	if (where == null)
	  where = "from LMT";
	String timestamp = convert_timestamp(concept.getDateUpdated());
	if (aedm != null)
	  aedm.println(" (:UPDATED " + timestamp + " \"" +
		       where +"\" )");
	if (dmk != null)
	  dmk.println(" (:UPDATED " + timestamp + " \"" +
		      where +"\" )");
      }

      if (fulldmk && dmk != null)
      {
	if (concept.getDateCreated() != null &&
	    concept.getDateCreated().length() != 0)
	  dmk.println(" (:CREATED " + 
		      convert_timestamp(concept.getDateCreated()) + " \"" +
		      concept.getAuthorCreating() + "\" )");

	if (concept.getDateUpdated().length() != 0)
	{
	  String where = concept.getAuthorUpdating();
	  if (where == null)
	    where = "from LMT";
	  dmk.println(" (:UPDATED " + 
		      convert_timestamp(concept.getDateUpdated()) + " \"" +
		      where +"\" )");
	}
	
	if (concept.getSource().length() != 0)
	  dmk.println(" (:SOURCE \"" + concept.getSource() + "\" )");

	tmp = "";
	Vector comments = concept.getComments();
	for (int j = 0; j < comments.size(); j++)
	{
	  Comment comment = (Comment)comments.get(j);
	  
	  tmp += "\n           \"" + quoted(comment.getComments()) + "\"";
	}
	if (tmp.length() != 0)
	  dmk.println(" (:COMMENT" + tmp + " )");
	
      }
      
      if (dmk != null)
	dmk.println(")\n");

      if (aedm != null)
	aedm.println(")\n");
    }

//     dbCon.close();

  }

  private class EntryKey implements Comparable
  {
    protected String t, p, c;
    public EntryKey(String term, String pos, String concept)
    {
      t = term; p = pos; c = concept;
    }
    public int compareTo(Object o)
    {
      if (!( o instanceof EntryKey))
	return -1;
      EntryKey k = (EntryKey)o;
      if (!t.equals(k.t))
	return t.compareTo(k.t);
      if (!p.equals(k.p))
	return p.compareTo(k.p);
      return c.compareTo(k.c);
    }
  }
      
  private TreeMap smcsclassdata;
  private TreeMap smcscodedata;

  private void addSMCSData(TreeMap data, String s)
  {
    s = s.trim();
    StringTokenizer st = new StringTokenizer(s, "@");
    if (st.countTokens() != 5)
    {
      System.err.println("Skipping bad SMCS data:");
      System.err.println(s);
      return;
    }
    EntryKey k = new EntryKey(st.nextToken(), st.nextToken(), st.nextToken());
    String code = st.nextToken();
    Object o = data.get(k);
    if (o == null)
    {
      List list = new LinkedList();
      list.add(code);
      data.put(k, list);
    }
    else
    {
      List list = (List)o;
      list.add(code);
    }
  }

  private void loadSMCS()
  {
    System.out.println("Loading SMCS data...");
    try
    {
      BufferedReader smcsclass = 
	new BufferedReader(new FileReader("smcs-class.data"));
      BufferedReader smcscode = 
	new BufferedReader(new FileReader("smcs-code.data"));
      smcsclassdata = new TreeMap();
      smcscodedata = new TreeMap();
      String s;
      try
      {
	do
	{
	  s = smcsclass.readLine();
	  if (s != null && !s.equals(""))
	    addSMCSData(smcsclassdata, s);
	}
	while (s != null && !s.equals(""));
      }
      catch (IOException e){}
      try
      {
	do
	{
	  s = smcscode.readLine();
	  if (s != null && !s.equals(""))
	    addSMCSData(smcscodedata, s);
	}
	while (s != null && !s.equals(""));
      }
      catch (IOException e){}
    }
    catch (FileNotFoundException e)
    {
      System.err.
	println("Cannot find smcs-class.data and smcs-code.data in CWD.");
      System.err.println("Continuing without SMCS data.");
      return;
    }
    System.out.println("Finished loading SMCS data...");
  }

  private void doConversion()
  {
    String sql = "SELECT term_id FROM LMT_TERMS ORDER by term_string";
    Debug.debug("-- findAllTerms: " + sql);
    try {		
      // get the result set 
      SQLConnection.Result num_terms = 
	dbConnection.query("SELECT COUNT(*) FROM LMT_TERMS");
      int size;
      if (num_terms == null || !num_terms.hasData())
      {
	System.err.println("Can't decide how many terms were in the DB.");
	System.exit(2);
      }
      size = num_terms.rs.getInt(1);
      num_terms.close();
      System.out.println("Number of terms: " + size);
      SQLConnection.Result rs = dbConnection.query(sql);
      if (rs == null)
      {
	System.err.println("Can't find any terms in DB.");
	System.exit(2);
      }
      int i = 0;
      double last = -1;
      while (rs.hasData())
      {
	if ((double)i / size * 1000 >= last + 1)
	{
	  last = java.lang.Math.floor((double)i / size * 1000);
	  System.out.println(last / 10 + "%");
	}
	convertTerm(rs.rs.getString(1));
	i++;
      }
      rs.close();
    } catch (SQLException E) {
      System.err.println("SQLException: " + E.getMessage());
      System.exit(2);
    }
  }

  void go()
  {
    if (!openDBConnection())
    {
      System.err.println("Could not open database connection to " + 
			 databaseURL);
      System.exit(1);
    }
    openOutputFiles();
    if (realdmk || fulldmk)
      loadSMCS();
    doConversion();
    closeDBConnection();
  }

  private boolean fulldmk;
  private boolean realdmk;

  public LMTConverter(String db, boolean realdmk, boolean fulldmk)
  {
    this.realdmk = realdmk;
    this.fulldmk = fulldmk;

    int colon = db.indexOf(':');
    if (colon == -1)
      databaseURL = db + ":1521:lmt2";
    else
    {
      int colon2 = db.indexOf(':', colon + 1);
      if (colon2 == -1)
	databaseURL = db + ":lmt2";
      else
      {
	String machine = db.substring(0, colon);
	String port;
	if (colon2 == colon + 1)
	  port = "1521";
	else
	  port = db.substring(colon + 1, colon2);
	String dbname;
	if (db.length() <= colon2 + 1)
	  dbname = "lmt2";
	else
	  dbname = db.substring(colon2 + 1);
	databaseURL = machine + ":" + port + ":" + dbname;
      }
    }
  }

  private static void usage() 
  {
    System.err.println ("Usage: LMTConverter dbhost[:[port][:dbname]] { -dmk | -devlms | -fulldmk }");
    System.exit(1);
  }

  public static void main(String[] args)
  {
    Debug.debugging = false;
    if (args.length != 2)
      usage();
    boolean dmk = false;
    boolean fulldmk = false;
    if (args[1].equals("-dmk"))
      dmk = true;
    else if (args[1].equals("-fulldmk"))
    {
      dmk = true;
      fulldmk = true;
    }
    else if (!args[1].equals("-devlms"))
      usage();
    LMTConverter lmtcv = new LMTConverter(args[0], dmk, fulldmk);
    lmtcv.go();
  }
}
