/*
*
* 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.util.props;
/**
* Defines the interface that must be implemented by any configurable component in Sphinx-4. The life cycle of a
* component is as follows:
* <ul><li> <b>Class Parsing</b> The class file is parsed in order to determine all its configurable properties. These
* are defined using <code>public static final String</code> fields which are annotated with one of the following
* annotations: <ul> <li>S4Integer <li>S4Double <li>S4Boolean <li>S4Component <li>S4ComponentList </ul> Further
* informations about property-specific fields can be found in the javadoc of the property-annotation-definitions. Only
* names of annotated properties will be allowed by the configuration system later on.
* <li> <b>Construction</b> - The (empty) component constructor is called in order to instantiate the component.
* Typically the constructor does little, if any work, since the component has not been configured yet.
* <li> <b> Configuration</b> - Shortly after instantiation, the component's <code>newProperties</code> method is
* called. This method is called with a <code>PropertySheet</code> containing the properties (usually taken from an
* external configuration file). The component should extract the properties from the property sheet. If some properties
* defined for a component does not fulfill the property definition given by the annotation (type, range, etc.) a
* <code>PropertyException</code> is thrown. Typically, once a component gets its configuration data via the
* <code>newData</code> method, the component will initialize itself.
* <p>
* Note: In most cases <code>newProperties</code> is called only once as a result of system configuration during
* startup. But nevertheless it is possible (and sometimes necessary) to reconfigure a component while it's running.
* Therefore, a well behaved component should react properly to multiple <code>newProperties</code> calls. </ul>
* <p>
* <b>Connecting to other components</b>
* <p> Components often need to interact with other components in the system.
* One of the design goals of Sphinx-4 is that it allows for very flexible hook up of components in the system.
* Therefore, it is *not* considered good S4 style to hardcode which subcomponents a particular subcomponent is
* interacting with. Instead, the component should use the configuration manager to provide the hook up to another
* component.
* <p>
* For example, if a component needs to interact with a Linguist. Instead of explicitly setting which linguist is to be
* used via a constructor or via a <code>setLinguist</code> call, the component should instead define a configuration
* property for the linguist. This would be done like so:
* <code>
* \@S4Component(type=Linguist.class)
* public static String PROP_LINGUIST = "linguist";
* </code>
* <p> The linguist is made available in the <code>newProperties</code> method, like so: <p>
* <code>
* public void newProperties(PropertySheet propertySheet) {
* linguist = (Linguist) propertySheet.getComponent(PROP_LINGUIST);
* }
* </code>
* This <code>getComponent</code> call will find the proper linguist based upon the configuration data. Thus, if the
* configuration for this component had the 'linguist' defined to be 'dynamicLexTreeLinguist', then the configuration
* manager will look up and return a linguist with that name, creating and configuring it as necessary. Of course, the
* dynamicLexTreeLinguist itself may have a number of sub-components that will be created and configured as a result. If
* the component doesn't exist (but was defined to mandatory) and no configuration information is found in the config
* file for it, or if it is of the wrong type, a <code>PropertyException</code> will be thrown.
*/
public interface Configurable {
/**
* This method is called when this configurable component needs to be reconfigured.
*
* @param ps a property sheet holding the new data
* @throws PropertyException if there is a problem with the properties.
*/
public void newProperties(PropertySheet ps) throws PropertyException;
}