// SetOfHierarchy.cpp: implementation of the CSetOfHierarchy class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "addin.h"
#include "SetOfHierarchy.h"
#include "Preprocessor.h"
#include <locale.h>
#include "istrmap.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

extern CMetaDataCont * pMetaDataCont;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSetOfHierarchy* CSetOfHierarchy::pGlobalHierarchy = NULL;

CSetOfHierarchy::CSetOfHierarchy() : bIsOpenCompForm(false)
{
  //AfxMessageBox("Hello world");
}

void CSetOfHierarchy::Init(const char* IBDir, const char* BinDir)
{  
  pCreatedCompModule = NULL;
  //bool bFindIBDir  = false;
  //bool bFindBinDir = false;
  m_CountParametersInCallMethod = -1;
  
  

  pathBase1C = BinDir;
  pathBin1C  = IBDir;
  
  if (IBDir == NULL || BinDir == NULL)
  {
	try
	{
		pathBase1C = ::CallMethodOfGlobalContexts0("IBDir");
		pathBin1C = ::CallMethodOfGlobalContexts0("BinDir");
	}
	catch(...)
	{
	}
  }
  
  if (pathBin1C.IsEmpty())
  {
    pBkEndUI->DoMessageLine("Не удалось получить функцией BinDir() каталог bin 1C!", mmBlackErr);	
  }
  else
  {
    CFile file;
    CString strFileNameIni = pathBin1C;
    strFileNameIni += "OXY.ini";
    if (file.Open(strFileNameIni, CFile::modeRead))
    {          
      DWORD nLength = file.GetLength();
      file.Close();
      char* pBuf = new char[nLength+2];
      int nSize = 0;
      nSize = GetPrivateProfileSection("alias_path", pBuf, nLength+2, strFileNameIni);
      if (nSize > 0)
      {
        CString str;
        for (int i = 0; i < nSize; i++)
        {
          
          if (pBuf[i] == '\0')
          {         
            int nPosEq = str.Find("=");
            if (-1 != nPosEq)
            {
              CString strAlias       = str.Left(nPosEq);
              CString strPathOfAlias = str.Right(str.GetLength() - nPosEq - 1);
              strAlias.TrimLeft(); strAlias.TrimRight();
              strPathOfAlias.TrimLeft(); strPathOfAlias.TrimRight();
              m_Meta.m_AliasOfPaths[strAlias] = strPathOfAlias;
              //pBkEndUI->DoMessageLine(strAlies, mmBlackErr);	
              //pBkEndUI->DoMessageLine(strPathOfAlies, mmBlackErr);	
            }
            str.Empty();
            if (pBuf[i+1] == '\0')
              break; // конец секции
            continue;
          }
          str += pBuf[i];        
        }
      }          
      delete pBuf;
    }        
  }  
}

CSetOfHierarchy::~CSetOfHierarchy()
{
  CString key;
  POSITION pos;
  for (pos = m_Meta.m_ClassesHierarchyMap.GetStartPosition(); pos != NULL;)
  {
    CStringList* pList = NULL;    
    m_Meta.m_ClassesHierarchyMap.GetNextAssoc( pos, key, (CObject*&)pList);
    delete pList;
  }
  
  for (pos = m_Meta.m_TypeOfClassMeth.GetStartPosition(); pos != NULL;)
  {
    CMapStringToOb* pMapFunc = NULL;
    CString key;
    m_Meta.m_TypeOfClassMeth.GetNextAssoc( pos, key, (CObject*&)pMapFunc);
    
    for (POSITION pos2 = pMapFunc->GetStartPosition(); pos2 != NULL;)
    {
      ARR_TYPE_NAME* param = NULL;
      pMapFunc->GetNextAssoc( pos2, key, (CObject*&)param);      
      delete param;
    }
    delete pMapFunc;
  }  
}

CSetOfHierarchy* CSetOfHierarchy::GetHierarchy()
{
  if (pGlobalHierarchy == NULL)
    pGlobalHierarchy = new CSetOfHierarchy;
  return pGlobalHierarchy;
}

void CSetOfHierarchy::DeInitHierarchy()
{
  if (pGlobalHierarchy)
  {
    CString name;
    CString NameFile;
    CFile file;  
    for (POSITION pos = pGlobalHierarchy->m_Meta.m_ClassBindFile.GetStartPosition(); pos != NULL;)
    {
      pGlobalHierarchy->m_Meta.m_ClassBindFile.GetNextAssoc( pos, name, NameFile);
      
      CSetOfHierarchy::MakeFullFileName(&NameFile);
      
      if (file.Open(NameFile, CFile::modeRead, NULL))
      {
        CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CComponentClass));      
        file.Close();
      }    
    }    
    delete pGlobalHierarchy;
  }
}

// artbear для проверки рекурсии
// 1 - рекурсия, 0 - нет
bool CSetOfHierarchy::VerifyRecursiveInBaseClasses(CString ClassName, CString BaseClassName, CString& sRecursiveHierarchy)
{
  CStringList* pList = (CStringList*)m_Meta.m_ClassesHierarchyMap[BaseClassName];
  if (pList)
  {
	sRecursiveHierarchy = BaseClassName+ " - "+sRecursiveHierarchy;
    for(POSITION posList = pList->GetHeadPosition(); posList != NULL; )
    {
		CString strBaseClassName = pList->GetNext( posList );

		if (!ClassName.CompareNoCase(strBaseClassName))
		{
			sRecursiveHierarchy = strBaseClassName + " - "+sRecursiveHierarchy;
			return true;
		}

		bool bHaveRecursive = VerifyRecursiveInBaseClasses(ClassName, strBaseClassName, sRecursiveHierarchy);	

		if (bHaveRecursive)
			return true;

    }
  }
  return false;
}

