/* ALMA - Atacama Large Millimiter Array * Copyright (c) European Southern Observatory, 2013 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package alma.alarmsystem.clients; import org.omg.CORBA.ORB; import cern.laser.client.data.Alarm; import cern.laser.client.services.selection.AlarmSelectionHandler; import cern.laser.client.services.selection.AlarmSelectionListener; import cern.laser.client.services.selection.Filter; import cern.laser.client.services.selection.LaserSelectionException; import alma.acs.container.ContainerServices; import alma.acs.logging.AcsLogger; import alma.alarmsystem.Category; import alma.alarmsystem.clients.alarm.AlarmCategoryStatListener; import alma.alarmsystem.clients.alarm.AlarmClientException; import alma.alarmsystem.clients.alarm.AlarmFilter; import alma.alarmsystem.clients.alarm.AlarmListenersContainer; import alma.alarmsystem.clients.alarm.AlarmListenersContainer.AlarmListener; import alma.alarmsystem.clients.alarm.AlarmStatistics; import alma.maciErrType.wrappers.AcsJCannotGetComponentEx; /** * {@link AlarmCategoryClient} listens to alarms produced by the alarm server, * by means of a {@link CategoryClient} and offers greater functionalities to listeners like: * <UL> * <LI>Filtering of alarms based on the value of their triplets * <LI>Notification about the number of active alarms for each priority * </UL> * <P> * After instantiating a object of this class, the clients should * register in order to be notified with callbacks and only after * call {@link #connect()} or {@link #connect(Category[])}. * <BR>{@link #close()}must be called when finished using this object * to ensure the correct cleanup of the allocated resources. * <P> * {@link AlarmCategoryClient} has been introduced after ICT-547 offering * more functionality of what has been requested in the ticket to be ready * for next generation of user needs. * As a such, its API will most likely expanded in the future * to cope with new requirements. * <P> * Note that it is possible to add filtering capabilities while * connecting to the categories by properly setting {@link Filter} to * the {@link AlarmSelectionHandler}. However a quick look to filtering * seems to suggest that it is based on SQL because CERN AS originally * persisted alarms in a database. In out implementation all the alarms are * in memory and therefore we can't get advantage of SQL for filtering. * * @author acaproni * @since ACS-12.2 */ public class AlarmCategoryClient implements AlarmSelectionListener { /** * The {@link CategoryClient} to listen to alarms from the alarm server * and on top of which, objects of this class offer more functionalities */ private final CategoryClient client; /** * Signal that the object has been closed */ private volatile boolean closed=false; /** * The container with all the listeners */ private final AlarmListenersContainer listenersContainer = new AlarmListenersContainer(); /** * The statistics elaborated on the category alarms processed */ private final AlarmStatistics statistics = new AlarmStatistics(); /** * Constructor * * @param contServices The containerServices * @throws AlarmClientException * @see {{@link #AlarmCategoryClient(ContainerServices)} */ public AlarmCategoryClient(ContainerServices contServices) throws AlarmClientException { this(contServices.getAdvancedContainerServices().getORB(),contServices.getLogger()); } /** * Contructor * * @param orb The orb * @param logger The logger * @see {{@link #AlarmCategoryClient(ORB, AcsLogger)} */ public AlarmCategoryClient(ORB orb, AcsLogger logger) { client = new CategoryClient(orb,logger); } /** * Connects to all the categories of the alarm system. * * It is equivalent to <code>connect(null)</code>. * * @throws AlarmClientException In case of failure connecting the client * @throws AcsJCannotGetComponentEx If the alarm service component is not available * * @see CategoryClient#connect(AlarmSelectionListener, Category[]) */ public void connect() throws AlarmClientException, AcsJCannotGetComponentEx { connect(null); } /** * Connects to the passed categories of the alarm system * * @param categories The categories to connect to * * @throws AcsJCannotGetComponentEx In case the AlarmService is not available * @throws AlarmClientException In case of failure connecting the client * * @see CategoryClient#connect(AlarmSelectionListener, Category[]) */ public void connect(Category[] categories) throws AlarmClientException, AcsJCannotGetComponentEx { client.connect(this, categories); } /** * Release all the resource, * * @throws AlarmClientException */ public void close() throws AlarmClientException { closed=true; listenersContainer.close(); client.close(); } /** * This method is executed whenever a new alarm is received. * * @see AlarmSelectionListener */ @Override public void onAlarm(Alarm alarm) { if (closed) { return; } listenersContainer.dispatchAlarm(alarm); statistics.update(alarm); listenersContainer.dispatchStatistics(statistics); } /** * This method is executed whenever a new exception happens. * * * @see AlarmSelectionListener */ @Override public void onException(LaserSelectionException e) { if (closed) { return; } listenersContainer.dispatchException(e); } /** * @see {@link CategoryClient#getParents(String, boolean)} */ public Alarm[] getParents(String id, boolean node) throws AlarmClientException { return client.getParents(id, node); } /** * @see {@link CategoryClient#getChildren(String, boolean)} */ public Alarm[] getChildren(String id, boolean node) throws AlarmClientException { return client.getChildren(id, node); } /** * @see {@link CategoryClient#getMultiplicityThreshold(String)} */ public int getMultiplicityThreshold(String id) throws AlarmClientException { return client.getMultiplicityThreshold(id); } /** * @see {@link CategoryClient#getActiveChildren(String, boolean)} */ public Alarm[] getActiveChildren(String id, boolean node) throws AlarmClientException { return client.getActiveChildren(id, node); } /** * @see AlarmListenersContainer#addAlarmListener(AlarmListener) */ public boolean addAlarmListener(AlarmListener listener) { return listenersContainer.addAlarmListener(listener); } /** * @see AlarmListenersContainer#addAlarmListener(AlarmSelectionListener, AlarmFilter) */ public AlarmListener addAlarmListener(AlarmSelectionListener listener, AlarmFilter filter) { return listenersContainer.addAlarmListener(listener, filter); } /** * @see AlarmListenersContainer#addAlarmListener(AlarmSelectionListener) */ public AlarmListener addAlarmListener(AlarmSelectionListener listener) { return listenersContainer.addAlarmListener(listener); } /** * @see AlarmListenersContainer#removeAlarmListener(AlarmListener) */ public boolean removeAlarmListener(AlarmListener listenerToRemove) { return listenersContainer.removeAlarmListener(listenerToRemove); } /** * @see AlarmListenersContainer#addStatsListener(AlarmCategoryStatListener) */ public boolean addStatsListener(AlarmCategoryStatListener listener) { return listenersContainer.addStatsListener(listener); } /** * @see AlarmListenersContainer#removeStatListener(AlarmCategoryStatListener) */ public boolean removeStatListener(AlarmCategoryStatListener listenerToRemove) { return listenersContainer.removeStatListener(listenerToRemove); } }