/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.queplix.core.modules.alert.eql;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.AccessRightsManager;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.integrator.security.NoSuchGroupException;
import com.queplix.core.integrator.security.NoSuchUserException;
import com.queplix.core.integrator.security.User;
import com.queplix.core.integrator.security.WorkGroup;
import com.queplix.core.jxb.entity.Entity;
import com.queplix.core.modules.alert.Alert;
import com.queplix.core.modules.alert.AlertData;
import com.queplix.core.modules.alert.ejb.AlertManagerLocal;
import com.queplix.core.modules.alert.ejb.AlertManagerLocalHome;
import com.queplix.core.modules.alert.utils.AlertSelectorCriteria;
import com.queplix.core.modules.eql.CompoundKey;
import com.queplix.core.modules.eql.EQLEReq;
import com.queplix.core.modules.eql.EQLERes;
import com.queplix.core.modules.eql.EQLObject;
import com.queplix.core.modules.eql.EQLReq;
import com.queplix.core.modules.eql.EQLReqField;
import com.queplix.core.modules.eql.EQLReqSelect;
import com.queplix.core.modules.eql.EQLRes;
import com.queplix.core.modules.eql.EQLResCell;
import com.queplix.core.modules.eql.EQLResMetaData;
import com.queplix.core.modules.eql.EQLResRecord;
import com.queplix.core.modules.eql.EQLSession;
import com.queplix.core.modules.eql.error.EQLException;
import com.queplix.core.modules.eql.parser.EQLAgentStub;
import com.queplix.core.modules.eql.parser.generic.SQLExecutorGenericImpl;
import com.queplix.core.utils.JNDINames;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;

import javax.ejb.CreateException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * <p>Default EQL agent class to search Alerts as an entity</p>
 *
 * @author Baranov Andrey [ALB]
 * @version $Revision: 1.2 $ $Date: 2005/10/26 14:03:51 $
 */

