/* * WBI Indicator Explorer * * Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com> * * This file is part of WBI. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package client.managers.models.watcher; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import models.Indicator; /** * Real-time watcher for changes in {@link Indicator} objects. */ public abstract class IndicatorWatcher { /** * Interface for {@link IndicatorWatcher} listeners. */ public interface Listener { /** * Handle {@code Indicator} change. * * @param indicator Updated indicator. */ public void onChange(Indicator indicator); } /** * {@code Listener} objects listening to changes in this manager. */ protected List<Listener> listeners = new ArrayList<Listener>(); /** * {@code Indicator} objects being watched. */ protected Map<Indicator, List<Indicator.Status>> watched = new HashMap<Indicator, List<Indicator.Status>>(); protected IndicatorWatcher() {} /** * Start watching for changes in an {@code Indicator}. * * @param indicator Indicator to watch. */ public void watch(Indicator indicator) { if (!watched.containsKey(indicator)) { watched.put(indicator, null); } } /** * Stop watching for changes in an {@code Indicator}. * * @param indicator Indicator to stop watching. */ public void unwatch(Indicator indicator) { if (watched.containsKey(indicator)) { watched.remove(indicator); } } /** * Start watching an {@code Indicator} until its status equals to the * specified {@code Indicator.Status}. * * @param indicator Indicator to watch. * @param status Status required. */ public void watchUntilStatusEquals( Indicator indicator, Indicator.Status status) { List<Indicator.Status> watchedStatusList = watched.get(indicator); if (watchedStatusList == null) { watchedStatusList = new ArrayList<Indicator.Status>(); watchedStatusList.add(status); watched.put(indicator, watchedStatusList); } else { if (!watchedStatusList.contains(status)) { watchedStatusList.add(status); } } } /** * Attach {@code Listener}. * * @param listener Listener to attach. */ public void addListener(Listener listener) { listeners.add(listener); } /** * Detach {@code Listener}. * * @param listener Listener to detach. */ public void removeListener(Listener listener) { listeners.remove(listener); } /** * Start watching. */ public abstract void start(); /** * Stop watching. */ public abstract void stop(); /** * Stop watching an {@code Indicator} only if the required status is met. * * @param indicator Indicator to stop watching. */ private void autoUnwatch(Indicator indicator) { List<Indicator.Status> watchedStatusList = watched.get(indicator); if (watchedStatusList != null) { watchedStatusList.remove(indicator.getStatus()); if (watchedStatusList.isEmpty()) { watched.remove(indicator); } } } /** * Exhibit changes in an {@code Indicator}. * * @param indicator Indicator changed. */ protected void change(Indicator indicator) { for (Listener listener : listeners) { listener.onChange(indicator); autoUnwatch(indicator); } } /** * Create a new instance of {@code IndicatorWatcher}. * * @return Instance created. */ public static IndicatorWatcher create() { if (LiveIndicatorWatcher.isSupported()) { return new LiveIndicatorWatcher(); } else { return new PollingIndicatorWatcher(); } } }