// Выполняет инициализацию экземпляра класса на основе информации полученной
// из файла составленного пользователем
bool CSetOfHierarchy::InitInstanceComp(CComponentClass* pComponent)
{
  CString NameOfComponent = pComponent->GetTypeString();  
  if (!NameOfComponent.IsEmpty()) 
  {
    if (!pCreatedCompModule)
    {
      // Запоминаем создаваемый объект КОП, это первый вызов метода-инициализации
      pCreatedCompModule = pComponent;
      pComponent->SetDebugInfo(pComponent);
    }
    
    CString NameOfFile = m_Meta.m_ClassBindFile[NameOfComponent];
    CStringList* pList = NULL;
    if (!NameOfFile.IsEmpty() )
    {
      pList = (CStringList*)m_Meta.m_ClassesHierarchyMap[NameOfComponent];
      if (pList)
      {
		// artbear проверю рекурсию
		CString sRecursiveHierarchy = ""; //NameOfComponent;
		if (VerifyRecursiveInBaseClasses(NameOfComponent, NameOfComponent, sRecursiveHierarchy))
		{
			pCreatedCompModule = NULL;
			CString error = "\r\nНайдена рекурсия (предок-потомок): "+sRecursiveHierarchy;
			RuntimeError("Ошибка создания класса " + NameOfComponent + error);        
		}

        CString str;
        bool isError = false;
        for(POSITION posList = pList->GetHeadPosition(); posList != NULL; )
        {
          str = pList->GetNext( posList );
			
			CBLContext* pCont;
			if (!str.CompareNoCase("ГрупповойКонтекст") || !str.CompareNoCase("GroupContext"))
			{
				pCont = (CGroupContext*)(RUNTIME_CLASS(CGroupContext)->CreateObject());
			}
			else
			{
	          pCont = CBLContext::CreateInstance(str);
			}

          if (pCont)
          {
            CString strKey;
            CBLContext *pBase = pCont;
            if (pBase)
            {              
              pComponent->SetNestedObj(pBase);
            }
          }
          else
          {
            isError = true;
            CString error;
            error = "Базовый класс: " + str + " для класса: " + NameOfComponent + " не создан!";
            pBkEndUI->DoMessageLine(error, mmBlackErr);            
          }
        }
        if (isError)       
        {
          pCreatedCompModule = NULL;
          CBLModule::RaiseExtRuntimeError("Ошибка содания класса",0);        
        }
      }
    }
    CBLModule* pModWrapper = pComponent->Init(NameOfFile, pCreatedCompModule);
    if (pModWrapper)
    {
      m_MapOfModulesAndComp[pModWrapper] = pComponent;
    }
    else
    {
      CString error = "Внимание! Инициализация класса: ";
      error += NameOfComponent;
      error += " закончилась не удачно!";
      pCreatedCompModule = NULL;
      CBLModule::RaiseExtRuntimeError(error,0);            
    }
  }
  else
  {
    pCreatedCompModule = NULL;
    return false; 
  }
  
  if (pCreatedCompModule == pComponent)
  {
    // Теперь объект КОП полностью создан, можно вызвать все его конструкторы        
    pCreatedCompModule = NULL;
    pComponent->InvokeConstructor();
    pComponent->ClearDebugInfo();
    
  }
  return true;
}

void CSetOfHierarchy::DeInitInstanceComp(CBLModule *pModWrapper)
{
  m_MapOfModulesAndComp.RemoveKey(pModWrapper);      
}

// Выполняет регистрацию имен компонентов 1С полученных из файла объявлений
void CSetOfHierarchy::RegistersContextClasses()
{
  
  CString name;
  CString NameFile;
  CFile file;  
  for (POSITION pos = m_Meta.m_ClassBindFile.GetStartPosition(); pos != NULL;)
  {
    m_Meta.m_ClassBindFile.GetNextAssoc( pos, name, NameFile);
    int npos = NameFile.Find("@MD");
    if (-1 == npos)
	    npos = NameFile.Find("@md");
    if (npos != -1)
    {
      CString nameRep = NameFile.Left(npos);
      CMetaDataCont *pMD = GetMetaData();
      CMetaDataObj* pObj=(CMetaDataObj*)pMD->GetCalcVarDef(nameRep);  
      if (pObj)
      {
        RegisterCBLContext(RUNTIME_CLASS(CComponentClass), name);
        //CBLContext::RegisterContextClass(RUNTIME_CLASS(CComponentClass),name, CType(100));      
      }
      else
      {
        CString error;
        error = "Не существует обработки в конфигурации: ";
        error += nameRep;
        error += " для класса: ";
        error += name;
        pBkEndUI->DoMessageLine(error,mmUnderlinedErr);
        pBkEndUI->DoMessageLine("Регистрация класса закончилась неудачно!",mmUnderlinedErr);
      }      
    }
    else
    {    
      CSetOfHierarchy::MakeFullFileName(&NameFile);    
      if (file.Open(NameFile, CFile::modeRead, NULL))
      {
        RegisterCBLContext(RUNTIME_CLASS(CComponentClass), name);
        //CBLContext::RegisterContextClass(RUNTIME_CLASS(CComponentClass),name, CType(100));      
        file.Close();
      }
		// АЛьФ --->
	  // класс зашитый в dll регистрируем как есть
	  // возможно, в будущем это место надо будет подправить, но пока я считаю лучше
	  // оставить так
	  else if(NameFile.Find(".dll") != -1)
	  {
        RegisterCBLContext(RUNTIME_CLASS(CComponentClass), name);
	  }
		// АЛьФ <---
      else
      {
        CString error;
        error = "Не существует файла: ";
        error += NameFile;
        error += " для класса: ";
        error += name;
        pBkEndUI->DoMessageLine(error,mmUnderlinedErr);
        pBkEndUI->DoMessageLine("Регистрация класса закончилась неудачно!",mmUnderlinedErr);
      }
    }
    
  }
  
  
  /*CString name;
  CStringList* pList = NULL;
  for (POSITION pos = m_Meta.m_ClassesHierarchyMap.GetStartPosition(); pos != NULL;)
  {
  m_Meta.m_ClassesHierarchyMap.GetNextAssoc( pos, name, (CObject*&)pList);
  if (pList)
  {
  CString str;
  for(POSITION posList = pList->GetHeadPosition(); posList != NULL; )
  {
  str = pList->GetNext( posList );
  }
  
    }
}*/
}

