/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     tware - contribution direct from Oracle TopLink
//     tware - updates for new SessionProfiling API
package org.eclipse.persistence.tools.profiler.oracle;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.persistence.internal.localization.DMSLocalization;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.server.ServerSession;

import oracle.dms.instrument.DMSConsole;
import oracle.dms.instrument.Event;
import oracle.dms.instrument.Noun;
import oracle.dms.instrument.PhaseEvent;
import oracle.dms.instrument.Sensor;
import oracle.dms.instrument.State;
import oracle.dms.spy.ConfigurationError;
import oracle.dms.spy.PublisherError;
import oracle.dms.spy.Spy;

/**
 * <b>Purpose</b>: Define the interface of EclipseLink profiler for using DMS gate.<p>
 * <b>Description</b>: A mechanism used to provide a link for EclipseLink performance profiling by using the DMS tool.
 *                     The predefined EclipseLink metrics will be monitored by using DMS sensors. EclipseLink library
 *                     instrumentation will be done by inserting DMS calls for the purpose of measuring its performance<p>
 * <b>Responsibilities</b>:
 * <ul>
 * <li> Define the EclipseLink metrics.</li>
 * <li> Provide APIs to monitor the sensors at runtime.</li>
 * <li> Change DMS sensor weight at runtime</li>
 * </ul>
 * @since TopLink 10.1.3
 */
public class DMSPerformanceProfiler implements Serializable, Cloneable, SessionProfiler {

    //nouns type display name
    public static final String EclipseLinkRootNoun = "/EclipseLink";
    public static final String SessionNounType = "EclipseLink Session";
    public static final String TransactionNounType = "EclipseLink Transaction";
    public static final String RcmNounType = "EclipseLink RCM";
    public static final String ConnectionNounType = "EclipseLink Connections";
    public static final String CacheNounType = "EclipseLink Cache";
    public static final String MiscellaneousNounType = "EclipseLink Miscellaneous";

    public static final String ConnectionInUse = "ConnectionsInUse";
    public static final String MergeTime = "MergeTime";
    public static final String UnitOfWorkRegister = "UnitOfWorkRegister";
    public static final String DistributedMergeDmsDisplayName = "DistributedMerge";
    public static final String Sequencing = "Sequencing";

    public static final String CONNECT = "connect";
    public static final String CACHE = "cache";

    protected AbstractSession session;
    protected Noun root;
    protected Map<String, Sensor> normalWeightSensors;
    protected Map<String, Sensor> heavyWeightSensors;
    protected Map<String, Sensor> allWeightSensors;
    protected Map<String, Sensor> normalAndHeavyWeightSensors;
    protected Map<String, Sensor> normalHeavyAndAllWeightSensors;
    protected Map<String, Noun> normalWeightNouns;
    protected Map<String, Noun> heavyWeightNouns;
    protected Map<String, Noun> allWeightNouns;
    protected ThreadLocal operationStartTokenThreadLocal;
    protected static boolean isDMSSpyInitialized;
    protected int weight;

    /**
     * PUBLIC:
     * Create a new dms profiler.
     * The profiler can be registered with a session to log performance information.
     */
    public DMSPerformanceProfiler() {
        this(null);
    }

    /**
     * PUBLIC:
     * Create a new dms profiler.
     * The profiler can be registered with a session to log performance information.
     */
    public DMSPerformanceProfiler(Session session) {
        this.session = (AbstractSession)session;
        this.normalWeightNouns = new Hashtable<String, Noun>(1);
        this.heavyWeightNouns = new Hashtable<String, Noun>(5);
        this.allWeightNouns = new Hashtable<String, Noun>(1);
        this.normalWeightSensors = new Hashtable<String, Sensor>(4);
        this.heavyWeightSensors = new Hashtable<String, Sensor>();
        this.allWeightSensors = new Hashtable<String, Sensor>(22);
        this.normalAndHeavyWeightSensors = new Hashtable<String, Sensor>();
        this.normalHeavyAndAllWeightSensors = new Hashtable<String, Sensor>();
        this.operationStartTokenThreadLocal = new ThreadLocal();
        this.weight = DMSConsole.getSensorWeight();
        if (!isDMSSpyInitialized) {
            isDMSSpyInitialized = true;
            initSpy();
        }
    }

