/*
 Copyright (C) 2007 Richard Gomes

 This source code is release under the BSD License.

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the JQuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

package org.jquantlib.util;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jquantlib.QL;


// --------------------------------------------------------
// This class is based on the work done by Martin Fischer.
// See references in JavaDoc
//--------------------------------------------------------

/**
 * Default implementation of an {@link Observable}.
 * 

* This implementation notifies the observers in a synchronous fashion. Note that this can cause trouble if you notify the observers * while in a transactional context because once the notification is done it cannot be rolled back. * * @note This class is not thread safe * * @see Martin Fischer: Observer and * Observable interfaces * @see Improved Observer/Observable * * @see Observable * @see Observer * @see WeakReferenceObservable * * @author Richard Gomes * @author Srinivas Hasti */ public class DefaultObservable implements Observable { final private static String OBSERVABLE_IS_NULL = "observable is null"; final private static String CANNOT_NOTIFY_OBSERVERS = "could not notify one or more observers"; // // private final fields // private final List observers; private final Observable observable; // // public constructors // public DefaultObservable(final Observable observable) { QL.require(observable != null, DefaultObservable.OBSERVABLE_IS_NULL); this.observers = new CopyOnWriteArrayList(); this.observable = observable; } // // public methods // @Override public void addObserver(final Observer observer) { observers.add(observer); } @Override public int countObservers() { return observers.size(); } @Override public List getObservers() { return Collections.unmodifiableList(this.observers); } @Override public void deleteObserver(final Observer observer) { observers.remove(observer); } @Override public void deleteObservers() { observers.clear(); } @Override public void notifyObservers() { notifyObservers(null); } @Override public void notifyObservers(final Object arg) { Exception exception = null; for (final Observer observer : observers) { try { wrappedNotify(observer, observable, arg); } catch (final Exception e) { // Quite a dilemma. If we don't catch the exception, // other observers will not receive the notification // and might be left in an incorrect state. If we do // catch it and continue the loop (as we do here) we // lose the exception. The least evil might be to try // and notify all observers, while raising an // exception if something bad happened. exception = e; } } if (exception!=null) QL.error(DefaultObservable.CANNOT_NOTIFY_OBSERVERS, exception); } // // protected methods // /** * This method is intended to encapsulate the notification semantics, in * order to let extended classes to implement their own version. Possible * implementations are: *

  • remote notification;
  • *
  • notification via SwingUtilities.invokeLater
  • *
  • others...
  • * *

    * The default notification simply does *

         * observer.update(observable, arg);
         * 
    * * @param observer * @param observable * @param arg */ protected void wrappedNotify(final Observer observer, final Observable observable, final Object arg) { //XXX::OBS observer.update(observable, arg); observer.update(); } }

    Ads help maintain this website.