org.drools.eclipse.debug.AuditView.java Source code

Java tutorial

Introduction

Here is the source code for org.drools.eclipse.debug.AuditView.java

Source

/*
 * Copyright 2010 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.drools.eclipse.debug;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.drools.audit.event.ActivationLogEvent;
import org.drools.audit.event.LogEvent;
import org.drools.audit.event.ObjectLogEvent;
import org.drools.audit.event.RuleBaseLogEvent;
import org.drools.audit.event.RuleFlowGroupLogEvent;
import org.drools.audit.event.RuleFlowLogEvent;
import org.drools.audit.event.RuleFlowNodeLogEvent;
import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.DroolsPluginImages;
import org.drools.eclipse.debug.actions.DeleteLogAction;
import org.drools.eclipse.debug.actions.FileAuditDropAdapter;
import org.drools.eclipse.debug.actions.OpenLogAction;
import org.drools.eclipse.debug.actions.RefreshLogAction;
import org.drools.eclipse.debug.actions.ShowEventCauseAction;
import org.eclipse.debug.ui.AbstractDebugView;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.StreamException;

public class AuditView extends AbstractDebugView {

    private static final String LOG_FILE_NAME = "LogFileName";
    private static final String CAUSE_EVENT_COLOR = "CauseEventColor";

    private String logFileName;
    private IAction deleteAction;
    private IAction refreshAction;
    private boolean drools4 = false;

    protected Viewer createViewer(Composite parent) {
        final TreeViewer variablesViewer = new TreeViewer(parent);
        variablesViewer.setContentProvider(new AuditViewContentProvider());
        variablesViewer.setLabelProvider(new AuditLabelProvider());
        variablesViewer.setUseHashlookup(true);
        variablesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                getViewer().refresh();
            }
        });

        int ops = DND.DROP_COPY | DND.DROP_MOVE;
        Transfer[] transfers = new Transfer[] { FileTransfer.getInstance() };
        variablesViewer.addDropSupport(ops, transfers, new FileAuditDropAdapter(variablesViewer, this));

        return variablesViewer;
    }

    public void setLogFile(String logFileName) {
        this.logFileName = logFileName;
        refresh();
        deleteAction.setEnabled(logFileName != null);
        refreshAction.setEnabled(logFileName != null);
    }

    @SuppressWarnings("unchecked")
    public void refresh() {
        drools4 = false;
        if (logFileName == null) {
            getViewer().setInput(null);
            return;
        }
        List<LogEvent> eventList = new ArrayList<LogEvent>();
        try {
            XStream xstream = new XStream();
            ObjectInputStream in = xstream.createObjectInputStream(new FileReader(logFileName));
            try {
                while (true) {
                    Object object = in.readObject();
                    if (object instanceof LogEvent) {
                        eventList.add((LogEvent) object);
                    } else if (object instanceof List) {
                        drools4 = true;
                        eventList.addAll((List<LogEvent>) object);
                    } else {
                        throw new IllegalArgumentException("Unexpected element in log: " + object);
                    }
                }
            } catch (StreamException e) {
                if (!(e.getCause() instanceof EOFException)) {
                    throw e;
                }
            } catch (EOFException e) {
                // do nothing
            }
        } catch (FileNotFoundException e) {
            setLogFile(null);
        } catch (Throwable t) {
            DroolsEclipsePlugin.log(t);
        }
        if (drools4) {
            getViewer().setInput(createDrools4EventList(eventList));
        } else {
            getViewer().setInput(createEventList(eventList));
        }
        // TODO: this is necessary because otherwise, the show cause action
        // cannot find the cause event if it hasn't been shown yet
        ((TreeViewer) getViewer()).expandAll();
    }

    protected List<Event> createEventList(List<LogEvent> logEvents) {
        Iterator<LogEvent> iterator = logEvents.iterator();
        List<Event> events = new ArrayList<Event>();
        Stack<Event> beforeEvents = new Stack<Event>();
        List<Event> newActivations = new ArrayList<Event>();
        Map<String, Event> activationMap = new HashMap<String, Event>();
        Map<Long, Event> objectMap = new HashMap<Long, Event>();
        while (iterator.hasNext()) {
            LogEvent inEvent = (LogEvent) iterator.next();
            Event event = new Event(inEvent.getType());
            switch (inEvent.getType()) {
            case LogEvent.INSERTED:
                ObjectLogEvent inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString("Object inserted (" + inObjectEvent.getFactId() + "): "
                        + inObjectEvent.getObjectToString());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                objectMap.put(new Long(((ObjectLogEvent) inEvent).getFactId()), event);
                break;
            case LogEvent.UPDATED:
                inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString(
                        "Object updated (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                Event assertEvent = (Event) objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId()));
                if (assertEvent != null) {
                    event.setCauseEvent(assertEvent);
                }
                break;
            case LogEvent.RETRACTED:
                inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString(
                        "Object removed (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                assertEvent = (Event) objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId()));
                if (assertEvent != null) {
                    event.setCauseEvent(assertEvent);
                }
                break;
            case LogEvent.ACTIVATION_CREATED:
                ActivationLogEvent inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation created: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                newActivations.add(event);
                activationMap.put(((ActivationLogEvent) inEvent).getActivationId(), event);
                break;
            case LogEvent.ACTIVATION_CANCELLED:
                inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation cancelled: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                newActivations.add(event);
                event.setCauseEvent((Event) activationMap.get(((ActivationLogEvent) inEvent).getActivationId()));
                break;
            case LogEvent.BEFORE_ACTIVATION_FIRE:
                inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation executed: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                events.add(event);
                beforeEvents.push(event);
                event.setCauseEvent((Event) activationMap.get(((ActivationLogEvent) inEvent).getActivationId()));
                break;
            case LogEvent.AFTER_ACTIVATION_FIRE:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULEFLOW_CREATED:
                RuleFlowLogEvent inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
                event.setString("Process started: " + inRuleFlowEvent.getProcessName() + "["
                        + inRuleFlowEvent.getProcessId() + "]");
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULEFLOW_CREATED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULEFLOW_COMPLETED:
                inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
                event.setString("Process completed: " + inRuleFlowEvent.getProcessName() + "["
                        + inRuleFlowEvent.getProcessId() + "]");
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULEFLOW_COMPLETED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED:
                RuleFlowNodeLogEvent inRuleFlowNodeEvent = (RuleFlowNodeLogEvent) inEvent;
                event.setString("Process node triggered: " + inRuleFlowNodeEvent.getNodeName() + " in process "
                        + inRuleFlowNodeEvent.getProcessName() + "[" + inRuleFlowNodeEvent.getProcessId() + "]");
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED:
                RuleFlowGroupLogEvent inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
                event.setString("RuleFlow Group activated: " + inRuleFlowGroupEvent.getGroupName() + "[size="
                        + inRuleFlowGroupEvent.getSize() + "]");
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED:
                inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
                event.setString("RuleFlow Group deactivated: " + inRuleFlowGroupEvent.getGroupName() + "[size="
                        + inRuleFlowGroupEvent.getSize() + "]");
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_PACKAGE_ADDED:
                RuleBaseLogEvent ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Package added: " + ruleBaseEvent.getPackageName());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_PACKAGE_ADDED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_PACKAGE_REMOVED:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Package removed: " + ruleBaseEvent.getPackageName());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_PACKAGE_REMOVED:
                beforeEvents.pop();
                break;
            case LogEvent.BEFORE_RULE_ADDED:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Rule added: " + ruleBaseEvent.getRuleName());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULE_ADDED:
                if (!beforeEvents.isEmpty()) {
                    Event beforeEvent = (Event) beforeEvents.pop();
                    beforeEvent.addSubEvents(newActivations);
                    newActivations.clear();
                }
                break;
            case LogEvent.BEFORE_RULE_REMOVED:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Rule removed: " + ruleBaseEvent.getRuleName());
                if (!beforeEvents.isEmpty()) {
                    ((Event) beforeEvents.peek()).addSubEvent(event);
                } else {
                    events.add(event);
                }
                beforeEvents.push(event);
                break;
            case LogEvent.AFTER_RULE_REMOVED:
                if (!beforeEvents.isEmpty()) {
                    Event beforeEvent = (Event) beforeEvents.pop();
                    beforeEvent.addSubEvents(newActivations);
                    newActivations.clear();
                }
                break;
            default:
                // do nothing
                break;
            }
        }
        return events;
    }

    protected List createDrools4EventList(List logEvents) {
        Iterator iterator = logEvents.iterator();
        List events = new ArrayList();
        Event currentBeforeActivationEvent = null;
        Event currentBeforePackageEvent = null;
        List newActivations = new ArrayList();
        Map activationMap = new HashMap();
        Map objectMap = new HashMap();
        while (iterator.hasNext()) {
            LogEvent inEvent = (LogEvent) iterator.next();
            Event event = new Event(inEvent.getType());
            switch (inEvent.getType()) {
            case LogEvent.INSERTED:
                ObjectLogEvent inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString("Object inserted (" + inObjectEvent.getFactId() + "): "
                        + inObjectEvent.getObjectToString());
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                objectMap.put(new Long(((ObjectLogEvent) inEvent).getFactId()), event);
                break;
            case LogEvent.UPDATED:
                inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString(
                        "Object updated (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString());
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                Event assertEvent = (Event) objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId()));
                if (assertEvent != null) {
                    event.setCauseEvent(assertEvent);
                }
                break;
            case LogEvent.RETRACTED:
                inObjectEvent = (ObjectLogEvent) inEvent;
                event.setString(
                        "Object removed (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString());
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                assertEvent = (Event) objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId()));
                if (assertEvent != null) {
                    event.setCauseEvent(assertEvent);
                }
                break;
            case LogEvent.ACTIVATION_CREATED:
                ActivationLogEvent inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation created: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                newActivations.add(event);
                activationMap.put(((ActivationLogEvent) inEvent).getActivationId(), event);
                break;
            case LogEvent.ACTIVATION_CANCELLED:
                inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation cancelled: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                newActivations.add(event);
                event.setCauseEvent((Event) activationMap.get(((ActivationLogEvent) inEvent).getActivationId()));
                break;
            case LogEvent.BEFORE_ACTIVATION_FIRE:
                inActivationEvent = (ActivationLogEvent) inEvent;
                event.setString("Activation executed: Rule " + inActivationEvent.getRule() + " "
                        + inActivationEvent.getDeclarations());
                events.add(event);
                currentBeforeActivationEvent = event;
                event.setCauseEvent((Event) activationMap.get(((ActivationLogEvent) inEvent).getActivationId()));
                break;
            case LogEvent.AFTER_ACTIVATION_FIRE:
                currentBeforeActivationEvent = null;
                break;
            case 8:
                RuleFlowLogEvent inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
                event.setString("RuleFlow started: " + inRuleFlowEvent.getProcessName() + "["
                        + inRuleFlowEvent.getProcessId() + "]");
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                break;
            case 9:
                inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
                event.setString("RuleFlow completed: " + inRuleFlowEvent.getProcessName() + "["
                        + inRuleFlowEvent.getProcessId() + "]");
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                break;
            case 10:
                RuleFlowGroupLogEvent inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
                event.setString("RuleFlowGroup activated: " + inRuleFlowGroupEvent.getGroupName() + "[size="
                        + inRuleFlowGroupEvent.getSize() + "]");
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                break;
            case 11:
                inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
                event.setString("RuleFlowGroup deactivated: " + inRuleFlowGroupEvent.getGroupName() + "[size="
                        + inRuleFlowGroupEvent.getSize() + "]");
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                break;
            case 12:
                RuleBaseLogEvent ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Package added: " + ruleBaseEvent.getPackageName());
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                currentBeforePackageEvent = event;
                break;
            case 13:
                currentBeforePackageEvent = null;
                break;
            case 14:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Package removed: " + ruleBaseEvent.getPackageName());
                if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                currentBeforePackageEvent = event;
                break;
            case 15:
                currentBeforePackageEvent = null;
                break;
            case 17:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Rule added: " + ruleBaseEvent.getRuleName());
                if (currentBeforePackageEvent != null) {
                    currentBeforePackageEvent.addSubEvent(event);
                } else if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                break;
            case 19:
                ruleBaseEvent = (RuleBaseLogEvent) inEvent;
                event.setString("Rule removed: " + ruleBaseEvent.getRuleName());
                if (currentBeforePackageEvent != null) {
                    currentBeforePackageEvent.addSubEvent(event);
                } else if (currentBeforeActivationEvent != null) {
                    currentBeforeActivationEvent.addSubEvent(event);
                } else {
                    events.add(event);
                }
                event.addSubEvents(newActivations);
                newActivations.clear();
                break;
            }
        }
        return events;
    }

    public void deleteLog() {
        if (logFileName != null) {
            File file = new File(logFileName);
            try {
                file.delete();
                // TODO delete file cause this doesn't seem to work
                setLogFile(null);
                refresh();
            } catch (Throwable t) {
                t.printStackTrace();
                DroolsEclipsePlugin.log(t);
            }
        }
    }

    protected void becomesVisible() {
        refresh();
    }

    protected String getHelpContextId() {
        return null;
    }

    public Event getSelectedEvent() {
        ISelection selection = getViewer().getSelection();
        if (selection instanceof IStructuredSelection) {
            Object selected = ((IStructuredSelection) selection).getFirstElement();
            if (selected instanceof Event) {
                return (Event) selected;
            }
        }
        return null;
    }

    public void showEvent(Event event) {
        ((TreeViewer) getViewer()).reveal(event);
    }

    protected void fillContextMenu(IMenuManager menu) {
        Event selected = getSelectedEvent();
        if (selected != null) {
            Event causeEvent = selected.getCauseEvent();
            if (causeEvent != null) {
                menu.add(getAction("ShowEventCause"));
            }
        }
        menu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
    }

    protected void createActions() {
        deleteAction = new DeleteLogAction(this);
        setAction("ClearLog", deleteAction);
        deleteAction.setEnabled(logFileName != null);
        refreshAction = new RefreshLogAction(this);
        setAction("RefreshLog", refreshAction);
        refreshAction.setEnabled(logFileName != null);
        IAction action = new OpenLogAction(this);
        setAction("OpenLog", action);
        action = new ShowEventCauseAction(this);
        setAction("ShowEventCause", action);
    }

    protected void configureToolBar(IToolBarManager tbm) {
        tbm.add(getAction("OpenLog"));
        tbm.add(getAction("RefreshLog"));
        tbm.add(getAction("ClearLog"));
    }

    public void saveState(IMemento memento) {
        memento.putString(LOG_FILE_NAME, logFileName);
    }

    public void init(IViewSite site, IMemento memento) throws PartInitException {
        super.init(site, memento);
        if (memento != null) {
            logFileName = memento.getString(LOG_FILE_NAME);
        }
    }

    public class Event {

        private String toString;
        private int type;
        private List<Event> subEvents = new ArrayList<Event>();
        private Event causeEvent;

        public Event(int type) {
            this.type = type;
        }

        public void setString(String toString) {
            this.toString = toString;
        }

        public String toString() {
            return toString;
        }

        public int getType() {
            return type;
        }

        public void addSubEvent(Event subEvent) {
            subEvents.add(subEvent);
        }

        public void addSubEvents(Collection<Event> subEvents) {
            this.subEvents.addAll(subEvents);
        }

        public Object[] getSubEvents() {
            return subEvents.toArray();
        }

        public boolean hasSubEvents() {
            return !subEvents.isEmpty();
        }

        public void setCauseEvent(Event causeEvent) {
            this.causeEvent = causeEvent;
        }

        public Event getCauseEvent() {
            return causeEvent;
        }
    }

    public class AuditLabelProvider extends LabelProvider implements IColorProvider {

        public Color getForeground(Object element) {
            return null;
        }

        public Color getBackground(Object element) {
            Event selected = getSelectedEvent();
            if (selected != null) {
                if (element.equals(selected.getCauseEvent())) {
                    Color color = DroolsEclipsePlugin.getDefault().getColor(CAUSE_EVENT_COLOR);
                    if (color == null) {
                        color = new Color(getControl().getDisplay(), 0, 255, 0);
                        DroolsEclipsePlugin.getDefault().setColor(CAUSE_EVENT_COLOR, color);
                    }
                    return color;
                }
            }
            return null;
        }

        public Image getImage(Object element) {
            if (element instanceof Event) {
                int type = ((Event) element).getType();
                if (drools4) {
                    switch (type) {
                    case LogEvent.INSERTED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.INSERT);
                    case LogEvent.UPDATED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.UPDATE);
                    case LogEvent.RETRACTED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RETRACT);
                    case LogEvent.ACTIVATION_CREATED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.CREATE_ACTIVATION);
                    case LogEvent.ACTIVATION_CANCELLED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.CANCEL_ACTIVATION);
                    case LogEvent.BEFORE_ACTIVATION_FIRE:
                        return DroolsPluginImages.getImage(DroolsPluginImages.EXECUTE_ACTIVATION);
                    case 8:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW);
                    case 9:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW);
                    case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_NODE_TRIGGERED);
                    case 10:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP);
                    case 11:
                        return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP);
                    case 12:
                        return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                    case 14:
                        return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                    case 17:
                        return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                    case 19:
                        return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                    }
                }
                switch (type) {
                case LogEvent.INSERTED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.INSERT);
                case LogEvent.UPDATED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.UPDATE);
                case LogEvent.RETRACTED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RETRACT);
                case LogEvent.ACTIVATION_CREATED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.CREATE_ACTIVATION);
                case LogEvent.ACTIVATION_CANCELLED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.CANCEL_ACTIVATION);
                case LogEvent.BEFORE_ACTIVATION_FIRE:
                    return DroolsPluginImages.getImage(DroolsPluginImages.EXECUTE_ACTIVATION);
                case LogEvent.BEFORE_RULEFLOW_CREATED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW);
                case LogEvent.BEFORE_RULEFLOW_COMPLETED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW);
                case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_NODE_TRIGGERED);
                case LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP);
                case LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP);
                case LogEvent.BEFORE_PACKAGE_ADDED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                case LogEvent.BEFORE_PACKAGE_REMOVED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                case LogEvent.BEFORE_RULE_ADDED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                case LogEvent.BEFORE_RULE_REMOVED:
                    return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS);
                }
                return null;
            }
            return null;
        }
    }
}