    /**
     * INTERNAL:
     * Initialize TopLink noun tree based on dms weight.
     */
    protected void initializeNounTree(int newWeight) {
        if (newWeight == DMSConsole.NONE) {
            destroyNounsByWeight(DMSConsole.NORMAL);
            destroyNounsByWeight(DMSConsole.HEAVY);
            destroyNounsByWeight(DMSConsole.ALL);
            if (root != null) {
                root.destroy();
            }
            return;
        }

        if (newWeight == DMSConsole.NORMAL) {
            if (getProfileWeight() == DMSConsole.NONE) {
                initializeNormalWeightSensors();
            } else if (getProfileWeight() == DMSConsole.HEAVY) {
                destroyNounsByWeight(DMSConsole.HEAVY);
            } else if (getProfileWeight() == DMSConsole.ALL) {
                destroyNounsByWeight(DMSConsole.HEAVY);
                destroyNounsByWeight(DMSConsole.ALL);
            }
        }
        if (newWeight == DMSConsole.HEAVY) {
            if (getProfileWeight() == DMSConsole.NONE) {
                initializeNormalWeightSensors();
                initializeHeavyWeightSensors();
            } else if (getProfileWeight() == DMSConsole.NORMAL) {
                initializeHeavyWeightSensors();
            } else if (getProfileWeight() == DMSConsole.ALL) {
                destroyNounsByWeight(DMSConsole.ALL);
            }
        }

        if (newWeight == DMSConsole.ALL) {
            if (getProfileWeight() == DMSConsole.NONE) {
                initializeNormalWeightSensors();
                initializeHeavyWeightSensors();
                initializeAllWeightSensors();
            } else if (getProfileWeight() == DMSConsole.NORMAL) {
                initializeHeavyWeightSensors();
                initializeAllWeightSensors();
            } else if (getProfileWeight() == DMSConsole.HEAVY) {
                initializeAllWeightSensors();
            }
        }
    }

    /**
     * INTERNAL:
     * Api for changing dms weight dynamically.
     */
    @Override
    public void setProfileWeight(int newWeight) {
        if (newWeight != this.weight) {
            getSession().setIsInProfile(!(newWeight == DMSConsole.NONE));

            // It is necessary to reset the weight to the real weight of NONE to trigger
            //correct noun creation. This handles the case where the profiler
            //instance is recreated and the weight is set to the DMSConsole weight
            //which may differ since it currently does not change at runtime.
            if (getNormalWeightNouns().isEmpty()) {
                weight = DMSConsole.NONE;
            }
            initializeNounTree(newWeight);
            weight = newWeight;
        }
    }

    /**
     * INTERNAL:
     * Initialize TopLink noun tree by default (DMSConsole.getSensorWeight())
     */
    @Override
    public void initialize() {
        weight = DMSConsole.NONE;
        initializeNounTree(DMSConsole.getSensorWeight());
        weight = DMSConsole.getSensorWeight();

    }

    /**
     * INTERNAL:
     * Return current TopLink dms weight.
     */
    @Override
    public int getProfileWeight() {
        return weight;
    }

    /**
     * INTERNAL:
     * Link to the dms PhaseEvent api start().
     */
    @Override
    public void startOperationProfile(String operationName) {
        //due to DMS bug3242994 can't set DMS weight to NONE
        //shortcut for NORMAL weight since no operation profiles are every done for this level.
        if (getProfileWeight() == DMSConsole.NORMAL) {
            return;
        }
        Sensor phaseEvent = getSensorByName(operationName);
        if (phaseEvent != null) {
            Long startToken = ((PhaseEvent) phaseEvent).start();
            getPhaseEventStartToken().put(operationName, startToken);
        }
    }