public abstract class AlertEQLAgent
        extends EQLAgentStub {

    // ----------------------------------------------------- fields/constants

    // 'Last Read Alert ID' session parameter name.
    protected final static String LAST_READ_ALERT_ID = "__lastAlertId";

    // Logger.
    protected final AbstractLogger logger = Log.getLog(getClass());

    // Map for severity key-name pairs.
    // !!! Severity must be taken from read-only entity.
    protected final Map severityMap = new HashMap();

    // ----------------------------------------------------- interface implementation

    /**
     * Returns last read alert ID for current user.
     *
     * @param ls LogonSession
     * @return Alert ID or NULL
     */
    public static Long getLastReadAlert(LogonSession ls) {
        Object attr = ls.getParameter(LAST_READ_ALERT_ID);
        return (Long) attr;
    }

    /**
     * Remembers last read alert ID for current user.
     *
     * @param ls          LogonSession
     * @param lastAlertId Alert ID
     */
    public static void setLastReadAlert(LogonSession ls, Long lastAlertId) {
        ls.addParameter(LAST_READ_ALERT_ID, lastAlertId);
    }

    /*
     * No javadoc
     * @see EQLAgent#doCount
     */
    public int doCount(EQLSession eqlSession, EQLRes res)
            throws EQLException {

        long time = System.currentTimeMillis();

        // Create criteria and set mandatory parameters.
        AlertSelectorCriteria criteria = new AlertSelectorCriteria();
        criteria.setLogonSession(eqlSession.getLogonSession());

        // Search result.
        SortedMap map = callAlertManager(eqlSession, criteria);
        int ret;
        if(map != null) {
            ret = map.size();
        } else {
            ret = 0;
        }

        // Ok.
        if(logger.getLogger().isDebugEnabled()) {
            logger.DEBUG("Alert count operation completed. Found: " + ret +
                    ". Time(ms): " + (System.currentTimeMillis() - time));
        }
        return ret;
    }

    /*
     * No javadoc
     * @see EQLAgent#doSelect
     */
    public EQLRes doSelect(EQLSession eqlSession, EQLReq req)
            throws EQLException {

        long time = System.currentTimeMillis();

        // Probably 'new' request was received...
        if(!(req instanceof EQLEReq)) {
            return parseNewRequest(req);
        }

        try {
            // Init List of entity field names.
            EQLReqSelect reqSelect = req.getSelect();
            int columns = reqSelect.size();
            List columNames = new ArrayList(columns);
            for(int i = 0; i < columns; i++) {
                columNames.add(reqSelect.getAttr(i).getReqField()
                        .getField().getName());
            }

            // Get Last Alert ID.
            Long lastAlertId = getLastReadAlert(eqlSession.getLogonSession());

            // Get page and page size.
            Integer page = SQLExecutorGenericImpl.getPage(req);
            Integer pageSize = SQLExecutorGenericImpl.getPageSize(req);

            // Create criteria and set mandatory parameters.
            AlertSelectorCriteria criteria = new AlertSelectorCriteria();
            criteria.setLogonSession(eqlSession.getLogonSession());
            criteria.setPage(page);
            criteria.setPageSize(pageSize);

            // Search result.
            SortedMap ret = callAlertManager(eqlSession, criteria);

            // Build EQLERes.
            Entity entity = ((EQLEReq) req).getEntity();
            EQLERes res = new EQLERes(entity);
            EQLResMetaData metaData = new EQLResMetaData();
            metaData.setReq(req);
            res.setMetaData(metaData);

            // Fill EQLRes.
            if(ret != null) {

                // Check if Available More record.
                res.getMetaData().setParam(
                        SQLExecutorGenericImpl.HAS_MORE_PARAM,
                        Boolean.valueOf(criteria.isAvailableMore()));

                Long maxAlertID = null;
                for(Iterator it = ret.keySet().iterator(); it.hasNext();) {
                    Long key = (Long) it.next();
                    if(maxAlertID == null) {
                        // All keys must be sorted in DESC order!
                        maxAlertID = key;
                    }

                    Alert alert = (Alert) ret.get(key);

                    // Build new EQLResRecord with size = <code>columns</code>.
                    EQLResRecord record = new EQLResRecord(false, columns);
                    res.addRecord(record);

                    // Populate EQLResRecord.
                    addCells(eqlSession, record, entity, alert, columNames);
                }

                // Remember max alert ID in logon session.
                // All alerts must be sorted by ID in ASC order!

                if(logger.getLogger().isDebugEnabled()) {
                    logger.DEBUG(
                            "Try to remember last alert ID: " + maxAlertID +
                                    ". Prevous is: " + lastAlertId);
                }

                if(maxAlertID != null) {
                    if(lastAlertId == null
                            || maxAlertID.longValue() > lastAlertId
                            .longValue()) {
                        setLastReadAlert(eqlSession.getLogonSession(),
                                maxAlertID);
                    }
                }
            }

            // Ok.
            if(logger.getLogger().isDebugEnabled()) {
                logger.DEBUG("Alert search operation completed. Time(ms): " + (
                        System.currentTimeMillis() - time));
            }

            return res;

        } catch (EQLException ex) {
            logger.ERROR(ex);
            throw ex;

        } catch (Throwable t) {
            logger.ERROR(t);
            // Show user 'normal' exception.
            throw new EQLException(
                    "Problems retrieving the alerts, please retry later...");
        }
    }

    /*
     * No javadoc
     * @see EQLAgent#doUpdate
     */
    public int doUpdate(EQLSession eqlSession, EQLERes res,
                        EQLResRecord resRecord)
            throws EQLException {

        long time = System.currentTimeMillis();

        int updated;
        if(resRecord.isNew()) {
            // Do Insert.
            updated = __doInsert(eqlSession, res, resRecord);
        } else {
            // Do Update.
            updated = __doUpdate(eqlSession, res, resRecord);
        }

        // Ok.
        if(logger.getLogger().isDebugEnabled()) {
            logger.DEBUG(
                    "Alert update operation completed. Updated " + updated +
                            " records. Time(ms): " + (System.currentTimeMillis()
                            - time));
        }

        return updated;
    }

    /*
     * No javadoc
     * @see EQLAgent#doDelete
     */
    public int doDelete(EQLSession eqlSession, EQLERes res,
                        EQLResRecord resRecord)
            throws EQLException {

        long time = System.currentTimeMillis();

        // Read alert_id
        Entity entity = res.getEntity();
        EQLResCell resCell = resRecord.getResCell(getReqField(entity,
                "alert_id"));
        Long alertID = (resCell != null) ? resCell.getLong():null;
        if(alertID == null) {
            throwUserQueryParseException(eqlSession, res, "alert_id", null,
                    null);
        }

        AlertManagerLocal local = null;
        long[] ret;
        try {
            // Get local reference.
            local = getAlertManagerLocal(eqlSession);

            // Set mandatory attributes.
            local.setId(alertID.longValue());

            // Call Alert Manager
            ret = local.deleteAlerts();

        } finally {
            try {
                if(local != null) {
                    local.remove();
                }
            } catch (Exception ex) {
            }
        }

        // Ok.
        int updated = (ret != null) ? ret.length:0;
        if(logger.getLogger().isDebugEnabled()) {
            logger.DEBUG(
                    "Alert deletion operation completed. Removed " + updated +
                            " records. Time(ms): " + (System.currentTimeMillis()
                            - time));
        }

        return updated;
    }

    /*
     * No javadoc
     * @see EQLAgentStub#addSelectConstraint
     */
    protected void addSelectConstraint(Object result,
                                       EQLReqField field,
                                       EQLObject value) {
        // [ALB] constraints not supported
    }

    // ----------------------------------------------------- abstract methods

    /**
     * AlertManagerEJB caller.
     *
     * @param eqlSession EQLSession
     * @param criteria   search criteria value object
     * @return SortedMap search result
     * @throws EQLException
     */
    abstract SortedMap callAlertManager(EQLSession eqlSession,
                                        AlertSelectorCriteria criteria)
            throws EQLException;

    // ----------------------------------------------------- protected methods

    //
    // Build and add EQLResCell objects upon on <code>alert</code> to <code>record</code>.
    //

    protected void addCells(EQLSession eqlSession,
                            EQLResRecord record,
                            Entity entity,
                            Alert alert,
                            List columNames)
            throws EQLException {

        AlertData alertData = alert.getData();
        CompoundKey recordKey = (alertData != null) ? alertData.getRecordKey()
                :null;

        // 1) alert_id
        EQLResCell cell = getNumberCell(entity, "alert_id", new Long(
                alert.getAlertID()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("alert_id"));
        }

        // 2) creator_id
        cell = getNumberCell(entity, "creator_id", new Long(
                alert.getCreatorID()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("creator_id"));
            _addUserListCell(eqlSession, cell, alert.getCreatorID(),
                    alert.getCreatorType());
        }

        // 3) creator_type
        cell = getNumberCell(entity, "creator_type", new Integer(
                alert.getCreatorType()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("creator_type"));
        }

        // 4) sender_id
        cell = getNumberCell(entity, "sender_id", new Long(
                alert.getSenderID()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("sender_id"));
            _addUserListCell(eqlSession, cell, alert.getSenderID(),
                    alert.getSenderType());
        }

        // 5) sender_type
        cell = getNumberCell(entity, "sender_type", new Integer(
                alert.getSenderType()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("sender_type"));
        }

        // 6) message
        cell = getStringCell(entity, "message", alert.getMessage());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("message"));
        }

        // 7) severity
        cell = getNumberCell(entity, "severity", new Integer(
                alert.getSeverity()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("severity"));
            _addSeverityListCell(eqlSession, record, cell);
        }

        // 8) dateposted
        cell = getDateCell(entity, "dateposted", alert.getDateposted());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("dateposted"));
        }

        // 9) recipient_id
        cell = getNumberCell(entity, "recipient_id", alert.getRecipientID());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("recipient_id"));
            if(alert.getRecipientID() != null) {
                _addUserListCell(eqlSession, cell,
                        alert.getRecipientID().longValue(),
                        alert.getRecipientType().intValue());
            }
        }

        // 10) recipient_type
        cell = getNumberCell(entity, "recipient_type",
                alert.getRecipientType());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("recipient_type"));
        }

        // 11) workgroup_id
        cell = getNumberCell(entity, "workgroup_id", alert.getWorkgroupID());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("workgroup_id"));
            if(alert.getWorkgroupID() != null) {
                _addWorkgroupListCell(eqlSession, cell,
                        alert.getWorkgroupID().longValue());
            }
        }

        // 12) tier
        cell = getNumberCell(entity, "tier", alert.getTier());
        if(cell != null) {
            record.addData(cell, columNames.indexOf("tier"));
        }

        // 13) to_all
        cell = getBooleanCell(entity, "to_all", Boolean.valueOf(
                alert.isToAll()));
        if(cell != null) {
            record.addData(cell, columNames.indexOf("to_all"));
        }

        // 14) focus_id
        cell = getStringCell(entity, "focus_id",
                (alertData != null) ? alertData.getFocusID():null);
        if(cell != null) {
            record.addData(cell, columNames.indexOf("focus_id"));
        }

        // 15) tab_id
        cell = getStringCell(entity, "tab_id",
                (alertData != null) ? alertData.getTabID():null);
        if(cell != null) {
            record.addData(cell, columNames.indexOf("tab_id"));
        }

        // 16) form_id
        cell = getStringCell(entity, "form_id",
                (alertData != null) ? alertData.getFormID():null);
        if(cell != null) {
            record.addData(cell, columNames.indexOf("form_id"));
        }

        // 17) record_id
        cell = getStringCell(entity, "record_id",
                (recordKey != null) ? (String) recordKey.getKey(0):null);
        if(cell != null) {
            record.addData(cell, columNames.indexOf("record_id"));
        }

        // 18) record_id2
        // 19) record_id3
        // 20) record_id4
        int keys = (recordKey != null) ? recordKey.size():0;
        for(int i = 1; i < 4; i++) {
            cell = getStringCell(entity, "record_id" + (i + 1),
                    (i < keys) ? (String) recordKey.getKey(i):null);
            if(cell != null) {
                record.addData(cell, columNames.indexOf("record_id" + (i + 1)));
            }
        }
    }

    //
    // Fulfil insert operation
    //
    protected int __doInsert(EQLSession eqlSession, EQLERes res,
                             EQLResRecord resRecord)
            throws EQLException {

        // Read params.

        // 1) alert_id
        Entity entity = res.getEntity();
        EQLResCell resCell = resRecord.getResCell(getReqField(entity,
                "alert_id"));
        Long alertID = (resCell != null) ? resCell.getLong():null;

        // 2) creator_id
        resCell = resRecord.getResCell(getReqField(entity, "creator_id"));
        Long creatorID = (resCell != null) ? resCell.getLong():null;

        Integer creatorType = null;
        if(creatorID != null) {
            // 3) creator_type
            resCell = resRecord.getResCell(getReqField(entity, "creator_type"));
            creatorType = (resCell != null) ? resCell.getInteger():null;
            if(creatorType == null) {
                throwUserQueryParseException(eqlSession, res, "creator_type",
                        null, null);
            }
        }

        // 4) sender_id
        resCell = resRecord.getResCell(getReqField(entity, "sender_id"));
        Long senderID = (resCell != null) ? resCell.getLong():null;

        Integer senderType = null;
        if(senderID != null) {
            // 5) sender_type
            resCell = resRecord.getResCell(getReqField(entity, "sender_type"));
            senderType = (resCell != null) ? resCell.getInteger():null;
            if(senderType == null) {
                throwUserQueryParseException(eqlSession, res, "sender_type",
                        null, null);
            }
        }

        // 6) message
        resCell = resRecord.getResCell(getReqField(entity, "message"));
        String message = (resCell != null) ? resCell.getString():null;
        if(message == null) {
            throwUserQueryParseException(eqlSession, res, "message", null,
                    null);
        }

        // 7) severity
        resCell = resRecord.getResCell(getReqField(entity, "severity"));
        Integer severity = (resCell != null) ? resCell.getInteger():null;
        if(severity == null) {
            throwUserQueryParseException(eqlSession, res, "severity", null,
                    null);
        }

        // 8) dateposted
        resCell = resRecord.getResCell(getReqField(entity, "dateposted"));
        Date dateposted = (resCell != null) ? resCell.getDate():null;

        // 9) recipient_id
        Long recipientID = null;
        resCell = resRecord.getResCell(getReqField(entity, "recipient_id"));
        recipientID = (resCell != null) ? resCell.getLong():null;

        Integer recipientType = null;
        if(recipientID != null) {
            // 10) recipient_type
            resCell = resRecord.getResCell(getReqField(entity,
                    "recipient_type"));
            recipientType = (resCell != null) ? resCell.getInteger():null;
        }

        Long workgroupID = null;
        Integer tier = null;
        if(recipientID == null) {
            // 11) workgroup_id
            resCell = resRecord.getResCell(getReqField(entity, "workgroup_id"));
            workgroupID = (resCell != null) ? resCell.getLong():null;

            if(workgroupID != null) {
                // 12) tier
                resCell = resRecord.getResCell(getReqField(entity, "tier"));
                tier = (resCell != null) ? resCell.getInteger():null;
            }
        }

        // 13) to_all
        resCell = resRecord.getResCell(getReqField(entity, "to_all"));
        Integer i = (resCell != null) ? resCell.getInteger():null;
        boolean toAll = (i != null) ? (i.intValue() == 1):false;
        if(!toAll && recipientID == null && workgroupID == null) {
            throwUserQueryParseException(eqlSession, res, "to_all", null,
                    "Either user, workgroup or 'To All' must be specified");
        }

        // 14) focus_id
        resCell = resRecord.getResCell(getReqField(entity, "focus_id"));
        String focusID = (resCell != null) ? resCell.getString():null;

        AlertData data = null;
        if(focusID != null) {

            // 15) tab_id
            resCell = resRecord.getResCell(getReqField(entity, "tab_id"));
            String tabID = (resCell != null) ? resCell.getString():null;

            // 16) form_id
            resCell = resRecord.getResCell(getReqField(entity, "form_id"));
            String formID = (resCell != null) ? resCell.getString():null;

            // 17) record_id
            resCell = resRecord.getResCell(getReqField(entity, "record_id"));
            String recordID = (resCell != null) ? resCell.getString():null;

            // 18) record_id2
            resCell = resRecord.getResCell(getReqField(entity, "record_id2"));
            String recordID2 = (resCell != null) ? resCell.getString():null;

            // 19) record_id3
            resCell = resRecord.getResCell(getReqField(entity, "record_id3"));
            String recordID3 = (resCell != null) ? resCell.getString():null;

            // 20) record_id4
            resCell = resRecord.getResCell(getReqField(entity, "record_id4"));
            String recordID4 = (resCell != null) ? resCell.getString():null;

            // Init AlertData.
            CompoundKey recordKey = new CompoundKey();
            if(recordID != null) {
                recordKey.addKey(recordID);
            }
            if(recordID2 != null) {
                recordKey.addKey(recordID2);
            }
            if(recordID3 != null) {
                recordKey.addKey(recordID3);
            }
            if(recordID4 != null) {
                recordKey.addKey(recordID4);
            }
            data = new AlertData(focusID, tabID, formID, recordKey);
        }

        AlertManagerLocal local = null;
        long[] ret;
        try {
            // Get local reference.
            local = getAlertManagerLocal(eqlSession, message,
                    severity.intValue());

            // Set optional attributes.
            if(alertID != null) {
                local.setId(alertID.longValue());
            }
            if(creatorID != null) {
                local.setCreator(creatorID.longValue(), creatorType.intValue());
            }
            if(senderID != null) {
                local.setSender(senderID.longValue(), senderType.intValue());
            }
            if(dateposted != null) {
                local.setDateposted(dateposted);
            }
            if(data != null) {
                local.setData(data);
            }

            // Call Alert Manager
            if(recipientID != null) {
                ret = local.sendAlert(recipientID.longValue(),
                        recipientType.intValue());
            } else if(workgroupID != null) {
                ret = local.sendAlerts(workgroupID.longValue(), tier, toAll);
            } else {
                ret = local.sendAlert();
            }

        } finally {
            try {
                if(local != null) {
                    local.remove();
                }
            } catch (Exception ex) {
            }
        }

        // Ok.
        return (ret != null) ? ret.length:0;
    }

    //
    // Fulfil update operation
    //
    protected int __doUpdate(EQLSession eqlSession, EQLERes res,
                             EQLResRecord resRecord)
            throws EQLException {

        // Read params.
        // WARINING: Support update only for message and severity.

        // 1) alert_id
        Entity entity = res.getEntity();
        EQLResCell resCell = resRecord.getResCell(getReqField(entity,
                "alert_id"));
        Long alertID = (resCell != null) ? resCell.getLong():null;
        if(alertID == null) {
            throwUserQueryParseException(eqlSession, res, "alert_id", null,
                    null);
        }

        // 2) message
        resCell = resRecord.getResCell(getReqField(entity, "message"));
        String message = (resCell != null) ? resCell.getString():null;
        if(message == null) {
            throwUserQueryParseException(eqlSession, res, "message", null,
                    null);
        }

        // 3) severity
        resCell = resRecord.getResCell(getReqField(entity, "severity"));
        Integer severity = (resCell != null) ? resCell.getInteger():null;
        if(severity == null) {
            throwUserQueryParseException(eqlSession, res, "severity", null,
                    null);
        }

        AlertManagerLocal local = null;
        long[] ret;
        try {
            // Get local reference.
            local = getAlertManagerLocal(eqlSession, message,
                    severity.intValue());

            // Set ID.
            local.setId(alertID.longValue());

            // Call Alert Manager
            ret = local.updateAlert();

        } finally {
            try {
                if(local != null) {
                    local.remove();
                }
            } catch (Exception ex) {
            }
        }

        // Ok.
        return (ret != null) ? ret.length:0;
    }

    //
    // Get AlertManager local interface
    //
    protected AlertManagerLocal getAlertManagerLocal(EQLSession eqlSession) {

        AlertManagerLocalHome home = (AlertManagerLocalHome) eqlSession.getCOM()
                .
                        getLocalHome(JNDINames.AlertManager,
                                AlertManagerLocalHome.class);

        try {
            return home.create(eqlSession.getLogonSession());
        } catch (CreateException ex) {
            throw new GenericSystemException("Can't create AlertManager EJB.",
                    ex);
        }
    }

    //
    // Adds List EQLResCell for user-like EQLResCell.
    //
    protected void _addUserListCell(EQLSession eqlSession,
                                    EQLResCell cell,
                                    long userID,
                                    int userType) {
        try {
            User user = AccessRightsManager.getUser(userID);
            EQLResCell listCell = getStringListCell(eqlSession, cell,
                    user.getFullName());
            if(listCell != null) {
                cell.addListField(listCell);
            }
        } catch (NoSuchUserException ex) {
            logger.WARN(ex.getMessage());
        }
    }

    //
    // Adds List EQLResCell for workgroup-like EQLResCell.
    //
    protected void _addWorkgroupListCell(EQLSession eqlSession,
                                         EQLResCell cell,
                                         long wgID) {
        try {
            WorkGroup wg = AccessRightsManager.getGroup(wgID);
            EQLResCell listCell = getStringListCell(eqlSession, cell,
                    wg.getGroupName());
            if(listCell != null) {
                cell.addListField(listCell);
            }
        } catch (NoSuchGroupException ex) {
            logger.WARN(ex.getMessage());
        }
    }

    //
    // Adds List EQLResCell for severity EQLResCell.
    //
    protected void _addSeverityListCell(EQLSession eqlSession,
                                        EQLResRecord record,
                                        EQLResCell cell)
            throws EQLException {

        Object key = cell.getEQLObject().getObject();

        // Check in Map first.
        EQLResCell listCell = null;
        EQLObject listObj = (EQLObject) severityMap.get(key);
        if(listObj != null) {

            logger.DEBUG("Found severity in the cache: " + listObj);

            EQLReqField listReqField = getListReqField(eqlSession,
                    cell.getReqField().getField());
            if(listReqField != null) {
                listCell = new EQLResCell(listReqField, listObj);
            }
        } else {
            listCell = getListResCell(eqlSession, record, cell);

            // Put to the cache.
            severityMap.put(key, listCell.getEQLObject());
        }

        if(listCell != null) {
            cell.addListField(listCell);
        }
    }

    //
    // Get AlertManager local interface
    //
    protected AlertManagerLocal
    getAlertManagerLocal(EQLSession eqlSession,
                         String message,
                         int severityId) {

        AlertManagerLocalHome home = (AlertManagerLocalHome) eqlSession.getCOM()
                .
                        getLocalHome(JNDINames.AlertManager,
                                AlertManagerLocalHome.class);

        try {
            return home.create(message, severityId,
                    eqlSession.getLogonSession());
        } catch (CreateException ex) {
            throw new GenericSystemException("Can't create AlertManager EJB.",
                    ex);
        }
    }
}
