/** @file

Copyright (C) Siemens AG 1994-2003  ALL RIGHTS RESERVED

This software is protected by the inclusion of the above copyright
notice. This software may not be provided or otherwise made available
to, or used by, any other person. No title to or ownership of the
software is  hereby  transferred.
The information contained in this document is considered the
CONFIDENTIAL and PROPRIETARY information of Siemens AG and may
not be disclosed or discussed with anyone who is not employed by
Siemens AG, unless the individual / company
(i) has an express need to know such information, and
(ii) disclosure of information is subject to the terms of a duly
executed Confidentiality and Non-Disclosure Agreement between
Siemens AG and the individual / company.

Created using template RCSfile: templ_h.h,v, Revision: 1.7, genxfile V1.11

.AUTHOR         Murat Korkmaz 

.FILENAME       pluginmanager.cpp

.TODO           

.SHORT_DESCR    PlugIn Manager implementation. 

.SW_COMPONENT   PC-SIMU PlugIn

.SW_TYPE        

.CHANGE_CONTROL

Version   Date       Changed by          Reason of change<br>
--------------------------------------------------------------------------------<br>
01.00.00  2004-01-14 Murat Korkmaz       Initial Version.<br> 
01.00.01  2004-01-27 Walter Stroell      PLUGIN_FOLDER now located at C_mobsim\plugins
01.02.00  2004-02-09 Murat Korkmaz       preprocessor JAVA_SDK added
01.02.01  2004-02-25 Murat Korkmaz       BugFix PlugInMessagePort function
01.02.02  2004-03-10 Murat Korkmaz       BugFix LoadPlugIns(void) 
01.01.02  2004-04-06 L.Khera(SISL,India) DockPlugInsToolBars() added to dock the Toolbars of PlugIns to the main
01.02.03  2004-06-10 Fang Yunchao       Add UNICODE support 
------------------------------------------------------------------------------*/
#ifndef JAVA_SDK
/* -----------------------------------------------------------------------------
INCLUDES
------------------------------------------------------------------------------*/

#include "pluginmanager.h"

/* -----------------------------------------------------------------------------
DEFINES
-------------------------------------------------------------------------------*/
/*!
 * The folder where the plug-ins resides.
 */
#define PLUGIN_FOLDER    "C_mobsim\\plugins\\"
/*!
 * The extension of the plug-ins.
 */
#define PLUGIN_EXTENSION "*.dll"



IMPLEMENT_DYNCREATE(CPlugInManager, CCmdTarget)

BEGIN_MESSAGE_MAP(CPlugInManager, CCmdTarget)
    //{{AFX_MSG_MAP(CPlugInManager)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/**
 *   Base Constructor of the ClassCPlugInManager.
 */
CPlugInManager::CPlugInManager()
{
}

/**
 *   Default Constructor of the ClassCPlugInManager.
 *   
 *   @param pcMainFrmWnd: pointer to MainWindow.
 */
CPlugInManager::CPlugInManager(CMainFrame* pcMainFrmWnd)
{
    ASSERT (pcMainFrmWnd != NULL);
    m_pcMainFrmWnd   = pcMainFrmWnd;
    m_uiCurrentCmdID = PLUGIN_COMMAND_START_ID;
}

/**
 *   Destructor of the Class CPlugInManager.
 *   Used to free memmory and unload the plug-ins.
 */
CPlugInManager::~CPlugInManager()
{
    FreePlugIns();
}

/**
 *   This function returns commands IDs for plug-ins.
 *   The range of commands are between PLUGIN_COMMAND_START_ID 
 *   and PLUGIN_COMMAND_END_ID.
 *
 *   @param  num : number of requested command ID.
 *   @return UINT: free command ID. 
 */
UINT CPlugInManager::GetCommandIDs(int num)
{
    UINT uifreeID     = m_uiCurrentCmdID;
    m_uiCurrentCmdID += num;
    return uifreeID;
}