    /**
     * INTERNAL:
     * Link to the dms PhaseEvent api start().  Intended to be used for query profiling.
     */
    @Override
    public void startOperationProfile(String operationName, DatabaseQuery query, int weight) {
        //due to DMS bug3242994 can't set DMS weight to NONE
        //shortcut for NORMAL weight since no operation profiles are every done for this level.
        if (getProfileWeight() == DMSConsole.NORMAL) {
            return;
        }
        if (getProfileWeight() < weight) {
            return;
        }

        Sensor phaseEvent = getPhaseEventForQuery(operationName, query, weight);
        if (phaseEvent != null) {
            Long startToken = ((PhaseEvent) phaseEvent).start();
            if (query != null) {
                getPhaseEventStartToken().put(query.getSensorName(operationName, getSessionName()), startToken);
            } else {
                getPhaseEventStartToken().put(operationName, startToken);
            }
        }
    }

    /**
     * INTERNAL:
     * Link to the dms PhaseEvent api stop().
     */
    @Override
    public void endOperationProfile(String operationName) {
        //due to DMS bug3242994 can't set DMS weight to NONE
        //shortcut for NORMAL weight since no operation profiles are every done for this level.
        if (getProfileWeight() == DMSConsole.NORMAL) {
            return;
        }
        Sensor phaseEvent = getSensorByName(operationName);
        if (phaseEvent != null) {
            Long startTime = (Long)getPhaseEventStartToken().get(operationName);
            ((PhaseEvent)phaseEvent).stop(startTime);
        }
    }

    /**
     * INTERNAL:
     * Link to the dms PhaseEvent api stop().  Intended to be used for query profiling.
     */
    @Override
    public void endOperationProfile(String operationName, DatabaseQuery query, int weight) {
        //due to DMS bug3242994 can't set DMS weight to NONE
        //shortcut for NORMAL weight since no operation profiles are every done for this level.
        if (getProfileWeight() == DMSConsole.NORMAL) {
            return;
        }
        if (getProfileWeight() < weight) {
            return;
        }

        Sensor phaseEvent = getPhaseEventForQuery(operationName, query, weight);
        if (phaseEvent != null) {
            Long startTime;
            if (query != null) {
                startTime = (Long)getPhaseEventStartToken().get(query.getSensorName(operationName, getSessionName()));
            } else {
                startTime = (Long)getPhaseEventStartToken().get(operationName);
            }
            ((PhaseEvent)phaseEvent).stop(startTime);
        }
    }

    /**
     * INTERNAL:
     * Link to the dms State api update().
     */
    @Override
    public void update(String operationName, Object value) {
        Sensor state = getSensorByName(operationName);
        if (state != null) {
            ((State)state).update(value);
        }
    }

    /**
     * INTERNAL:
     * Link to the dms Event api occurred().
     */
    @Override
    public void occurred(String operationName, AbstractSession session) {
        Sensor event = getSensorByName(operationName);
        if (event != null) {
            ((Event)event).occurred();
        }
    }

    /**
     * INTERNAL:
     * Increase DMS Event sensor occurrence.(DMS)
     */
    @Override
    public void occurred(String operationName, DatabaseQuery query, AbstractSession session) {
        Sensor event = getSensorByName(operationName);
        if (event != null) {
            ((Event)event).occurred();
            occurred(query.getMonitorName(), session);
        }
    }

