/*
* $Id: AlarmSelectionHelper.java,v 1.11 2011/04/13 15:45:42 acaproni Exp $
*
* $Date: 2011/04/13 15:45:42 $
* $Revision: 1.11 $
* $Author: acaproni $
*
* Copyright CERN, All Rights Reserved.
*/
package cern.laser.client.impl.services.selection;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import org.apache.log4j.Logger;
import org.omg.CORBA.ORB;
import alma.acs.container.ContainerServicesBase;
import alma.acs.logging.AcsLogger;
import alma.alarmsystem.CERNAlarmService;
import com.cosylab.acs.jms.ACSJMSTextMessage;
import cern.cmw.mom.pubsub.ExceptionListener;
import cern.cmw.mom.pubsub.MOMException;
import cern.cmw.mom.pubsub.PubSubFactory;
import cern.cmw.mom.pubsub.Subscriber;
import cern.cmw.mom.pubsub.SubscriptionListener;
import cern.laser.client.LaserConnectionException;
import cern.laser.client.LaserException;
import cern.laser.client.LaserTimeOutException;
import cern.laser.client.data.Category;
import cern.laser.client.impl.common.AlarmServiceSingleton;
import cern.laser.client.impl.data.AlarmImpl;
import cern.laser.client.services.selection.AlarmSelectionListener;
import cern.laser.client.services.selection.LaserSelectionException;
import cern.laser.client.services.selection.Selection;
import cern.laser.util.UUIDGenerator;
import alma.alarmsystem.alarmmessage.AlarmMessageConversion;
/**
*
*
* @version $Revision: 1.11 $ $Date: 2011/04/13 15:45:42 $
* @author Katarina Sigerud
*/
class AlarmSelectionHelper implements SubscriptionListener, ExceptionListener {
private static final Logger LOGGER = Logger.getLogger(AlarmSelectionHelper.class.getName());
private static final String LASER_INIT_PROPERTY = "LASER_INIT";
private static final long INIT_DELAY = 1000;
private static final long INIT_TIMEOUT = 30000;
private boolean initialized = false;
private long initWaitTime = 0;
private Subscriber cmwSubscriber;
private String clientRootTopic;
private boolean cmwConnected = true;
private AlarmSelectionListener selectionListener;
private Map initialSelection = null;
private SubscriptionListener initialSelectionListener;
private String categoryRootTopic;
// The AlarmService component
private CERNAlarmService m_laser;
//
// -- CONSTRUCTORS ------------------------------------------------
//
AlarmSelectionHelper(AlarmSelectionListener selectionListener, ORB orb, AcsLogger logger) throws LaserException {
this.selectionListener = selectionListener;
initialSelection = Collections.synchronizedMap(new HashMap());
try {
this.m_laser = AlarmServiceSingleton.getInstance(orb,logger);
} catch (Exception e) {
throw new LaserException("unable to setup initial selection", e);
}
}
//
// -- PUBLIC METHODS ----------------------------------------------
//
public Map subscribe(Selection selection) throws LaserConnectionException, LaserException, LaserTimeOutException {
String sql_filter = buildSQLFilter(selection);
Collection category_ids = setupCategorySubscriptions(selection, sql_filter);
// start init subscription
setInitialized(false);
String console_id = "";
String host_name = "";
try {
console_id = UUIDGenerator.getInstance().getUUID().toString();
host_name = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
throw new LaserException("unable to get a unique id for the console", e);
}
String init_topic = getClientRootTopic() + "." + console_id;
String init_sql_filter = buildInitSQLFilter(sql_filter);
long init_subscription;
try {
init_subscription = getSubscriber().subscribe(init_topic, getInitialSelectionListener(), init_sql_filter);
} catch (Exception e) {
LOGGER.error("unable to subscribe to topic " + init_topic, e);
throw new LaserException("unable to subscribe to topic " + init_topic, e);
}
try {
if (m_laser!=null) {
int[] cis = new int[category_ids.size()];
int pos = 0;
for (Iterator iter = category_ids.iterator(); iter.hasNext(); ) {
cis[pos++] = ((Integer)iter.next()).intValue();
}
m_laser.select(cis, console_id);
} else {
throw new NullPointerException("AlarmSystem component is null");
}
} catch (alma.alarmsystem.LaserProcessingException lpe) {
try {
getSubscriber().unSubscribe(init_subscription);
} catch (JMSException e1) {
// Intentionally left blank
} catch (LaserException e1) {
// Intentionally left blank
}
LOGGER.error("server is initializing");
throw new LaserConnectionException("server is initializing", lpe);
} catch (Exception e3) {
throw new LaserException("unable to perform initial selection at host " + host_name, e3);
}
resetInitWaitTime();
waitForInit();
try {
// stop init subscription
getSubscriber().unSubscribe(init_subscription);
} catch (Exception e) {
LOGGER.info("exception when unsubscribing", e);
}
if (isInitialized()) {
return getInitialSelection();
} else {
//throw new LaserTimeOutException("initial selection timed out");
}
return getInitialSelection();
}
public void resetSelection() throws LaserException {
try {
Subscriber subscriber=getSubscriber();
subscriber.unSubscribeAll();
} catch (Exception e) {
throw new LaserException("unable to unsubscribe all");
}
if (cmwSubscriber != null) {
cmwSubscriber.close();
// cmwSubscriber = null;
}
}
//
// -- implements ExceptionListener ---------------------------------
//
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*/
public void onException(MOMException e) {
if (e.testException(MOMException.CONNECTION_LOST_EXCEPTION)) {
cmwConnected = false;
if (selectionListener != null) {
selectionListener.onException(new LaserSelectionException(
cern.laser.client.services.selection.LaserSelectionException.CONNECTION_DROPPED));
}
} else {
if (e.testException(MOMException.CONNECTION_RECOVERED_EXCEPTION)) {
cmwConnected = true;
if (selectionListener != null) {
selectionListener.onException(new LaserSelectionException(
cern.laser.client.services.selection.LaserSelectionException.CONNECTION_REESTABILISHED));
}
}
}
}
//
// -- implements SubscriptionListener ---------------------------------
//
/**
* DOCUMENT ME!
*
* @param msg DOCUMENT ME!
*/
public void onMessage(Message msg) {
ACSJMSTextMessage acsMsg = (ACSJMSTextMessage)msg;
if (selectionListener != null) {
try {
cern.laser.business.data.AlarmImpl business_alarm = AlarmMessageConversion.getAlarm(((ACSJMSTextMessage)msg).getText());
AlarmImpl alarm = new AlarmImpl(business_alarm);
selectionListener.onAlarm(alarm);
} catch (Exception e) {
LOGGER.warn("error on message", e);
}
}
}
//
// -- PROTECTED METHODS -------------------------------------------
//
//
// -- PRIVATE METHODS ---------------------------------------------
//
private void waitForInit() {
while (!isInitTimedOut()) {
try {
Thread.sleep(INIT_DELAY);
} catch (InterruptedException ie) {
}
if (isInitialized()) {
break;
}
increaseInitWaitTime();
}
}
private String buildSQLFilter(Selection selection) {
String sql_filter = selection.getFilterSelection().toSQLString();
if (sql_filter == null) {
if (selection.getReducedMaskedSelection()) {
sql_filter = "REDUCED_MASKED_SET = TRUE";
} else {
sql_filter = "NOT_REDUCED_MASKED_SET = TRUE";
}
} else {
StringBuffer sql_filter_buffer = new StringBuffer();
sql_filter_buffer.append("(");
sql_filter_buffer.append(sql_filter);
sql_filter_buffer.append(")");
if (selection.getReducedMaskedSelection()) {
sql_filter_buffer.append(" AND REDUCED_MASKED_SET = TRUE");
} else {
sql_filter_buffer.append(" AND NOT_REDUCED_MASKED_SET = TRUE");
}
sql_filter = sql_filter_buffer.toString();
}
if (LOGGER.isDebugEnabled()) LOGGER.debug("sql filter " + sql_filter);
return sql_filter;
}
private String buildInitSQLFilter(String sql_filter) {
StringBuffer init_sql_filter_buffer = new StringBuffer();
init_sql_filter_buffer.append("(");
init_sql_filter_buffer.append(sql_filter);
init_sql_filter_buffer.append(") OR ");
init_sql_filter_buffer.append(LASER_INIT_PROPERTY);
init_sql_filter_buffer.append(" = TRUE");
String init_sql_filter = init_sql_filter_buffer.toString();
if (LOGGER.isDebugEnabled()) LOGGER.debug("init sql filter " + init_sql_filter);
return init_sql_filter;
}
private Collection setupCategorySubscriptions(Selection selection, String sql_filter)
throws LaserConnectionException, LaserException {
Category[] categories = selection.getCategorySelection().list();
Collection category_ids = new ArrayList(categories.length);
for (int i = 0; i < categories.length; i++) {
Category category = categories[i];
String topic = getCategoryRootTopic() + "." + category.getPath();
if (selectionListener != null) {
try {
getSubscriber().subscribe(topic, this, sql_filter);
} catch (Exception e1) {
new LaserException("unable to subscribe to topic " + topic, e1);
}
}
category_ids.add(category.getCategoryId());
}
return category_ids;
}
private synchronized void setInitialized(boolean value) {
initialized = value;
}
private synchronized boolean isInitialized() {
return initialized;
}
private synchronized void increaseInitWaitTime() {
initWaitTime += INIT_DELAY;
}
private void resetInitWaitTime() {
initWaitTime = 0;
}
private boolean isInitTimedOut() {
return initWaitTime > INIT_TIMEOUT;
}
private Map getInitialSelection() {
Map result = new HashMap(initialSelection);
initialSelection.clear();
return result;
}
private String getCategoryRootTopic() throws LaserConnectionException, LaserException {
if (categoryRootTopic == null) {
try {
if (m_laser!=null) {
categoryRootTopic = m_laser.getCategoryRootTopic();
} else {
throw new NullPointerException("AlarmSystem component is null");
}
} catch (Exception e1) {
throw new LaserException("unable to find category root topic", e1);
}
}
return categoryRootTopic;
}
private String getClientRootTopic() throws LaserException, LaserConnectionException {
if (clientRootTopic == null) {
try {
if (m_laser!=null) {
clientRootTopic = m_laser.getClientRootTopic();
} else {
throw new NullPointerException("AlarmSystem component is null");
}
} catch (Exception e1) {
throw new LaserException("unable to find client root topic", e1);
}
}
return clientRootTopic;
}
private SubscriptionListener getInitialSelectionListener() {
if (initialSelectionListener == null) {
initialSelectionListener = new SubscriptionListener() {
public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
ACSJMSTextMessage acsMsg = (ACSJMSTextMessage)msg;
if (acsMsg.getText().trim().length()>0) {
cern.laser.business.data.Alarm business_alarm = AlarmMessageConversion.getAlarm(acsMsg.getText());
initialSelection.put(business_alarm.getAlarmId(), new AlarmImpl(business_alarm));
}
}
if (msg.propertyExists(LASER_INIT_PROPERTY)) {
setInitialized(true);
}
} catch (Exception e) {
LOGGER.warn("error on message", e);
}
}
};
}
return initialSelectionListener;
}
private Subscriber getSubscriber() throws LaserException {
try {
if (cmwSubscriber == null) {
cmwSubscriber = PubSubFactory.subscriber();
cmwSubscriber.setExceptionListener(this);
}
} catch (Exception e) {
throw new LaserException("unable to create the CMW subscriber", e);
}
return cmwSubscriber;
}
}