/*
 *  Copyright (c) 1998-2001, The University of Sheffield.
 *
 *  This file is part of GATE (see http://gate.ac.uk/), and is free
 *  software, licenced under the GNU Library General Public License,
 *  Version 2, June 1991 (in the distribution as file licence.html,
 *  and also available at http://gate.ac.uk/gate/licence.html).
 *
 *  Valentin Tablan, 01 Feb 2000
 *
 *  $Id: SentenceSplitter.java,v 1.24 2002/03/06 17:15:44 kalina Exp $
 */


package gate.creole.splitter;

import gate.*;
import gate.util.*;
import gate.event.*;
import gate.creole.tokeniser.*;
import gate.creole.gazetteer.*;
import gate.creole.*;

import java.util.*;
/**
 * A sentence splitter. This is module similar to a
 * {@link gate.creole.nerc.Nerc} in the fact that it conatins a tokeniser, a
 * gazetteer and a Jape grammar. This class is used so we can have a different
 * entry in the creole.xml file describing the default resources and to add
 * some minor processing after running the components in order to extract the
 * results in a usable form.
 */
public class SentenceSplitter extends AbstractLanguageAnalyser{

  public static final String
    SPLIT_DOCUMENT_PARAMETER_NAME = "document";

  public static final String
    SPLIT_INPUT_AS_PARAMETER_NAME = "inputASName";

  public static final String
    SPLIT_OUTPUT_AS_PARAMETER_NAME = "outputASName";

  public static final String
    SPLIT_ENCODING_PARAMETER_NAME = "encoding";

  public static final String
    SPLIT_GAZ_URL_PARAMETER_NAME = "gazetteerListsURL";

  public static final String
    SPLIT_TRANSD_URL_PARAMETER_NAME = "transducerURL";

  public Resource init()throws ResourceInstantiationException{
    //create all the componets
    FeatureMap params;
    FeatureMap features;

    //gazetteer
    fireStatusChanged("Creating the gazetteer");
    params = Factory.newFeatureMap();
    if(gazetteerListsURL != null)
      params.put(DefaultGazetteer.DEF_GAZ_LISTS_URL_PARAMETER_NAME,
                                             gazetteerListsURL);
    params.put(DefaultGazetteer.DEF_GAZ_ENCODING_PARAMETER_NAME, encoding);
    features = Factory.newFeatureMap();
    Gate.setHiddenAttribute(features, true);


    gazetteer = (DefaultGazetteer)Factory.createResource(
                    "gate.creole.gazetteer.DefaultGazetteer",
                    params, features);
    gazetteer.setName("Gazetteer " + System.currentTimeMillis());
    fireProgressChanged(10);

    //transducer
    fireStatusChanged("Creating the JAPE transducer");

    params = Factory.newFeatureMap();
    if(transducerURL != null)
      params.put(Transducer.TRANSD_GRAMMAR_URL_PARAMETER_NAME, transducerURL);
    params.put(Transducer.TRANSD_ENCODING_PARAMETER_NAME, encoding);
    features = Factory.newFeatureMap();
    Gate.setHiddenAttribute(features, true);

    transducer = (Transducer)Factory.createResource(
                    "gate.creole.Transducer",
                    params, features);
    transducer.setName("Transducer " + System.currentTimeMillis());

    fireProgressChanged(100);
    fireProcessFinished();

    return this;
  }