    /**
     * INTERNAL:
     * Look for sensor for the name: TopLink_&lt;sessionName&gt;_&lt;domainClass&gt;_&lt;queryClass&gt;_&lt;queryName&gt;(if exist)_&lt;operationName&gt;(if exist).
     * If not found, look for the noun the sensor should be built on.  If the noun is not found, create a new one.  Create the sensor
     * based on the noun.
     */
     protected Sensor getPhaseEventForQuery(String operationName, DatabaseQuery query, int weight) {
        String sensorName;
        if (query != null) {
            sensorName = query.getSensorName(operationName, getSessionName());
        } else {
            sensorName = operationName;
        }

        Sensor phaseEvent = getSensorByName(sensorName);

        if (phaseEvent == null) {
            Noun queryNoun;
            if (query != null) {
                String queryNounName = query.getQueryNounName(getSessionName());
                queryNoun = getNounByType(queryNounName, null, DMSConsole.HEAVY);
                if (queryNoun == null) {
                    Noun domainClassNoun = getNounByType(query.getDomainClassNounName(getSessionName()), root, DMSConsole.HEAVY);
                    queryNoun = getNounByType(queryNounName, domainClassNoun, DMSConsole.HEAVY);
                }
                phaseEvent = PhaseEvent.create(queryNoun, sensorName, DMSLocalization.buildMessage("query", new Object[]{sensorName}));
            } else {
                queryNoun = getAllWeightNouns().get(MiscellaneousNounType);
                phaseEvent = PhaseEvent.create(queryNoun, sensorName, DMSLocalization.buildMessage("query_misc", new Object[]{sensorName}));
            }
            phaseEvent.deriveMetric(Sensor.all);
            if (weight == DMSConsole.HEAVY) {
                getHeavyWeightSensors().put(sensorName, phaseEvent);
                getNormalAndHeavyWeightSensors().put(sensorName, phaseEvent);
            } else if (weight == DMSConsole.ALL) {
                getAllWeightSensors().put(sensorName, phaseEvent);
                getNormalHeavyAndAllWeightSensors().put(sensorName, phaseEvent);
            }
        }

        return phaseEvent;
     }

    /**
     * INTERNAL:
     * Look for noun based on the given type and weight.  If not found and the parent noun is not null, create a new noun.
     */
    protected Noun getNounByType(String type, Noun parentNoun, int weight) {
        if (getProfileWeight() < weight) {
            return null;
        }
        Noun noun = null;
        Map map = null;
        if (weight == DMSConsole.NORMAL) {
            map = getNormalWeightNouns();
        } else if (weight == DMSConsole.HEAVY) {
            map = getHeavyWeightNouns();
        } else if (weight == DMSConsole.ALL) {
            map = getAllWeightNouns();
        }
        if (map != null) {
            noun = (Noun)map.get(type);
            if (noun == null) {
                if (parentNoun != null) {
                    noun = Noun.create(parentNoun, type, type);
                    map.put(type, noun);
                }
            }
        }

        return noun;
    }

    /**
     * INTERNAL:
     * Return dms sensor which created by pre-defined TopLink metrics.
     */
    protected Sensor getSensorByName(String operationName) {
        Sensor sensor = null;
        if (getProfileWeight() == DMSConsole.NORMAL) {
            sensor = getNormalWeightSensors().get(operationName);
        } else if (getProfileWeight() == DMSConsole.HEAVY) {
            sensor = getNormalAndHeavyWeightSensors().get(operationName);
        } else if (getProfileWeight() == DMSConsole.ALL) {
            sensor = getNormalHeavyAndAllWeightSensors().get(operationName);
        }
        return sensor;
    }

    /**
     * INTERNAL:
     * Create root noun for TopLink dms metrics.
     */
    protected void createRootNoun() {
        root = Noun.create(EclipseLinkRootNoun);
    }

    /**
     * INTERNAL:
     * Build dms NORMAL weight sensors for TopLink dms metrics.
     */
    protected void initializeNormalWeightSensors() {
        createRootNoun();
        Noun sessionNoun = Noun.create(root, "Session" + getSessionName(), SessionNounType);

        //SessionName
        State.create(sessionNoun, SessionProfiler.SessionName, "", DMSLocalization.buildMessage("session_name"), (this.getSession().getName() == "") ? "session name not specified" : getSession().getName());

        //LoginTime
        State sessionLoginTime = State.create(sessionNoun, SessionProfiler.LoginTime, "", DMSLocalization.buildMessage("session_login_time"), "not available");
        this.getNormalWeightSensors().put(SessionProfiler.LoginTime, sessionLoginTime);
        this.getNormalWeightNouns().put(SessionNounType, sessionNoun);
    }

