Mercurial > hg > icedrobot > ika
view src/main/java/org/icedrobot/ika/output/StatusKeeper.java @ 29:3b0d6002605a
Add patch to output commands names. Contributed by Giulio Franco.
author | Mario Torre <neugens.limasoftware@gmail.com> |
---|---|
date | Fri, 15 Apr 2011 17:13:03 +0200 |
parents | |
children |
line wrap: on
line source
/* * IKA - IcedRobot Kiosk Application * Copyright (C) 2011 IcedRobot team * * 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 org.icedrobot.ika.output; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; /** * Central repository which can gather status information from multiple * working threads. * Working threads can register to the StatusKeeper using * {@link #registerThread}, then they can periodically send status information * updates with the {@link #updateStatus} method. * Data consumers can access progress information through getter methods or * by registering themselves as listeners. */ public class StatusKeeper { private static StatusKeeper instance; //Singleton instance private ConcurrentMap<String, WorkerStatus> workerData; private final List<String> insertionOrder; private CopyOnWriteArrayList<StatusListener> listeners; /** * StatusKeeper is a singleton, because it is a centralized repository. */ private StatusKeeper() { workerData = new ConcurrentHashMap<String, WorkerStatus>(); insertionOrder = new ArrayList<String>(); listeners = new CopyOnWriteArrayList<StatusListener>(); } /** * Obtains the instance of StatusKeeper */ public static synchronized StatusKeeper getInstance() { if (instance == null) { instance = new StatusKeeper(); } return instance; } /** * Registers a new worker as active. * Each worker is registered with a unique name * @param workerName Unique name identifying the worker. * @param status Current status of the process. */ public void registerWorker (WorkerStatus status) { if (workerData.putIfAbsent(status.getName(), status) != null) { throw new IllegalArgumentException("Worker " + status.getName() + " is already registered."); } synchronized (insertionOrder) { insertionOrder.add(status.getName()); } } /** * Registers a new worker as active, with a starting empty status. * Each worker is registered with a unique name * @param workerName Unique name identifying the worker. * @param status Current status of the process. */ public void registerWorker (String workerName) { registerWorker(new DefaultWorkerStatus(workerName)); } /** * Deregister a previously registered worker, notifying its termination. * @param workerName Name the worker was registered with. */ public void deregisterWorker (String workerName) { synchronized (insertionOrder) { if (insertionOrder.remove(workerName) == false) { throw new IllegalArgumentException( "Worker " + workerName + " is not registered."); } } workerData.remove(workerName); } /** * Updates the status associated to a previously registered worker. * @param workerName Worker whose status is to be updated * @param data New status of the worker. */ public void reportStatus (WorkerStatus data) { if (workerData.replace(data.getName(), data) == null) { throw new IllegalArgumentException("Worker " + data.getName() + " is not registered."); } fireStatusUpdate(data.getName(), data); } /** * Returns an iterable collection over the workers currently registered and * their statuses. * @return Iterable collection of map entries */ public Iterable<WorkerStatus> statusList() { String[] workerNames; ArrayList<WorkerStatus> iterable; WorkerStatus status; synchronized (insertionOrder) { workerNames = new String[insertionOrder.size()]; workerNames = insertionOrder.toArray(workerNames); } iterable = new ArrayList<WorkerStatus>(workerNames.length); for (String w : workerNames) { status = workerData.get(w); if (status != null) { iterable.add(status); } } return iterable; } /** * Returns the current status of a worker * @param workerName Name of the worker * @return Current status of the worker, * or null if workerName is not a registered worker. */ public WorkerStatus getWorkerStatus(String workerName) { return workerData.get(workerName); } /** * Returns the number of active workers, * i.e. the number of registered workers that are not completed. * @return Count of active workers */ public int getActiveTasksCount() { int aCount = 0; for (WorkerStatus stat : workerData.values()) { if (!stat.completed()) { aCount += 1; } } return aCount; } /** * Adds a listener to the list of those that will be notified about * changes in registered tasks' statuses. * @param l Listener to register */ public void addStatusListener (StatusListener l) { listeners.add(l); } /** * Removes a status listener from the StatusKeeper * @param l Listener to remove */ public void removeStatusListener (StatusListener l) { listeners.remove(l); } public int getStatusListenersCount () { return listeners.size(); } protected void fireStatusUpdate (String workerName, WorkerStatus status) { for (StatusListener l : listeners) { l.statusUpdate(workerName, status); } } }