// $Id: Wortschatz.java 199 2005-06-22 13:21:30Z olau $

package de.ct.wortschatz;

import java.lang.String;

import javax.xml.rpc.ServiceException;

import de.ct.wortschatz.thesaurus.ThesaurusServiceLocator;
import de.ct.wortschatz.thesaurus.ThesaurusSoapBindingStub;
import de.ct.wortschatz.thesaurus.RequestParameter;
import de.ct.wortschatz.thesaurus.ResponseParameter;
import de.ct.wortschatz.thesaurus.DataMatrix;
import de.ct.wortschatz.thesaurus.DataVector;

import org.apache.log4j.Logger;

public class Wortschatz {

	/**
	 * Benutzerkennung, unter der der Thesaurus auf den Webservice zugreift.
	 */
	private final String userName = "ct-thesaur";

	/**
	 * Passwort des Benutzers.
	 * 
	 * @see userName
	 */
	private final String password = "ct-thesaurus";

	/**
	 * Der Parameter "Wort" enthält Begriff, für den Synonyme ermittelt werden
	 * sollen.
	 */
	private final String wordParm = "Wort";

	/**
	 * Der Parameter "Limit" beschränkt die Anzahl der Synonyme.
	 */
	private final String limitParm = "Limit";

	/**
	 * Der Begriff, für den die Synonyme ermittelt werden soll. Wird als Wert
	 * für den Parameter in <code>wordParam</code> an den Webservice
	 * übergeben.
	 */
	private String term = null;

	// private int limit = Integer.MAX_VALUE; /* unlimited synonyms */
	/** 
	 * Die maximale Anzahl der Synonyme, die der Webservice zurückliefern soll.
	 */
	private int limit = 100;

	/**
	 * Der Textkorpus (sprich: das Vokabular), aus dem die Synonyme stammen sollen. 
	 */
	private String corpus = "de";

	private Logger logger = null;

	/** 
	 * Das Objekt, das die Verbindung zum Webservice herstellt.
	 */
	private ThesaurusSoapBindingStub thesBinding = null;

	private DataMatrix thesObjParameters = null;

	/**
	 * Das Objekt, das die Übergabewerte für den Webservice aufnimmt.
	 */
	private RequestParameter thesRequestParm = null;

	/**
	 * Das Objekt, in dem das Ergebnis der Webservice-Anfrage zurückgeliefert wird.
	 */
	private ResponseParameter thesResponseParm = null;
	
	private boolean connected = false;
	
	private String lastExecutionTime = null;

	public Wortschatz() {
	}

	/**
	 * @param term
	 *            Begriff, für den die Synonyme geholt werden sollen.
	 */
	public Wortschatz(String term) {
		this.term = term;
	}

	/**
	 * @param term
	 *            Begriff, für den die Synonyme geholt werden sollen.
	 * @param limit
	 *            Maximale Anzahl der zurückzugebenden Synonyme.
	 */
	public Wortschatz(String term, int limit) {
		this.term = term;
		this.limit = limit;
	}

	/**
	 * @param term
	 *            Begriff, für den die Synonyme geholt werden sollen.
	 * @param limit
	 *            Maximale Anzahl der zurückzugebenden Synonyme.
	 * @param corpus
	 *            Zu durchsuchender Korpus.
	 */
	public Wortschatz(String term, int limit, String corpus) {
		this.term = term;
		this.limit = limit;
		this.corpus = corpus;
	}

	/**
	 * @param term
	 *            Begriff, für den die Synonyme geholt werden sollen.
	 * @param corpus
	 *            Zu durchsuchender Korpus.
	 */
	public Wortschatz(String term, String corpus) {
		this.term = term;
		this.corpus = corpus;
	}

	/**
	 * Mit Thesaurus-Webservice verbinden.
	 */
	protected void connect() {
		try {
			thesBinding = (ThesaurusSoapBindingStub) new ThesaurusServiceLocator()
					.getThesaurus();
		} catch (ServiceException se) {
			writeErrorLog(se.getMessage());
		}
		thesBinding.setUsername(userName);
		thesBinding.setPassword(password);
		connected = true;
	}

	/**
	 * Synonyme vom Webservice beziehen.
	 * 
	 * @return String-Array mit der Liste der gefundenen Synonyme für den
	 *         Begriff in <code>term</code>
	 * @see term
	 */
	public String[] getSynonyms() {
		if (!connected) 
			connect();
		thesObjParameters = new DataMatrix();
		DataVector[] v = new DataVector[] {
				new DataVector(new String[]{ wordParm, term }),
				new DataVector(new String[]{ limitParm, String.valueOf(limit) })
				};
		thesObjParameters.setDataVectors(v);
		thesRequestParm = new RequestParameter();
		thesRequestParm.setCorpus(corpus);
		thesRequestParm.setParameters(thesObjParameters);
		ResponseParameter thesResult = null;
		DataVector[] res = null;
		String[] synonyms = null;
		try {
			thesResult = thesBinding.execute(thesRequestParm);
		} catch (Exception e) {
			writeErrorLog(e.getMessage());
		}
		res = thesResult.getResult().getDataVectors();
		lastExecutionTime = thesResult.getExecutionTime();
		if (res != null) {
			int numResults = (res.length < limit) ? res.length : limit;
			if (numResults > 0) {
				synonyms = new String[numResults];
				for (int i = 0; i < numResults; i++) {
					synonyms[i] = res[i].getDataRow(0);
				}
			}
		}
		return synonyms;
	}
	
	public String getStatus() {
		if (!connected) 
			connect();
		String res = null;
		try {
			res = thesBinding.ping();
		} catch (Exception e) {
			writeErrorLog(e.getMessage());
		}
		return res;
	}
	
	public String getExecutionTime() {
		return (lastExecutionTime != null) ? lastExecutionTime : new String("");
	}
	
	public void setTerm(String term) {
		this.term = term;
	}

	/**
	 * <code>Logger</code> bestimmen.
	 * 
	 * @param logger
	 *            Zum Loggen zu verwendendes <code>Logger</code>-Objekt
	 * @see org.apache.log4j.Logger
	 */
	public void setLogger(Logger logger) {
		this.logger = logger;
	}

	/**
	 * Einen Eintrag ins Log schreiben. Wenn ein Logger per
	 * <code>setLogger()</code> definiert ist, wird der Eintrag dort hinein
	 * geschrieben, andernfalls landet er in der Standardausgabe.
	 * 
	 * @param entry
	 *            Eintrag fürs Log.
	 * @see setLogger()
	 */
	private void writeLog(String entry) {
		if (logger != null)
			logger.info(entry);
		else
			System.out.println(entry);
	}


	/**
	 * Eine Fehlermeldung ins Log schreiben. Wenn ein Logger per
	 * <code>setLogger()</code> definiert ist, wird die Fehlermeldung dort
	 * hinein geschrieben, andernfalls landet sie in der Standardfehlerausgabe.
	 * 
	 * @param entry
	 *            Eintrag fürs Log.
	 * @see setLogger()
	 */
	private void writeErrorLog(String entry) {
		if (logger != null)
			logger.error(entry);
		else
			System.err.println(entry);
	}
}
