/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.tools; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import javax.swing.SwingUtilities; /** * @author Simon Fischer */ public class AbstractObservable<A> implements Observable<A> { private final LinkedList<Observer<A>> observersRegular = new LinkedList<Observer<A>>(); private final LinkedList<Observer<A>> observersEDT = new LinkedList<Observer<A>>(); private final Object lock = new Object(); @Override public void addObserverAsFirst(Observer<A> observer, boolean onEDT) { if (observer == null) { throw new NullPointerException("Observer is null."); } if (onEDT) { synchronized (lock) { observersEDT.addFirst(observer); } } else { synchronized (lock) { observersRegular.addFirst(observer); } } } @Override public void addObserver(Observer<A> observer, boolean onEDT) { if (observer == null) { throw new NullPointerException("Observer is null."); } if (onEDT) { synchronized (lock) { observersEDT.add(observer); } } else { synchronized (lock) { observersRegular.add(observer); } } } @Override public void removeObserver(Observer<A> observer) { boolean success = false; synchronized (lock) { success |= observersRegular.remove(observer); success |= observersEDT.remove(observer); } if (!success) { throw new NoSuchElementException("No such observer: "+observer); } } /** Updates the observers in the given list. */ private void fireUpdate(List<Observer<A>> observerList, A argument) { for (Observer<A> observer : observerList) { observer.update(this, argument); } } /** Equivalent to <code>fireUpdate(null)</code>. */ protected void fireUpdate() { fireUpdate(null); } /** Updates all observers with the given argument. */ protected void fireUpdate(final A argument) { // lists are copied in order to avoid ConcurrentModification occurs if updating // an observer triggers insertion of another List<Observer<A>> copy; synchronized (lock) { copy = new LinkedList<Observer<A>>(observersRegular); } fireUpdate(copy, argument); if (!observersEDT.isEmpty()) { final List<Observer<A>> copyEDT; synchronized (lock) { copyEDT = new LinkedList<Observer<A>>(observersEDT); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fireUpdate(copyEDT, argument); } }); } } // protected void copyObserversFrom(AbstractObservable<A> other) { // this.observersEDT.addAll(other.observersEDT); // this.observersRegular.addAll(other.observersRegular); // } }