/*******************************************************************************
*   Copyright 2014 Analog Devices, Inc.
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
********************************************************************************/

/**
 * Classes for controlling the generation and handling of events specific to Dimple.
 * 
 * <h2>Overview</h2>
 * 
 * Dimple events are intended for use in monitoring changes to a Dimple model, data values
 * or solver state. The events can either by passed to an external monitoring system, logged
 * somewhere, or even used synchronously respond to changes. The event system is is designed to
 * have minimal overhead when there are no listeners active for a given event type.
 * 
 * <h2>Events</h2>
 * 
 * Events are represented by instances of concrete subclasses of the class
 * {@linkplain com.analog.lyric.dimple.events.DimpleEvent DimpleEvent}. There are three classes of event types,
 * represented by distinct abstract subclasses:
 * <ul>
 * <li>{@linkplain com.analog.lyric.dimple.events.ModelEvent ModelEvent}: changes to model such as add or removal of
 * factors or variables.
 * <li>{@linkplain com.analog.lyric.dimple.events.DataEvent DataEvent}: changes to observed data values or variable
 * input distributions.
 * <li>{@linkplain com.analog.lyric.dimple.events.SolverEvent SolverEvent}: solver-specific events such as message
 * updates for belief-propagation solvers or new sample values for sampling solvers.
 * </ul>
 * 
 * A full hierarchy of events can be seen easily using the Type Hierarchy view in Eclipse (press
 * Ctrl+Shift+H, type "DimpleEvent" in the dialog, and hit "Ok").
 * 
 * <h2>Event listeners</h2>
 * 
 * An instance of the {@linkplain com.analog.lyric.dimple.events.DimpleEventListener DimpleEventListener}
 * class is responsible for dispatching of events raised from event sources from the same
 * {@linkplain com.analog.lyric.dimple.environment.DimpleEnvironment Dimple environment}. Almost always the
 * {@linkplain com.analog.lyric.dimple.environment.DimpleEnvironment#active() active} environment is the
 * only environment, but if there is more than one, the event source object knows which environment it belongs
 * to. If there is no listener on the environment, which is the default, then no events should be generated.
 * You may set or clear the listener on the environment using the
 * {@linkplain com.analog.lyric.dimple.environment.DimpleEnvironment#setEventListener setEventListener} method or
 * you can simply force creation of a listener using the
 * {@linkplain com.analog.lyric.dimple.environment.DimpleEnvironment#createEventListener createEventListener} method.
 * <p>
 * Once a listener has been associated with the environment, then one or more handlers may be registered to
 * handle events. The registration must specify the base class of the type of event to
 * be handled and the root object on which events will be raised. It will be easiest to register for
 * events on the root factor graph, but it may sometimes be desirable to set up handlers for specific variables,
 * factors or subgraphs. For instance, to register handlers for various belief propagation messages on
 * a graph, you could write:
 * 
 * <pre>
 *     void registerHandlers(FactorGraph fg)
 *     {
 *         DimpleEventListener listener = fg.getEnvironment().createEventListener();
 *         listener.register(factorMessageHandler, FactorToVariableMessageEvent.class, fg);
 *         listener.register(variableMessageHandler, VariableToFactorMessageEvent.class, fg);
 *     }
 * </pre>
 * 
 * It is also possible to register for events on the environment itself, which will affect all graphs
 * in the environment:
 * 
 * <pre>
 *     DimpleEnvironment env = DimpleEnvironment.active();
 *     DimpleEventListener listener = env.createEventListener();
 *     listener.register(factorMessageHandler, FactorToVariableMessageEvent.class, env);
 *     listener.register(variableMessageHandler, VariableToFactorMessageEvent.class, env);
 * </pre>

 * Handlers can be removed by one of the various {@code unregister} methods on the listener.
 * <p>
 * Changes to event registration or the value of the root listener are not guaranteed to take effect until
 * the next time the affected objects have been initialized or
 * {@linkplain com.analog.lyric.dimple.events.IDimpleEventSource#notifyListenerChanged() notifyListenerChanged()}
 * has been invoked on the object that generates the event. This is important for model events in particular
 * since model changes typically occur prior to initialization.
 * 
 * <h2>Event handlers</h2>
 * 
 * Dimple event handlers are objects that implement the
 * {@linkplain com.analog.lyric.dimple.events.IDimpleEventHandler IDimpleEventHandler}
 * interface. In practice most handlers should simply extend
 * {@linkplain com.analog.lyric.dimple.events.DimpleEventHandler DimpleEventHandler}.
 * For example, here is a simple handler class that simply prints events out to the console with a verbosity of one:
 * 
 * <pre>
 * public class EventPrinter extends DimpleEventHandler&LT;DimpleEvent&GT;
 * {
 *     public void handleEvent(DimpleEvent event)
 *     {
 *         event.println(System.out, 1);
 *     }
 * }
 * </pre>
 * 
 * Handler classes that are specific to a particular event subclass can be parameterized appropriately
 * to avoid the need for downcasts. For example, here is a simple handler that keeps a running total
 * of the total graph score during Gibbs sampling based on sample score differences:
 * 
 * <pre>
 * public class RunningScoreHandler extends DimpleEventHandler&LT;GibbsScoredVariableUpdateEvent&GT;
 * {
 *     public double score;
 * 
 *     RunningScoreHandler(double startingScore)
 *     {
 *         score = startingScore;
 *     }
 * 
 *     public void handleEvent(GibbsScoredVariableUpdateEvent event)
 *     {
 *         score += event.getScoreDifference();
 *     }
 * }
 * </pre>
 * 
 * <h2>Concurrency issues</h2>
 * 
 * Handlers are invoked synchronously as soon as the events have been constructed. Accessing the attributes
 * of the event objects is guaranteed to be thread safe, but calling methods on the event source or model
 * objects referred to in the event may not be safe.
 * 
 * <h2>Serialization</h2>
 * 
 * Dimple events implement the {@link java.io.Serializable} interface, which allows them to be serialized
 * to binary form for persistent storage or transmission to a remote monitor. However, note that events
 * purposely will not attempt to serialize references to model or solver elements, since that would require
 * serializing the entire graph. This means that deserialized event objects will contain null references for
 * any such object. Instead of serializing the actual object, the name and id of the object will be serialized.
 * <p>
 * @since
 * <li>0.07 - support for DimpleEnvironment
 * <li>0.06 - package was first introduced
 * @author Christopher Barber
 */
@org.eclipse.jdt.annotation.NonNullByDefault
package com.analog.lyric.dimple.events;