int CSetOfHierarchy::GetParamDefValue(int iMethodNum, int iParamNum, CValue* pDefValue,
                                      const CComponentClass* pComponentClass)
{
  if (pComponentClass == NULL || pDefValue == NULL)
    return 0;  
  
  int nRealParamNum = iParamNum;
  if (pComponentClass->HasRetVal(iMethodNum) == 1)  
    iParamNum++; // это необходимо потому что в массиве первым идет возвращаемый параметр  
  //CMapStringToOb* pMapFunc = NULL;
  CMapStringToOb* pMapFunc = pComponentClass->defFnNames->pMapFunc;
  
  //if (m_Meta.m_TypeOfClassMeth.Lookup(NameOfClass, (CObject*&)pMapFunc))
  if (pMapFunc)  
  {
    ARR_TYPE_NAME* param = (*pComponentClass->defFnNames)[iMethodNum].pDefParam;
    if (param == NULL)
    {
      CString NameMeth = pComponentClass->GetMethodName(iMethodNum, 1);
      pMapFunc->Lookup(NameMeth, (CObject*&)param);
    }
    if (param)
    {
      if (param->GetSize() <= iParamNum)      
        return 0;
      
      NameBindOfType* NameBind = param->operator[](iParamNum);
      CString strVal  = NameBind->value;
      CString strType = NameBind->type;      
      if (!strVal.IsEmpty() && !strType.IsEmpty())
      {
        int res = 1;
        if (!strType.CompareNoCase("Число") || !strType.CompareNoCase("Number"))
        {          
          if (strVal != "\"\"")
          {
            CNumeric num;
            char** ppChar = NULL;
            num.FromString(strVal, ppChar);          
            *pDefValue = num;
            if (pDefValue->IsEmpty())
            {
              CBLModule* pM = pComponentClass->GetModule();
              CValue* masval[1];
              CValue val;
              masval[0] = &val;
              res = pM->EvalExpr(strVal, *pDefValue, &masval[0]);            
            }          
          }
          else
          {
            pDefValue->Reset();
            if (pMainAddIn && pMainAddIn->m_EnabledCheckType)            
              m_VecNumOfParForPassCheckType.push_back(nRealParamNum);             
          }
        }
        else if (!strType.CompareNoCase("Дата") || !strType.CompareNoCase("Date"))
        {
          int year, month, day;
          year = 0; month = 0; day = 0;          
          if (strVal != "\"\"")
          {
            if (strVal.Find("'") == -1)
            {
              CBLModule* pM = pComponentClass->GetModule();
              CValue* masval[1];
              CValue val;
              masval[0] = &val;
              res = pM->EvalExpr(strVal, *pDefValue, &masval[0]);
            }
            else
            {
              strVal.Replace("'", NULL);          
              int nLen = strVal.GetLength();
              CString token;
              int what = 0;
              for (int i = 0; i < nLen; i++)
              {
                if (strVal[i] == '.')
                {
                  if (what == 0 && !token.IsEmpty())
                  {
                    // День
                    day = atoi(token);
                    what = 1;                
                  }
                  else if (what == 1 && !token.IsEmpty())
                  {
                    // Месяц
                    month = atoi(token);
                    what = 2;
                  }
                  token.Empty();
                  continue;
                }
                token += strVal[i];
              }
              if (what == 2 && !token.IsEmpty())
                year = atoi(token); // Год
              
              CDate date(year, month, day);
              *pDefValue = date;
            }
          }
          else
          {
            pDefValue->Reset();
            if (pMainAddIn && pMainAddIn->m_EnabledCheckType)            
              m_VecNumOfParForPassCheckType.push_back(nRealParamNum);             
          }
          
        }
        else if (!strType.CompareNoCase("Строка") || !strType.CompareNoCase("String"))
        {
		  // следующая строка закомментирована для решения бага 2128 http://cvs.alterplast.ru/bugs/show_bug.cgi?id=2128
          //if (strVal != "\"\"")
          {            
            if (strVal[0] == '"' && strVal[strVal.GetLength()-1] == '"')
            {
              strVal.Replace("\"", NULL);          
              *pDefValue = strVal;            
            }
            else
            {
              CBLModule* pM = pComponentClass->GetModule();
              CValue* masval[1];
              CValue val;
              masval[0] = &val;
              res = pM->EvalExpr(strVal, *pDefValue, &masval[0]);
            }
          }
        }
        else
        {
          if (strVal != "\"\"")
          {
            if (strVal[0] == '"' && strVal[strVal.GetLength()-1] == '"')
            {
              strVal.Replace("\"", NULL);          
              pDefValue->CreateObject(strVal); 
            }
            else
            {
              CBLModule* pM = pComponentClass->GetModule();
              CValue* masval[1];
              CValue val;
              masval[0] = &val;
              res = pM->EvalExpr(strVal, *pDefValue, &masval[0]);
            }
          }
          else
          {
            pDefValue->Reset();
            if (pMainAddIn && pMainAddIn->m_EnabledCheckType)            
              m_VecNumOfParForPassCheckType.push_back(nRealParamNum);             
          }
        }
        if (res == 0)
        {          
          CString strError;
          strError = "Не верно указано выражение значения по умолчанию(";
          strError += strVal;
          strError += ")\r\nдля параметра:";
          strError += NameBind->name;
          strError += " метода: ";
          CString NameOfClass = pComponentClass->GetTypeString();
          CString NameMeth = pComponentClass->GetMethodName(iMethodNum, 1);
          strError += NameOfClass + "::"+NameMeth;
          pBkEndUI->DoMessageLine(strError, mmBlackErr);	
        }
        return 1;
      }
    }
  }
  return 0;
}