  public void execute() throws ExecutionException{
    interrupted = false;
    //set the runtime parameters
    FeatureMap params;
    if(inputASName != null && inputASName.equals("")) inputASName = null;
    if(outputASName != null && outputASName.equals("")) outputASName = null;
    try{
      fireProgressChanged(0);
      params = Factory.newFeatureMap();
      params.put(DefaultGazetteer.DEF_GAZ_DOCUMENT_PARAMETER_NAME, document);
      params.put(DefaultGazetteer.DEF_GAZ_ANNOT_SET_PARAMETER_NAME, inputASName);
      gazetteer.setParameterValues(params);

      params = Factory.newFeatureMap();
      params.put(Transducer.TRANSD_DOCUMENT_PARAMETER_NAME, document);
      params.put(Transducer.TRANSD_INPUT_AS_PARAMETER_NAME, inputASName);
      params.put(Transducer.TRANSD_OUTPUT_AS_PARAMETER_NAME, inputASName);
      transducer.setParameterValues(params);
    }catch(Exception e){
      throw new ExecutionException(e);
    }
    ProgressListener pListener = null;
    StatusListener sListener = null;
    fireProgressChanged(5);

    //run the gazetteer
    if(isInterrupted()) throw new ExecutionInterruptedException(
        "The execution of the \"" + getName() +
        "\" sentence splitter has been abruptly interrupted!");
    pListener = new IntervalProgressListener(5, 10);
    sListener = new StatusListener(){
      public void statusChanged(String text){
        fireStatusChanged(text);
      }
    };
    gazetteer.addProgressListener(pListener);
    gazetteer.addStatusListener(sListener);
    gazetteer.execute();
    gazetteer.removeProgressListener(pListener);
    gazetteer.removeStatusListener(sListener);

    //run the transducer
    if(isInterrupted()) throw new ExecutionInterruptedException(
        "The execution of the \"" + getName() +
        "\" sentence splitter has been abruptly interrupted!");
    pListener = new IntervalProgressListener(11, 90);
    transducer.addProgressListener(pListener);
    transducer.addStatusListener(sListener);
    transducer.execute();
    transducer.removeProgressListener(pListener);
    transducer.removeStatusListener(sListener);

    //get pointers to the annotation sets
    AnnotationSet inputAS = (inputASName == null) ?
                            document.getAnnotations() :
                            document.getAnnotations(inputASName);

    AnnotationSet outputAS = (outputASName == null) ?
                             document.getAnnotations() :
                             document.getAnnotations(outputASName);

    //copy the results to the output set if they are different
    if(inputAS != outputAS){
      outputAS.addAll(inputAS.get(SENTENCE_ANNOTATION_TYPE));
    }

    //create one big sentence if none were found
    AnnotationSet sentences = outputAS.get(SENTENCE_ANNOTATION_TYPE);
    if(sentences == null || sentences.isEmpty()){
      outputAS.add(outputAS.firstNode(), outputAS.lastNode(),
                   SENTENCE_ANNOTATION_TYPE,
                   Factory.newFeatureMap());;
    }else{
      //add a sentence covering all the tokens after the last sentence
      Long endSentences = sentences.lastNode().getOffset();
      AnnotationSet remainingTokens = inputAS.get(TOKEN_ANNOTATION_TYPE, endSentences,
                                                  inputAS.lastNode().getOffset());
      if(remainingTokens != null && !remainingTokens.isEmpty()){
        try{
          outputAS.add(remainingTokens.firstNode().getOffset(),
                       remainingTokens.lastNode().getOffset(),
                       SENTENCE_ANNOTATION_TYPE,
                       Factory.newFeatureMap());
        }catch(InvalidOffsetException ioe){
          throw new ExecutionException(ioe);
        }
      }
    }
    fireProcessFinished();
  }//execute()

  /**
   * Notifies all the PRs in this controller that they should stop their
   * execution as soon as possible.
   */
  public synchronized void interrupt(){
    interrupted = true;
    gazetteer.interrupt();
    transducer.interrupt();
  }

  public void setTransducerURL(java.net.URL newTransducerURL) {
    transducerURL = newTransducerURL;
  }
  public java.net.URL getTransducerURL() {
    return transducerURL;
  }
  DefaultGazetteer gazetteer;
  Transducer transducer;
  private java.net.URL transducerURL;
  private String encoding;
  private java.net.URL gazetteerListsURL;


  public void setEncoding(String newEncoding) {
    encoding = newEncoding;
  }
  public String getEncoding() {
    return encoding;
  }
  public void setGazetteerListsURL(java.net.URL newGazetteerListsURL) {
    gazetteerListsURL = newGazetteerListsURL;
  }
  public java.net.URL getGazetteerListsURL() {
    return gazetteerListsURL;
  }
  public void setInputASName(String newInputASName) {
    inputASName = newInputASName;
  }

  public String getInputASName() {
    return inputASName;
  }
  public void setOutputASName(String newOutputASName) {
    outputASName = newOutputASName;
  }
  public String getOutputASName() {
    return outputASName;
  }



  private static final boolean DEBUG = false;
  private String inputASName;
  private String outputASName;
}//public class SentenceSplitter extends Nerc