/**
 *   This function returns the last used commands ID for plug-ins.
 *   The range of commands are between PLUGIN_COMMAND_START_ID 
 *   and PLUGIN_COMMAND_END_ID.
 *
 *   @return UINT: last used command ID. 
 */
UINT CPlugInManager::GetCurrentCommandID()
{
    return m_uiCurrentCmdID;
}

/**
 *   Called by the CMainFrame by the message CN_COMMAND to route and dispatch command messages 
 *   and to handle the update of command user-interface objects for the plug-in (Menus, Toolbars).
 *
 *   @param  nID:    Contains the command ID. 
 *   @param  nCode:  Identifies the command notification code.
 *   @param  pExtra: Used according to the value of nCode. 
 *   @param  pHandlerInfo: If not NULL, OnCmdMsg fills in the pTarget and pmf members of 
 *                         the pHandlerInfo structure instead of dispatching the command.
 *
 *   @return UINT: Nonzero if the message is handled; otherwise 0.
 */
BOOL CPlugInManager::PlugInOnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
    if (nID >= PLUGIN_COMMAND_START_ID && nID <= m_uiCurrentCmdID)
        return TRUE;
    else
        return FALSE;
}

/**
 *   This function unloads the loaded plugins and frees memories 
 *   which were allocated during the call of the function 
 *   InizializePlugIns(void).
 */
void CPlugInManager::FreePlugIns(void)
{
    CPlugInFrameWork*      pPlugInFrmWrk = NULL;
    CAppiBase*             pAppInterface = NULL;
    int                    iArraySize    = m_ArrayCPlugInFrameWork.GetSize();
    int                    iIndex        = 0; 

    for (iIndex; iIndex < iArraySize; iIndex++)
    {
        pPlugInFrmWrk = m_ArrayCPlugInFrameWork.GetAt(iIndex);
        if (pPlugInFrmWrk != NULL)
        {
            pPlugInFrmWrk->FreePlugIn();
            delete pPlugInFrmWrk;
            pPlugInFrmWrk = NULL;
        }
    }
    m_ArrayCPlugInFrameWork.RemoveAll();
}

/**
 *   This function docks the Toolbars of all the loaded Plug-Ins
     to the left of the main toolbar of the MainFrame.
 */
void CPlugInManager::DockPlugInsToolBars()
{
    CPlugInFrameWork*      pPlugInFrmWrk = NULL;
    CMainFrame* pcMainFrm = ((CMainFrame*)GET_APP()->m_pMainWnd);
    int                    iArraySize    = m_ArrayCPlugInFrameWork.GetSize();
    int                    iIndex        = 0; 

    for (iIndex; iIndex < iArraySize; iIndex++)
    {
        pPlugInFrmWrk = m_ArrayCPlugInFrameWork.GetAt(iIndex);
        if (pPlugInFrmWrk != NULL)
        {
            pcMainFrm->DockControlBarLeftOf(&pPlugInFrmWrk->GetPlugInToolBar(), &pcMainFrm->m_wndToolBarView);
        }
    }
}

/**
 *   This function loads the plug-ins. And returns the number of loaded
 *   plug-ins.
 *    
 *   @return int: Number of loaded plug-ins.
 */