bool CSetOfHierarchy::CheckTypeOfParam (CComponentClass* pComponentClass, int nNumMeth,
                                        CValue** ppParamOfMeth, CBLProcInfo* pProcInfo, 
                                        CValue* pRetValue)
{  
  bool result = true;
  int num = pComponentClass->GetNParams(nNumMeth);
  
  if (pRetValue != NULL || num > 0)
  {
    //CString NameOfClass = pComponentClass->GetTypeString();
    //CMapStringToOb* pMapFunc = NULL;    
    CMapStringToOb* pMapFunc = pComponentClass->defFnNames->pMapFunc;
    
    //if (m_Meta.m_TypeOfClassMeth.Lookup(NameOfClass, (CObject*&)pMapFunc))
    if (pMapFunc)
    {      
      ARR_TYPE_NAME* param = (*pComponentClass->defFnNames)[nNumMeth].pDefParam;
      if (param == NULL)
      {
        CString NameMeth = pComponentClass->GetMethodName(nNumMeth, 1);
        pMapFunc->Lookup(NameMeth, (CObject*&)param);
      }
      if (param != NULL)
      {
        int nSize = param->GetSize();
        bool IsHasRetVal = false;
        
        if (pComponentClass->HasRetVal(nNumMeth) == 1)
        {
          num++;
          IsHasRetVal = true;
        }
        
        nSize =  num < nSize ? num : nSize;
        int nNumParam = 0;
        CStringList ListOfErrors;        
        bool IsRetValue = false;        
        for (int i = 0; i < nSize && !IsRetValue; i++, nNumParam++)
        {    
          
          NameBindOfType* NameBind = param->operator[](i);
          CString pName;
          CBLContext* pCont = NULL;
          
          if (NameBind->type.CompareNoCase("...") == 0)
            break;          
          
          if (IsHasRetVal && i == 0 && pRetValue != NULL && !NameBind->name.CompareNoCase("#return"))
          {
            // Проверяем тип возврата
            pName = pRetValue->GetTypeString();
            pCont = pRetValue->GetContext();
            nNumParam--;
            IsRetValue = true;                        
          }
          else if (IsHasRetVal && pRetValue == NULL && i == 0 && !NameBind->name.CompareNoCase("#return"))
          {
            // Сначала надо проверить у функции переданные ей параметры, поэтому пропускаем
            // информацию о возвращаемом типе, т.к. возврат идет у нас первым в массиве
            nNumParam--;
            continue;
          }          
          else
          {
            // Проверим параметры метода
            if (num < nNumParam)
              break;
            
            if (find(m_VecNumOfParForPassCheckType.begin(), m_VecNumOfParForPassCheckType.end(), nNumParam) != m_VecNumOfParForPassCheckType.end())
              continue;
            
            pName = ppParamOfMeth[nNumParam]->GetTypeString();
            pCont = ppParamOfMeth[nNumParam]->GetContext();
          }
          
          if ((NameBind->type.CompareNoCase("Неопределенный") == 0)||(NameBind->type.CompareNoCase("Undefine") == 0)) // нечего проверять
            continue;
          
          if(pCont != NULL)
          {
            int meth = pCont->FindMethod("Kind");
            if (meth != -1 && stricmp("CComponentClass", pCont->GetRuntimeClass()->m_lpszClassName)) // Нашли номер метода
            {
              CValue value;
              CValue ValueParam;
              CValue *pMassVal[1] = {0};
              pMassVal[0] = &ValueParam;
              pCont->CallAsFunc(meth, value, &pMassVal[0]);
              const CString& Kind = value.GetString();
              if (!Kind.IsEmpty())
              {
                pName += ".";
                pName += Kind;
              }              
            }
          }
          else
          {
            
            if (pName.Find("Справочник") != -1 || pName.Find("Документ") != -1 || pName.Find("Перечисление") != -1 )
            {              
              long lll = 0;
              CValue *pCheckValue = IsRetValue ? pRetValue : ppParamOfMeth[nNumParam];
              pName = pMetaDataCont->GetFullName(pCheckValue->GetRealTypeID(), &lll, 1);                 
            }
            else if (pName.Find("Referens") != -1 || pName.Find("Document") != -1 || pName.Find("Enum") != -1)
            {
              long lll = 0;
              CValue *pCheckValue = IsRetValue ? pRetValue : ppParamOfMeth[nNumParam];
              pName = pMetaDataCont->GetFullName(pCheckValue->GetRealTypeID(), &lll, 0);
            }            
          }
          //if (pName.IsEmpty())
          //  continue;
          
          CString strNameEng;
          if (!pName.CompareNoCase("Строка"))
          {
            strNameEng = "String";
          }
          else if (!pName.CompareNoCase("Дата"))
          {
            strNameEng = "Date";
          }
          else if (!pName.CompareNoCase("Число"))
          {
            strNameEng = "Number";
          }          
          
          if (NameBind->type.CompareNoCase(pName) != 0 && NameBind->type.CompareNoCase(strNameEng) != 0)
          {	        
            // Далее необходимо проверить возможность того, что тип указан базового типа, а пере
            // дан производный. В этом случае несовпадение не является ошибкой
            if (NameBind->type.CompareNoCase("Документ") == 0 && pName.Find("Документ") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Document") == 0 && pName.Find("Document") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Справочник") == 0 && pName.Find("Справочник") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Referens") == 0 && pName.Find("Referens") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Регистр") == 0 && pName.Find("Регистр") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Registr") == 0 && pName.Find("Registr") >= 0)              
              continue;
            if (NameBind->type.CompareNoCase("ГрупповойКонтекст") == 0 && pName.Find("ГрупповойКонтекст") >= 0)              
              continue;
            if (NameBind->type.CompareNoCase("GroupContext") == 0 && pName.Find("GroupContext") >= 0)              
              continue;
            if (NameBind->type.CompareNoCase("Перечисление") == 0 && pName.Find("Перечисление") >= 0)
              continue;
            if (NameBind->type.CompareNoCase("Enum") == 0 && pName.Find("Enum") >= 0)
              continue;
            
            if (TheClassIsDerive(pName, NameBind->type))
              continue;
            CString NameOfClass = pComponentClass->GetTypeString();
            CString NameMeth = pComponentClass->GetMethodName(nNumMeth, 1);
            
            CString strErr = "В методе: ";
            strErr += NameMeth;
            
            strErr += " не совпадают типы в ";
            if (IsRetValue)
              strErr += "возвращаемом значении";
            else
            {
              strErr += "параметре: ";
              //strErr += NameBind->name;              
              CBLVarInfo VarInfo;
              pProcInfo->GetVarDescr(nNumParam, VarInfo);              
              strErr += VarInfo.GetName();
            }
            strErr += ". Заявленный тип: ";
            strErr += NameBind->type;
            strErr += "; полученный тип: ";
            strErr += pName;
            ListOfErrors.AddTail(strErr);
            result = false;            
          }
        }
        if (!ListOfErrors.IsEmpty()) // Есть ошибки
        {
          CBLModule *pCurModule = CBLModule::GetExecutedModule();
          if (pCurModule) {
          /*char buf[100];
          CString str(32,500);
          int nLine = pCurModule->GetExecutedLineNum();
          pCurModule->GetCurSourceLine(nLine, str);
          sprintf(buf, "Ошибка в текущем модуле! Строка: %d", nLine);
          pBkEndUI->DoMessageLine(buf, mmUnderlinedErr);
          str.TrimLeft();                  
            pBkEndUI->DoMessageLine(str, mmUnderlinedErr);*/
            CString Error;
            for(POSITION posList = ListOfErrors.GetHeadPosition(); posList != NULL; )
            {
              Error = ListOfErrors.GetNext( posList );
              pBkEndUI->DoMessageLine(Error, mmUnderlinedErr);	           
            }
            CString strError = "Ошибка: неверный тип метода в классе: ";            
            CString NameOfClass = pComponentClass->GetTypeString();
            strError += NameOfClass;
            strError += " файл: ";
            strError += m_Meta.m_ClassBindFile[NameOfClass];
            //pBkEndUI->DoMessageLine(strError, mmUnderlinedErr);
            CBLModule::RaiseExtRuntimeError(strError,0);
          }
          
          
        }        
      }      
    }
  } 
  m_VecNumOfParForPassCheckType.clear();
  return result;
}