    /**
     * INTERNAL:
     * Build dms HEAVY weight sensors for TopLink dms metrics.
     */
    protected void initializeHeavyWeightSensors() {
        Noun baseSessionNoun = getNormalWeightNouns().get(SessionNounType);

        //clientSession
        Event clientSession = Event.create(baseSessionNoun, SessionProfiler.ClientSessionCreated, DMSLocalization.buildMessage("client_session_count"));
        getHeavyWeightSensors().put(SessionProfiler.ClientSessionCreated, clientSession);
        //UnitOfWork
        Event unitOfWork = Event.create(baseSessionNoun, SessionProfiler.UowCreated, DMSLocalization.buildMessage("unitofwork_count"));
        getHeavyWeightSensors().put(SessionProfiler.UowCreated, unitOfWork);

        Noun transactionNoun = Noun.create(root, "Transaction" + getSessionName(), TransactionNounType);
        getHeavyWeightNouns().put(TransactionNounType, transactionNoun);

        //UowOfWorkCommits
        PhaseEvent uowCommit = PhaseEvent.create(transactionNoun, SessionProfiler.UowCommit, DMSLocalization.buildMessage("unitofwork_commit"));
        uowCommit.deriveMetric(Sensor.all);
        getHeavyWeightSensors().put(SessionProfiler.UowCommit, uowCommit);
        Event uowCommits = Event.create(transactionNoun, SessionProfiler.UowCommits, DMSLocalization.buildMessage("unitofwork_commits"));
        getHeavyWeightSensors().put(SessionProfiler.UowCommits, uowCommits);
        //UnitOfWorkRollbacks
        Event uowRollbacks = Event.create(transactionNoun, SessionProfiler.UowRollbacks, DMSLocalization.buildMessage("unitofwork_rollback"));
        getHeavyWeightSensors().put(SessionProfiler.UowRollbacks, uowRollbacks);
        //OptimisticLocks
        Event optimisticLock = Event.create(transactionNoun, SessionProfiler.OptimisticLockException, DMSLocalization.buildMessage("optimistic_lock"));
        getHeavyWeightSensors().put(SessionProfiler.OptimisticLockException, optimisticLock);

        //RCM noun
        Noun rcmNoun = Noun.create(root, "RCM" + getSessionName(), RcmNounType);
        getHeavyWeightNouns().put(RcmNounType, rcmNoun);

        //Status
        State rcmStatus = State.create(rcmNoun, SessionProfiler.RcmStatus, "", DMSLocalization.buildMessage("rcm_status"), "not available");
        getHeavyWeightSensors().put(SessionProfiler.RcmStatus, rcmStatus);
        //MessagesReceived
        Event messagesReceived = Event.create(rcmNoun, SessionProfiler.RcmReceived, DMSLocalization.buildMessage("rcm_message_received"));
        getHeavyWeightSensors().put(SessionProfiler.RcmReceived, messagesReceived);
        //MessagesSent
        Event messagesSent = Event.create(rcmNoun, SessionProfiler.RcmSent, DMSLocalization.buildMessage("rcm_message_sent"));
        getHeavyWeightSensors().put(SessionProfiler.RcmSent, messagesSent);
        //RemoteChangeSets
        Event remoteChangeSets = Event.create(rcmNoun, SessionProfiler.RemoteChangeSet, DMSLocalization.buildMessage("remote_change_set"));
        getHeavyWeightSensors().put(SessionProfiler.RemoteChangeSet, remoteChangeSets);

        //connections noun
        Noun connectionsNoun = Noun.create(root, "Connection" + getSessionName(), ConnectionNounType);
        getHeavyWeightNouns().put(ConnectionNounType, connectionsNoun);
        //ConnectionsInUse
        if (getSession().isServerSession()) {
            Iterator<String> enumtr = ((ServerSession)getSession()).getConnectionPools().keySet().iterator();
            while (enumtr.hasNext()) {
                String poolName = (String)enumtr.next();
                State connectionInUse = State.create(connectionsNoun, ConnectionInUse + "(" + poolName + ")", "", DMSLocalization.buildMessage("connection_in_used"), "not available");
                getHeavyWeightSensors().put(poolName, connectionInUse);
            }
        }

        //ConnectionHealth Ping
        PhaseEvent connectionPing = PhaseEvent.create(connectionsNoun, SessionProfiler.ConnectionPing, DMSLocalization.buildMessage("connection_ping"));
        connectionPing.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.ConnectionPing, connectionPing);