int CPlugInManager::LoadPlugIns(void)
{
    CPlugInFrameWork* pPlugInFrmWrk;
    CString			  cStrSearchPath;
    CString           cStrCommandLine;
    CString           cStrError;
    CFileFind         finder;
    BOOL              bWorking;
    char              exePath[256];
    DWORD             dwReturns = PLUGIN_ERROR_SUCCESS;
    
    if (m_ArrayCPlugInFrameWork.GetSize())
        FreePlugIns();


    GetModuleFileName( NULL, exePath, 256);

    cStrCommandLine   = exePath;//GetCommandLine();                    // so we know where to look for DLL's
    cStrCommandLine   = cStrCommandLine.TrimLeft("\"");      // lose left "
    cStrCommandLine   = cStrCommandLine.TrimRight("\" ");    // lose right "
    cStrCommandLine   = cStrCommandLine.TrimRight(".exe");
    cStrCommandLine   = cStrCommandLine.TrimRight(GET_APP()->m_pszExeName);// lose module name of the application
    cStrCommandLine  += PLUGIN_FOLDER;                        // add the plugins folder 
    cStrSearchPath    = cStrCommandLine + PLUGIN_EXTENSION;   // add the extensions of plug-ins

    bWorking           = finder.FindFile(cStrSearchPath);     // find the first plug-in
    m_pAppInterface    = new CAppiBase(this);                 // create the app interface for the plug-in
    
    // Find the plug-ins and load them
    while (bWorking)                                           
    {
        bWorking           = finder.FindNextFile();
        pPlugInFrmWrk      = new CPlugInFrameWork(this, m_pAppInterface);   // create a new framework to handle the plug-in

        dwReturns =  pPlugInFrmWrk->LoadPlugIn(finder.GetFilePath()); // load the plug-in  
        if (PLUGIN_ERROR_SUCCESS == dwReturns)
        {
            dwReturns =  pPlugInFrmWrk->InitPlugIn(); // init the loaded plug-in
            if (PLUGIN_ERROR_SUCCESS == dwReturns)
            {
                pPlugInFrmWrk->SetPlugInFilePathFileName(finder.GetFilePath(),
                                                         finder.GetFileName());

                m_ArrayCPlugInFrameWork.Add(pPlugInFrmWrk); // we have found a appropiate plug-in and have initialized it
                                                            // now we  can save it in a framwork array for further use. 
            }
            else
            {
                // an error has occured during initializing of the plug-in. show messagebox.
                pPlugInFrmWrk->FreePlugIn();
                cStrError = GetPlugInErrorString(dwReturns) + " " + finder.GetFileName();
                AfxMessageBox(cStrError, MB_ICONINFORMATION);
                delete pPlugInFrmWrk;
            }
        }
        else
        {
            // we could not load the plug-in! show messagebox and delete the framwork object.
            cStrError = GetPlugInErrorString(dwReturns) + finder.GetFileName();
            AfxMessageBox(cStrError, MB_ICONINFORMATION);
            delete pPlugInFrmWrk;
        }
    }
    return m_ArrayCPlugInFrameWork.GetSize();
}

/**
 *   This function gives the number of current loaded plugins.  
 *    
 *   @return UINT: Number of loaded plug-ins.
 */
UINT CPlugInManager::GetNumberOfLoadedPlugIns()
{
    return m_ArrayCPlugInFrameWork.GetSize();
}

/**
 *   This function verifies whether the plug-in is loaded.    
 *    
 *   @param cStrPlugInName: plug-in name to verify.    
 *
 *   @return BOOL: True if the plug-in is loaded.
 */
BOOL CPlugInManager::IsPlugInLoaded(const CString cStrPlugInName)
{
    BOOL bReturn    = FALSE;
    int  iArraySize = m_ArrayCPlugInFrameWork.GetSize();
    int  iIndex     = 0; 

    for (iIndex; iIndex < iArraySize; iIndex++)
    {
        if (!cStrPlugInName.Compare(m_ArrayCPlugInFrameWork.GetAt(iIndex)->GetPlugInName()))
        {
            bReturn = TRUE;
            iIndex  = iArraySize;
        }
    }

    return bReturn;
}