bool CSetOfHierarchy::TheClassIsDerive(const CString& derive, const CString& base) const
{
  CStringList *pStrList = (CStringList*)(const_cast<CIStringMapToOb*>(&m_Meta.m_ClassesHierarchyMap)->operator[](derive));
  if (pStrList)
  {
    //CString str;
    for(POSITION posList = pStrList->GetHeadPosition(); posList != NULL; )
    {
      /*str = pStrList->GetNext( posList );
      /*if (!str.CompareNoCase(base))
        return true;
      else
        if (TheClassIsDerive(str, base))
          return true;*/
		if (IsObject(pStrList->GetNext( posList ), base))
			return true;
    }
    
  }
  return false;
}

bool CSetOfHierarchy::IsObject(const CString& sClassName, const CString& sTryName) const
{
	if (!sClassName.CompareNoCase(sTryName))
		return true;
	else
		return TheClassIsDerive(sClassName, sTryName);
}  

CString& CSetOfHierarchy::GetNameOfFile(const CString &strNameOfMod)
{
  return m_Meta.m_ClassBindFile[strNameOfMod];
}

void CSetOfHierarchy::RemoveNeedlessBlank(CString &str)
{
  CMetaDataOfClasses::RemoveNeedlessBlank(str);
}

bool CSetOfHierarchy::SaveValParam(CComponentClass *pComponentClass, int nNumMeth, CValue **ppParam, ARRAY_VAL *arrValOfMeth)
{  
  
  // m_strClassAndMethCurrent - устанавливается ранее GetNParams
  
  ARR_TYPE_NAME* param;
  if (m_Meta.m_ValParamInMeth.Lookup(m_strClassAndMethCurrent, (CObject*&)param))
  {
    int num = pComponentClass->GetNParams(nNumMeth);    
    int nSize = param->GetSize();
    int nPlus = 0;
    
    if (pComponentClass->HasRetVal(nNumMeth) == 1)
    {
      nPlus = 1;
      nSize--;
    }
    
    nSize =  min(num,nSize);
    int nNumParam = 0;
    
    for (int i = 0; i < nSize; i++, nNumParam++)
    {          
      NameBindOfType* NameBind = param->operator[](i+nPlus);
      if (NameBind->bIsVal)
      {     
        arrValOfMeth->Add(new CValue(*(ppParam[i])));
      }
      else
        arrValOfMeth->Add(NULL);      
    }
    return true;
  }
  else
    return false;  
}

void CSetOfHierarchy::RestoreValParam(CComponentClass *pComponentClass, int nNumMeth, CValue **ppParam, ARRAY_VAL *arrValOfMeth)
{
  
  int nParams = pComponentClass->GetNParams(nNumMeth);
  int nSize   = arrValOfMeth->GetSize();
  int nS = min(nParams, nSize);
  
  for(int i = 0; i < nS; i++)
  {
    CValue* pVal = NULL;
    pVal = arrValOfMeth->GetAt(i);
    if (pVal)
    {      
      *(ppParam[i]) = *pVal;
      delete pVal;
    }
  }  
}

size_t Hash(const char* key)
{
  size_t res = 0;
  while(*key) res = (res<<1)^*key++;
  
  return res;
}

int CSetOfHierarchy::GetNParams(const CComponentClass *pComp, int nNumMeth, int nNParams)
{  
  InfoUnlimitsParams *pInfo = NULL;
  int nRes = m_CountParametersInCallMethod < 0 ? 0 : m_CountParametersInCallMethod;

//+ kms: deprecated code cut нах
/*
  if (m_CountParametersInCallMethod >= 0 && m_CountParametersInCallMethod < 30)
  {
    nRes = m_CountParametersInCallMethod;      
  }
  else    
  {
    if (pComp->m_BindInstaceValueList.Lookup(m_strClassAndMethCurrent, (void*&)pInfo))
      return pInfo->nNumAllParams;
    
    CString str("", 200);
    CBLModule *pCurMod = CBLModule::GetExecutedModule();
    CString strMethodName;
    int nPosColon = m_strClassAndMethCurrent.Find(':');
    if (nPosColon != -1)
    {
      int nLen = m_strClassAndMethCurrent.GetLength();
      strMethodName = m_strClassAndMethCurrent.Right(nLen - nPosColon - 1);
    }
    
    
    int nCountPairBrackets  = 0;
    
    int nNSourceLines =  pCurMod->GetNSourceLines();
    bool bNotCommas = true;
    bool isSearchOpenBracket = true;
    bool bFindMethName = false;
    
    CString strLexem;
    
    for (int i = pCurMod->GetExecutedLineNum(); i < nNSourceLines; i++)
    {
      pCurMod->GetCurSourceLine(i, str);    		  
      str.TrimRight(); str.TrimLeft();
      str.Replace(" ", "");
      
      int pos = 0;      
      if (!bFindMethName)
      {
        int nPosMethodName = str.Find(strMethodName);
        if (nPosMethodName != -1)
        {      
          bFindMethName = true;
          pos = nPosMethodName + strMethodName.GetLength() - 1;                   
        }
        else
          continue;
      }           
      //pBkEndUI->DoMessageLine(str, mmBlackErr);	
      
      
      
      int nLenStr = str.GetLength();     
      for (; pos < nLenStr; pos++)
      {        
        if (str[pos] == '\"' && bNotCommas)        
          bNotCommas = false; // Символы в кавычках, необходим их пропустить
        else if (str[pos] == '\"' && !bNotCommas)
          bNotCommas = true;
        
        if (str[pos] == '/' && str[pos+1] == '/')
          break; // Дальше до конца строки идет комментарий, можно пропустить
        
        if (bNotCommas)
        {
          if (str[pos] == '(')
          {
            nCountPairBrackets++;
            isSearchOpenBracket = false;
          }
          else if (str[pos] == ')')
          {
            nCountPairBrackets--;
            if (nCountPairBrackets == 0)
              break;
          }
          else if (str[pos] == ',' && nCountPairBrackets < 2 && nCountPairBrackets > 0 && !strLexem.IsEmpty())
          {            
            strLexem.Empty();
            nRes++;
          }
          else if (str[pos] != '\r' && str[pos] != '\n' && nCountPairBrackets != 0)
            strLexem += str[pos];
          
        }
      }
      if (nCountPairBrackets == 0 && !isSearchOpenBracket)
        break;
    }
    
    if (!strLexem.IsEmpty())      
      nRes++;    
  }
*/

  if (nRes < nNParams)
    return nNParams;    
  
  if (pComp->m_BindInstaceValueList.Lookup(m_strClassAndMethCurrent, (void*&)pInfo))
  {
    static const int nNMeth = pInfo->cont_ValueList->FindMethod("RemoveAll");
    CValue *Params[1] = {0};        
    CValue par;      
    Params[0] = &par;      
    pInfo->cont_ValueList->CallAsProc(nNMeth, Params);      
  }
  else
  {
    pInfo = new InfoUnlimitsParams;
    pInfo->cont_ValueList     = CBLContext::CreateInstance("ValueList");
    pComp->m_BindInstaceValueList[m_strClassAndMethCurrent] = pInfo;
  }    
  pInfo->nNumAllParams      = nRes;
  pInfo->nNumExplicitParams = nNParams;        
  
  return nRes;    
}

