/*******************************************************************************
 * Copyright (c) 2003 Hyades project.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.hyades.logc.extensions.ICorrelationMonitor;
import org.eclipse.hyades.logc.extensions.ILogRecordCorrelationEngine;
import org.eclipse.hyades.logs.correlators.RecordList;
import org.eclipse.hyades.models.cbe.CBECommonBaseEvent;
import org.eclipse.hyades.models.hierarchy.CorrelationContainer;
import org.eclipse.hyades.models.hierarchy.CorrelationContainerProxy;
import org.eclipse.hyades.models.hierarchy.CorrelationEngine;

/**
 * A simple correlation engine created to illustrate how one can make correlations
 * between log records.
 */
public class MyCorEngine implements ILogRecordCorrelationEngine {

    private CorrelationEngine correlationEngine = null;
    private CorrelationContainer correlationContainer = null;

    /* The name and type of the simple correlation engine */
    private final String CORRELATION_NAME = "Simple Correlation Engine V1.0";
    private final String CORRELATION_TYPE = "Correlated";

    /* 
     * Makes the necessary correlation between the log records based up on a number
     * of factor(s). Currently the factor that is used to correlate log records is 
     * the ID of each record included in the log file associated with 'Simple Parser 
     * V1.0'
     *
     * @param logFiles - A listing of the processes (i.e. the log files) for which 
     * correlation are to be made.
     */
    public void correlate(CorrelationContainerProxy correlationContainerProxy, EList logFiles, ICorrelationMonitor mon) {

        correlationEngine = correlationContainerProxy.getCorrelationEngine();
        correlationContainer = correlationContainerProxy.getCorrelationContainer();

        if (correlationEngine == null) {
            correlationEngine.setType(CORRELATION_TYPE);
            correlationEngine.setName(CORRELATION_NAME);
            correlationEngine.setId(CORRELATION_NAME);
        }

        /* Traverse through each of the log files that a correlation needs to be made */
        for (int i = 0; i < logFiles.size(); i++) {
            /* For each of the existing log file, traverse through its log records and make the necessary correlations */
            if (logFiles.get(i) != null) {
                /* Store the list corresponding to the log records of the i-th logFile */
                EList recordList = ((RecordList) logFiles.get(i)).getList();

                /* Make the necessary correlations */
                makeCorrelations(recordList, logFiles, i);
            }
        } // End of for-loop
    } // End of correlator (EList)

    /* 
     * A helper method to 'correlate(EList)' that is used to make the necessary 
     * correlations between the log records 
     * 
     * @param recordList - A list of log records for which correlations are made 
     * logFiles - 'logRecord' belongs to a log file listed under this parameter
     * logFileIndex - The index of 'logFiles' identifying the log file that 
     * logRecord belongs to 
     */
    private void makeCorrelations(EList recordList, EList logFiles, int logFileIndex) {

        /* Traverse through each of the log records and make the necessary correlations */
        for (int j = 0; j < recordList.size(); j++) {
            /* Make the correlation for the j-th log record */
            setPartners(recordList.get(j), logFiles, logFileIndex);
        } // End of for-loop
    } // End of makeCorrelations (EList)

    /* 
     * A helper method to 'makeCorrelations (EList, EList, int)' used to set the partners 
     * 
     * @param logRec                - The log record for which partners are set 
     *                logFiles              - 'logRecord' belongs to a log file listed under this parameter
     *                logFileIndex  - The index of 'logFiles' identifying the log file that logRecord belongs to 
     */
    private void setPartners(Object logRec, EList logFiles, int logFileIndex) {

        /* The log records are mapped to a Common Base Event */
        CBECommonBaseEvent logRecord = (CBECommonBaseEvent) logRec;

        /* The list of records that will be checked */
        EList recordList = null;

        /* The correlators list and the correlated records of 'logRecord' */
        EList correlators = null;

        /* Get the record ID of the passed log record */
        String recordID = getRecordID(logRecord);

        /* Traverse through the logFiles (starting from index 'logFileIndex') and make the proper correlations*/
        for (int i = logFileIndex; i < logFiles.size(); i++) {

            /* The record list of the i-th logFile */
            recordList = ((RecordList) logFiles.get(i)).getList();

            /* Traverse through the record list of the i-th log file and make the proper correlations */
            if (recordList != null) {
                for (int j = 0; j < recordList.size(); j++) {
                    if (recordList.get(j) != null && recordList.get(j) != logRec && getRecordID(recordList.get(j)).equals(recordID) && recordList.get(j) != logRec) {
                        addCorrelation((CBECommonBaseEvent) logRec, (CBECommonBaseEvent) recordList.get(j));
                    }
                } // End of the j-th loop 
            }
        } // End of the i-th loop
    } // End of setPartners (Object, EList, int)

    private EList addCorrelation(CBECommonBaseEvent artifact, CBECommonBaseEvent associtatedEvent) {

        EList correlations = (EList) correlationContainer.getCorrelations().get(artifact);

        if (correlations == null) {
            correlations = new BasicEList();
            correlations.add(associtatedEvent);
            correlationContainer.getCorrelations().put(artifact, correlations);
        }
        else {
            correlations.add(associtatedEvent);
        }

        return correlations;
    }

    /* Returns the ID associated with a log record from the 'syslog' log file (i.e. The log file that is associated 
     * with the 'Simple Parser V1.0' */
    private String getRecordID(Object logRecord) {

        String textField = ((CBECommonBaseEvent) logRecord).getMsg();

        return textField.substring(textField.lastIndexOf(' '), textField.lastIndexOf('.'));
    }
} // End of MyCorEngine class