/**
*   Function to send messages to al loaded plug-ins. Yoo can use * to send message to all loaded
*   plug-ins
*   
*   @param cStrPlugInName: The name of the plug-in, or * 
*   @param uiMsg         : Specifies the message to be sent.
*   @param lParam        : Specifies additional message-dependent information.
*   @param pParam        : Specifies additional message-dependent information. 
*
*   @return UINT         : Okay if PM_MESSAGE_OK is returned.
*/
UINT CPlugInManager::PlugInMessagePort(const CString cStrPlugInName , UINT uiMsg, LPARAM lParam, PVOID pParam)
{
    BOOL bReturn    = FALSE;
    int  iArraySize = m_ArrayCPlugInFrameWork.GetSize();
    int  iIndex     = 0; 

    for (iIndex; iIndex < iArraySize; iIndex++)
    {
       if (   !cStrPlugInName.Compare(m_ArrayCPlugInFrameWork.GetAt(iIndex)->GetPlugInName()) 
            || !cStrPlugInName.Compare(_T("*")))
        {
            m_ArrayCPlugInFrameWork.GetAt(iIndex)->PlugInMessagePort(cStrPlugInName, uiMsg, lParam, pParam);
        }
    }
    return bReturn;
}

/**                                                                       
 *  Function to get  appropriate error string.  
 *    
 *  @param   lReturn: Error ID  
 *  
 *  @return  CString: Error String
 */                                                                        
CString GetPlugInErrorString(long lReturn)
{
#ifndef LOCALIZATION_SUPPORT
    CString strError; 
#else
    CLocalizationString strError; 
#endif
    switch(lReturn)
    {
    case PLUGIN_ERROR_INTERFACE_IS_NULLP:
        strError.LoadString(IDS_PLUGIN_ERROR_INTERFACE_IS_NULLP);
        break;
    case PLUGIN_ERROR_INIT_PLUGIN_FNC_NOT_FOUND:
        strError.LoadString(IDS_PLUGIN_ERROR_INIT_PLUGIN_FNC_NOT_FOUND);
        break;
    case PLUGIN_ERROR_INIT_FUNCTION_NOT_LOAD:
        strError.LoadString(IDS_PLUGIN_ERROR_INIT_FUNCTION_NOT_LOAD);
        break;
    case PLUGIN_ERROR_HINSTANCE_IS_NULLP:
        strError.LoadString(IDS_PLUGIN_ERROR_HINSTANCE_IS_NULLP);
        break;
    case PLUGIN_ERROR_FREE_PLUGIN:
        strError.LoadString(IDS_PLUGIN_ERROR_FREE_PLUGIN);
        break;
    case PLUGIN_ERROR_PLUGIN_COULD_NOT_LOAD:
        strError.LoadString(IDS_PLUGIN_ERROR_PLUGIN_COULD_NOT_LOAD);
        break;
    case PLUGIN_ERROR_WRONG_PLUGIN_API_VERSION:
        strError.LoadString(IDS_PLUGIN_ERROR_WRONG_PLUGIN_API_VERSION);
        break;
    case PLUGIN_ERROR_WRONG_APPL_API_VERSION:
        strError.LoadString(IDS_PLUGIN_ERROR_WRONG_APPL_API_VERSION);
        break;
    case PLUGIN_ERROR_APPL_INTERFACE_IS_NULLP:
        strError.LoadString(IDS_PLUGIN_ERROR_APPL_INTERFACE_IS_NULLP);
        break;
    case PLUGIN_ERROR_PLUGIN_INTERFACE_IS_NOT_NULLP:
        strError.LoadString(IDS_PLUGIN_ERROR_PLUGIN_INTERFACE_IS_NOT_NULLP);
        break;
    case PLUGIN_ERROR_PLUGIN_ALREADY_LOADED:
        strError.LoadString(IDS_PLUGIN_ERROR_PLUGIN_ALREADY_LOADED);
        break;
    default:
        strError.Format(IDS_PLUGIN_ERROR_NUMBER, lReturn);
        break;

    }
    return strError;
}
#endif //JAVA_SDK
/* -----------------------------------------------------------------------------
END OF FILE pluginmanager.cpp
------------------------------------------------------------------------------*/