bool CSetOfHierarchy::GetImplicitParams(CComponentClass *pComp, CValue **ppPar, int nNumMeth)
{
  
  //pBkEndUI->DoMessageLine("CSetOfHierarchy::GetImplicitParams", mmBlackErr);	
  InfoUnlimitsParams *pInfo = NULL;  
  if (pComp->m_BindInstaceValueList.Lookup(m_strClassAndMethCurrent, (void*&)pInfo))
  {
    m_strClassAndMethImplicit = m_strClassAndMethCurrent;
    pInfo->vecPointOfPars.clear();

    for (int i = 0; i < pInfo->nNumAllParams - pInfo->nNumExplicitParams; i++)
    {
      pInfo->vecPointOfPars.push_back(ppPar[i+pInfo->nNumExplicitParams]);      
    }
    /*CString strN;
    strN.Format("nRes = %d",nRes);
    pBkEndUI->DoMessageLine(strN, mmBlackErr);	*/
    
    CStringArray ArrString;
    for (int ind = 0; ind < pInfo->nNumExplicitParams; ind++)
    {
      CString strType = ppPar[ind]->GetTypeString();
      if (strType.CompareNoCase("string") != 0)
      {      
        CString strSourse = ppPar[ind]->GetString();
        if (!strSourse.IsEmpty())
        {
          if (strSourse[0] == '{' && strSourse[strSourse.GetLength()-1] == '}')
          {
            strSourse.Replace("{", "");
            strSourse.Replace("}", "");
            strSourse.Replace(" ", "");
            strSourse.Replace("\r", "");
            strSourse.Replace("\n", "");
            CString token;
            for (int n = 0; n < strSourse.GetLength(); n++)
            {
              if (strSourse[n] == ',' && !token.IsEmpty())
              {                 
                ArrString.Add(token);
                token.Empty();                
              }
              else      
                token += strSourse[n];                
            }
            if (!token.IsEmpty())
              ArrString.Add(token);
            break;
          }
        }
      }
    }
    CBLContext *pCont = pInfo->cont_ValueList;
    ASSERT(pCont != NULL);
    
    const int nNMeth = pCont->FindMethod("AddValue");
    if (nNMeth != -1)
    {
      int nSizeArr = ArrString.GetSize();
      for (int i = pInfo->nNumExplicitParams; i < pInfo->nNumAllParams; i++)
      {                       
        CValue *Params[2] = {0};        
        CValue par2;
        int nInd = i - pInfo->nNumExplicitParams;
        if (nInd < nSizeArr)
          par2 = ArrString[nInd];
        if ((ppPar[i]->IsEmpty())&&(ppPar[i]->GetTypeCode() == UNDEFINE_TYPE_1C))
        {          
          CValue emptyVal("");
          ppPar[i]->MakeExactValueFrom(&emptyVal);          
        }
        Params[0] = ppPar[i];
        Params[1] = &par2;
        pCont->CallAsProc(nNMeth, Params);          
      }
      return true;
    }
  }  
  return false;
}

CBLContext* CSetOfHierarchy::GetImplicitParamsList(CComponentClass *pComp, const char* lpcsNameMeth)
{
  if (!lpcsNameMeth)
    return 0;
  
  CComponentClass* pCompReal = GetComponentClassCurExModule();
  if (pCompReal == NULL)
    CBLModule::RaiseExtRuntimeError("Нельзя вызывать функцию GetParamsList в модуле не принадлежащему текущему классу!",0);
  
  if (pCompReal != pComp)
    pComp = pCompReal;
  
  //pBkEndUI->DoMessageLine(m_strClassAndMethImplicit, mmBlackErr);	
  CString str = pComp->GetTypeString();
  str += ":";
  str += lpcsNameMeth;
  
  InfoUnlimitsParams *pInfo = NULL;  
  if (pComp->m_BindInstaceValueList.Lookup(str, (void*&)pInfo))
    return pInfo->cont_ValueList;
  else
    return NULL;  
}

int CSetOfHierarchy::SetImplicitParamOfInd(CComponentClass *pComp, const char *lpcsNameMeth, int nIndex, CValue* pVal)
{
  if (!lpcsNameMeth)
    return 0;
  
  CComponentClass* pCompReal = GetComponentClassCurExModule();
  if (pCompReal == NULL)
    CBLModule::RaiseExtRuntimeError("Нельзя вызывать функцию GetParamsList в модуле не принадлежащему текущему классу!",0);
  
  if (pCompReal != pComp)
    pComp = pCompReal;
  
  CString str = pComp->GetTypeString();
  str += ":";
  str += lpcsNameMeth;

  CSetOfHierarchy::InfoUnlimitsParams *pInfo = NULL;  
  if (pComp->m_BindInstaceValueList.Lookup(str, (void*&)pInfo))
  {
    if (nIndex >  (pInfo->nNumAllParams - pInfo->nNumExplicitParams) || (nIndex < 1))
      CBLModule::RaiseExtRuntimeError("Указан неверный индекс в параметре 2 метода УстановитьПараметрПоИндексу!",0);        
    *pInfo->vecPointOfPars[nIndex-1] = *pVal;
    return 1;
  }
  else
    return 0;           
}

void CSetOfHierarchy::ClearImplicitParams(CComponentClass *pComp)
{
/*InfoUnlimitsParams *pInfo = NULL;
size_t res = Hash(m_strClassAndMethImplicit);
LONG adress = reinterpret_cast<ULONG>(pComp);
adress ^= res;
if (m_BindInstaceValueList.Lookup(reinterpret_cast<void*>(adress), (void*&)pInfo))
{
pInfo->cont_ValueList->DecrRef();
delete pInfo;    
m_BindInstaceValueList.RemoveKey(reinterpret_cast<void*>(adress));    
} */  
}


