/* * Copyright 1999-2002 Carnegie Mellon University. * Portions Copyright 2002 Sun Microsystems, Inc. * Portions Copyright 2002 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.search; import edu.cmu.sphinx.util.props.PropertyException; import edu.cmu.sphinx.util.props.PropertySheet; import edu.cmu.sphinx.util.props.S4Boolean; import edu.cmu.sphinx.util.props.S4ComponentList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.logging.Logger; /** * A list of ActiveLists. Different token types are placed in different lists. * <p> * This class is not thread safe and should only be used by a single thread. */ public class SimpleActiveListManager implements ActiveListManager { /** * This property is used in the Iterator returned by the getNonEmittingListIterator() method. When the * Iterator.next() method is called, this property determines whether the lists prior to that returned by next() are * empty (they should be empty). If they are not empty, an Error will be thrown. */ @S4Boolean(defaultValue = false) public static final String PROP_CHECK_PRIOR_LISTS_EMPTY = "checkPriorListsEmpty"; /** The property that defines the name of the active list factory to be used by this search manager. */ @S4ComponentList(type = ActiveListFactory.class) public final static String PROP_ACTIVE_LIST_FACTORIES = "activeListFactories"; // -------------------------------------- // Configuration data // -------------------------------------- private Logger logger; private boolean checkPriorLists; private List<ActiveListFactory> activeListFactories; private ActiveList[] currentActiveLists; /** * Create a simple list manager * @param activeListFactories factories * @param checkPriorLists check prior lists during operation */ public SimpleActiveListManager(List<ActiveListFactory> activeListFactories, boolean checkPriorLists) { this.logger = Logger.getLogger( getClass().getName() ); this.activeListFactories = activeListFactories; this.checkPriorLists = checkPriorLists; } public SimpleActiveListManager() { } /* * (non-Javadoc) * * @see edu.cmu.sphinx.util.props.Configurable#newProperties(edu.cmu.sphinx.util.props.PropertySheet) */ public void newProperties(PropertySheet ps) throws PropertyException { logger = ps.getLogger(); activeListFactories = ps.getComponentList(PROP_ACTIVE_LIST_FACTORIES, ActiveListFactory.class); checkPriorLists = ps.getBoolean(PROP_CHECK_PRIOR_LISTS_EMPTY); } /* * (non-Javadoc) * * @see edu.cmu.sphinx.decoder.search.ActiveListManager#setNumStateOrder(java.lang.Class[]) */ public void setNumStateOrder(int numStateOrder) { // check to make sure that we have the correct // number of active list factories for the given search states currentActiveLists = new ActiveList[numStateOrder]; if (activeListFactories.isEmpty()) { logger.severe("No active list factories configured"); throw new Error("No active list factories configured"); } if (activeListFactories.size() != currentActiveLists.length) { logger.warning("Need " + currentActiveLists.length + " active list factories, found " + activeListFactories.size()); } createActiveLists(); } /** * Creates the emitting and non-emitting active lists. When creating the non-emitting active lists, we will look at * their respective beam widths (eg, word beam, unit beam, state beam). */ private void createActiveLists() { int nlists = activeListFactories.size(); for (int i = 0; i < currentActiveLists.length; i++) { int which = i; if (which >= nlists) { which = nlists - 1; } ActiveListFactory alf = activeListFactories.get(which); currentActiveLists[i] = alf.newInstance(); } } /** * Adds the given token to the list * * @param token the token to add */ public void add(Token token) { ActiveList activeList = findListFor(token); if (activeList == null) { throw new Error("Cannot find ActiveList for " + token.getSearchState().getClass()); } activeList.add(token); } /** * Given a token find the active list associated with the token type * * @param token * @return the active list */ private ActiveList findListFor(Token token) { return currentActiveLists[token.getSearchState().getOrder()]; } /** * Returns the emitting ActiveList from the manager * * @return the emitting ActiveList */ public ActiveList getEmittingList() { ActiveList list = currentActiveLists[currentActiveLists.length - 1]; return list; } /** * Clears emitting list in manager */ public void clearEmittingList() { ActiveList list = currentActiveLists[currentActiveLists.length - 1]; currentActiveLists[currentActiveLists.length - 1] = list.newInstance(); } /** * Returns an Iterator of all the non-emitting ActiveLists. The iteration order is the same as the search state * order. * * @return an Iterator of non-emitting ActiveLists */ public Iterator<ActiveList> getNonEmittingListIterator() { return (new NonEmittingListIterator()); } private class NonEmittingListIterator implements Iterator<ActiveList> { private int listPtr; public NonEmittingListIterator() { listPtr = -1; } public boolean hasNext() { return listPtr + 1 < currentActiveLists.length - 1; } public ActiveList next() throws NoSuchElementException { listPtr++; if (listPtr >= currentActiveLists.length) { throw new NoSuchElementException(); } if (checkPriorLists) { checkPriorLists(); } return currentActiveLists[listPtr]; } /** Check that all lists prior to listPtr is empty. */ private void checkPriorLists() { for (int i = 0; i < listPtr; i++) { ActiveList activeList = currentActiveLists[i]; if (activeList.size() > 0) { throw new Error("At while processing state order" + listPtr + ", state order " + i + " not empty"); } } } public void remove() { currentActiveLists[listPtr] = currentActiveLists[listPtr].newInstance(); } } /** Outputs debugging info for this list manager */ public void dump() { System.out.println("--------------------"); for (ActiveList al : currentActiveLists) { dumpList(al); } } /** * Dumps out debugging info for the given active list * * @param al the active list to dump */ private void dumpList(ActiveList al) { System.out.println("Size: " + al.size() + " Best token: " + al.getBestToken()); } }