        //ConnectCalls
        Event tl_connects = Event.create(connectionsNoun, SessionProfiler.Connects, DMSLocalization.buildMessage("connect_call"));
        getHeavyWeightSensors().put(SessionProfiler.Connects, tl_connects);
        //DisconnectCalls
        Event tl_disconnects = Event.create(connectionsNoun, SessionProfiler.Disconnects, DMSLocalization.buildMessage("disconnect_call"));
        getHeavyWeightSensors().put(SessionProfiler.Disconnects, tl_disconnects);

        //cache noun
        Noun cacheNoun = Noun.create(root, "Cache" + getSessionName(), CacheNounType);
        getHeavyWeightNouns().put(CacheNounType, cacheNoun);
        //CacheHits
        Event cacheHits = Event.create(cacheNoun, SessionProfiler.CacheHits, DMSLocalization.buildMessage("cache_hits"));
        getHeavyWeightSensors().put(SessionProfiler.CacheHits, cacheHits);
        //CacheMisses
        Event cacheMisses = Event.create(cacheNoun, SessionProfiler.CacheMisses, DMSLocalization.buildMessage("cache_misses"));
        getHeavyWeightSensors().put(SessionProfiler.CacheMisses, cacheMisses);

        //put in NormalAndHeavyWeightSensors
        getNormalAndHeavyWeightSensors().putAll(getNormalWeightSensors());
        getNormalAndHeavyWeightSensors().putAll(getHeavyWeightSensors());
    }

    /**
     * INTERNAL:
     * Build dms ALL weight sensors for TopLink dms metrics.
     */
    protected void initializeAllWeightSensors() {
        //MergeTime
        Noun baseTransactionNoun = getHeavyWeightNouns().get(TransactionNounType);
        PhaseEvent mergeTime = PhaseEvent.create(baseTransactionNoun, MergeTime, DMSLocalization.buildMessage("merge_time"));
        mergeTime.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.Merge, mergeTime);

        //JTS afterCompletion
        PhaseEvent jtsAferCompletion = PhaseEvent.create(baseTransactionNoun, SessionProfiler.JtsAfterCompletion, DMSLocalization.buildMessage("jts_aftercompletion"));
        jtsAferCompletion.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.JtsAfterCompletion, jtsAferCompletion);

        //JTS beforeCompletion
        PhaseEvent jtsBeforeCompletion = PhaseEvent.create(baseTransactionNoun, SessionProfiler.JtsBeforeCompletion, DMSLocalization.buildMessage("jts_beforecompletion"));
        jtsBeforeCompletion.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.JtsBeforeCompletion, jtsBeforeCompletion);

        //UnitOfWorkRegister
        PhaseEvent uowRegister = PhaseEvent.create(baseTransactionNoun, UnitOfWorkRegister, DMSLocalization.buildMessage("unitofwork_register"));
        uowRegister.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.Register, uowRegister);
        //DistributedMerge
        PhaseEvent distributedMerge = PhaseEvent.create(baseTransactionNoun, DistributedMergeDmsDisplayName, DMSLocalization.buildMessage("distributed_merge"));
        distributedMerge.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.DistributedMerge, distributedMerge);

        //assigning sequence numbers
        PhaseEvent sequence = PhaseEvent.create(baseTransactionNoun, Sequencing, DMSLocalization.buildMessage("assigning_sequence_numbers"));
        sequence.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.AssignSequence, sequence);

        //Caching
        Noun baseCacheNoun = getHeavyWeightNouns().get(CacheNounType);
        PhaseEvent cache = PhaseEvent.create(baseCacheNoun, SessionProfiler.Caching, DMSLocalization.buildMessage("caching"));
        cache.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(CACHE, cache);

        //Connection
        Noun baseConnectionNoun = getHeavyWeightNouns().get(ConnectionNounType);
        PhaseEvent dbConnect = PhaseEvent.create(baseConnectionNoun, SessionProfiler.ConnectionManagement, DMSLocalization.buildMessage("connection"));
        dbConnect.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(CONNECT, dbConnect);

        //rcm
        Noun baseRcmNoun = getHeavyWeightNouns().get(RcmNounType);

        //ChangeSetsMerged
        Event changeSetsProcessed = Event.create(baseRcmNoun, SessionProfiler.ChangeSetsProcessed, DMSLocalization.buildMessage("change_set_processed"));
        getAllWeightSensors().put(SessionProfiler.ChangeSetsProcessed, changeSetsProcessed);
        //ChangeSetsNotMerged
        Event changeSetsNotProcessed = Event.create(baseRcmNoun, SessionProfiler.ChangeSetsNotProcessed, DMSLocalization.buildMessage("change_set_not_processed"));
        getAllWeightSensors().put(SessionProfiler.ChangeSetsNotProcessed, changeSetsNotProcessed);

        //miscellaneous noun
        Noun miscellaneousNoun = Noun.create(root, "Miscellaneous" + getSessionName(), MiscellaneousNounType);
        getAllWeightNouns().put(MiscellaneousNounType, miscellaneousNoun);

        //Logging
        PhaseEvent logging = PhaseEvent.create(miscellaneousNoun, SessionProfiler.Logging, DMSLocalization.buildMessage("logging"));
        logging.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.Logging, logging);

        //DescriptorEvents
        PhaseEvent descriptorEvent = PhaseEvent.create(miscellaneousNoun, SessionProfiler.DescriptorEvent, DMSLocalization.buildMessage("descriptor_event"));
        descriptorEvent.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.DescriptorEvent, descriptorEvent);

        //SessionEvents
        PhaseEvent sessionEvent = PhaseEvent.create(miscellaneousNoun, SessionProfiler.SessionEvent, DMSLocalization.buildMessage("session_event"));
        sessionEvent.deriveMetric(Sensor.all);
        this.getAllWeightSensors().put(SessionProfiler.SessionEvent, sessionEvent);

        //put in NormalHeavyAndAllWeightSensors
        getNormalHeavyAndAllWeightSensors().putAll(getNormalAndHeavyWeightSensors());
        getNormalHeavyAndAllWeightSensors().putAll(getAllWeightSensors());
    }

    /**
     * INTERNAL:
     * This method is useful for standalone TopLink application
     * Initialize DMS, should be called once and should be called before any other DMS calls.
     */
    protected void initSpy() {
        try {
            Spy.init("TopLink", null);
        } catch (PublisherError p) {
            getSession().log(SessionLog.WARNING, SessionLog.DMS, "an_error_occured_initializing_dms_listener");
            getSession().logThrowable(SessionLog.WARNING, SessionLog.DMS, p);
            setProfileWeight(DMSConsole.NONE);
        } catch (ConfigurationError c) {
            getSession().log(SessionLog.WARNING, SessionLog.DMS, "an_error_occured_initializing_dms_listener");
            getSession().logThrowable(SessionLog.WARNING, SessionLog.DMS, c);
            setProfileWeight(DMSConsole.NONE);
        }
    }

    /**
     * INTERNAL:
     * Destroy sensors based on dms weight when user changes the weight at runtime.
     */
    protected void destroySensorsByWeight(int weight) {
        Iterator iterator = null;
        if (weight == DMSConsole.HEAVY) {
            iterator = getHeavyWeightSensors().values().iterator();
        } else if (weight == DMSConsole.ALL) {
            iterator = getAllWeightSensors().values().iterator();
        }
        if (iterator != null) {
            while (iterator.hasNext()) {
                ((Sensor)iterator.next()).destroy();
            }
        }
    }

    /**
     * INTERNAL:
     * Destroy nouns based on dms weight when user changes the weight at runtime.
     */
    protected void destroyNounsByWeight(int weight) {
        if (weight == DMSConsole.NORMAL) {
            Iterator<Noun> iterator = getNormalWeightNouns().values().iterator();
            while (iterator.hasNext()) {
                ((Noun)iterator.next()).destroy();
            }
            getNormalWeightNouns().clear();
            getNormalWeightSensors().clear();
        }
        if (weight == DMSConsole.HEAVY) {
            Iterator<Noun> iterator = getHeavyWeightNouns().values().iterator();
            while (iterator.hasNext()) {
                ((Noun)iterator.next()).destroy();
            }
            getHeavyWeightNouns().clear();
            destroySensorsByWeight(DMSConsole.HEAVY);
            getNormalAndHeavyWeightSensors().clear();
            getHeavyWeightSensors().clear();
        }
        if (weight == DMSConsole.ALL) {
            Iterator<Noun> iterator = getAllWeightNouns().values().iterator();
            while (iterator.hasNext()) {
                ((Noun)iterator.next()).destroy();
            }
            getAllWeightNouns().clear();
            destroySensorsByWeight(DMSConsole.ALL);
            getNormalHeavyAndAllWeightSensors().clear();
            getAllWeightSensors().clear();
        }
    }

    protected HashMap getPhaseEventStartToken() {
        if (getOperationStartTokenThreadLocal().get() == null) {
            getOperationStartTokenThreadLocal().set(new HashMap());
        }
        return (HashMap)getOperationStartTokenThreadLocal().get();
    }

    protected Map<String, Sensor> getNormalWeightSensors() {
        return normalWeightSensors;
    }

    protected Map<String, Sensor> getHeavyWeightSensors() {
        return heavyWeightSensors;
    }

    protected Map<String, Sensor> getAllWeightSensors() {
        return allWeightSensors;
    }

    protected Map<String, Sensor> getNormalAndHeavyWeightSensors() {
        return normalAndHeavyWeightSensors;
    }

    protected Map<String, Sensor> getNormalHeavyAndAllWeightSensors() {
        return normalHeavyAndAllWeightSensors;
    }

    protected Map<String, Noun> getNormalWeightNouns() {
        return normalWeightNouns;
    }

    protected Map<String, Noun> getHeavyWeightNouns() {
        return heavyWeightNouns;
    }

    protected Map<String, Noun> getAllWeightNouns() {
        return allWeightNouns;
    }

    protected ThreadLocal getOperationStartTokenThreadLocal() {
        return operationStartTokenThreadLocal;
    }

    public AbstractSession getSession() {
        return session;
    }

    public String getSessionName() {
        if (getSession().getName() != "") {
            return "_" + getSession().getName();
        } else {
            return getSession().getName();
        }
    }

    @Override
    public void setSession(Session session) {
        this.session = (AbstractSession)session;
    }

    @Override
    public Object profileExecutionOfQuery(DatabaseQuery query, Record row, AbstractSession session) {
        //This is to profile the query execution and no operation name is given
        startOperationProfile(null, query, DMSConsole.HEAVY);
        Object result = null;
        try {
            result = session.internalExecuteQuery(query, (AbstractRecord)row);
        } finally {
            endOperationProfile(null, query, DMSConsole.HEAVY);
        }
        return result;
    }
}