CComponentClass* CSetOfHierarchy::GetComponentClassCurExModule(CBLModule* pModWrapper)
{
  CBLModule* pMod = pModWrapper == NULL ? CBLModule::GetExecutedModule() : pModWrapper;  
  return static_cast<CComponentClass*>(m_MapOfModulesAndComp[pMod]);
}


void CSetOfHierarchy::PrintError(const char *cstrError, const char *cstrFileName, int nNumLine)
{
  CString strTextMess;
  strTextMess.Format("%s (%d):%s",cstrFileName,nNumLine,cstrError);
  pBkEndUI->DoMessageLine(strTextMess, mmBlackErr);	
}

CString CSetOfHierarchy::GetPathFromAlias(CString strAls)
{
  return m_Meta.m_AliasOfPaths[strAls];
}

void CSetOfHierarchy::ReadDefinesAndCompile(CString &str, CString &strNameFile)
{
  try 
  {
    CRangesOfDescr Ranges;
    CPreprocessor::Preprocess(false, str, m_SymbolOfPreprocessor, m_LoadedIncludeFiles, strNameFile, &Ranges);
    m_Meta.ParsingString(str, Ranges);        
  }
  catch (CPreprocessor::ExceptionPreprocessor &ex)
  {
    CString strErr;        
    strErr.Format("В модуле файла: %s", strNameFile);
    pBkEndUI->DoMessageLine(strErr, mmBlackErr);	
    strErr = ex.GetErrorString();        
    pBkEndUI->DoMessageLine(strErr, mmBlackErr);	
    strErr.Empty();
    if (!ex.GetCodeString().IsEmpty())
    {
      strErr.Format("(%d) %s",ex.GetNumString(),ex.GetCodeString());
      pBkEndUI->DoMessageLine(strErr, mmBlackErr);
    }
  }
}

void CSetOfHierarchy::ProcessDefines()
{
  if (pathBase1C.IsEmpty())
  {
    pBkEndUI->DoMessageLine("Не удалось получить функцией IBDir() каталог ИБ!", mmBlackErr);	
  }
  else
  {
    TRY 
    {     
      CString strDefFileName = pathBase1C;      
      strDefFileName += pcstrNameOfDef;
      
	  // TODO Добавить поиск от текущего каталога http://cvs.alterplast.ru/bugs/show_bug.cgi?id=1605
      CFile file(strDefFileName, CFile::modeRead); // fez TODO Добавить поиск от текущего каталога http://itland.ru/forum/index.php?showtopic=11696
      CString str;
/*		// artbear -- этот функционал закрыт
	  // artbear
	  bool bHaveDeflcsInMD = false;
	  {
		CString nameRep = "defcls"; // имя обработки в конфе
		CMetaDataCont *pMD = GetMetaData();

		CMetaDataObj* pObj=(CMetaDataObj*)pMD->GetCalcVarDef(nameRep);
		if (pObj) // есть такая обработка
			bHaveDeflcsInMD = true;
	  }
	  // end
*/
      DWORD dwLength = file.GetLength();
      LPTSTR buff = str.GetBuffer(dwLength);
      file.Read(buff, dwLength);
      str.ReleaseBuffer(dwLength);
      file.Close();

/*		// artbear -- этот функционал закрыт
	  if (bHaveDeflcsInMD)
	  {
		CString strTemp = str;
		strTemp.MakeLower();
		if (strTemp.Find("defcls@md") == -1)
			str = str + "\r\n//#include defcls@md\r\n";
	  }
*/

      ReadDefinesAndCompile(str, strDefFileName);
    }
    CATCH(CFileException, pEx)
    {
      CModuleString str;
      CString strDefFileName = "defcls@MD";
      if (str.LoadModule(strDefFileName))
      {
        ReadDefinesAndCompile(str, strDefFileName);
        
      }
      else // fez TODO Добавить какую-нибудь диагностику, но не забыть про тех, кто классами вообще не пользуется (нет самого первого defcls.prm)
      {
        //pBkEndUI->DoMessageLine("Не удалось открыть файл определения классов", mmBlackErr);	
        //pBkEndUI->DoMessageLine(pathBase1C+pcstrNameOfDef, mmBlackErr);	
      }
      
    }
    AND_CATCH(CMemoryException, pEx)
    {
      pBkEndUI->DoMessageLine("Внимание не хватило памяти для выделния буфера в функции CSetOfHierarchy::CSetOfHierarchy()", mmExclamation);	
    }
    END_CATCH
  }
}



bool CSetOfHierarchy::ThisIsUnLimMethod(CString strName)
{
  ARR_TYPE_NAME* param;  
  if (m_Meta.m_UnlimitsParams.Lookup(strName, (CObject*&)param))
    return true;
  else
    return false;
}

bool CSetOfHierarchy::isMethHaveParVal(CString strName)
{
  ARR_TYPE_NAME* param;  
  if (m_Meta.m_ValParamInMeth.Lookup(strName, (CObject*&)param))
    return true;
  else
    return false;
}

void CSetOfHierarchy::InitParamDefsClass(CParamDefs *par, CString strClass)
{  
  if (!m_Meta.m_TypeOfClassMeth.Lookup(strClass, (CObject*&)par->pMapFunc))
    par->pMapFunc = NULL;
}

bool CSetOfHierarchy::IsClassExist(const char *pcstrName)
{
  CString strResult;
  return m_Meta.m_ClassBindFile.Lookup(pcstrName, strResult) != 0;
}

int CSetOfHierarchy::GetCountClasses() const
{
  return m_Meta.m_ClassBindFile.GetCount();
}

int CSetOfHierarchy::GetCountMethods() const
{
  CString key;
  POSITION pos;
  int res = 0;
  for (pos = m_Meta.m_TypeOfClassMeth.GetStartPosition(); pos != NULL;)
  {
    CMapStringToOb* pMapFunc = NULL;
    CString key;
    m_Meta.m_TypeOfClassMeth.GetNextAssoc( pos, key, (CObject*&)pMapFunc);
    res += pMapFunc->GetCount();
    
  }  
  return res;
}

CString CSetOfHierarchy::GetLoadIncludeFiles(const char* sep) const
{
  CString key;
  POSITION pos;
  CString res;  
  for (pos = m_LoadedIncludeFiles.GetStartPosition(); pos != NULL;)
  {
    CString val;    
    m_LoadedIncludeFiles.GetNextAssoc( pos, key, val);    
    res += key;
    res += sep;        
  }  
  return res;
}

