// $Id: WortschatzOOExtension.java 177 2005-06-16 14:54:48Z olau $

package de.ct.wortschatz.oo;

import java.io.IOException;
import java.lang.String;

import com.sun.star.lib.uno.helper.ComponentBase;

import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XSingleServiceFactory;

import com.sun.star.linguistic2.XThesaurus;
import com.sun.star.lang.XInitialization;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XServiceDisplayName;

import com.sun.star.linguistic2.XMeaning;
import com.sun.star.lang.Locale;
import com.sun.star.beans.PropertyValue;

import de.ct.wortschatz.Wortschatz;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.FileAppender;
import org.apache.log4j.PatternLayout;

public class WortschatzOOExtension extends ComponentBase implements XThesaurus,
		XInitialization, XServiceInfo, XServiceDisplayName {

	/**
	 * <code>Logger</code> -Objekt.
	 * 
	 * @see org.apache.log4j.Logger
	 */
	private final Logger logger = Logger.getLogger(WortschatzOOExtension.class);

	/**
	 * Beschreibung eines Log-Eintrags.
	 * 
	 * @see logger
	 * @see org.apache.log4j.PatternLayout
	 */
	private final PatternLayout layout = new PatternLayout(
			"%r <%t> %-5p %c %x - %m%n");

	/**
	 * Name der Datei, in die die Log-Einträge geschrieben werden sollen.
	 * 
	 * @see logger
	 * @see org.apache.log4j.Logger
	 */
	private final String logFileName = "Wortschatz.log";

	/**
	 * @see org.apache.log4j.FileAppender
	 */
	private FileAppender appender = null;

	/**
	 * Liste der Locales, die der Thesaurus unterstützt (zurzeit nur "Deutsch
	 * (Deutschland)").
	 */
	private final Locale[] supportedLocales = { new Locale("de", "DE", "") };

	/**
	 * OpenOffice springt den Konstruktor beim Aufruf der Thesaurus-Extension
	 * an.
	 */
	public WortschatzOOExtension() {
		/* Loggen in Datei vorbereiten */
		try {
			appender = new FileAppender(layout, logFileName, false);
			appender.setName("Wortschatz-Logger");
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		/* Logger initialisieren */
		if (appender != null) {
			BasicConfigurator.configure(appender);
			logger.addAppender(appender);
		}
	}

	/**
	 * Prüfen, ob zwei <code>Locale</code> -Objekte denselben Inhalt haben.
	 * 
	 * @param loc1
	 *            <code>Locale</code> -Objekt
	 * @param aLoc2
	 *            <code>Locale</code> -Objekt, das mit <code>loc1</code>
	 *            verglichen werden soll.
	 * @return <code>true</code>, wenn beide Objekte identisch, sonst
	 *         <code>false</code>
	 */
	private boolean isEqual(Locale loc1, Locale loc2) {
		return loc1.Language.equals(loc2.Language)
				&& loc1.Country.equals(loc2.Country)
				&& loc1.Variant.equals(loc2.Variant);
	}

	// ---------------------------------------
	//
	//    Schnittstellen-Implementierungen
	//
	// ---------------------------------------

	//*******************
	// XSupportedLocales
	//*******************

	/**
	 * Liste der unterstützten Spracheinstellungen zurückgeben.
	 * 
	 * @return Liste der unterstützten Locales
	 * @see com.sun.star.linguistic2.XSupportedLocales#getLocales()
	 */
	public Locale[] getLocales() throws com.sun.star.uno.RuntimeException {
		return supportedLocales;
	}

	/**
	 * Prüfen, ob die angefragte Spracheinstellung vom Thesaurus unterstützt
	 * wird.
	 * 
	 * @return <code>true</code>, wenn der Thesaurus die angefragte
	 *         <code>Locale</code> unterstützt, sonst <code>false</code>.
	 * @see com.sun.star.linguistic2.XSupportedLocales#hasLocale(com.sun.star.lang.Locale)
	 */
	public boolean hasLocale(Locale locale)
			throws com.sun.star.uno.RuntimeException {
		for (int i = 0; i < supportedLocales.length; i++) {
			if (isEqual(locale, supportedLocales[i]))
				return true;
		}
		return false;
	}

	//************
	// XThesaurus
	//************

	/**
	 * Das ist die Kernmethode des Thesaurus. Sie ermittelt mit Hilfe des
	 * <code>Wortschatz</code> -Objekts die sinn- und sachverwandten Begriffe
	 * für den Begriff in <code>term</code>. Das zurückgegebene
	 * XMeaning[]-Objekt ist <code>null</code>, wenn die Synonymsuche
	 * erfolglos war, etwa weil der Wortschatz keine Synonyme für den Begriff
	 * gespeichert hat oder weil die Spracheinstellung nicht unterstützt wird
	 * 
	 * @param term
	 *            der Begriff, für den die Synonyme ermittelt werden sollen.
	 * @param locale
	 *            die Spracheinstellungen des Dokuments, aus dem der Begriff
	 *            angefragt wurde.
	 * @param properties
	 *            (nicht verwendet)
	 * @return XMeaning[]-Objekt, das die sinn- und sachverwandten Begriffe
	 *         enthält.
	 */
	public XMeaning[] queryMeanings(String term, Locale locale,
			PropertyValue[] properties)
			throws com.sun.star.lang.IllegalArgumentException,
			com.sun.star.uno.RuntimeException {

		if (isEqual(locale, new Locale())) {
			logger.error("Locale-Angabe fehlt");
			return null;
		}
		if (term.length() == 0) {
			logger.error("Suchbegriff fehlt");
			return null;
		}
		if (!hasLocale(locale)) {
			logger.error("Nicht unterstützte Locale-Angabe: " + locale.Language
					+ "_" + locale.Country);
			return null;
		}
		logger.info("Verwenden des Corpus '" + locale.Language + "'");
		XMeaning[] meanings = new XMeaning[] { null };
		Wortschatz ws = new Wortschatz(term, locale.Language);
		ws.setLogger(logger);
		String[] synonyms = ws.getSynonyms();
		if (synonyms != null) {
			logger.info(synonyms.length + " Synonyme für '" + term
					+ "' gefunden");
		} else {
			logger.info("Keine Synonyme für '" + term + "' gefunden");
		}
		meanings[0] = new XMeaning_impl(null, synonyms);
		return meanings;
	}

	//*********************
	// XServiceDisplayName
	//*********************
	public String getServiceDisplayName(Locale locale)
			throws com.sun.star.uno.RuntimeException {
		return "Thesaurus Wortschatz Uni Leipzig";
	}

	//*****************
	// XInitialization
	//*****************
	public void initialize(Object[] args) throws com.sun.star.uno.Exception,
			com.sun.star.uno.RuntimeException {
	}

	//**************
	// XServiceInfo
	//**************

	/* (non-Javadoc)
	 * @see com.sun.star.lang.XServiceInfo#supportsService(java.lang.String)
	 */
	public boolean supportsService(String serviceName)
			throws com.sun.star.uno.RuntimeException {
		String[] services = getSupportedServiceNames_Static();
		for (int i = 0; i < services.length; ++i)
			if (serviceName.equals(services[i]))
				return true;
		return false;
	}

	/* (non-Javadoc)
	 * @see com.sun.star.lang.XServiceInfo#getImplementationName()
	 */
	public String getImplementationName()
			throws com.sun.star.uno.RuntimeException {
		return _aSvcImplName;
	}

	/* (non-Javadoc)
	 * @see com.sun.star.lang.XServiceInfo#getSupportedServiceNames()
	 */
	public String[] getSupportedServiceNames()
			throws com.sun.star.uno.RuntimeException {
		return getSupportedServiceNames_Static();
	}

	// ---------------------------------------
	//
	//         Statische Deklarationen
	//
	// ---------------------------------------

	/**
	 * Name des Service.
	 */
	public static String _aSvcImplName = "de.ct.wortschatz.oo.thesaurus";

	/**
	 * @return Liste der von dieser Erweiterung unterstützten Services zurückgeben.
	 */
	public static String[] getSupportedServiceNames_Static() {
		String[] result = { "com.sun.star.linguistic2.Thesaurus" };
		return result;
	}

	/**
	 * Returns a factory for creating the service. This method is called by the
	 * <code>JavaLoader</code>
	 * <p>
	 * 
	 * @return returns a <code>XSingleServiceFactory</code> for creating the
	 *         component
	 * @param implName
	 *            the name of the implementation for which a service is desired
	 * @param multiFactory
	 *            the service manager to be used if needed
	 * @param regKey
	 *            the registryKey
	 * @see com.sun.star.comp.loader.JavaLoader
	 */
	public static XSingleServiceFactory __getServiceFactory(String implName,
			XMultiServiceFactory xMultiFactory,
			com.sun.star.registry.XRegistryKey xRegKey) {
		XSingleServiceFactory xSingleServiceFactory = null;
		if (implName.equals(_aSvcImplName)) {
			xSingleServiceFactory = new OneInstanceFactory(
					WortschatzOOExtension.class, _aSvcImplName,
					getSupportedServiceNames_Static(), xMultiFactory);
		}
		return xSingleServiceFactory;
	}

	/**
	 * Writes the service information into the given registry key. This method
	 * is called by the <code>JavaLoader</code>
	 * 
	 * @return returns true if the operation succeeded
	 * @param xRegKey
	 *            the registryKey
	 * @see com.sun.star.comp.loader.JavaLoader
	 */
	public static boolean __writeRegistryServiceInfo(
			com.sun.star.registry.XRegistryKey regKey) {
		boolean result = true;
		String[] services = getSupportedServiceNames_Static();
		int length = services.length;
		for (int i = 0; i < length; ++i) {
			result = result
					&& com.sun.star.comp.loader.FactoryHelper
							.writeRegistryServiceInfo(_aSvcImplName,
									services[i], regKey);
		}
		return result;
	}
}
