/*
* Copyright 1999-2004 Carnegie Mellon University.
* Portions Copyright 2004 Sun Microsystems, Inc.
* Portions Copyright 2004 Mitsubishi Electric Research Laboratories.
* All Rights Reserved. Use is subject to license terms.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*
*/
package edu.cmu.sphinx.decoder;
import edu.cmu.sphinx.decoder.search.SearchManager;
import edu.cmu.sphinx.result.Result;
import edu.cmu.sphinx.util.props.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/** An abstract decoder which implements all functionality which is independent of the used decoding-paradigm (pull/push). */
public abstract class AbstractDecoder implements ResultProducer, Configurable {
/**
* The property that defines the name of the search manager to use
* */
@S4Component(type = SearchManager.class)
public final static String PROP_SEARCH_MANAGER = "searchManager";
protected SearchManager searchManager;
@S4ComponentList(type = ResultListener.class)
public static final String PROP_RESULT_LISTENERS = "resultListeners";
protected final List<ResultListener> resultListeners = new ArrayList<ResultListener>();
/**
* If set to true the used search-manager will be automatically allocated
* in <code>newProperties()</code>.
* */
@S4Boolean(defaultValue = false)
public static final String AUTO_ALLOCATE = "autoAllocate";
/**
* If set to <code>false</code> the used search-manager all registered
* result listeners will be notified only for final results. Per default
* non-final results don't trigger notification, because in most
* application the utterance final result will be sufficient.
*/
@S4Boolean(defaultValue = false)
public static final String FIRE_NON_FINAL_RESULTS = "fireNonFinalResults";
private boolean fireNonFinalResults;
private String name;
protected Logger logger;
public AbstractDecoder() {
}
/**
* Abstract decoder to implement live and batch recognizers
* @param searchManager search manager to use
* @param fireNonFinalResults to fire result during decoding
* @param autoAllocate automatic allocate all components
* @param resultListeners listeners to get noification
*/
public AbstractDecoder(SearchManager searchManager, boolean fireNonFinalResults, boolean autoAllocate, List<ResultListener> resultListeners) {
String name = getClass().getName();
init( name, Logger.getLogger(name),
searchManager, fireNonFinalResults, autoAllocate, resultListeners);
}
/**
* Decode frames until recognition is complete
*
* @param referenceText the reference text (or null)
* @return a result
*/
public abstract Result decode(String referenceText);
public void newProperties(PropertySheet ps) throws PropertyException {
init( ps.getInstanceName(), ps.getLogger(), (SearchManager) ps.getComponent(PROP_SEARCH_MANAGER), ps.getBoolean(FIRE_NON_FINAL_RESULTS), ps.getBoolean(AUTO_ALLOCATE), ps.getComponentList(PROP_RESULT_LISTENERS, ResultListener.class));
}
private void init(String name, Logger logger, SearchManager searchManager, boolean fireNonFinalResults, boolean autoAllocate, List<ResultListener> listeners) {
this.name = name;
this.logger = logger;
this.searchManager = searchManager;
this.fireNonFinalResults = fireNonFinalResults;
if (autoAllocate) {
searchManager.allocate();
}
for (ResultListener listener : listeners) {
addResultListener(listener);
}
}
/** Allocate resources necessary for decoding */
public void allocate() {
searchManager.allocate();
}
/** Deallocate resources */
public void deallocate() {
searchManager.deallocate();
}
/**
* Adds a result listener to this recognizer. A result listener is called whenever a new result is generated by the
* recognizer. This method can be called in any state.
*
* @param resultListener the listener to add
*/
public void addResultListener(ResultListener resultListener) {
resultListeners.add(resultListener);
}
/**
* Removes a previously added result listener. This method can be called in any state.
*
* @param resultListener the listener to remove
*/
public void removeResultListener(ResultListener resultListener) {
resultListeners.remove(resultListener);
}
/**
* Fires new results as soon as they become available.
*
* @param result the new result
*/
protected void fireResultListeners(Result result) {
if (fireNonFinalResults || result.isFinal()) {
for (ResultListener resultListener : resultListeners) {
resultListener.newResult(result);
}
}else {
logger.finer("skipping non-final result " + result);
}
}
@Override
public String toString() {
return name;
}
}