CString CSetOfHierarchy::GetDefSymbolOfPreproc(const char* sep) const
{
  CString key;
  POSITION pos;
  CString res;  
  for (pos = m_SymbolOfPreprocessor.GetStartPosition(); pos != NULL;)
  {
    void *ptr;    
    m_SymbolOfPreprocessor.GetNextAssoc( pos, key, (void*&)ptr);
    res += key;
    res += sep;
  }  
  return res;
  
}

CString CSetOfHierarchy::GetAllClassesNames(const char* sep) const
{
  CString key;
  POSITION pos;
  CString res;  
  for (pos = m_Meta.m_ClassBindFile.GetStartPosition(); pos != NULL;)
  {
    CString val;    
    m_Meta.m_ClassBindFile.GetNextAssoc( pos, key, val);    
    res += key;
    res += " = ";
    res += val;
    res += sep;        
  }  
  return res;
}

CString CSetOfHierarchy::GetAllAliasAndPath(const char* sep) const
{
  CString key;
  POSITION pos;
  CString res;  
  for (pos = m_Meta.m_AliasOfPaths.GetStartPosition(); pos != NULL;)
  {
    CString val;    
    m_Meta.m_AliasOfPaths.GetNextAssoc( pos, key, val);    
    res += key;
    res += " = ";
    res += val;
    res += sep;
  }  
  return res;
}

void CSetOfHierarchy::LoadListNameOfIncludeFiles(CStringArray &arr)
{
  CString key;
  POSITION pos;  
  for (pos = m_LoadedIncludeFiles.GetStartPosition(); pos != NULL;)
  {
    CString val;    
    m_LoadedIncludeFiles.GetNextAssoc( pos, key, val);
    arr.Add(key);
  }    
}
CString CSetOfHierarchy::GetBaseClasses(const char* strNameCl, const char* sep) const
{
  CString str;
  CStringList *pList = NULL;
  m_Meta.m_ClassesHierarchyMap.Lookup(strNameCl, (CObject*&)pList);
  if (pList)
  {
    for(POSITION posList = pList->GetHeadPosition(); posList != NULL; )
    {
      str += pList->GetNext( posList );
      str += sep;
    }    
  }
  return str;
}

CString CSetOfHierarchy::GetNamesMethOfClass(const char *pNameClass, const char *sep) const
{
  CString res;
  CMapStringToOb* pMapFunc = NULL;
  if (m_Meta.m_TypeOfClassMeth.Lookup(pNameClass, (CObject*&)pMapFunc))
    if (pMapFunc)
    {
      for (POSITION pos = pMapFunc->GetStartPosition(); pos != NULL;)
      {
        ARR_TYPE_NAME* param = NULL;
        CString key;
        pMapFunc->GetNextAssoc( pos, key, (CObject*&)param);
        res += key;
        res += sep;
      }
    }
    return res;
}

CSetOfHierarchy::ARR_TYPE_NAME* CSetOfHierarchy::GetInfoParamMeth(const char *pNameClass, const char *pNameMeth) const
{  
  CMapStringToOb* pMapFunc = NULL;
  if (m_Meta.m_TypeOfClassMeth.Lookup(pNameClass, (CObject*&)pMapFunc))
    if (pMapFunc)
    {
      ARR_TYPE_NAME* arr = NULL;
      if (pMapFunc->Lookup(pNameMeth, (CObject*&)arr))
        return arr;      
    }
    return NULL;
}

bool CSetOfHierarchy::IsMethExist(const char *pNameClass, const char *pNameMeth) const
{
  CMapStringToOb* pMapFunc = NULL;
  if(m_Meta.m_TypeOfClassMeth.Lookup(pNameClass, (CObject*&)pMapFunc))
  {
    ARR_TYPE_NAME* arr = NULL;
    if (pMapFunc->Lookup(pNameMeth, (CObject*&)arr))
      return true;
  }
  return false;
}

// Получить полный путь файла или из каталога ИБ 
// или, если файл не найден в каталоге ИБ, ищем относительно переданного каталога
// если и здесь файл не найден, возвращается путь относительно каталога ИБ
//
void CSetOfHierarchy::MakeFullFileName(CString* name, LPCSTR sSecondPath)
{
//Msg("%s %s", "name", (LPCTSTR) *name); 
  name->Replace("\"", ""); // artbear уберу кавычки

  if (name->Find(":") == -1)
  {
    if (name->Find("@MD") == -1)
    if (name->Find("@md") == -1)
    {
// artbear
//      if (name->GetLength() > 1 && (name->GetAt(0) != '\\' || name->GetAt(0) != '.') && name->GetAt(1) != '\\')
//        name->Insert(0, pGlobalHierarchy->pathBase1C);
	
      if (('.' == name->GetAt(0) && '\\' == name->GetAt(1)) || (name->GetLength() > 1 && (name->GetAt(0) != '\\') && name->GetAt(1) != '\\'))
	{
  		CString sPath =  *name;
		sPath.Insert(0, pGlobalHierarchy->pathBase1C);
		sPath = ::AbsoluteFilePath(sPath);
//Msg("%s %s", "sPath", (LPCTSTR) sPath); 

		bool bFileExists = ::FileExists((LPCTSTR)sPath);
		if (bFileExists || !sSecondPath)
			*name = sPath; // TODO удалить когда удастся найти след. строку
		else
		{
			//Msg("Неудача при поиске относительно каталога ИБ %s", (LPCTSTR)*name);  			
			CString sPath =  *name;
			sPath.Insert(0, sSecondPath);
			sPath = ::AbsoluteFilePath(sPath);
//Msg("%s %s", "sPath", (LPCTSTR) sPath); 

			bool bFileExists = ::FileExists((LPCTSTR)sPath);
			if (bFileExists)
				*name = sPath; // TODO удалить когда удастся найти след. строку
		}
	}
// end
    }
  }
}

// чтобы название класса писалось не как пользователь напишет, а бралось из файла описания artbear
// используется в CComponentClass::InitObject - т.е. когда в 1С пишем СоздатьОбъект(ТипОбъекта)
//
CString CSetOfHierarchy::GetClassNameFromDefinition(const CString& ClassName) const
{
	LPSTR strResult;
	m_Meta.m_ClassBindFile.LookupKey(ClassName, strResult);
//	Msg("%s %s - <%s>", "CSetOfHierarchy::GetClassNameFormDefinition", "LookupKey", strResult);
  return strResult;
}