diff --git a/.gitignore b/.gitignore index 9cbf6f4..55e020e 100644 --- a/.gitignore +++ b/.gitignore @@ -86,4 +86,7 @@ Compile *.res *.rc docs/ -*.ps1 \ No newline at end of file +*.ps1 +Analize +.clinerules +.continue \ No newline at end of file diff --git a/src/APIcfBase.cpp b/src/APIcfBase.cpp index e04be86..567ecca 100644 --- a/src/APIcfBase.cpp +++ b/src/APIcfBase.cpp @@ -1062,7 +1062,7 @@ __fastcall v8catalog::v8catalog(String name) } else { - cfu = new TFileStream(name, fmOpenReadWrite); + cfu = new TFileStream(name, fmOpenReadWrite | fmShareDenyNone); ZInflateStream(cfu, data); } } @@ -1077,7 +1077,7 @@ __fastcall v8catalog::v8catalog(String name) data->WriteBuffer(_empty_catalog_template, 16); delete data; } - data = new TFileStream(name, fmOpenReadWrite); + data = new TFileStream(name, fmOpenReadWrite | fmShareDenyNone); } file = NULL; @@ -1117,7 +1117,7 @@ __fastcall v8catalog::v8catalog(String name, bool _zipped) delete data; } - data = new TFileStream(name, fmOpenReadWrite); + data = new TFileStream(name, fmOpenReadWrite | fmShareDenyNone); file = NULL; @@ -1996,9 +1996,9 @@ void __fastcall v8catalog::HalfOpen(const String& name) Lock->Acquire(); if(is_cfu) - cfu = new TFileStream(name, fmOpenReadWrite); + cfu = new TFileStream(name, fmOpenReadWrite | fmShareDenyNone); else - data = new TFileStream(name, fmOpenReadWrite); + data = new TFileStream(name, fmOpenReadWrite | fmShareDenyNone); Lock->Release(); } diff --git a/src/APIcfBase.h b/src/APIcfBase.h index a8306cb..2a1208f 100644 --- a/src/APIcfBase.h +++ b/src/APIcfBase.h @@ -37,14 +37,7 @@ typedef System::DynamicArray ByteArr; //=========================================================================== -const size_t V8_DEFAULT_PAGE_SIZE = 512; -const uint32_t V8_FF_SIGNATURE = 0x7fffffff; - -// Для конфигурации старше 8.3.16, без режима совместимости -//const uint64_t V8_FF64_SIGNATURE = 0xffffffffffffffff; -const __int64 V8_FF64_SIGNATURE = 0xffffffffffffffff; -//const size_t V8_OFFSET_8316 = 0x1359; // волшебное смещение, откуда такая цифра неизвестно... -const int V8_OFFSET_8316 = 0x1359; // волшебное смещение, откуда такая цифра неизвестно... +#include "v8_constants.h" //=========================================================================== diff --git a/src/Bots.cpp b/src/Bots.cpp index 9e10552..899e795 100644 --- a/src/Bots.cpp +++ b/src/Bots.cpp @@ -6,6 +6,25 @@ //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} __fastcall TBots::TBots() : BaseMetadataObject() { @@ -16,12 +35,14 @@ __fastcall TBots::TBots() : BaseMetadataObject() __fastcall TBots::TBots(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) { botName = ""; + initializeFromTree(); root_data.reset(); } __fastcall TBots::TBots(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) { botName = _name; + initializeFromTree(); root_data.reset(); } @@ -37,6 +58,7 @@ String __fastcall TBots::GetBotName() void __fastcall TBots::SetBotName(String _name) { botName = _name; + name = _name; } std::vector>& TBots::getAttributes() @@ -66,6 +88,14 @@ std::vector>& TBots::getForms() void __fastcall TBots::initializeFromTree() { - // Инициализация бота из дерева метаданных - // Имя бота уже установлено в конструкторе + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 1, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + botName = name; + return; + } + + if (botName.IsEmpty()) + botName = name; } diff --git a/src/BusinessProceses.cpp b/src/BusinessProceses.cpp index 180da06..218e8c4 100644 --- a/src/BusinessProceses.cpp +++ b/src/BusinessProceses.cpp @@ -10,15 +10,15 @@ static MetadataTreePaths GetBusinessProcessesPaths() { MetadataTreePaths paths; - paths.attIdx = 5; + paths.attIdx = 6; paths.attItemPath = {0, 1, 1, 1, 2}; - paths.tabIdx = 3; + paths.tabIdx = 7; paths.tabItemPath = {0, 1, 5, 1, 2}; - paths.formsIdx = 7; - paths.cmdIdx = 6; + paths.formsIdx = 4; + paths.cmdIdx = 5; paths.cmdItemPath = {0, 1, 3, 2, 9, 2}; - paths.moxIdx = 4; - paths.getFormNameFunc = GetNameFormCatalogs; + paths.moxIdx = 3; + paths.getFormNameFunc = GetNameFormDescriptor; paths.hasTabulars = true; return paths; } diff --git a/src/ChartOfAccounts.cpp b/src/ChartOfAccounts.cpp index 764f9ab..2a8e35d 100644 --- a/src/ChartOfAccounts.cpp +++ b/src/ChartOfAccounts.cpp @@ -91,10 +91,27 @@ void __fastcall TChartOfAccounts::initializeFromTree() int DeltaTab = CountAttTab - 2; for (int i = 0; i < CountAttTab; i++) { - tree* node_att_tab = root_data.get(); - node_att_tab = &(*node_att_tab)[0][5][i+CountAttTab-DeltaTab][0][1][5][1][2]; + tree* tabularNode = &(*root_data.get())[0][5][i+CountAttTab-DeltaTab]; + tree* node_att_tab = &(*tabularNode)[0][1][5][1][2]; String NameAttTab = node_att_tab->get_value(); - tabulars.push_back(std::make_unique(NameAttTab, "")); + String GuidAttTab; + try { + GuidAttTab = (*tabularNode)[0][1][5][1][1].get_value(); + } catch (...) { + GuidAttTab = L""; + } + + auto tabular = std::make_unique(NameAttTab, GuidAttTab); + std::unique_ptr tabularRootData; + if (parent && !GuidAttTab.IsEmpty()) + { + v8file* tabularFile = parent->GetFile(GuidAttTab); + if (tabularFile) + tabularRootData.reset(get_treeFromV8file(tabularFile)); + } + + tabular->initializeFromTree(tabularRootData ? tabularRootData.get() : tabularNode); + tabulars.push_back(std::move(tabular)); } // Получаем имена форм diff --git a/src/ChartOfCharacteristicTypes.cpp b/src/ChartOfCharacteristicTypes.cpp index 1a0685e..11517b3 100644 --- a/src/ChartOfCharacteristicTypes.cpp +++ b/src/ChartOfCharacteristicTypes.cpp @@ -60,10 +60,27 @@ void __fastcall TChartOfCharacteristicTypes::initializeFromTree() int DeltaTab = CountAttTab - 2; for (int i = 0; i < CountAttTab; i++) { - tree* node_att_tab = root_data.get(); - node_att_tab = &(*node_att_tab)[0][5][i+CountAttTab-DeltaTab][0][1][5][1][2]; + tree* tabularNode = &(*root_data.get())[0][5][i+CountAttTab-DeltaTab]; + tree* node_att_tab = &(*tabularNode)[0][1][5][1][2]; String NameAttTab = node_att_tab->get_value(); - tabulars.push_back(std::make_unique(NameAttTab, "")); + String GuidAttTab; + try { + GuidAttTab = (*tabularNode)[0][1][5][1][1].get_value(); + } catch (...) { + GuidAttTab = L""; + } + + auto tabular = std::make_unique(NameAttTab, GuidAttTab); + std::unique_ptr tabularRootData; + if (parent && !GuidAttTab.IsEmpty()) + { + v8file* tabularFile = parent->GetFile(GuidAttTab); + if (tabularFile) + tabularRootData.reset(get_treeFromV8file(tabularFile)); + } + + tabular->initializeFromTree(tabularRootData ? tabularRootData.get() : tabularNode); + tabulars.push_back(std::move(tabular)); } // Получаем имена форм diff --git a/src/Class_1CD.cpp b/src/Class_1CD.cpp index 0782e83..46318bb 100644 --- a/src/Class_1CD.cpp +++ b/src/Class_1CD.cpp @@ -7819,7 +7819,7 @@ __fastcall T_1CD::T_1CD(String _filename, MessageRegistrator* _err, bool _monopo try { - if(_monopoly) fs = new TFileStream(filename, fmOpenReadWrite | fmShareDenyWrite); + if(_monopoly) fs = new TFileStream(filename, fmOpenReadWrite | fmShareDenyNone); else fs = new TFileStream(filename, fmOpenRead | fmShareDenyNone); //fs = new TFileStream(filename, fmOpenRead); } diff --git a/src/Common.cpp b/src/Common.cpp index e58d287..8be2fa0 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -524,6 +524,11 @@ String __fastcall GetNameFormPVH(v8catalog *cf, String &guid_md) // return Result; } +String __fastcall GetNameFormDescriptor(v8catalog *cf, String &guid_md) +{ + std::vector path = {0, 1, 1, 2}; + return GetNameFromTreePath(cf, guid_md, path); +} String __fastcall GetNameMoxCatalogs(v8catalog *cf, String &guid_md) { diff --git a/src/Common.h b/src/Common.h index f5ff91f..0ce9595 100644 --- a/src/Common.h +++ b/src/Common.h @@ -33,6 +33,7 @@ String __fastcall GetNameFromTreePath(v8catalog *cf, String &guid_md, const std: String __fastcall GetNameFormCatalogs(v8catalog *cf, String &guid_md); String __fastcall GetNameFormReports(v8catalog *cf, String &guid_md); String __fastcall GetNameFormPVH(v8catalog *cf, String &guid_md); +String __fastcall GetNameFormDescriptor(v8catalog *cf, String &guid_md); String __fastcall GetNameMoxCatalogs(v8catalog *cf, String &guid_md); //--------------------------------------------------------------------------- diff --git a/src/CommonForms.cpp b/src/CommonForms.cpp index f5b23cf..6c0b824 100644 --- a/src/CommonForms.cpp +++ b/src/CommonForms.cpp @@ -6,23 +6,58 @@ //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + bool __fastcall LooksLike1CModuleText(const String& value) + { + return value.Pos(L"Процедура ") > 0 + || value.Pos(L"Функция ") > 0 + || value.Pos(L"КонецПроцедуры") > 0 + || value.Pos(L"КонецФункции") > 0 + || value.Pos(L"\n") > 0; + } + + String __fastcall FindEmbeddedModuleText(tree* node) + { + if (!node) + return L""; + + if (node->get_type() == nd_string && LooksLike1CModuleText(node->get_value())) + return node->get_value(); + + for (int i = 0; i < node->get_num_subnode(); i++) + { + String found = FindEmbeddedModuleText(node->get_subnode(i)); + if (!found.IsEmpty()) + return found; + } + + return L""; + } +} __fastcall TCommonForms::TCommonForms() : BaseMetadataObject() { name = ""; root_data.reset(); + text = L""; + textLoaded = false; } __fastcall TCommonForms::TCommonForms(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) { name = ""; root_data.reset(); + text = L""; + textLoaded = false; } __fastcall TCommonForms::TCommonForms(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) { name = _name; root_data.reset(); + text = L""; + textLoaded = false; } __fastcall TCommonForms::~TCommonForms() @@ -39,6 +74,75 @@ void __fastcall TCommonForms::SetFormName(String _name) name = _name; } +void __fastcall TCommonForms::LoadTextIfNeeded() +{ + if (textLoaded) + return; + + text = L""; + + if ((parent) && (!guid.IsEmpty())) + { + v8file* data_form = parent->GetFile(guid + ".0"); + if (data_form) + { + v8catalog* data_form_cat = new v8catalog(data_form); + if (data_form_cat) + { + auto module_file = data_form_cat->GetFile("module"); + if (module_file) + { + data_form_cat->ClearIs8316(); + TBytes bytes; + TBytesStream* sb = new TBytesStream(bytes); + module_file->SaveToStream(sb); + + TEncoding* enc = nullptr; + TBytes sb_bytes = sb->Bytes; + if (!sb_bytes.empty()) + { + int off = TEncoding::GetBufferEncoding(sb_bytes, enc); + if (off > 0) + { + bytes = TEncoding::Convert(enc, TEncoding::Unicode, sb_bytes, off, sb->Size - off); + if (!bytes.empty()) + text = String((wchar_t*)&bytes[0], bytes.Length / 2); + } + else + { + text = String((char*)sb->Memory, sb->Size); + } + } + + delete sb; + } + + delete data_form_cat; + } + } + + if (text.IsEmpty()) + { + std::unique_ptr form_tree(get_treeFromV8file(data_form)); + text = FindEmbeddedModuleText(form_tree.get()); + } + } + + textLoaded = true; +} + +String __fastcall TCommonForms::GetText() +{ + LoadTextIfNeeded(); + return text; +} + +void __fastcall TCommonForms::SetText(String _text) +{ + text = _text; + textLoaded = true; +} + std::vector>& TCommonForms::getAttributes() { return attributes; diff --git a/src/CommonForms.h b/src/CommonForms.h index 9d64d32..59886d6 100644 --- a/src/CommonForms.h +++ b/src/CommonForms.h @@ -6,44 +6,38 @@ #include "BaseMetadataObject.h" //--------------------------------------------------------------------------- -/** - * @class TCommonForms - * @brief Класс для хранения общих форм (md_CommonForms) - * - * Общие формы - это объекты метаданных, которые содержат - * формы, доступные в различных частях конфигурации. - */ class TCommonForms : public BaseMetadataObject { private: - // formName хранится в унаследованном поле name из BaseMetadataObject + String text; + bool textLoaded; public: - __fastcall TCommonForms(); - __fastcall TCommonForms(v8catalog* _parent, const String& _guid); - __fastcall TCommonForms(v8catalog* _parent, const String& _guid, const String& _name); - virtual __fastcall ~TCommonForms(); + __fastcall TCommonForms(); + __fastcall TCommonForms(v8catalog* _parent, const String& _guid); + __fastcall TCommonForms(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TCommonForms(); - // Методы для получения имени общей формы - String __fastcall GetFormName(); - void __fastcall SetFormName(String _name); + String __fastcall GetFormName(); + void __fastcall SetFormName(String _name); + String __fastcall GetText(); + void __fastcall SetText(String _text); - // Реализация виртуальных методов BaseMetadataObject - std::vector>& getAttributes() override; - std::vector>& getCommands() override; - std::vector>& getLayouts() override; - std::vector>& getTabularSections() override; - std::vector>& getForms() override; + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; - void __fastcall initializeFromTree() override; + void __fastcall initializeFromTree() override; private: - // Внутренние хранилища для совместимости с интерфейсом - std::vector> attributes; - std::vector> commands; - std::vector> layouts; - std::vector> tabularSections; - std::vector> forms; + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; + void __fastcall LoadTextIfNeeded(); }; #endif diff --git a/src/ConfigStorage.cpp b/src/ConfigStorage.cpp index b9c2031..e236679 100644 --- a/src/ConfigStorage.cpp +++ b/src/ConfigStorage.cpp @@ -50,7 +50,7 @@ ConfigFile* __fastcall ConfigStorageDirectory::readfile(const String& path) cf = new ConfigFile; try { - cf->str = new TFileStream(filename, fmOpenRead); + cf->str = new TFileStream(filename, fmOpenRead | fmShareDenyNone); cf->addin = NULL; return cf; } diff --git a/src/ExchangePlans.cpp b/src/ExchangePlans.cpp index 4ffff47..f5b75f3 100644 --- a/src/ExchangePlans.cpp +++ b/src/ExchangePlans.cpp @@ -2,26 +2,396 @@ #pragma hdrstop +#include + +#include "Common.h" #include "ExchangePlans.h" +#include "Comand.h" +#include "Form.h" //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + tree* GetNodeByPath(tree* root, const std::vector& indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + bool IsGuidLikeValue(const String& value) + { + String trimmed = Trim(value); + if (trimmed.Length() != 36) + return false; + + for (int i = 1; i <= trimmed.Length(); i++) + { + wchar_t ch = trimmed[i]; + bool isHex = (ch >= L'0' && ch <= L'9') || (ch >= L'a' && ch <= L'f') || (ch >= L'A' && ch <= L'F'); + bool isDash = (ch == L'-'); + if (!isHex && !isDash) + return false; + } + + return true; + } + + bool IsNumericLikeValue(const String& value) + { + String trimmed = Trim(value); + if (trimmed.IsEmpty()) + return false; + + for (int i = 1; i <= trimmed.Length(); i++) + { + wchar_t ch = trimmed[i]; + if (!((ch >= L'0' && ch <= L'9') || ch == L'.' || ch == L',' || ch == L'-')) + return false; + } + + return true; + } + + String FindFirstMeaningfulString(tree* node) + { + if (!node) + return L""; + + String value = Trim(node->get_value()); + if (!value.IsEmpty() && !IsGuidLikeValue(value) && !IsNumericLikeValue(value) && value.SubString(1, 1) != L"#") + return value; + + for (int i = 0; i < node->get_num_subnode(); i++) + { + String nested = FindFirstMeaningfulString(node->get_subnode(i)); + if (!nested.IsEmpty()) + return nested; + } + + return L""; + } + + bool TryCollectExchangePlanAttributes(tree* root, std::vector>& attributes) + { + static const String ExchangePlanAttributeSectionGuid = L"1a1b4fea-e093-470d-94ff-1d2f16cda2ab"; + + tree* sectionNodeByGuid = find_metadata_node_by_guid(root, ExchangePlanAttributeSectionGuid); + if (sectionNodeByGuid) + { + tree* countNode = sectionNodeByGuid->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count > 0) + { + std::vector> parsed; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String attributeName; + +tree* nameNode = GetNodeByPath(current, {0, 1, 1, 1, 2}); + if (nameNode) + attributeName = Trim(nameNode->get_value()); + + if (attributeName.IsEmpty()) + attributeName = FindFirstMeaningfulString(current); + + if (!attributeName.IsEmpty()) + parsed.push_back(std::make_unique(attributeName, L"")); + + if ((int)parsed.size() >= count) + break; + } + + if (!parsed.empty()) + { + attributes = std::move(parsed); + return true; + } + } + } + + const int candidateSections[] = {5, 7, 6, 3, 8, 4, 2, 1}; + const std::vector> itemPrefixes = { + {0}, + {0, 1} + }; + const std::vector> namePaths = { + {0, 1, 1, 1, 2}, + {0, 1, 1, 1, 1, 2}, + {0, 1, 1, 2}, + {0, 1, 3, 2}, + {1, 1, 1, 2}, + {1, 1, 2}, + {1, 3, 2} + }; + + for (int sectionIndex : candidateSections) + { + tree* countNode = GetNodeByPath(root, {0, sectionIndex, 1}); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + continue; + + int delta = count - 2; + std::vector> parsed; + + for (const auto& itemPrefix : itemPrefixes) + { + for (int i = 0; i < count; i++) + { + try + { + std::vector itemPath = itemPrefix; + itemPath.push_back(sectionIndex); + itemPath.push_back(i + count - delta); + + tree* itemNode = GetNodeByPath(root, itemPath); + if (!itemNode) + continue; + + String attributeName; + for (const auto& namePath : namePaths) + { + tree* nameNode = GetNodeByPath(itemNode, namePath); + if (!nameNode) + continue; + + attributeName = Trim(nameNode->get_value()); + if (!attributeName.IsEmpty()) + break; + } + + if (attributeName.IsEmpty()) + attributeName = FindFirstMeaningfulString(itemNode); + + if (!attributeName.IsEmpty() && attributeName != Trim(FindFirstMeaningfulString(root))) + parsed.push_back(std::make_unique(attributeName, L"")); + } + catch (...) + { + } + } + + if (!parsed.empty()) + { + attributes = std::move(parsed); + return true; + } + } + } + + return false; + } + + bool TryCollectExchangePlanTabularSections(tree* root, std::vector>& tabulars) + { + static const String ExchangePlanTabularSectionGuid = L"52293f4b-f98c-43ea-a80f-41047ae7ab58"; + + tree* sectionNodeByGuid = find_metadata_node_by_guid(root, ExchangePlanTabularSectionGuid); + if (!sectionNodeByGuid) + return false; + + tree* countNode = sectionNodeByGuid->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + std::vector> parsed; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String tabularName; + tree* nameNode = GetNodeByPath(current, {0, 1, 1, 1, 2}); + if (nameNode) + tabularName = Trim(nameNode->get_value()); + + if (tabularName.IsEmpty()) + tabularName = FindFirstMeaningfulString(current); + + if (tabularName.IsEmpty()) + continue; + + auto tabular = std::make_unique(tabularName, L""); + + tree* tabularAttributesNode = GetNodeByPath(current, {0, 1, 1, 1, 2}); + tabular->initializeFromTree(tabularAttributesNode ? tabularAttributesNode : current); + parsed.push_back(std::move(tabular)); + + if ((int)parsed.size() >= count) + break; + } + + if (parsed.empty()) + return false; + + tabulars = std::move(parsed); + return true; + } +} + +bool TryCollectExchangePlanCommands(tree* root, std::vector>& commands) +{ + static const String ExchangePlanCommandsGuid = L"d5207c64-11d5-4d46-bba2-55b7b07ff4eb"; + + tree* sectionNodeByGuid = find_metadata_node_by_guid(root, ExchangePlanCommandsGuid); + if (!sectionNodeByGuid) + return false; + + tree* countNode = sectionNodeByGuid->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + std::vector> parsed; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String commandName; + tree* nameNode = GetNodeByPath(current, {0, 1, 3, 2, 9, 2}); + if (nameNode) + commandName = Trim(nameNode->get_value()); + + if (commandName.IsEmpty()) + commandName = FindFirstMeaningfulString(current); + + if (!commandName.IsEmpty()) + parsed.push_back(std::make_unique(commandName, L"")); + + if ((int)parsed.size() >= count) + break; + } + + if (parsed.empty()) + return false; + + commands = std::move(parsed); + return true; +} + +bool TryCollectExchangePlanForms(v8catalog* parent, tree* root, std::vector>& forms) +{ + static const String ExchangePlanFormsGuid = L"87c509ab-3d38-4d67-b379-aca796298578"; + + if (!parent) + return false; -__fastcall TExchangePlans::TExchangePlans() : BaseMetadataObject() + tree* sectionNodeByGuid = find_metadata_node_by_guid(root, ExchangePlanFormsGuid); + if (!sectionNodeByGuid) + return false; + + tree* countNode = sectionNodeByGuid->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + std::vector> parsed; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String guid_md = Trim(current->get_value()); + if (guid_md.IsEmpty()) + continue; + + String formName = GetNameFormCatalogs(parent, guid_md); + + if (!formName.IsEmpty()) + parsed.push_back(std::make_unique(formName, L"")); + + if ((int)parsed.size() >= count) + break; + } + + if (parsed.empty()) + return false; + + forms = std::move(parsed); + return true; +} + +bool TryCollectExchangePlanLayouts(v8catalog* parent, tree* root, std::vector>& moxels) +{ + static const String ExchangePlanLayoutsGuid = L"3daea016-69b7-4ed4-9453-127911372fe6"; + + if (!parent) + return false; + + tree* sectionNodeByGuid = find_metadata_node_by_guid(root, ExchangePlanLayoutsGuid); + if (!sectionNodeByGuid) + return false; + + tree* countNode = sectionNodeByGuid->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + std::vector> parsed; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String guid_md = Trim(current->get_value()); + if (guid_md.IsEmpty()) + continue; + + String layoutName = GetNameMoxCatalogs(parent, guid_md); + if (!layoutName.IsEmpty()) + parsed.push_back(std::make_unique(layoutName, guid_md)); + + if ((int)parsed.size() >= count) + break; + } + + if (parsed.empty()) + return false; + + moxels = std::move(parsed); + return true; +} + +static MetadataTreePaths GetExchangePlansPaths() +{ + MetadataTreePaths paths; + paths.attIdx = 3; + paths.attItemPath = {0, 1, 1, 1, 2}; + paths.tabIdx = 5; + paths.tabItemPath = {0, 1, 5, 1, 2}; + paths.formsIdx = 6; + paths.cmdIdx = 7; + paths.cmdItemPath = {0, 1, 3, 2, 9, 2}; + paths.moxIdx = 4; + paths.getFormNameFunc = GetNameFormCatalogs; + paths.hasTabulars = true; + return paths; +} + +__fastcall TExchangePlans::TExchangePlans() : MetadataObjectWithSections() { exchangePlanName = ""; root_data.reset(); } -__fastcall TExchangePlans::TExchangePlans(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +__fastcall TExchangePlans::TExchangePlans(v8catalog* _parent, const String& _guid) : MetadataObjectWithSections(_parent, _guid) { exchangePlanName = ""; + initializeFromTree(); root_data.reset(); } -__fastcall TExchangePlans::TExchangePlans(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +__fastcall TExchangePlans::TExchangePlans(v8catalog* _parent, const String& _guid, const String& _name) : MetadataObjectWithSections(_parent, _guid, _name) { exchangePlanName = _name; + initializeFromTree(); root_data.reset(); } @@ -39,33 +409,22 @@ void __fastcall TExchangePlans::SetExchangePlanName(String _name) exchangePlanName = _name; } -std::vector>& TExchangePlans::getAttributes() +void __fastcall TExchangePlans::initializeFromTree() { - return attributes; -} + MetadataObjectWithSections::initializeFromTreeWithPaths(GetExchangePlansPaths()); -std::vector>& TExchangePlans::getCommands() -{ - return commands; -} + if (getAttributes().empty() && root_data) + TryCollectExchangePlanAttributes(root_data.get(), getAttributes()); -std::vector>& TExchangePlans::getLayouts() -{ - return layouts; -} + if (getTabularSections().empty() && root_data) + TryCollectExchangePlanTabularSections(root_data.get(), getTabularSections()); -std::vector>& TExchangePlans::getTabularSections() -{ - return tabularSections; -} + if (getCommands().empty() && root_data) + TryCollectExchangePlanCommands(root_data.get(), getCommands()); -std::vector>& TExchangePlans::getForms() -{ - return forms; -} + if (getForms().empty() && root_data) + TryCollectExchangePlanForms(parent, root_data.get(), getForms()); -void __fastcall TExchangePlans::initializeFromTree() -{ - // Инициализация плана обмена из дерева метаданных - // Имя плана обмена уже установлено в конструкторе + if (getLayouts().empty() && root_data) + TryCollectExchangePlanLayouts(parent, root_data.get(), getLayouts()); } diff --git a/src/ExchangePlans.h b/src/ExchangePlans.h index 72e30ad..7ca4c9f 100644 --- a/src/ExchangePlans.h +++ b/src/ExchangePlans.h @@ -3,7 +3,7 @@ #ifndef ExchangePlansH #define ExchangePlansH -#include "BaseMetadataObject.h" +#include "MetadataObjectWithSections.h" //--------------------------------------------------------------------------- /** @@ -13,7 +13,7 @@ * Планы обмена - это объекты метаданных, которые определяют * правила обмена данными между информационными базами 1С. */ -class TExchangePlans : public BaseMetadataObject +class TExchangePlans : public MetadataObjectWithSections { private: String exchangePlanName; // Имя плана обмена @@ -28,22 +28,7 @@ class TExchangePlans : public BaseMetadataObject String __fastcall GetExchangePlanName(); void __fastcall SetExchangePlanName(String _name); - // Реализация виртуальных методов BaseMetadataObject - std::vector>& getAttributes() override; - std::vector>& getCommands() override; - std::vector>& getLayouts() override; - std::vector>& getTabularSections() override; - std::vector>& getForms() override; - void __fastcall initializeFromTree() override; - -private: - // Внутренние хранилища для совместимости с интерфейсом - std::vector> attributes; - std::vector> commands; - std::vector> layouts; - std::vector> tabularSections; - std::vector> forms; }; #endif diff --git a/src/ExternalDataSources.cpp b/src/ExternalDataSources.cpp index 1dc703f..2bc5f66 100644 --- a/src/ExternalDataSources.cpp +++ b/src/ExternalDataSources.cpp @@ -5,3 +5,333 @@ #include "ExternalDataSources.h" //--------------------------------------------------------------------------- #pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + String GetValueByPath(tree* root, std::initializer_list indexes) + { + tree* node = GetNodeByPath(root, indexes); + return node ? node->get_value() : String(); + } + + String GetFirstValueByPath(tree* root, std::initializer_list> paths) + { + for (const auto& path : paths) + { + String value = GetValueByPath(root, path); + if (!value.IsEmpty()) + return value; + } + + return String(); + } + + tree* GetPayloadRoot(tree* root) + { + if (!root) + return nullptr; + if (root->get_num_subnode() == 1) + return root->get_subnode(0); + return root; + } + + tree* GetSection(tree* root, int index) + { + return GetNodeByPath(root, {index}); + } + + int GetSectionCount(tree* root, int index) + { + tree* section = GetSection(root, index); + if (!section || section->get_num_subnode() < 2) + return 0; + + return section->get_subnode(1)->get_value().ToIntDef(0); + } + + String GetFileNameByPath(v8catalog* parent, const String& guid, std::initializer_list indexes) + { + if (!parent || guid.IsEmpty()) + return String(); + + v8file* file = parent->GetFile(guid); + if (!file) + return String(); + + try + { + std::unique_ptr fileTree(get_treeFromV8file(file)); + return GetValueByPath(GetPayloadRoot(fileTree.get()), indexes); + } + catch (...) + { + return String(); + } + } + + void ReadFileList(tree* root, int sectionIndex, v8catalog* parent, + std::initializer_list namePath, std::vector& target) + { + tree* section = GetSection(root, sectionIndex); + int count = GetSectionCount(root, sectionIndex); + if (!section) + return; + + for (int i = 0; i < count; ++i) + { + tree* guidNode = section->get_subnode(i + 2); + if (!guidNode) + continue; + + String itemName = GetFileNameByPath(parent, guidNode->get_value(), namePath); + if (!itemName.IsEmpty()) + target.push_back(itemName); + } + } + + void ReadInlineList(tree* root, int sectionIndex, std::initializer_list namePath, + std::vector& target) + { + tree* section = GetSection(root, sectionIndex); + int count = GetSectionCount(root, sectionIndex); + if (!section) + return; + + for (int i = 0; i < count; ++i) + { + tree* itemNode = section->get_subnode(i + 2); + String itemName = GetValueByPath(itemNode, namePath); + if (!itemName.IsEmpty()) + target.push_back(itemName); + } + } + + TExternalDataSourceTable ReadTable(v8catalog* parent, const String& guid) + { + TExternalDataSourceTable tableData; + if (!parent || guid.IsEmpty()) + return tableData; + + v8file* file = parent->GetFile(guid); + if (!file) + return tableData; + + std::unique_ptr tableTree; + try + { + tableTree.reset(get_treeFromV8file(file)); + } + catch (...) + { + tableData.name = guid; + return tableData; + } + tree* root = GetPayloadRoot(tableTree.get()); + + tableData.name = GetFirstValueByPath(root, { + {1, 1, 1, 2}, + {0, 1, 1, 2}, + {1, 0, 1, 2} + }); + if (tableData.name.IsEmpty()) + tableData.name = guid; + ReadFileList(root, 3, parent, {1, 1, 2}, tableData.forms); + ReadFileList(root, 4, parent, {1, 2, 2}, tableData.layouts); + ReadInlineList(root, 5, {0, 1, 3, 2, 9, 2}, tableData.commands); + ReadInlineList(root, 6, {0, 1, 1, 1, 2}, tableData.fields); + + return tableData; + } + + TExternalDataSourceCube ReadCube(v8catalog* parent, const String& guid) + { + TExternalDataSourceCube cubeData; + if (!parent || guid.IsEmpty()) + return cubeData; + + v8file* file = parent->GetFile(guid); + if (!file) + return cubeData; + + std::unique_ptr cubeTree; + try + { + cubeTree.reset(get_treeFromV8file(file)); + } + catch (...) + { + cubeData.name = guid; + return cubeData; + } + tree* root = GetPayloadRoot(cubeTree.get()); + + cubeData.name = GetFirstValueByPath(root, { + {1, 1, 1, 2}, + {0, 1, 1, 2}, + {1, 0, 1, 2} + }); + if (cubeData.name.IsEmpty()) + cubeData.name = guid; + ReadFileList(root, 3, parent, {1, 1, 2}, cubeData.forms); + ReadFileList(root, 4, parent, {1, 2, 2}, cubeData.layouts); + ReadInlineList(root, 5, {0, 1, 3, 2, 9, 2}, cubeData.commands); + ReadInlineList(root, 7, {0, 1, 1, 1, 2}, cubeData.dimensions); + ReadInlineList(root, 8, {0, 1, 1, 1, 2}, cubeData.resources); + + tree* tablesSection = GetSection(root, 6); + int tableCount = GetSectionCount(root, 6); + if (tablesSection) + { + for (int i = 0; i < tableCount; ++i) + { + tree* guidNode = tablesSection->get_subnode(i + 2); + if (guidNode) + cubeData.dimensionTables.push_back(ReadTable(parent, guidNode->get_value())); + } + } + + return cubeData; + } +} + +__fastcall TExternalDataSources::TExternalDataSources() + : BaseMetadataObject() +{ + root_data.reset(); +} + +__fastcall TExternalDataSources::TExternalDataSources(v8catalog* _parent, const String& _guid) + : BaseMetadataObject() +{ + name = _guid; + guid = _guid; + parent = _parent; + if (parent) + { + try + { + v8file* file = parent->GetFile(guid); + if (file) + root_data.reset(get_treeFromV8file(file)); + } + catch (...) + { + root_data.reset(); + } + } + if (root_data) + initializeFromTree(); + root_data.reset(); +} + +__fastcall TExternalDataSources::TExternalDataSources(v8catalog* _parent, const String& _guid, const String& _name) + : BaseMetadataObject() +{ + name = _name; + guid = _guid; + parent = _parent; + if (parent) + { + try + { + v8file* file = parent->GetFile(guid); + if (file) + root_data.reset(get_treeFromV8file(file)); + } + catch (...) + { + root_data.reset(); + } + } + if (root_data) + initializeFromTree(); + root_data.reset(); +} + +__fastcall TExternalDataSources::~TExternalDataSources() +{ +} + +std::vector>& TExternalDataSources::getAttributes() +{ + return attributes; +} + +std::vector>& TExternalDataSources::getCommands() +{ + return commands; +} + +std::vector>& TExternalDataSources::getLayouts() +{ + return layouts; +} + +std::vector>& TExternalDataSources::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TExternalDataSources::getForms() +{ + return forms; +} + +void __fastcall TExternalDataSources::initializeFromTree() +{ + tree* root = GetPayloadRoot(root_data.get()); + String sourceName = GetFirstValueByPath(root, { + {1, 1, 1, 2}, + {0, 1, 1, 2}, + {1, 0, 1, 2} + }); + if (!sourceName.IsEmpty()) + name = sourceName; + + tables.clear(); + cubes.clear(); + functions.clear(); + + tree* cubesSection = GetSection(root, 3); + int cubeCount = GetSectionCount(root, 3); + if (cubesSection) + { + for (int i = 0; i < cubeCount; ++i) + { + tree* guidNode = cubesSection->get_subnode(i + 2); + if (guidNode) + cubes.push_back(ReadCube(parent, guidNode->get_value())); + } + } + + ReadInlineList(root, 4, {0, 1, 1, 1, 2}, functions); + + tree* tablesSection = GetSection(root, 5); + int tableCount = GetSectionCount(root, 5); + if (tablesSection) + { + for (int i = 0; i < tableCount; ++i) + { + tree* guidNode = tablesSection->get_subnode(i + 2); + if (guidNode) + tables.push_back(ReadTable(parent, guidNode->get_value())); + } + } +} diff --git a/src/ExternalDataSources.h b/src/ExternalDataSources.h index 86dc3e3..4a960a0 100644 --- a/src/ExternalDataSources.h +++ b/src/ExternalDataSources.h @@ -3,4 +3,54 @@ #ifndef ExternalDataSourcesH #define ExternalDataSourcesH //--------------------------------------------------------------------------- +#include "BaseMetadataObject.h" + +struct TExternalDataSourceTable +{ + String name; + std::vector fields; + std::vector forms; + std::vector commands; + std::vector layouts; +}; + +struct TExternalDataSourceCube +{ + String name; + std::vector dimensionTables; + std::vector dimensions; + std::vector resources; + std::vector forms; + std::vector commands; + std::vector layouts; +}; + +class TExternalDataSources : public BaseMetadataObject +{ +public: + __fastcall TExternalDataSources(); + __fastcall TExternalDataSources(v8catalog* _parent, const String& _guid); + __fastcall TExternalDataSources(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TExternalDataSources(); + + std::vector tables; + std::vector cubes; + std::vector functions; + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + #endif diff --git a/src/FilterCriteria.cpp b/src/FilterCriteria.cpp index 19fbda2..88f3a08 100644 --- a/src/FilterCriteria.cpp +++ b/src/FilterCriteria.cpp @@ -2,10 +2,100 @@ #pragma hdrstop +#include "guids.h" #include "FilterCriteria.h" //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + constexpr const wchar_t* GUID_FilterCriteriaForms = L"00867c40-06b1-11d6-a3c7-0050bae0a776"; + + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + tree* FindChildListByFirstValue(tree* root, const String& firstValue) + { + if (!root) + return nullptr; + + tree* child = root->get_first(); + while (child) + { + tree* first = child->get_first(); + if (first && first->get_value().CompareIC(firstValue) == 0) + return child; + + child = child->get_next(); + } + + return nullptr; + } + + tree* FindMetadataDescriptor(tree* root) + { + if (!root) + return nullptr; + + tree* first = root->get_subnode(0); + tree* guidNode = GetNodeByPath(root, {1, 2}); + tree* nameNode = root->get_subnode(2); + if (first && guidNode && nameNode && first->get_value() == L"3") + return root; + + tree* child = root->get_first(); + while (child) + { + tree* descriptor = FindMetadataDescriptor(child); + if (descriptor) + return descriptor; + + child = child->get_next(); + } + + return nullptr; + } + + String GetDescriptorName(tree* descriptor) + { + tree* nameNode = descriptor ? descriptor->get_subnode(2) : nullptr; + return nameNode ? nameNode->get_value() : L""; + } + + String GetDescriptorGuid(tree* descriptor) + { + tree* guidNode = GetNodeByPath(descriptor, {1, 2}); + return guidNode ? Trim(guidNode->get_value()) : L""; + } + + String GetMetadataNameFromFile(v8catalog* parent, const String& guid) + { + if (!parent || guid.IsEmpty()) + return L""; + + v8file* file = parent->GetFile(guid); + if (!file) + return L""; + + std::unique_ptr metadataTree(get_treeFromV8file(file)); + tree* descriptor = FindMetadataDescriptor(metadataTree.get()); + return GetDescriptorName(descriptor); + } +} __fastcall TFilterCriteria::TFilterCriteria() : BaseMetadataObject() { @@ -16,12 +106,14 @@ __fastcall TFilterCriteria::TFilterCriteria() : BaseMetadataObject() __fastcall TFilterCriteria::TFilterCriteria(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) { name = ""; + initializeFromTree(); root_data.reset(); } __fastcall TFilterCriteria::TFilterCriteria(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) { name = _name; + initializeFromTree(); root_data.reset(); } @@ -66,6 +158,55 @@ std::vector>& TFilterCriteria::getForms() void __fastcall TFilterCriteria::initializeFromTree() { - // Инициализация критерия отбора из дерева метаданных - // Имя критерия отбора уже установлено в конструкторе + forms.clear(); + commands.clear(); + + if (!root_data) + return; + + if (name.IsEmpty()) + { + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 5, 1, 2}); + if (nameNode) + name = nameNode->get_value(); + } + + tree* rootNode = root_data->get_subnode(0); + + tree* formsNode = FindChildListByFirstValue(rootNode, GUID_FilterCriteriaForms); + if (!formsNode) + formsNode = GetNodeByPath(root_data.get(), {0, 3}); + + tree* formsCountNode = formsNode ? formsNode->get_subnode(1) : nullptr; + int formsCount = formsCountNode ? formsCountNode->get_value().ToIntDef(0) : 0; + for (int i = 0; i < formsCount; i++) + { + tree* formGuidNode = formsNode->get_subnode(i + 2); + if (!formGuidNode) + continue; + + String formGuid = Trim(formGuidNode->get_value()); + String formName = GetMetadataNameFromFile(parent, formGuid); + if (formName.IsEmpty()) + formName = formGuid; + + forms.push_back(std::make_unique(formName, formGuid)); + } + + tree* commandsNode = FindChildListByFirstValue(rootNode, GUID_SelCritCommands); + if (!commandsNode) + commandsNode = GetNodeByPath(root_data.get(), {0, 4}); + + tree* commandsCountNode = commandsNode ? commandsNode->get_subnode(1) : nullptr; + int commandsCount = commandsCountNode ? commandsCountNode->get_value().ToIntDef(0) : 0; + for (int i = 0; i < commandsCount; i++) + { + tree* commandNode = commandsNode->get_subnode(i + 2); + tree* descriptor = FindMetadataDescriptor(commandNode); + String commandName = GetDescriptorName(descriptor); + if (commandName.IsEmpty()) + continue; + + commands.push_back(std::make_unique(commandName, GetDescriptorGuid(descriptor))); + } } diff --git a/src/IntegrationServices.cpp b/src/IntegrationServices.cpp new file mode 100644 index 0000000..206e377 --- /dev/null +++ b/src/IntegrationServices.cpp @@ -0,0 +1,101 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "IntegrationServices.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} + +__fastcall TIntegrationServices::TIntegrationServices() : BaseMetadataObject() +{ + serviceName = ""; + root_data.reset(); +} + +__fastcall TIntegrationServices::TIntegrationServices(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +{ + serviceName = ""; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TIntegrationServices::TIntegrationServices(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +{ + serviceName = _name; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TIntegrationServices::~TIntegrationServices() +{ +} + +String __fastcall TIntegrationServices::GetServiceName() +{ + return serviceName; +} + +void __fastcall TIntegrationServices::SetServiceName(String _name) +{ + serviceName = _name; + name = _name; +} + +std::vector>& TIntegrationServices::getAttributes() +{ + return attributes; +} + +std::vector>& TIntegrationServices::getCommands() +{ + return commands; +} + +std::vector>& TIntegrationServices::getLayouts() +{ + return layouts; +} + +std::vector>& TIntegrationServices::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TIntegrationServices::getForms() +{ + return forms; +} + +void __fastcall TIntegrationServices::initializeFromTree() +{ + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 1, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + serviceName = name; + return; + } + + if (serviceName.IsEmpty()) + serviceName = name; +} diff --git a/src/IntegrationServices.h b/src/IntegrationServices.h new file mode 100644 index 0000000..3c2b705 --- /dev/null +++ b/src/IntegrationServices.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef IntegrationServicesH +#define IntegrationServicesH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TIntegrationServices : public BaseMetadataObject +{ +private: + String serviceName; + +public: + __fastcall TIntegrationServices(); + __fastcall TIntegrationServices(v8catalog* _parent, const String& _guid); + __fastcall TIntegrationServices(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TIntegrationServices(); + + String __fastcall GetServiceName(); + void __fastcall SetServiceName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif diff --git a/src/MDObject.cpp b/src/MDObject.cpp index 0b9bb3f..3c63fe2 100644 --- a/src/MDObject.cpp +++ b/src/MDObject.cpp @@ -1,13 +1,13 @@ //--------------------------------------------------------------------------- +#pragma package(smart_init) #pragma hdrstop #include "MDObject.h" //--------------------------------------------------------------------------- -#pragma package(smart_init) -TMDObject* TMDObjectManager::newMetaData() +TMDObject* __fastcall TMDObjectManager::newMetaData() { TMDObject* md = CreateMetaData(); md_list->Add(md); diff --git a/src/MDObject.h b/src/MDObject.h index 0c5ec9a..2424b25 100644 --- a/src/MDObject.h +++ b/src/MDObject.h @@ -45,9 +45,9 @@ class TMDObjectManager : public TObject { private: TObjectList *md_list; - virtual __fastcall TMDObject* CreateMetaData() = 0; + virtual TMDObject* __fastcall CreateMetaData() = 0; public: - __fastcall TMDObject* newMetaData(); + TMDObject* __fastcall newMetaData(); __fastcall TMDObjectManager(); }; diff --git a/src/MainUnit.cpp b/src/MainUnit.cpp index 2bdad9f..d14835d 100644 --- a/src/MainUnit.cpp +++ b/src/MainUnit.cpp @@ -15,6 +15,7 @@ #include "V8File.h" #include "ApicfBase.h" +#include "MetadataTreeBuilder.h" #include "Class_1CD.h" #include "CommonModules.h" #include "MainUnit.h" @@ -57,8 +58,14 @@ #include "SettingsStorages.h" #include "XDTOPackages.h" #include "WebServices.h" +#include "WSReferences.h" #include "HTTPServices.h" +#include "WebSocketClients.h" +#include "IntegrationServices.h" +#include "StyleItems.h" +#include "Styles.h" #include "Langs.h" +#include "Subsystem.h" //--------------------------------------------------------------------------- @@ -136,18 +143,13 @@ static void AddConditionalInfoMessage(Messager* mess, const String& message) mess->AddMessage(message, msInfo); } -static void AddConditionalInfoMessageParams(Messager* mess, const String& description, - const String& parname1, const String& par1, - const String& parname2, const String& par2) +static void AddConditionalInfoMessageParams(Messager* mess, const String& description, const String& parname1, const String& par1, const String& parname2, const String& par2) { if (mess && mess->getUiMessagesEnabled() && IsVerboseUiLoggingEnabled()) mess->AddMessage_(description, msInfo, parname1, par1, parname2, par2); } -static void AddConditionalInfoMessageParams(Messager* mess, const String& description, - const String& parname1, const String& par1, - const String& parname2, const String& par2, - const String& parname3, const String& par3) +static void AddConditionalInfoMessageParams(Messager* mess, const String& description, const String& parname1, const String& par1, const String& parname2, const String& par2, const String& parname3, const String& par3) { if (mess && mess->getUiMessagesEnabled() && IsVerboseUiLoggingEnabled()) mess->AddMessage_(description, msInfo, parname1, par1, parname2, par2, parname3, par3); @@ -184,57 +186,7 @@ static void LogHeapStatus(const String& stage, msreg->AddMessage(stage, msInfo, ts); } -namespace TreeImage -{ - constexpr int Root = 72; - constexpr int Attributes = 83; - constexpr int TabularSections = 82; - constexpr int Forms = 86; - constexpr int Commands = 98; - constexpr int Layouts = 79; - constexpr int Dimensions = 10; - constexpr int Resources = 11; - constexpr int AccountingFlags = 118; - constexpr int SubcontoFlags = 119; - constexpr int JournalColumns = 6; -} -constexpr int DefaultTreeNodeAge = 30; - -static void initNode(VirtualTreeData* data, const String& name, int imageIndex, int age = DefaultTreeNodeAge) -{ - data->Name = name; - data->Age = age; - data->ImgIndex = imageIndex; -} - -static PVirtualNode addChildNode(TVirtualStringTree* tree, - PVirtualNode parent, - const String& name, - int imageIndex, - int age = DefaultTreeNodeAge) -{ - PVirtualNode childNode = tree->AddChild(parent); - VirtualTreeData* childData = static_cast(tree->GetNodeData(childNode)); - initNode(childData, name, imageIndex, age); - return childNode; -} - -template -static void addSection(TVirtualStringTree* tree, - PVirtualNode parent, - const String& sectionName, - int sectionImageIndex, - int itemImageIndex, - const Collection& items, - NameGetter getName, - int age = DefaultTreeNodeAge) -{ - PVirtualNode sectionNode = addChildNode(tree, parent, sectionName, sectionImageIndex, age); - - for (const auto& item : items) - addChildNode(tree, sectionNode, getName(item), itemImageIndex, age); -} //--------------------------------------------------------------------------- __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner), MDManager(std::make_unique()) @@ -255,6 +207,7 @@ __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner), MDManager(std } } + //--------------------------------------------------------------------------- void __fastcall TMainForm::ResetLoadProgress(int maxValue, const String& statusText) { @@ -298,6 +251,7 @@ void __fastcall TMainForm::CompleteLoadProgress(const String& statusText) Application->ProcessMessages(); LoadProgressBar->Visible = false; } + //--------------------------------------------------------------------------- void __fastcall TMainForm::btnOpenEditNameClick(TObject *Sender) { @@ -309,18 +263,16 @@ void __fastcall TMainForm::btnOpenEditNameClick(TObject *Sender) throw(Exception("File does not exist.")); } } -//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- void __fastcall TMainForm::btnGOClick(TObject *Sender) { std::vector filter; //v8unpack::Parse(AnsiString(EditNameCF->Text).c_str(), AnsiString(editFolderName->Text).c_str(), filter); } -//--------------------------------------------------------------------------- - -void __fastcall TMainForm::VirtualStringTreeValue1CInitNode(TBaseVirtualTree *Sender, - PVirtualNode ParentNode, PVirtualNode Node, TVirtualNodeInitStates &InitialStates) +//--------------------------------------------------------------------------- +void __fastcall TMainForm::VirtualStringTreeValue1CInitNode(TBaseVirtualTree *Sender, PVirtualNode ParentNode, PVirtualNode Node, TVirtualNodeInitStates &InitialStates) { if(!ParentNode) { @@ -328,11 +280,9 @@ void __fastcall TMainForm::VirtualStringTreeValue1CInitNode(TBaseVirtualTree *Se initNode(d, L"Типы 1С", TreeImage::Root, 0); } } -//--------------------------------------------------------------------------- -void __fastcall TMainForm::VirtualStringTreeValue1CGetText(TBaseVirtualTree *Sender, - PVirtualNode Node, TColumnIndex Column, TVSTTextType TextType, - UnicodeString &CellText) +//--------------------------------------------------------------------------- +void __fastcall TMainForm::VirtualStringTreeValue1CGetText(TBaseVirtualTree *Sender, PVirtualNode Node, TColumnIndex Column, TVSTTextType TextType, UnicodeString &CellText) { VirtualTreeData *NodeData = (VirtualTreeData*)Sender->GetNodeData(Node); CellText = NodeData->Name; @@ -374,195 +324,14 @@ void __fastcall TMainForm::FillTreeMDConcrete(TVirtualStringTree *tree1C, PVirtu } } -void __fastcall TMainForm::fillCatalogsTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Табличные части", TreeImage::TabularSections, TreeImage::TabularSections, - tabulars, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - -void __fastcall TMainForm::fillAccumulationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, - dimensions, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, - resources, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - -void __fastcall TMainForm::fillAccountingRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& accountingFlags, - const std::vector>& dimensionAccountingFlags, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, - dimensions, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, - resources, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Признаки учета", TreeImage::AccountingFlags, TreeImage::AccountingFlags, - accountingFlags, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Признаки учета субконто", TreeImage::SubcontoFlags, TreeImage::SubcontoFlags, - dimensionAccountingFlags, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - -void __fastcall TMainForm::fillCalculationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, - dimensions, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, - resources, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - -void __fastcall TMainForm::fillInformationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, - dimensions, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, - resources, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - -void __fastcall TMainForm::fillChartAccTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& accflags, - const std::vector>& dimaccflags, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Признаки учета", TreeImage::AccountingFlags, TreeImage::AccountingFlags, - accflags, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Признаки учета субконто", TreeImage::SubcontoFlags, TreeImage::SubcontoFlags, - dimaccflags, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Табличные части", TreeImage::TabularSections, TreeImage::TabularSections, - tabulars, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - - -void __fastcall TMainForm::fillJournalTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels) -{ - initNode(childData, name, imgIndex); - addSection(VirtualStringTreeValue1C, childNode, L"Графы", TreeImage::JournalColumns, TreeImage::JournalColumns, - attributes, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Табличные части", TreeImage::TabularSections, TreeImage::TabularSections, - tabulars, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - forms, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - comands, [](const auto& item) { return item->name; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - moxels, [](const auto& item) { return item->name; }); -} - - -// Вспомогательная функция для заполнения дерева перечислений -void __fastcall TMainForm::fillEnumTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, TEnums* CurCat) -{ - initNode(childData, CurCat->name, imgIndex); - - addSection(VirtualStringTreeValue1C, childNode, L"Значения", TreeImage::Attributes, TreeImage::Attributes, - CurCat->attributes, [](const auto& item) { return item; }); - addSection(VirtualStringTreeValue1C, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, - CurCat->forms, [](const auto& item) { return item; }); - addSection(VirtualStringTreeValue1C, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, - CurCat->comands, [](const auto& item) { return item; }); - addSection(VirtualStringTreeValue1C, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, - CurCat->moxels, [](const auto& item) { return item; }); -} void __fastcall TMainForm::FillTreeMD(PVirtualNode parentNode, const MetadataVector& mdData, const String& md_name, int imgIndex) { - static const std::unordered_set catalogTypes = {md_Catalogs, md_Documents, md_Reports, md_DataProcessors, md_ChartsOfCharacteristicTypes, md_ChartOfCalculationTypes, md_BusinessProcesses, md_Tasks}; +static const std::unordered_set catalogTypes = {md_Catalogs, md_Documents, md_Reports, md_DataProcessors, md_ChartsOfCharacteristicTypes, md_ChartOfCalculationTypes, md_BusinessProcesses, md_Tasks}; static const std::unordered_set journalTypes = {md_DocumentJournals}; static const std::unordered_set chartAccTypes = {md_ChartOfAccounts}; static const std::unordered_set informationRegisterTypes = {md_InformationRegisters, md_AccumulationRegisters, md_AccountingRegisters, md_CalculationRegisters}; - + static const std::unordered_set exchangePlanTypes = {md_ExchangePlans}; for(size_t i = 0; i < mdData.size(); i++) { PVirtualNode childNode = VirtualStringTreeValue1C->AddChild(parentNode); @@ -570,61 +339,24 @@ void __fastcall TMainForm::FillTreeMD(PVirtualNode parentNode, const MetadataVec if (catalogTypes.count(md_name)) { - if (md_name == md_Catalogs) - { - TCatalogs* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_Documents) - { - TDocuments* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_Reports) - { - TReports* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_DataProcessors) - { - TDataProcessors* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_ChartsOfCharacteristicTypes) - { - TChartOfCharacteristicTypes* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_ChartOfCalculationTypes) - { - TChartOfCalculationTypes* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_BusinessProcesses) - { - TBusinessProceses* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } - else if (md_name == md_Tasks) - { - TTasks* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCatalogsTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); - } + BaseMetadataObject* metadataObject = dynamic_cast(mdData[i].get()); + if (metadataObject) + ::fillCatalogsTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, metadataObject); } else if (journalTypes.count(md_name)) { if (md_name == md_DocumentJournals) { TJournals* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillJournalTree(childNode, childData, imgIndex, CurCat->name, CurCat->getAttributes(), CurCat->getTabularSections(), CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); + if (CurCat) ::fillJournalTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } } - else if (chartAccTypes.count(md_name)) +else if (chartAccTypes.count(md_name)) { if (md_name == md_ChartOfAccounts) { TChartOfAccounts* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillChartAccTree(childNode, childData, imgIndex, CurCat->name, CurCat->attributes, CurCat->accflags, CurCat->dimaccflags, CurCat->tabulars, CurCat->forms, CurCat->comands, CurCat->moxels); + if (CurCat) ::fillChartAccTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } } else if (informationRegisterTypes.count(md_name)) @@ -632,55 +364,67 @@ void __fastcall TMainForm::FillTreeMD(PVirtualNode parentNode, const MetadataVec if (md_name == md_InformationRegisters) { TInformationRegisters* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillInformationRegisterTree(childNode, childData, imgIndex, CurCat->name, - CurCat->getAttributes(), CurCat->getDimensions(), CurCat->getResources(), - CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); + if (CurCat) ::fillInformationRegisterTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } else if (md_name == md_AccumulationRegisters) { TAccumulationRegisters* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillAccumulationRegisterTree(childNode, childData, imgIndex, CurCat->name, - CurCat->getAttributes(), CurCat->getDimensions(), CurCat->getResources(), - CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); + if (CurCat) ::fillAccumulationRegisterTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } else if (md_name == md_AccountingRegisters) { TAccountingRegisters* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillAccountingRegisterTree(childNode, childData, imgIndex, CurCat->name, - CurCat->getAttributes(), CurCat->getDimensions(), CurCat->getResources(), - CurCat->getAccountingFlags(), CurCat->getDimensionAccountingFlags(), - CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); + if (CurCat) ::fillAccountingRegisterTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } else if (md_name == md_CalculationRegisters) { TCalculationRegisters* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillCalculationRegisterTree(childNode, childData, imgIndex, CurCat->name, - CurCat->getAttributes(), CurCat->getDimensions(), CurCat->getResources(), - CurCat->getForms(), CurCat->getCommands(), CurCat->getLayouts()); + if (CurCat) ::fillCalculationRegisterTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } } + else if (exchangePlanTypes.count(md_name)) + { + TExchangePlans* CurCat = dynamic_cast(mdData[i].get()); + if (CurCat) ::fillCatalogsTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); + } + else if (md_name == md_FilterCriteria) + { + BaseMetadataObject* metadataObject = dynamic_cast(mdData[i].get()); + if (metadataObject) ::fillFormsCommandsTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, metadataObject); + } else if (md_name == md_Enums) { TEnums* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) fillEnumTree(childNode, childData, imgIndex, CurCat); + if (CurCat) ::fillEnumTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); + } + else if (md_name == md_ExternalDataSources) + { + TExternalDataSources* CurCat = dynamic_cast(mdData[i].get()); + if (CurCat) ::fillExternalDataSourceTree(VirtualStringTreeValue1C, childNode, childData, imgIndex, CurCat); } else { if (md_name == md_DocumentNumerators) { TNumerators* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) { childData->Name = CurCat->name; childData->Age = 30; childData->ImgIndex = imgIndex; } + if (CurCat) initNode(childData, CurCat->name, imgIndex); } else if (md_name == md_Sequences) { TSequences* CurCat = dynamic_cast(mdData[i].get()); - if (CurCat) { childData->Name = CurCat->name; childData->Age = 30; childData->ImgIndex = imgIndex; } + if (CurCat) initNode(childData, CurCat->name, imgIndex); } } } } void __fastcall TMainForm::FillVirtualTree() { + // Добавление команд и форм плана обмена + PVirtualNode exchangePlansNode = VirtualStringTreeValue1C->AddChild(nullptr); + VirtualTreeData *exchangePlansData = (VirtualTreeData*)VirtualStringTreeValue1C->GetNodeData(exchangePlansNode); + initNode(exchangePlansData, L"Планы обмена", 41, 25); + VirtualStringTreeValue1C->Expanded[exchangePlansNode] = true; + struct CategoryData { const MetadataVector* data; @@ -711,6 +455,7 @@ void __fastcall TMainForm::FillVirtualTree() { }; std::vector md_categoriesCommon = { + {&MainForm->mdSubsystems, md_Subsystems, 74, 25}, {&MainForm->mdCommonModules, md_CommonModules, 87, 25}, {&MainForm->mdSessionParameters, md_SessionParameters, 90, 25}, {&MainForm->mdRoles, md_Roles, 81, 25}, @@ -734,6 +479,7 @@ void __fastcall TMainForm::FillVirtualTree() { {&MainForm->mdWebServices, md_WebServices, 92, 25}, {&MainForm->mdHTTPServices, md_HTTPServices, 113, 25}, {&MainForm->mdWSReferences, md_WSReferences, 96, 25}, + {&MainForm->mdWebSocketClients, md_WebSocketClients, 96, 25}, {&MainForm->mdIntegrationServices, md_IntegrationServices, 131, 25}, {&MainForm->mdStyleItems, md_StyleItems, 76, 25}, {&MainForm->mdStyles, md_Styles, 75, 25}, @@ -761,6 +507,8 @@ void __fastcall TMainForm::FillVirtualTree() { if (category.name == "Общие") { + std::unordered_set nestedSubsystemGuids = collectChildSubsystemGuids(MainForm->GlobalCF.get(), MainForm->mdSubsystems); + for (const auto& categoryCom : md_categoriesCommon) { PVirtualNode parentNodeCom = VirtualStringTreeValue1C->AddChild(parentNode); @@ -769,182 +517,51 @@ void __fastcall TMainForm::FillVirtualTree() { parentNodeDataCom->Name = categoryCom.name; parentNodeDataCom->Age = categoryCom.age; parentNodeDataCom->ImgIndex = categoryCom.imgIndex; + if (categoryCom.name == md_Subsystems || categoryCom.name == md_ExchangePlans || categoryCom.name == md_FilterCriteria) + VirtualStringTreeValue1C->Expanded[parentNodeCom] = true; for (const auto& item : *categoryCom.data) { - PVirtualNode childNodeCom = VirtualStringTreeValue1C->AddChild(parentNodeCom); - VirtualTreeData *childDataCom = (VirtualTreeData*)VirtualStringTreeValue1C->GetNodeData(childNodeCom); + BaseMetadataObject* mdObj = dynamic_cast(item.get()); + if (!mdObj) continue; - if (categoryCom.name == md_CommonModules) - { - TCommonModules* CurModule = static_cast(item.get()); - childDataCom->Name = CurModule->name; - childDataCom->text_module = L""; - childDataCom->MetadataObject = CurModule; - } - else if (categoryCom.name == md_SessionParameters) - { - TSessionParameters* CurParam = static_cast(item.get()); - childDataCom->Name = CurParam->name; - childDataCom->text_module = L""; - childDataCom->MetadataObject = CurParam; - } - else if (categoryCom.name == md_Roles) - { - TRoles* CurRole = static_cast(item.get()); - childDataCom->Name = CurRole->GetRoleName(); - childDataCom->text_module = L""; - childDataCom->MetadataObject = CurRole; - } - else if (categoryCom.name == md_CommonAttributes) - { - TCommonAttributes* CurCommonAtt = static_cast(item.get()); - childDataCom->Name = CurCommonAtt->name; - childDataCom->text_module = L""; - childDataCom->MetadataObject = CurCommonAtt; - } - else if (categoryCom.name == md_ExchangePlans) - { - TExchangePlans* CurExchPlan = static_cast(item.get()); - childDataCom->Name = CurExchPlan->GetExchangePlanName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_FilterCriteria) - { - TFilterCriteria* CurFilter = static_cast(item.get()); - childDataCom->Name = CurFilter->GetFilterCriteriaName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_EventSubscriptions) - { - TEventSubscriptions* CurEventSub = static_cast(item.get()); - childDataCom->Name = CurEventSub->GetEventSubscriptionName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_ScheduledJobs) - { - TScheduledJobs* CurScheduledJob = static_cast(item.get()); - childDataCom->Name = CurScheduledJob->GetScheduledJobsName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_CommonCommands) - { - TCommonCommands* CurCommonCommand = static_cast(item.get()); - childDataCom->Name = CurCommonCommand->GetCommandName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_CommandGroups) - { - TCommandGroups* CurCommandGroup = static_cast(item.get()); - childDataCom->Name = CurCommandGroup->GetCommandName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_CommonForms) - { - TCommonForms* CurCommonForm = static_cast(item.get()); - childDataCom->Name = CurCommonForm->GetFormName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_Interfaces) - { - TInterfaces* CurInterface = static_cast(item.get()); - childDataCom->Name = CurInterface->GetInterfaceName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_CommonTemplates) - { - TCommonTemplates* CurCommonTemplate = static_cast(item.get()); - childDataCom->Name = CurCommonTemplate->GetTemplateName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_CommonPictures) - { - TCommonPictures* CurCommonPicture = static_cast(item.get()); - childDataCom->Name = CurCommonPicture->GetPictureName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_XDTOPackages) - { - TXDTOPackages* CurXDTOPackage = static_cast(item.get()); - childDataCom->Name = CurXDTOPackage->GetXDTOPackageName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_WebServices) - { - TWebServices* CurWebService = static_cast(item.get()); - childDataCom->Name = CurWebService->GetWebServiceName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_HTTPServices) - { - THTTPServices* CurHTTPServices = static_cast(item.get()); - childDataCom->Name = CurHTTPServices->GetHTTPServicesName(); - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_FunctionalOptions) - { - TFunctionalOptions* CurFO = static_cast(item.get()); - childDataCom->Name = CurFO->name; - childDataCom->text_module = L""; - childDataCom->Age = 99; - childDataCom->ImgIndex = categoryCom.imgIndex; - } - else if (categoryCom.name == md_FunctionalOptionsParameters) - { - TFunctionalOptionsParameters* CurFOP = static_cast(item.get()); - childDataCom->Name = CurFOP->name; - childDataCom->Age = 99; - childDataCom->ImgIndex = categoryCom.imgIndex; - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_DefinedTypes) - { - TDefinedTypes* CurDT = static_cast(item.get()); - childDataCom->Name = CurDT->name; - childDataCom->Age = 99; - childDataCom->ImgIndex = categoryCom.imgIndex; - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_SettingsStorages) + if (categoryCom.name == md_Subsystems) { - TSettingsStorages* CurSS = static_cast(item.get()); - childDataCom->Name = CurSS->name; - childDataCom->Age = 99; - childDataCom->ImgIndex = categoryCom.imgIndex; - childDataCom->text_module = L""; - } - else if (categoryCom.name == md_Languages) - { - TLangs* CurLang = static_cast(item.get()); - childDataCom->Name = CurLang->name; - childDataCom->Age = 99; - childDataCom->ImgIndex = categoryCom.imgIndex; - childDataCom->text_module = L""; - } - else - { - childDataCom->Name = L""; - childDataCom->text_module = L""; - childDataCom->MetadataObject = nullptr; + TSubsystem* CurSubsystem = static_cast(mdObj); + String subsystemFileGuid = normalizeGuid(CurSubsystem->guid); + String originalGuid = CurSubsystem->guid; + String subsystemInnerGuid = normalizeGuid(GetSubsystemInnerGuid(MainForm->GlobalCF.get(), originalGuid)); + if (nestedSubsystemGuids.count(subsystemFileGuid) || nestedSubsystemGuids.count(subsystemInnerGuid)) + continue; } + + PVirtualNode childNodeCom = VirtualStringTreeValue1C->AddChild(parentNodeCom); + VirtualTreeData *childDataCom = (VirtualTreeData*)VirtualStringTreeValue1C->GetNodeData(childNodeCom); + + childDataCom->Name = mdObj->GetName(); childDataCom->Age = 99; childDataCom->ImgIndex = categoryCom.imgIndex; - } + childDataCom->text_module = L""; + childDataCom->MetadataObject = mdObj; + if (categoryCom.name == md_ExchangePlans || categoryCom.name == md_FilterCriteria) + { + BaseMetadataObject* metadataObject = dynamic_cast(mdObj); + if (metadataObject) + { + if (categoryCom.name == md_FilterCriteria) + ::fillFormsCommandsTree(VirtualStringTreeValue1C, childNodeCom, childDataCom, categoryCom.imgIndex, metadataObject); + else + ::fillCatalogsTree(VirtualStringTreeValue1C, childNodeCom, childDataCom, categoryCom.imgIndex, metadataObject); + VirtualStringTreeValue1C->Expanded[childNodeCom] = true; + } + } - // Для Bots добавляем элементы из MainForm->mdBots - if (categoryCom.name == md_Bots && !MainForm->mdBots.empty()) - { - for (size_t i = 0; i < MainForm->mdBots.size(); i++) + if (categoryCom.name == md_Subsystems) { - TBots* CurBot = static_cast(MainForm->mdBots[i].get()); - PVirtualNode childNodeBots = VirtualStringTreeValue1C->AddChild(parentNodeCom); - VirtualTreeData *childDataBots = (VirtualTreeData*)VirtualStringTreeValue1C->GetNodeData(childNodeBots); - childDataBots->Name = CurBot->name; - childDataBots->Age = 99; - childDataBots->ImgIndex = categoryCom.imgIndex; - childDataBots->text_module = L""; - childDataBots->MetadataObject = CurBot; + TSubsystem* CurSubsystem = static_cast(mdObj); + VirtualStringTreeValue1C->Expanded[childNodeCom] = true; + addSubsystemChildrenToTree(VirtualStringTreeValue1C, childNodeCom, MainForm->GlobalCF.get(), MainForm->mdSubsystems, CurSubsystem, categoryCom.imgIndex); } } } @@ -1040,6 +657,18 @@ void __fastcall TMainForm::FillVirtualTree() { { FillTreeMD(parentNode, MainForm->mdInformationRegisters, md_InformationRegisters, category.imgIndex); } + else if (category.name == md_ExchangePlans) + { + FillTreeMD(parentNode, MainForm->mdExchangePlans, md_ExchangePlans, category.imgIndex); + } + else if (category.name == md_FilterCriteria) + { + FillTreeMD(parentNode, MainForm->mdFilterCriteria, md_FilterCriteria, category.imgIndex); + } + else if (category.name == md_ExternalDataSources) + { + FillTreeMD(parentNode, MainForm->mdExternalDataSources, md_ExternalDataSources, category.imgIndex); + } } @@ -1158,6 +787,7 @@ void __fastcall TMainForm::ActionFileOpenExecute(TObject *Sender) mdTasks.clear(); mdWebServices.clear(); mdWSReferences.clear(); + mdWebSocketClients.clear(); mdXDTOPackages.clear(); mdIntegrationServices.clear(); mdSequences.clear(); @@ -1222,6 +852,7 @@ void __fastcall TMainForm::ActionOpenCFExecute(TObject *Sender) { TMainForm::ActionFileOpenExecute(Sender); } + //--------------------------------------------------------------------------- // Messager //--------------------------------------------------------------------------- @@ -1468,61 +1099,6 @@ void get_cf_name(v8catalog* cf, Messager* mess) get_cf_name(tr.release(), mess); } -String GetNameSubsystem(v8catalog *cf, String &guid_md) -{ - String Result = ""; - v8file *filedata = cf->GetFile(guid_md); - if(!filedata) - { - return Result; - } - tree* tree_md = get_treeFromV8file(filedata); - if(!tree_md) - { - return Result; - } - tree* node = tree_md; - - node = &(*node)[0][1][1][2]; // guid подсистемы - - Result = node->get_value(); // имя подсистемы - - -} - -void GetListChildrenSubsystem(v8catalog *cf, String &guid_md, std::vector& child) -{ - v8file *filedata = cf->GetFile(guid_md); - if(!filedata) - { - return; - } - tree* tree_md = get_treeFromV8file(filedata); - if(!tree_md) - { - return; - } - tree* node = tree_md; - - node = &(*node)[0][3][0]; - - int CountChild = (node->get_next())->get_value().ToInt(); - - tree* curNodeChild = node->get_next(); - - while (curNodeChild) - { - curNodeChild = curNodeChild->get_next(); - if (curNodeChild) - { - child.push_back(curNodeChild->get_value()); - } - - } - -} - - void fill_subsystem(tree* tr, std::vector &md_subsys) { v8file *filedata; @@ -1560,6 +1136,113 @@ void fill_subsystem(tree* tr, std::vector &md_subsys) } } +namespace +{ + tree* GetNodeByPathSafe(tree* startNode, const std::vector& path) + { + tree* currentNode = startNode; + if (!currentNode) + return nullptr; + + for (size_t i = 0; i < path.size(); i++) + { + int idx = path[i]; + if (idx < 0 || idx >= currentNode->get_num_subnode()) + return nullptr; + + currentNode = currentNode->get_subnode(idx); + if (!currentNode) + return nullptr; + } + + return currentNode; + } + + void AddUniqueGuid(std::vector& guids, const String& guid) + { + if (guid.IsEmpty()) + return; + + for (const auto& existingGuid : guids) + { + if (existingGuid.CompareIC(guid) == 0) + return; + } + + guids.push_back(guid); + } + + void CollectMetadataSectionGuids(tree* node, const String& sectionGuid, std::vector& guids) + { + if (!node) + return; + + if (node->get_type() == nd_list && node->get_num_subnode() >= 2) + { + tree* guidNode = node->get_subnode(0); + tree* countNode = node->get_subnode(1); + if (guidNode && countNode && guidNode->get_value().CompareIC(sectionGuid) == 0 && countNode->get_type() == nd_number) + { + int count = countNode->get_value().ToIntDef(0); + for (int i = 0; i < count && i + 2 < node->get_num_subnode(); i++) + { + tree* itemNode = node->get_subnode(i + 2); + if (itemNode) + AddUniqueGuid(guids, itemNode->get_value()); + } + } + } + + for (int i = 0; i < node->get_num_subnode(); i++) + CollectMetadataSectionGuids(node->get_subnode(i), sectionGuid, guids); + } + + String GetObjectNameByPath(v8catalog* cf, const String& objectGuid, const std::vector& path) + { + if (!cf || objectGuid.IsEmpty()) + return L""; + + v8file* filedata = cf->GetFile(objectGuid); + if (!filedata) + return L""; + + std::unique_ptr objectTree(get_treeFromV8file(filedata)); + tree* nameNode = GetNodeByPathSafe(objectTree.get(), path); + if (nameNode && !nameNode->get_value().IsEmpty()) + return nameNode->get_value(); + + std::function findWsReferenceName = [&](tree* node) -> String + { + if (!node) + return L""; + + if (node->get_type() == nd_list && node->get_num_subnode() >= 3) + { + tree* markerNode = node->get_subnode(0); + tree* possibleNameNode = node->get_subnode(2); + if (markerNode && possibleNameNode && + (markerNode->get_value() == L"2" || markerNode->get_value() == L"3") && + possibleNameNode->get_type() == nd_string && + !possibleNameNode->get_value().IsEmpty()) + { + return possibleNameNode->get_value(); + } + } + + for (int i = 0; i < node->get_num_subnode(); i++) + { + String result = findWsReferenceName(node->get_subnode(i)); + if (!result.IsEmpty()) + return result; + } + + return L""; + }; + + return findWsReferenceName(objectTree.get()); + } +} + // Процедура заполняет метаданные по корневому гуиду void fill_md(tree* tr, String guid_md) @@ -1594,6 +1277,9 @@ void fill_md(tree* tr, String guid_md) {GUID_CommonPictures, {0,1,1,2}}, {GUID_ExchangePlans, {0,1,12,2}}, {GUID_WebServices, {0,1,2,2}}, + {GUID_WSReferences, {1,2,2}}, + {GUID_WebSocketClients, {0,1,1,2}}, + {GUID_IntegrationServices, {0,1,1,2}}, {GUID_FunctionalOptions, {0,1,1,2}}, {GUID_DefinedTypes, {0,1,3,2}}, {GUID_XDTOPackages, {0,1,1,2}}, @@ -1615,14 +1301,35 @@ void fill_md(tree* tr, String guid_md) {GUID_ChartsOfCalculationTypes, {0,1,1,1,2}}, {GUID_AccumulationRegisters, {0,1,13,1,2}}, {GUID_Sequences, {0,1,7,1,2}}, + {GUID_ExternalDataSources, {1,1,1,2}}, {GUID_DataProcessors, {0,1,3,1,2}}, {GUID_Enums, {0,1,5,1,2}}, - {GUID_DefinedTypes, {0,1,3,2}}, + {GUID_DefinedTypes, {0,1,3,2}}, {GUID_Bots, {0,1,1,2}} }; auto pathIt = namePaths.find(guid_md); + auto tryGetNodeByPath = [](tree* startNode, const std::vector& candidatePath) -> tree* + { + tree* currentNode = startNode; + if (!currentNode) + return nullptr; + + for (size_t i = 0; i < candidatePath.size(); i++) + { + int idx = candidatePath[i]; + if (idx < 0 || idx >= currentNode->get_num_subnode()) + return nullptr; + + currentNode = currentNode->get_subnode(idx); + if (!currentNode) + return nullptr; + } + + return currentNode; + }; + if (pathIt == namePaths.end()) { // GUID не найден в карте путей, пропустить msreg->AddMessage(L"fill_md: GUID не найден в карте путей: " + guid_md, MessageState::msWarning); @@ -1639,6 +1346,25 @@ void fill_md(tree* tr, String guid_md) const std::vector& path = pathIt->second; + if (guid_md == GUID_WSReferences) + { + std::vector referenceGuids; + CollectMetadataSectionGuids(tr, GUID_WSReferences, referenceGuids); + msreg->AddMessage(L"fill_md: WS-ссылок найдено структурным поиском: " + String((int)referenceGuids.size()), MessageState::msInfo); + + for (const auto& referenceGuid : referenceGuids) + { + String val = GetObjectNameByPath(cf, referenceGuid, path); + if (val.IsEmpty()) + val = referenceGuid; + + msreg->AddMessage(L"fill_md: Создание WS-ссылки: " + val, MessageState::msInfo); + MainForm->mdWSReferences.push_back(std::make_unique(cf, referenceGuid, val)); + } + + return; + } + msreg->AddMessage(L"fill_md: Получение количества элементов", MessageState::msInfo); tree* nextNode = node_md->get_next(); if (!nextNode) { @@ -1648,6 +1374,25 @@ void fill_md(tree* tr, String guid_md) int CountMD = nextNode->get_value().ToInt(); msreg->AddMessage(L"fill_md: Количество элементов: " + String(CountMD), MessageState::msInfo); + if (guid_md == GUID_ExternalDataSources) + { + tree* sourceNode = node_md->get_next(); + int processedExternalCount = 0; + while (sourceNode) + { + sourceNode = sourceNode->get_next(); + if (!sourceNode) + continue; + + processedExternalCount++; + String sourceGuid = sourceNode->get_value(); + msreg->AddMessage(L"fill_md: Создание внешнего источника данных из списка GUID: " + sourceGuid, MessageState::msInfo); + MainForm->mdExternalDataSources.push_back(std::make_unique(cf, sourceGuid)); + } + msreg->AddMessage(L"fill_md: Внешних источников данных создано: " + String((int)MainForm->mdExternalDataSources.size()), MessageState::msInfo); + return; + } + //md_list.clear(); tree* curNode = node_md->get_next(); @@ -1711,29 +1456,27 @@ void fill_md(tree* tr, String guid_md) } msreg->AddMessage(L"fill_md: Дерево разобрано успешно", MessageState::msInfo); - node = tree_md; - + node = nullptr; msreg->AddMessage(L"fill_md: Навигация по пути", MessageState::msInfo); try { - for (size_t i = 0; i < path.size(); i++) + std::vector> candidatePaths = {path}; + + if (guid_md == GUID_BusinessProcesses || guid_md == GUID_Tasks) { - int idx = path[i]; - msreg->AddMessage(L"fill_md: Шаг " + String((int)i) + L", индекс: " + String(idx), MessageState::msInfo); - - // Проверка границ - индекс должен быть в пределах количества подчиненных узлов - if (idx < 0 || idx >= node->get_num_subnode()) { - msreg->AddMessage(L"fill_md: Ошибка - индекс выходит за пределы на шаге " + String((int)i) - + L", доступно узлов: " + String(node->get_num_subnode()) - + L", запрошен индекс: " + String(idx), MessageState::msError); - node = nullptr; - break; - } + candidatePaths.push_back({0,1,1}); + candidatePaths.push_back({0,1,2}); + } + else if (guid_md == GUID_ExternalDataSources) + { + candidatePaths.push_back({1,0,1,2}); + candidatePaths.push_back({0,1,1,2}); + } - node = &(*node)[idx]; - if (!node) { - msreg->AddMessage(L"fill_md: Ошибка - узел стал null на шаге " + String((int)i), MessageState::msError); - break; - } + for (size_t candidateIndex = 0; candidateIndex < candidatePaths.size() && !node; candidateIndex++) + { + const std::vector& candidatePath = candidatePaths[candidateIndex]; + msreg->AddMessage(L"fill_md: Попытка пути #" + String((int)candidateIndex + 1), MessageState::msInfo); + node = tryGetNodeByPath(tree_md, candidatePath); } } catch (...) { @@ -1760,266 +1503,296 @@ void fill_md(tree* tr, String guid_md) String val = node->get_value(); msreg->AddMessage(L"fill_md: Получено значение длиной: " + String(val.Length()), MessageState::msInfo); if (val.Length() == 0) { - msreg->AddMessage(L"fill_md: Пропуск элемента - пустое значение: " + curNodeValue, MessageState::msError); - delete tree_md; - continue; + if (guid_md == GUID_ExternalDataSources) + { + val = curNodeValue; + msreg->AddMessage(L"fill_md: Имя внешнего источника данных пустое, используется GUID файла: " + val, MessageState::msWarning); + } + else + { + msreg->AddMessage(L"fill_md: Пропуск элемента - пустое значение: " + curNodeValue, MessageState::msError); + delete tree_md; + continue; + } } msreg->AddMessage(L"fill_md: Получено имя: " + val, MessageState::msInfo); + if ((processedCount == 1) || (processedCount % 25 == 0)) LogHeapStatus(L"fill_md: состояние памяти перед созданием объекта", guid_md, curNodeValue, processedCount, CountMD); - // Создание объектов для специфических типов - try { - if (guid_md == GUID_Catalogs) - { - msreg->AddMessage(L"fill_md: Создание справочника: " + val, MessageState::msInfo); - MainForm->mdCatalogs.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Languages) - { - msreg->AddMessage(L"fill_md: Создание языка: " + val, MessageState::msInfo); - MainForm->mdLanguages.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CommonModules) - { - msreg->AddMessage(L"fill_md: Создание общего модуля: " + val, MessageState::msInfo); - MainForm->mdCommonModules.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Roles) - { - msreg->AddMessage(L"fill_md: Создание роли: " + val, MessageState::msInfo); - MainForm->mdRoles.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CommonTemplates) - { - msreg->AddMessage(L"fill_md: Создание общего макета: " + val, MessageState::msInfo); - MainForm->mdCommonTemplates.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_HTTPServices) - { - msreg->AddMessage(L"fill_md: Создание HTTP-сервиса: " + val, MessageState::msInfo); - MainForm->mdHTTPServices.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_ScheduledJobs) - { - msreg->AddMessage(L"fill_md: Создание регламентного задания: " + val, MessageState::msInfo); - MainForm->mdScheduledJobs.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CommonAttributes) - { - msreg->AddMessage(L"fill_md: Создание общего реквизита: " + val, MessageState::msInfo); - MainForm->mdCommonAttributes.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_SessionParameters) - { - msreg->AddMessage(L"fill_md: Создание параметра сеанса: " + val, MessageState::msInfo); - MainForm->mdSessionParameters.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_FunctionalOptionsParameters) - { - msreg->AddMessage(L"fill_md: Создание параметра функциональной опции: " + val, MessageState::msInfo); - MainForm->mdFunctionalOptionsParameters.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Subsystems) - { - msreg->AddMessage(L"fill_md: Пропуск подсистемы: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_Interfaces) - { - msreg->AddMessage(L"fill_md: Создание интерфейса: " + val, MessageState::msInfo); - MainForm->mdInterfaces.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Styles) - { - msreg->AddMessage(L"fill_md: Пропуск стиля: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_FilterCriteria) - { - msreg->AddMessage(L"fill_md: Создание критерия отбора: " + val, MessageState::msInfo); - MainForm->mdFilterCriteria.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_SettingsStorages) - { - msreg->AddMessage(L"fill_md: Создание хранилища настроек: " + val, MessageState::msInfo); - MainForm->mdSettingsStorages.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_StyleItems) - { - msreg->AddMessage(L"fill_md: Пропуск элемента стиля: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_CommonPictures) - { - msreg->AddMessage(L"fill_md: Создание общей картинки: " + val, MessageState::msInfo); - MainForm->mdCommonPictures.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_ExchangePlans) - { - msreg->AddMessage(L"fill_md: Создание плана обмена: " + val, MessageState::msInfo); - MainForm->mdExchangePlans.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_EventSubscriptions) - { - msreg->AddMessage(L"fill_md: Создание подписки на событие: " + val, MessageState::msInfo); - MainForm->mdEventSubscriptions.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_WebServices) - { - msreg->AddMessage(L"fill_md: Создание веб-сервиса: " + val, MessageState::msInfo); - MainForm->mdWebServices.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_FunctionalOptions) - { - msreg->AddMessage(L"fill_md: Создание функциональной опции: " + val, MessageState::msInfo); - MainForm->mdFunctionalOptions.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_DefinedTypes) - { - msreg->AddMessage(L"fill_md: Создание определяемого типа: " + val, MessageState::msInfo); - MainForm->mdDefinedTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_XDTOPackages) - { - msreg->AddMessage(L"fill_md: Создание XDTO-пакета: " + val, MessageState::msInfo); - MainForm->mdXDTOPackages.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_WSReferences) - { - msreg->AddMessage(L"fill_md: Пропуск WS-ссылки: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_Constants) - { - msreg->AddMessage(L"fill_md: Создание константы: " + val, MessageState::msInfo); - MainForm->mdConstants.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Documents) - { - msreg->AddMessage(L"fill_md: Создание документа: " + val, MessageState::msInfo); - MainForm->mdDocuments.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CommonForms) - { - msreg->AddMessage(L"fill_md: Создание общей формы: " + val, MessageState::msInfo); - MainForm->mdCommonForms.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_InformationRegisters) - { - msreg->AddMessage(L"fill_md: Создание регистра сведений: " + val, MessageState::msInfo); - MainForm->mdInformationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CalculationRegisters) - { - msreg->AddMessage(L"fill_md: Создание регистра расчета: " + val, MessageState::msInfo); - MainForm->mdCalculationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_BusinessProcesses) - { - msreg->AddMessage(L"fill_md: Создание бизнес-процесса: " + val, MessageState::msInfo); - MainForm->mdBusinessProcesses.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Tasks) - { - msreg->AddMessage(L"fill_md: Создание задачи: " + val, MessageState::msInfo); - MainForm->mdTasks.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_AccountingRegisters) - { - msreg->AddMessage(L"fill_md: Создание регистра бухгалтерии: " + val, MessageState::msInfo); - MainForm->mdAccountingRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); - msreg->AddMessage(L"fill_md: Регистр бухгалтерии создан успешно: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_CommandGroups) - { - msreg->AddMessage(L"fill_md: Создание группы команд: " + val, MessageState::msInfo); - MainForm->mdCommandGroups.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_CommonCommands) - { - msreg->AddMessage(L"fill_md: Создание общей команды: " + val, MessageState::msInfo); - MainForm->mdCommonCommands.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Numerators) - { - msreg->AddMessage(L"fill_md: Создание нумератора: " + val, MessageState::msInfo); - MainForm->mdDocumentNumerators.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_JournDocuments) - { - msreg->AddMessage(L"fill_md: Создание журнала документов: " + val, MessageState::msInfo); - MainForm->mdDocumentJournals.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Reports) - { - msreg->AddMessage(L"fill_md: Создание отчета: " + val, MessageState::msInfo); - MainForm->mdReports.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_ChartOfCharacteristicTypes) - { - msreg->AddMessage(L"fill_md: Создание ПВХ: " + val, MessageState::msInfo); - MainForm->mdChartsOfCharacteristicTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_ChartsOfAccounts) - { - msreg->AddMessage(L"fill_md: Создание плана счетов: " + val, MessageState::msInfo); - MainForm->mdChartOfAccounts.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_ChartsOfCalculationTypes) - { - msreg->AddMessage(L"fill_md: Создание ПВР: " + val, MessageState::msInfo); - MainForm->mdChartOfCalculationTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_AccumulationRegisters) - { - msreg->AddMessage(L"fill_md: Создание регистра накопления: " + val, MessageState::msInfo); - MainForm->mdAccumulationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); - msreg->AddMessage(L"fill_md: Регистр накопления создан успешно: " + val, MessageState::msInfo); - } - else if (guid_md == GUID_Sequences) - { - msreg->AddMessage(L"fill_md: Создание последовательности: " + val, MessageState::msInfo); - MainForm->mdSequences.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_DataProcessors) - { - msreg->AddMessage(L"fill_md: Создание обработки: " + val, MessageState::msInfo); - MainForm->mdDataProcessors.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Enums) - { - msreg->AddMessage(L"fill_md: Создание перечисления: " + val, MessageState::msInfo); - MainForm->mdEnums.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else if (guid_md == GUID_Bots) - { - msreg->AddMessage(L"fill_md: Создание бота: " + val, MessageState::msInfo); - MainForm->mdBots.push_back(std::make_unique(cf, curNode->get_value(), val)); - } - else - { - msreg->AddMessage(L"fill_md: Неизвестный GUID для объекта: " + val, MessageState::msWarning); - } - } - catch (const Exception &e) { - msreg->AddMessage_(L"fill_md: VCL exception при создании объекта", msError, - L"Name", val, - L"GUID", guid_md, - L"File", curNodeValue, - L"Message", e.Message); - LogHeapStatus(L"fill_md: память при VCL exception создания объекта", guid_md, curNodeValue, processedCount, CountMD); - } - catch (...) { - msreg->AddMessage_(L"fill_md: неизвестное исключение при создании объекта", msError, - L"Name", val, - L"GUID", guid_md, - L"File", curNodeValue); - LogHeapStatus(L"fill_md: память при неизвестном exception создания объекта", guid_md, curNodeValue, processedCount, CountMD); - } - delete tree_md; - //md_list.push_back(val); - } + // Создание объектов для специфических типов + try { + if (guid_md == GUID_Catalogs) + { + msreg->AddMessage(L"fill_md: Создание справочника: " + val, MessageState::msInfo); + MainForm->mdCatalogs.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Languages) + { + msreg->AddMessage(L"fill_md: Создание языка: " + val, MessageState::msInfo); + MainForm->mdLanguages.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonModules) + { + msreg->AddMessage(L"fill_md: Создание общего модуля: " + val, MessageState::msInfo); + MainForm->mdCommonModules.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Roles) + { + msreg->AddMessage(L"fill_md: Создание роли: " + val, MessageState::msInfo); + MainForm->mdRoles.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonTemplates) + { + msreg->AddMessage(L"fill_md: Создание общего макета: " + val, MessageState::msInfo); + MainForm->mdCommonTemplates.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_HTTPServices) + { + msreg->AddMessage(L"fill_md: Создание HTTP-сервиса: " + val, MessageState::msInfo); + MainForm->mdHTTPServices.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ScheduledJobs) + { + msreg->AddMessage(L"fill_md: Создание регламентного задания: " + val, MessageState::msInfo); + MainForm->mdScheduledJobs.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonAttributes) + { + msreg->AddMessage(L"fill_md: Создание общего реквизита: " + val, MessageState::msInfo); + MainForm->mdCommonAttributes.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_SessionParameters) + { + msreg->AddMessage(L"fill_md: Создание параметра сеанса: " + val, MessageState::msInfo); + MainForm->mdSessionParameters.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_FunctionalOptionsParameters) + { + msreg->AddMessage(L"fill_md: Создание параметра функциональной опции: " + val, MessageState::msInfo); + MainForm->mdFunctionalOptionsParameters.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Subsystems) + { + //msreg->AddMessage(L"fill_md: Пропуск подсистемы: " + val, MessageState::msInfo); + msreg->AddMessage(L"fill_md: Создание подсистемы: " + val, MessageState::msInfo); + MainForm->mdSubsystems.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Interfaces) + { + msreg->AddMessage(L"fill_md: Создание интерфейса: " + val, MessageState::msInfo); + MainForm->mdInterfaces.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Styles) + { + msreg->AddMessage(L"fill_md: Создание стиля: " + val, MessageState::msInfo); + MainForm->mdStyles.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_FilterCriteria) + { + msreg->AddMessage(L"fill_md: Создание критерия отбора: " + val, MessageState::msInfo); + MainForm->mdFilterCriteria.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_SettingsStorages) + { + msreg->AddMessage(L"fill_md: Создание хранилища настроек: " + val, MessageState::msInfo); + MainForm->mdSettingsStorages.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_StyleItems) + { + msreg->AddMessage(L"fill_md: Создание элемента стиля: " + val, MessageState::msInfo); + MainForm->mdStyleItems.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonPictures) + { + msreg->AddMessage(L"fill_md: Создание общей картинки: " + val, MessageState::msInfo); + MainForm->mdCommonPictures.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ExchangePlans) + { + msreg->AddMessage(L"fill_md: Создание плана обмена: " + val, MessageState::msInfo); + MainForm->mdExchangePlans.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_EventSubscriptions) + { + msreg->AddMessage(L"fill_md: Создание подписки на событие: " + val, MessageState::msInfo); + MainForm->mdEventSubscriptions.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_WebServices) + { + msreg->AddMessage(L"fill_md: Создание веб-сервиса: " + val, MessageState::msInfo); + MainForm->mdWebServices.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_FunctionalOptions) + { + msreg->AddMessage(L"fill_md: Создание функциональной опции: " + val, MessageState::msInfo); + MainForm->mdFunctionalOptions.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_DefinedTypes) + { + msreg->AddMessage(L"fill_md: Создание определяемого типа: " + val, MessageState::msInfo); + MainForm->mdDefinedTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_XDTOPackages) + { + msreg->AddMessage(L"fill_md: Создание XDTO-пакета: " + val, MessageState::msInfo); + MainForm->mdXDTOPackages.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_WSReferences) + { + msreg->AddMessage(L"fill_md: Создание WS-ссылки: " + val, MessageState::msInfo); + MainForm->mdWSReferences.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_WebSocketClients) + { + msreg->AddMessage(L"fill_md: Создание WebSocket-клиента: " + val, MessageState::msInfo); + MainForm->mdWebSocketClients.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_IntegrationServices) + { + msreg->AddMessage(L"fill_md: Создание сервиса интеграции: " + val, MessageState::msInfo); + MainForm->mdIntegrationServices.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Constants) + { + msreg->AddMessage(L"fill_md: Создание константы: " + val, MessageState::msInfo); + MainForm->mdConstants.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Documents) + { + msreg->AddMessage(L"fill_md: Создание документа: " + val, MessageState::msInfo); + MainForm->mdDocuments.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonForms) + { + msreg->AddMessage(L"fill_md: Создание общей формы: " + val, MessageState::msInfo); + MainForm->mdCommonForms.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_InformationRegisters) + { + msreg->AddMessage(L"fill_md: Создание регистра сведений: " + val, MessageState::msInfo); + MainForm->mdInformationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CalculationRegisters) + { + msreg->AddMessage(L"fill_md: Создание регистра расчета: " + val, MessageState::msInfo); + MainForm->mdCalculationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_BusinessProcesses) + { + msreg->AddMessage(L"fill_md: Создание бизнес-процесса: " + val, MessageState::msInfo); + MainForm->mdBusinessProcesses.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Tasks) + { + msreg->AddMessage(L"fill_md: Создание задачи: " + val, MessageState::msInfo); + MainForm->mdTasks.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_AccountingRegisters) + { + msreg->AddMessage(L"fill_md: Создание регистра бухгалтерии: " + val, MessageState::msInfo); + MainForm->mdAccountingRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); + msreg->AddMessage(L"fill_md: Регистр бухгалтерии создан успешно: " + val, MessageState::msInfo); + } + else if (guid_md == GUID_CommandGroups) + { + msreg->AddMessage(L"fill_md: Создание группы команд: " + val, MessageState::msInfo); + MainForm->mdCommandGroups.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_CommonCommands) + { + msreg->AddMessage(L"fill_md: Создание общей команды: " + val, MessageState::msInfo); + MainForm->mdCommonCommands.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Numerators) + { + msreg->AddMessage(L"fill_md: Создание нумератора: " + val, MessageState::msInfo); + MainForm->mdDocumentNumerators.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_JournDocuments) + { + msreg->AddMessage(L"fill_md: Создание журнала документов: " + val, MessageState::msInfo); + MainForm->mdDocumentJournals.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Reports) + { + msreg->AddMessage(L"fill_md: Создание отчета: " + val, MessageState::msInfo); + MainForm->mdReports.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ChartOfCharacteristicTypes) + { + msreg->AddMessage(L"fill_md: Создание ПВХ: " + val, MessageState::msInfo); + MainForm->mdChartsOfCharacteristicTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ChartsOfAccounts) + { + msreg->AddMessage(L"fill_md: Создание плана счетов: " + val, MessageState::msInfo); + MainForm->mdChartOfAccounts.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ChartsOfCalculationTypes) + { + msreg->AddMessage(L"fill_md: Создание ПВР: " + val, MessageState::msInfo); + MainForm->mdChartOfCalculationTypes.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_AccumulationRegisters) + { + msreg->AddMessage(L"fill_md: Создание регистра накопления: " + val, MessageState::msInfo); + MainForm->mdAccumulationRegisters.push_back(std::make_unique(cf, curNode->get_value(), val)); + msreg->AddMessage(L"fill_md: Регистр накопления создан успешно: " + val, MessageState::msInfo); + } + else if (guid_md == GUID_Sequences) + { + msreg->AddMessage(L"fill_md: Создание последовательности: " + val, MessageState::msInfo); + MainForm->mdSequences.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_DataProcessors) + { + msreg->AddMessage(L"fill_md: Создание обработки: " + val, MessageState::msInfo); + MainForm->mdDataProcessors.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Enums) + { + msreg->AddMessage(L"fill_md: Создание перечисления: " + val, MessageState::msInfo); + MainForm->mdEnums.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_Bots) + { + msreg->AddMessage(L"fill_md: Создание бота: " + val, MessageState::msInfo); + MainForm->mdBots.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else if (guid_md == GUID_ExternalDataSources) + { + msreg->AddMessage(L"fill_md: Создание внешнего источника данных: " + val, MessageState::msInfo); + MainForm->mdExternalDataSources.push_back(std::make_unique(cf, curNode->get_value(), val)); + } + else + { + msreg->AddMessage(L"fill_md: Неизвестный GUID для объекта: " + val, MessageState::msWarning); + } + } + catch (const Exception &e) { + msreg->AddMessage_(L"fill_md: VCL exception при создании объекта", msError, + L"Name", val, + L"GUID", guid_md, + L"File", curNodeValue, + L"Message", e.Message); + LogHeapStatus(L"fill_md: память при VCL exception создания объекта", guid_md, curNodeValue, processedCount, CountMD); + } + catch (...) { + msreg->AddMessage_(L"fill_md: неизвестное исключение при создании объекта", msError, + L"Name", val, + L"GUID", guid_md, + L"File", curNodeValue); + LogHeapStatus(L"fill_md: память при неизвестном exception создания объекта", guid_md, curNodeValue, processedCount, CountMD); + } + delete tree_md; + //md_list.push_back(val); + } - } + } } + void get_cf_name(tree* tr, Messager* mess) { int j, k; @@ -2460,7 +2233,7 @@ void get_cf_name(tree* tr, Messager* mess) if (MainForm) MainForm->AdvanceLoadProgress(L"Обработка подсистем..."); mess->AddMessage(L"Начало обработки подсистем", MessageState::msInfo); try { - fill_subsystem(tr, MainForm->Subsystems); + fill_md(tr, GUID_Subsystems); } catch (...) { mess->AddMessage(L"Исключение при обработке подсистем", MessageState::msError); @@ -2500,6 +2273,28 @@ void get_cf_name(tree* tr, Messager* mess) } mess->AddMessage(L"ws-ссылки обработаны", MessageState::msInfo); + // websocket-клиенты + if (MainForm) MainForm->AdvanceLoadProgress(L"Обработка WebSocket-клиентов..."); + mess->AddMessage(L"Начало обработки WebSocket-клиентов", MessageState::msInfo); + try { + fill_md(tr, GUID_WebSocketClients); + } + catch (...) { + mess->AddMessage(L"Исключение при обработке WebSocket-клиентов", MessageState::msError); + } + mess->AddMessage(L"WebSocket-клиенты обработаны", MessageState::msInfo); + + // сервисы интеграции + if (MainForm) MainForm->AdvanceLoadProgress(L"Обработка сервисов интеграции..."); + mess->AddMessage(L"Начало обработки сервисов интеграции", MessageState::msInfo); + try { + fill_md(tr, GUID_IntegrationServices); + } + catch (...) { + mess->AddMessage(L"Исключение при обработке сервисов интеграции", MessageState::msError); + } + mess->AddMessage(L"Сервисы интеграции обработаны", MessageState::msInfo); + // xdto-пакеты if (MainForm) MainForm->AdvanceLoadProgress(L"Обработка XDTO-пакетов..."); mess->AddMessage(L"Начало обработки XDTO-пакетов", MessageState::msInfo); @@ -2623,7 +2418,13 @@ void __fastcall TMainForm::VirtualStringTreeValue1CClick(TObject *Sender) if (module) MemoObject->Text = module->GetText(); else - MemoObject->Text = Data->text_module; + { + TCommonForms* commonForm = dynamic_cast(Data->MetadataObject); + if (commonForm) + MemoObject->Text = commonForm->GetText(); + else + MemoObject->Text = Data->text_module; + } } } //--------------------------------------------------------------------------- @@ -2647,6 +2448,36 @@ void __fastcall TMainForm::VirtualStringTreeValue1CClick(TObject *Sender) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MainUnit.h b/src/MainUnit.h index 830f363..9a518f9 100644 --- a/src/MainUnit.h +++ b/src/MainUnit.h @@ -123,57 +123,7 @@ class TMainForm : public TForm void __fastcall FillVirtualTree(); void __fastcall FillTreeMD(PVirtualNode parentNode, const MetadataVector& mdData, const String& md_name, int imgIndex); void __fastcall FillTreeMDConcrete(TVirtualStringTree *tree1C, PVirtualNode parentNode, const MetadataVector& mdData, const String& md_name, int imgIndex); - void __fastcall fillEnumTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, TEnums* CurCat); - void __fastcall fillCatalogsTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillJournalTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillChartAccTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& accflags, - const std::vector>& dimaccflags, - const std::vector>& tabulars, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillInformationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillAccumulationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillAccountingRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& accountingFlags, - const std::vector>& dimensionAccountingFlags, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); - void __fastcall fillCalculationRegisterTree(PVirtualNode childNode, VirtualTreeData *childData, int imgIndex, String name, - const std::vector>& attributes, - const std::vector>& dimensions, - const std::vector>& resources, - const std::vector>& forms, - const std::vector>& comands, - const std::vector>& moxels); + String ConfigName; @@ -218,11 +168,12 @@ class TMainForm : public TForm MetadataVector mdSettingsStorages; MetadataVector mdStyleItems; MetadataVector mdStyles; - std::vector Subsystems; + //std::vector Subsystems; - возможно надо удалить, т.к. лишнее уже MetadataVector mdSubsystems; MetadataVector mdTasks; MetadataVector mdWebServices; MetadataVector mdWSReferences; + MetadataVector mdWebSocketClients; MetadataVector mdXDTOPackages; MetadataVector mdIntegrationServices; MetadataVector mdSequences; diff --git a/src/MetaDataManager.cpp b/src/MetaDataManager.cpp index c1d793d..1200e26 100644 --- a/src/MetaDataManager.cpp +++ b/src/MetaDataManager.cpp @@ -23,6 +23,8 @@ #include "DefinedTypes.h" #include "SettingsStorages.h" #include "Interfaces.h" +// Added for tree population utilities +#include "MetadataTreeBuilder.h" //--------------------------------------------------------------------------- #pragma package(smart_init) @@ -132,7 +134,19 @@ bool MetaDataManager::Initialize(v8catalog* cf) void MetaDataManager::populateTreeView(TVirtualStringTree* tvSringTree) { - + // Simple implementation to ensure the tree view is populated with a root node. + if (!tvSringTree) + return; + + // Clear any existing nodes + tvSringTree->Clear(); + + // Add root node + PVirtualNode rootNode = tvSringTree->AddChild(nullptr); + VirtualTreeData* rootData = static_cast(tvSringTree->GetNodeData(rootNode)); + // Use the defined root icon index from TreeImage namespace + initNode(rootData, L"Metadata", TreeImage::Root); + tvSringTree->Expanded[rootNode] = true; } std::shared_ptr MetaDataManager::getObject(const String& type, const String& name) diff --git a/src/MetadataObjectWithSections.cpp b/src/MetadataObjectWithSections.cpp index b2e29a4..363e07e 100644 --- a/src/MetadataObjectWithSections.cpp +++ b/src/MetadataObjectWithSections.cpp @@ -8,6 +8,43 @@ //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + tree* GetNodeByPath(tree* root, const std::vector& indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} + __fastcall MetadataObjectWithSections::MetadataObjectWithSections() : BaseMetadataObject() { @@ -33,17 +70,16 @@ void MetadataObjectWithSections::initializeFromTreeWithPaths(const MetadataTreeP // Реквизиты attributes.clear(); - tree* node_att = root_data.get(); - node_att = &(*node_att)[0][paths.attIdx][1]; - int CountAtt = node_att->get_value().ToInt(); + tree* node_att = GetNodeByPath(root_data.get(), {0, paths.attIdx, 1}); + int CountAtt = node_att ? node_att->get_value().ToIntDef(0) : 0; int Delta = CountAtt - 2; for (int i = 0; i < CountAtt; i++) { try { - tree* node_att_att = root_data.get(); - tree* itemNode = &(*node_att_att)[0][paths.attIdx][i + CountAtt - Delta]; - for (size_t p = 0; p < paths.attItemPath.size(); p++) - itemNode = &(*itemNode)[paths.attItemPath[p]]; + tree* itemNode = GetNodeByPath(root_data.get(), {0, paths.attIdx, i + CountAtt - Delta}); + itemNode = GetNodeByPath(itemNode, paths.attItemPath); + if (!itemNode) + continue; String NameAtt = itemNode->get_value(); attributes.push_back(std::make_unique(NameAtt, "")); } catch (...) { @@ -54,67 +90,95 @@ void MetadataObjectWithSections::initializeFromTreeWithPaths(const MetadataTreeP tabulars.clear(); if (paths.hasTabulars) { - tree* node_att_t = root_data.get(); - node_att_t = &(*node_att_t)[0][paths.tabIdx][1]; - int CountAttTab = node_att_t->get_value().ToInt(); + tree* node_att_t = GetNodeByPath(root_data.get(), {0, paths.tabIdx, 1}); + int CountAttTab = node_att_t ? node_att_t->get_value().ToIntDef(0) : 0; int DeltaTab = CountAttTab - 2; for (int i = 0; i < CountAttTab; i++) { - tree* node_att_tab = root_data.get(); - tree* itemNode = &(*node_att_tab)[0][paths.tabIdx][i + CountAttTab - DeltaTab]; - for (size_t p = 0; p < paths.tabItemPath.size(); p++) - itemNode = &(*itemNode)[paths.tabItemPath[p]]; + tree* tabularNode = GetNodeByPath(root_data.get(), {0, paths.tabIdx, i + CountAttTab - DeltaTab}); + tree* itemNode = GetNodeByPath(tabularNode, paths.tabItemPath); + if (!itemNode || !tabularNode) + continue; String NameAttTab = itemNode->get_value(); - tabulars.push_back(std::make_unique(NameAttTab, "")); + String GuidAttTab; + tree* guidNode = GetNodeByPath(tabularNode, {0, 1, 5, 1, 1}); + if (guidNode) + GuidAttTab = Trim(guidNode->get_value()); + + auto tabular = std::make_unique(NameAttTab, GuidAttTab); + + std::unique_ptr tabularRootData; + if (parent && !GuidAttTab.IsEmpty()) + { + v8file* tabularFile = parent->GetFile(GuidAttTab); + if (tabularFile) + tabularRootData.reset(get_treeFromV8file(tabularFile)); + } + + tabular->initializeFromTree(tabularRootData ? tabularRootData.get() : tabularNode); + tabulars.push_back(std::move(tabular)); } } // Формы forms.clear(); - tree* node = root_data.get(); - node = &(*node)[0][paths.formsIdx][0]; - int CountChild = (node->get_next())->get_value().ToInt(); - tree* curNodeChild = node->get_next(); + tree* node = GetNodeByPath(root_data.get(), {0, paths.formsIdx, 0}); + tree* curNodeChild = node ? node->get_next() : nullptr; while (curNodeChild) { curNodeChild = curNodeChild->get_next(); if (curNodeChild) { - String guid_md = curNodeChild->get_value(); - String NameForm = paths.getFormNameFunc(parent, guid_md); - forms.push_back(std::make_unique(NameForm, "")); + try + { + String guid_md = curNodeChild->get_value(); + String NameForm = paths.getFormNameFunc(parent, guid_md); + forms.push_back(std::make_unique(NameForm, "")); + } + catch (...) + { + } } } // Команды comands.clear(); - tree* node_att_c = root_data.get(); - node_att_c = &(*node_att_c)[0][paths.cmdIdx][1]; - int CountCom = node_att_c->get_value().ToInt(); + tree* node_att_c = GetNodeByPath(root_data.get(), {0, paths.cmdIdx, 1}); + int CountCom = node_att_c ? node_att_c->get_value().ToIntDef(0) : 0; int DeltaCom = CountCom - 2; for (int i = 0; i < CountCom; i++) { - tree* node_com = root_data.get(); - tree* itemNode = &(*node_com)[0][paths.cmdIdx][i + CountCom - DeltaCom]; - for (size_t p = 0; p < paths.cmdItemPath.size(); p++) - itemNode = &(*itemNode)[paths.cmdItemPath[p]]; - String NameCom = itemNode->get_value(); - comands.push_back(std::make_unique(NameCom, "")); + try + { + tree* itemNode = GetNodeByPath(root_data.get(), {0, paths.cmdIdx, i + CountCom - DeltaCom}); + itemNode = GetNodeByPath(itemNode, paths.cmdItemPath); + if (!itemNode) + continue; + String NameCom = itemNode->get_value(); + comands.push_back(std::make_unique(NameCom, "")); + } + catch (...) + { + } } // Макеты moxels.clear(); - tree* node_mox = root_data.get(); - node_mox = &(*node_mox)[0][paths.moxIdx][0]; - int CountMox = (node_mox->get_next())->get_value().ToInt(); - tree* curNodeChildMox = node_mox->get_next(); + tree* node_mox = GetNodeByPath(root_data.get(), {0, paths.moxIdx, 0}); + tree* curNodeChildMox = node_mox ? node_mox->get_next() : nullptr; while (curNodeChildMox) { curNodeChildMox = curNodeChildMox->get_next(); if (curNodeChildMox) { - String NameMox = GetNameMoxCatalogs(parent, curNodeChildMox->get_value()); - moxels.push_back(std::make_unique(NameMox, "")); + try + { + String NameMox = GetNameMoxCatalogs(parent, curNodeChildMox->get_value()); + moxels.push_back(std::make_unique(NameMox, "")); + } + catch (...) + { + } } } } diff --git a/src/MetadataTreeBuilder.cpp b/src/MetadataTreeBuilder.cpp new file mode 100644 index 0000000..a419034 --- /dev/null +++ b/src/MetadataTreeBuilder.cpp @@ -0,0 +1,483 @@ +//--------------------------------------------------------------------------- +#pragma hdrstop + +#include "MetadataTreeBuilder.h" +#include "Parse_tree.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +//--------------------------------------------------------------------------- +// Базовые операции с узлами дерева + +void initNode(VirtualTreeData* data, const String& name, int imageIndex, int age) +{ + data->Name = name; + data->Age = age; + data->ImgIndex = imageIndex; +} + +PVirtualNode addChildNode(TVirtualStringTree* tree, PVirtualNode parent, const String& name, int imageIndex, int age) +{ + PVirtualNode childNode = tree->AddChild(parent); + VirtualTreeData* childData = static_cast(tree->GetNodeData(childNode)); + initNode(childData, name, imageIndex, age); + return childNode; +} + +void addTabularSections(TVirtualStringTree* tree, PVirtualNode parent, + const std::vector>& items, int age) +{ + PVirtualNode sectionNode = addChildNode(tree, parent, L"Табличные части", TreeImage::TabularSections, age); + tree->Expanded[sectionNode] = true; + + for (const auto& item : items) + { + PVirtualNode tabularNode = addChildNode(tree, sectionNode, item->name, TreeImage::TabularSections, age); + if (!item->attributes.empty()) + { + for (const auto& attribute : item->attributes) + addChildNode(tree, tabularNode, attribute->name, TreeImage::Attributes, age); + tree->Expanded[tabularNode] = true; + } + } +} + +//--------------------------------------------------------------------------- +// Секции для стандартных объектов и регистров + +void fillStandardMetadataSections(TVirtualStringTree* tree, PVirtualNode childNode, + BaseMetadataObject* metadataObject) +{ + if (!metadataObject) + return; + + addSection(tree, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, + metadataObject->getAttributes(), [](const auto& item) { return item->name; }); + addTabularSections(tree, childNode, metadataObject->getTabularSections(), 0); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + metadataObject->getLayouts(), [](const auto& item) { return item->name; }); +} + +void fillInformationRegisterSections(TVirtualStringTree* tree, PVirtualNode childNode, + MetadataObjectInformationRegister* metadataObject) +{ + if (!metadataObject) + return; + + addSection(tree, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, + metadataObject->getDimensions(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, + metadataObject->getResources(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, + metadataObject->getAttributes(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + metadataObject->getLayouts(), [](const auto& item) { return item->name; }); +} + +//--------------------------------------------------------------------------- +// fill*Tree + +void fillCatalogsTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + fillStandardMetadataSections(tree, childNode, metadataObject); +} + +void fillFormsCommandsTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); +} + +void fillAccumulationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + fillInformationRegisterSections(tree, childNode, metadataObject); +} + +void fillCalculationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + fillInformationRegisterSections(tree, childNode, metadataObject); +} + +void fillInformationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + fillInformationRegisterSections(tree, childNode, metadataObject); +} + +void fillAccountingRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TAccountingRegisters* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + + addSection(tree, childNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, + metadataObject->getDimensions(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, + metadataObject->getResources(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, + metadataObject->getAttributes(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Признаки учета", TreeImage::AccountingFlags, TreeImage::AccountingFlags, + metadataObject->getAccountingFlags(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Признаки учета субконто", TreeImage::SubcontoFlags, TreeImage::SubcontoFlags, + metadataObject->getDimensionAccountingFlags(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + metadataObject->getLayouts(), [](const auto& item) { return item->name; }); +} + +void fillChartAccTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TChartOfAccounts* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + + addSection(tree, childNode, L"Реквизиты", TreeImage::Attributes, TreeImage::Attributes, + metadataObject->getAttributes(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Признаки учета", TreeImage::AccountingFlags, TreeImage::AccountingFlags, + metadataObject->accflags, [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Признаки учета субконто", TreeImage::SubcontoFlags, TreeImage::SubcontoFlags, + metadataObject->dimaccflags, [](const auto& item) { return item->name; }); + addTabularSections(tree, childNode, metadataObject->getTabularSections(), 0); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + metadataObject->getLayouts(), [](const auto& item) { return item->name; }); +} + +void fillJournalTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject) +{ + if (!metadataObject) + return; + initNode(childData, metadataObject->name, imgIndex); + + addSection(tree, childNode, L"Графы", TreeImage::JournalColumns, TreeImage::JournalColumns, + metadataObject->getAttributes(), [](const auto& item) { return item->name; }); + addTabularSections(tree, childNode, metadataObject->getTabularSections()); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + metadataObject->getForms(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + metadataObject->getCommands(), [](const auto& item) { return item->name; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + metadataObject->getLayouts(), [](const auto& item) { return item->name; }); +} + +void fillEnumTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TEnums* curEnum) +{ + initNode(childData, curEnum->name, imgIndex); + + addSection(tree, childNode, L"Значения", TreeImage::Attributes, TreeImage::Attributes, + curEnum->attributes, [](const auto& item) { return item; }); + addSection(tree, childNode, L"Формы", TreeImage::Forms, TreeImage::Forms, + curEnum->forms, [](const auto& item) { return item; }); + addSection(tree, childNode, L"Команды", TreeImage::Commands, TreeImage::Commands, + curEnum->comands, [](const auto& item) { return item; }); + addSection(tree, childNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, + curEnum->moxels, [](const auto& item) { return item; }); +} + +namespace +{ + void addStringSection(TVirtualStringTree* tree, PVirtualNode parent, + const String& sectionName, int sectionImageIndex, int itemImageIndex, + const std::vector& items) + { + PVirtualNode sectionNode = nullptr; + for (const auto& item : items) + { + if (!item.IsEmpty()) + { + if (!sectionNode) + sectionNode = addChildNode(tree, parent, sectionName, sectionImageIndex); + addChildNode(tree, sectionNode, item, itemImageIndex); + } + } + } + + void fillExternalTableTree(TVirtualStringTree* tree, PVirtualNode parent, + const TExternalDataSourceTable& tableData, int imgIndex) + { + PVirtualNode tableNode = addChildNode(tree, parent, tableData.name, imgIndex); + addStringSection(tree, tableNode, L"Поля", TreeImage::Attributes, TreeImage::Attributes, tableData.fields); + addStringSection(tree, tableNode, L"Формы", TreeImage::Forms, TreeImage::Forms, tableData.forms); + addStringSection(tree, tableNode, L"Команды", TreeImage::Commands, TreeImage::Commands, tableData.commands); + addStringSection(tree, tableNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, tableData.layouts); + tree->Expanded[tableNode] = true; + } + + void fillExternalCubeTree(TVirtualStringTree* tree, PVirtualNode parent, + const TExternalDataSourceCube& cubeData, int imgIndex) + { + PVirtualNode cubeNode = addChildNode(tree, parent, cubeData.name, imgIndex); + + if (!cubeData.dimensionTables.empty()) + { + PVirtualNode dimensionTablesNode = addChildNode(tree, cubeNode, L"Таблицы измерений", TreeImage::TabularSections); + for (const auto& tableData : cubeData.dimensionTables) + fillExternalTableTree(tree, dimensionTablesNode, tableData, TreeImage::TabularSections); + tree->Expanded[dimensionTablesNode] = true; + } + + addStringSection(tree, cubeNode, L"Измерения", TreeImage::Dimensions, TreeImage::Dimensions, cubeData.dimensions); + addStringSection(tree, cubeNode, L"Ресурсы", TreeImage::Resources, TreeImage::Resources, cubeData.resources); + addStringSection(tree, cubeNode, L"Формы", TreeImage::Forms, TreeImage::Forms, cubeData.forms); + addStringSection(tree, cubeNode, L"Команды", TreeImage::Commands, TreeImage::Commands, cubeData.commands); + addStringSection(tree, cubeNode, L"Макеты", TreeImage::Layouts, TreeImage::Layouts, cubeData.layouts); + tree->Expanded[cubeNode] = true; + } +} + +void fillExternalDataSourceTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TExternalDataSources* metadataObject) +{ + if (!metadataObject) + return; + + initNode(childData, metadataObject->name, imgIndex); + + if (!metadataObject->tables.empty()) + { + PVirtualNode tablesNode = addChildNode(tree, childNode, L"Таблицы", TreeImage::TabularSections); + for (const auto& tableData : metadataObject->tables) + fillExternalTableTree(tree, tablesNode, tableData, TreeImage::TabularSections); + tree->Expanded[tablesNode] = true; + } + + if (!metadataObject->cubes.empty()) + { + PVirtualNode cubesNode = addChildNode(tree, childNode, L"Кубы", TreeImage::TabularSections); + for (const auto& cubeData : metadataObject->cubes) + fillExternalCubeTree(tree, cubesNode, cubeData, TreeImage::TabularSections); + tree->Expanded[cubesNode] = true; + } + + addStringSection(tree, childNode, L"Функции", TreeImage::Commands, TreeImage::Commands, metadataObject->functions); + tree->Expanded[childNode] = true; +} + +//--------------------------------------------------------------------------- +// Вспомогательные функции для подсистем + +String normalizeGuid(const String& guid) +{ + return Trim(guid).LowerCase(); +} + +String GetNameSubsystem(v8catalog* cf, String& guid_md) +{ + String Result = ""; + v8file* filedata = cf->GetFile(guid_md); + if (!filedata) + return Result; + tree* tree_md = get_treeFromV8file(filedata); + if (!tree_md) + return Result; + tree* node = tree_md; + node = &(*node)[0][1][1][2]; + Result = node->get_value(); + delete tree_md; + return Result; +} + +String GetSubsystemInnerGuid(v8catalog* cf, String& guid_md) +{ + String Result = ""; + v8file* filedata = cf->GetFile(guid_md); + if (!filedata) + return Result; + tree* tree_md = get_treeFromV8file(filedata); + if (!tree_md) + return Result; + tree* node = tree_md; + node = &(*node)[0][1][1][1]; + Result = node->get_value(); + delete tree_md; + return Result; +} + +void GetListChildrenSubsystem(v8catalog* cf, String& guid_md, std::vector& child) +{ + v8file* filedata = cf->GetFile(guid_md); + if (!filedata) + return; + tree* tree_md = get_treeFromV8file(filedata); + if (!tree_md) + return; + tree* node = tree_md; + node = &(*node)[0][3][0]; + + tree* curNodeChild = node->get_next(); + while (curNodeChild) + { + curNodeChild = curNodeChild->get_next(); + if (curNodeChild) + child.push_back(curNodeChild->get_value()); + } +} + +TSubsystem* findSubsystemByAnyGuid(v8catalog* cf, const MetadataVector& subsystems, const String& guid) +{ + String targetGuid = normalizeGuid(guid); + if (targetGuid.IsEmpty()) + return nullptr; + + for (const auto& item : subsystems) + { + TSubsystem* subsystem = dynamic_cast(item.get()); + if (!subsystem) + continue; + + if (normalizeGuid(subsystem->guid) == targetGuid) + return subsystem; + + String originalGuid = subsystem->guid; + if (normalizeGuid(GetSubsystemInnerGuid(cf, originalGuid)) == targetGuid) + return subsystem; + } + return nullptr; +} + +String getSubsystemDisplayNameByGuid(v8catalog* cf, const MetadataVector& subsystems, const String& guid) +{ + String guidCopy = guid; + String name = GetNameSubsystem(cf, guidCopy); + if (!name.IsEmpty()) + return name; + + TSubsystem* subsystem = findSubsystemByAnyGuid(cf, subsystems, guid); + if (subsystem) + return subsystem->name; + + return guid; +} + +void addSubsystemChildrenToTreeByGuid(TVirtualStringTree* tree, PVirtualNode parentNode, + v8catalog* cf, const MetadataVector& subsystems, + const String& parentGuid, int imgIndex) +{ + if (!tree || !cf) + return; + + tree->Expanded[parentNode] = true; + + String subsystemGuid = parentGuid; + std::vector childrenGuids; + GetListChildrenSubsystem(cf, subsystemGuid, childrenGuids); + if (childrenGuids.empty()) + { + String subsystemInnerGuid = GetSubsystemInnerGuid(cf, subsystemGuid); + if (!subsystemInnerGuid.IsEmpty()) + GetListChildrenSubsystem(cf, subsystemInnerGuid, childrenGuids); + } + + for (const auto& childGuid : childrenGuids) + { + TSubsystem* childSubsystem = findSubsystemByAnyGuid(cf, subsystems, childGuid); + + PVirtualNode childNode = tree->AddChild(parentNode); + VirtualTreeData* childData = static_cast(tree->GetNodeData(childNode)); + childData->Name = childSubsystem + ? childSubsystem->name + : getSubsystemDisplayNameByGuid(cf, subsystems, childGuid); + childData->Age = 99; + childData->ImgIndex = imgIndex; + childData->text_module = L""; + childData->MetadataObject = childSubsystem; + tree->Expanded[childNode] = true; + + String nextGuid = childSubsystem ? childSubsystem->guid : childGuid; + addSubsystemChildrenToTreeByGuid(tree, childNode, cf, subsystems, nextGuid, imgIndex); + } +} + +void addSubsystemChildrenToTree(TVirtualStringTree* tree, PVirtualNode parentNode, + v8catalog* cf, const MetadataVector& subsystems, + TSubsystem* parentSubsystem, int imgIndex) +{ + if (!tree || !cf || !parentSubsystem) + return; + addSubsystemChildrenToTreeByGuid(tree, parentNode, cf, subsystems, parentSubsystem->guid, imgIndex); +} + +std::unordered_set collectChildSubsystemGuids(v8catalog* cf, + const MetadataVector& subsystems) +{ + std::unordered_set childSubsystemGuids; + if (!cf) + return childSubsystemGuids; + + for (const auto& item : subsystems) + { + TSubsystem* subsystem = dynamic_cast(item.get()); + if (!subsystem) + continue; + + String subsystemGuid = subsystem->guid; + std::vector childrenGuids; + GetListChildrenSubsystem(cf, subsystemGuid, childrenGuids); + if (childrenGuids.empty()) + { + String subsystemInnerGuid = GetSubsystemInnerGuid(cf, subsystemGuid); + if (!subsystemInnerGuid.IsEmpty()) + GetListChildrenSubsystem(cf, subsystemInnerGuid, childrenGuids); + } + + for (const auto& childGuid : childrenGuids) + { + TSubsystem* childSubsystem = findSubsystemByAnyGuid(cf, subsystems, childGuid); + if (childSubsystem) + { + String childFileGuid = normalizeGuid(childSubsystem->guid); + if (!childFileGuid.IsEmpty()) + childSubsystemGuids.insert(childFileGuid); + + String originalChildGuid = childSubsystem->guid; + String childInnerGuid = normalizeGuid(GetSubsystemInnerGuid(cf, originalChildGuid)); + if (!childInnerGuid.IsEmpty()) + childSubsystemGuids.insert(childInnerGuid); + } + else + { + childSubsystemGuids.insert(normalizeGuid(childGuid)); + } + } + } + return childSubsystemGuids; +} diff --git a/src/MetadataTreeBuilder.h b/src/MetadataTreeBuilder.h new file mode 100644 index 0000000..64496eb --- /dev/null +++ b/src/MetadataTreeBuilder.h @@ -0,0 +1,128 @@ +//--------------------------------------------------------------------------- +#ifndef MetadataTreeBuilderH +#define MetadataTreeBuilderH +//--------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "VirtualTrees.hpp" +#include "MainUnit.h" +#include "BaseMetadataObject.h" +#include "MetadataObjectInformationRegister.h" +#include "AccountingRegisters.h" +#include "ChartOfAccounts.h" +#include "Enums.h" +#include "ExternalDataSources.h" +#include "Subsystem.h" +#include "APIcfBase.h" + +//--------------------------------------------------------------------------- +// Индексы иконок дерева метаданных +namespace TreeImage +{ + constexpr int Root = 72; + constexpr int Attributes = 83; + constexpr int TabularSections = 82; + constexpr int Forms = 86; + constexpr int Commands = 98; + constexpr int Layouts = 79; + constexpr int Dimensions = 10; + constexpr int Resources = 11; + constexpr int AccountingFlags = 118; + constexpr int SubcontoFlags = 119; + constexpr int JournalColumns = 6; +} + +constexpr int DefaultTreeNodeAge = 30; + +//--------------------------------------------------------------------------- +// Базовые операции с узлами дерева + +void initNode(VirtualTreeData* data, const String& name, int imageIndex, int age = DefaultTreeNodeAge); + +PVirtualNode addChildNode(TVirtualStringTree* tree, PVirtualNode parent, const String& name, int imageIndex, int age = DefaultTreeNodeAge); + +template +void addSection(TVirtualStringTree* tree, PVirtualNode parent, + const String& sectionName, int sectionImageIndex, int itemImageIndex, + const Collection& items, NameGetter getName, int age = DefaultTreeNodeAge) +{ + PVirtualNode sectionNode = addChildNode(tree, parent, sectionName, sectionImageIndex, age); + for (const auto& item : items) + addChildNode(tree, sectionNode, getName(item), itemImageIndex, age); +} + +void addTabularSections(TVirtualStringTree* tree, PVirtualNode parent, + const std::vector>& items, int age = DefaultTreeNodeAge); + +//--------------------------------------------------------------------------- +// Секции для стандартных объектов и регистров + +void fillStandardMetadataSections(TVirtualStringTree* tree, PVirtualNode childNode, + BaseMetadataObject* metadataObject); + +void fillInformationRegisterSections(TVirtualStringTree* tree, PVirtualNode childNode, + MetadataObjectInformationRegister* metadataObject); + +//--------------------------------------------------------------------------- +// fill*Tree — заполнение узла конкретного типа метаданных + +void fillCatalogsTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject); + +void fillFormsCommandsTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject); + +void fillAccumulationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject); + +void fillCalculationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject); + +void fillInformationRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, MetadataObjectInformationRegister* metadataObject); + +void fillAccountingRegisterTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TAccountingRegisters* metadataObject); + +void fillChartAccTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TChartOfAccounts* metadataObject); + +void fillJournalTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, BaseMetadataObject* metadataObject); + +void fillEnumTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TEnums* curEnum); + +void fillExternalDataSourceTree(TVirtualStringTree* tree, PVirtualNode childNode, VirtualTreeData* childData, + int imgIndex, TExternalDataSources* metadataObject); + +//--------------------------------------------------------------------------- +// Вспомогательные функции для подсистем + +String normalizeGuid(const String& guid); + +String GetNameSubsystem(v8catalog* cf, String& guid_md); +String GetSubsystemInnerGuid(v8catalog* cf, String& guid_md); +void GetListChildrenSubsystem(v8catalog* cf, String& guid_md, std::vector& child); + +TSubsystem* findSubsystemByAnyGuid(v8catalog* cf, const MetadataVector& subsystems, const String& guid); + +String getSubsystemDisplayNameByGuid(v8catalog* cf, const MetadataVector& subsystems, const String& guid); + +void addSubsystemChildrenToTree(TVirtualStringTree* tree, PVirtualNode parentNode, + v8catalog* cf, const MetadataVector& subsystems, + TSubsystem* parentSubsystem, int imgIndex); + +void addSubsystemChildrenToTreeByGuid(TVirtualStringTree* tree, PVirtualNode parentNode, + v8catalog* cf, const MetadataVector& subsystems, + const String& parentGuid, int imgIndex); + +std::unordered_set collectChildSubsystemGuids(v8catalog* cf, + const MetadataVector& subsystems); + +//--------------------------------------------------------------------------- +#endif diff --git a/src/Parse_tree.h b/src/Parse_tree.h index 62554c7..08420bd 100644 --- a/src/Parse_tree.h +++ b/src/Parse_tree.h @@ -4,8 +4,8 @@ #define Parse_treeH #include -#include #pragma hdrstop +#include #include "NodeTypes.h" #include "MessageRegistration.h" diff --git a/src/StyleItems.cpp b/src/StyleItems.cpp new file mode 100644 index 0000000..0d0444e --- /dev/null +++ b/src/StyleItems.cpp @@ -0,0 +1,101 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "StyleItems.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} + +__fastcall TStyleItems::TStyleItems() : BaseMetadataObject() +{ + styleItemName = ""; + root_data.reset(); +} + +__fastcall TStyleItems::TStyleItems(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +{ + styleItemName = ""; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TStyleItems::TStyleItems(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +{ + styleItemName = _name; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TStyleItems::~TStyleItems() +{ +} + +String __fastcall TStyleItems::GetStyleItemName() +{ + return styleItemName; +} + +void __fastcall TStyleItems::SetStyleItemName(String _name) +{ + styleItemName = _name; + name = _name; +} + +std::vector>& TStyleItems::getAttributes() +{ + return attributes; +} + +std::vector>& TStyleItems::getCommands() +{ + return commands; +} + +std::vector>& TStyleItems::getLayouts() +{ + return layouts; +} + +std::vector>& TStyleItems::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TStyleItems::getForms() +{ + return forms; +} + +void __fastcall TStyleItems::initializeFromTree() +{ + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 3, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + styleItemName = name; + return; + } + + if (styleItemName.IsEmpty()) + styleItemName = name; +} diff --git a/src/StyleItems.h b/src/StyleItems.h new file mode 100644 index 0000000..9ae268f --- /dev/null +++ b/src/StyleItems.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef StyleItemsH +#define StyleItemsH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TStyleItems : public BaseMetadataObject +{ +private: + String styleItemName; + +public: + __fastcall TStyleItems(); + __fastcall TStyleItems(v8catalog* _parent, const String& _guid); + __fastcall TStyleItems(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TStyleItems(); + + String __fastcall GetStyleItemName(); + void __fastcall SetStyleItemName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif diff --git a/src/Styles.cpp b/src/Styles.cpp new file mode 100644 index 0000000..e344d42 --- /dev/null +++ b/src/Styles.cpp @@ -0,0 +1,101 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "Styles.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} + +__fastcall TStyles::TStyles() : BaseMetadataObject() +{ + styleName = ""; + root_data.reset(); +} + +__fastcall TStyles::TStyles(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +{ + styleName = ""; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TStyles::TStyles(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +{ + styleName = _name; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TStyles::~TStyles() +{ +} + +String __fastcall TStyles::GetStyleName() +{ + return styleName; +} + +void __fastcall TStyles::SetStyleName(String _name) +{ + styleName = _name; + name = _name; +} + +std::vector>& TStyles::getAttributes() +{ + return attributes; +} + +std::vector>& TStyles::getCommands() +{ + return commands; +} + +std::vector>& TStyles::getLayouts() +{ + return layouts; +} + +std::vector>& TStyles::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TStyles::getForms() +{ + return forms; +} + +void __fastcall TStyles::initializeFromTree() +{ + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 1, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + styleName = name; + return; + } + + if (styleName.IsEmpty()) + styleName = name; +} diff --git a/src/Styles.h b/src/Styles.h new file mode 100644 index 0000000..a53bd7c --- /dev/null +++ b/src/Styles.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef StylesH +#define StylesH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TStyles : public BaseMetadataObject +{ +private: + String styleName; + +public: + __fastcall TStyles(); + __fastcall TStyles(v8catalog* _parent, const String& _guid); + __fastcall TStyles(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TStyles(); + + String __fastcall GetStyleName(); + void __fastcall SetStyleName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif diff --git a/src/Subsystem.cpp b/src/Subsystem.cpp new file mode 100644 index 0000000..2a52263 --- /dev/null +++ b/src/Subsystem.cpp @@ -0,0 +1,70 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "Subsystem.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +__fastcall TSubsystem::TSubsystem() : BaseMetadataObject() +{ + name = ""; + root_data.reset(); +} + +__fastcall TSubsystem::TSubsystem(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +{ + name = ""; + root_data.reset(); +} + +__fastcall TSubsystem::TSubsystem(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +{ + name = _name; + root_data.reset(); +} + +__fastcall TSubsystem::~TSubsystem() +{ +} + +String __fastcall TSubsystem::GetSubsystemName() +{ + return name; +} + +void __fastcall TSubsystem::SetSubsystemName(String _name) +{ + name = _name; +} + +std::vector>& TSubsystem::getAttributes() +{ + return attributes; +} + +std::vector>& TSubsystem::getCommands() +{ + return commands; +} + +std::vector>& TSubsystem::getLayouts() +{ + return layouts; +} + +std::vector>& TSubsystem::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TSubsystem::getForms() +{ + return forms; +} + +void __fastcall TSubsystem::initializeFromTree() +{ + // Инициализация подсистемы из дерева метаданных + // Имя подсистемы уже установлено в конструкторе +} \ No newline at end of file diff --git a/src/Subsystem.h b/src/Subsystem.h new file mode 100644 index 0000000..42e8dbc --- /dev/null +++ b/src/Subsystem.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef SubsystemH +#define SubsystemH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TSubsystem : public BaseMetadataObject +{ +private: + // subsystemName хранится в унаследованном поле name из BaseMetadataObject + +public: + __fastcall TSubsystem(); + __fastcall TSubsystem(v8catalog* _parent, const String& _guid); + __fastcall TSubsystem(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TSubsystem(); + + String __fastcall GetSubsystemName(); + void __fastcall SetSubsystemName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif \ No newline at end of file diff --git a/src/Tabular.cpp b/src/Tabular.cpp index 2944c54..6240472 100644 --- a/src/Tabular.cpp +++ b/src/Tabular.cpp @@ -3,9 +3,313 @@ #pragma hdrstop #include "Tabular.h" +#include "guids.h" //--------------------------------------------------------------------------- #pragma package(smart_init) +namespace +{ + bool IsServiceTabularAttributeName(const String& value) + { + String trimmed = Trim(value); + return trimmed == L"Реквизиты" || trimmed == L"Реквизит"; + } + + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + tree* GetNodeByPath(tree* root, const std::vector& indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + bool IsGuidLikeValue(const String& value) + { + String trimmed = Trim(value); + if (trimmed.Length() != 36) + return false; + + for (int i = 1; i <= trimmed.Length(); i++) + { + wchar_t ch = trimmed[i]; + bool isHex = (ch >= L'0' && ch <= L'9') || (ch >= L'a' && ch <= L'f') || (ch >= L'A' && ch <= L'F'); + bool isDash = (ch == L'-'); + if (!isHex && !isDash) + return false; + } + + return true; + } + + bool IsNumericLikeValue(const String& value) + { + String trimmed = Trim(value); + if (trimmed.IsEmpty()) + return false; + + for (int i = 1; i <= trimmed.Length(); i++) + { + wchar_t ch = trimmed[i]; + if (!((ch >= L'0' && ch <= L'9') || ch == L'.' || ch == L',' || ch == L'-')) + return false; + } + + return true; + } + + String FindFirstMeaningfulString(tree* node) + { + if (!node) + return L""; + + String value = Trim(node->get_value()); + if (!value.IsEmpty() && !IsGuidLikeValue(value) && !IsNumericLikeValue(value) && value.SubString(1, 1) != L"#" && !IsServiceTabularAttributeName(value)) + return value; + + for (int i = 0; i < node->get_num_subnode(); i++) + { + String nested = FindFirstMeaningfulString(node->get_subnode(i)); + if (!nested.IsEmpty()) + return nested; + } + + return L""; + } + + void CollectMeaningfulStrings(tree* node, std::vector& values) + { + if (!node) + return; + + String value = Trim(node->get_value()); + if (!value.IsEmpty() && !IsGuidLikeValue(value) && !IsNumericLikeValue(value) && value.SubString(1, 1) != L"#" && !IsServiceTabularAttributeName(value)) + values.push_back(value); + + for (int i = 0; i < node->get_num_subnode(); i++) + CollectMeaningfulStrings(node->get_subnode(i), values); + } + + bool TryCollectAttributesFromSection(tree* root, int sectionIndex, std::vector>& attributes) + { + const std::vector> countPaths = { + {0, 1, sectionIndex, 1}, + {0, 1, sectionIndex, 1, 1}, + {0, sectionIndex, 1}, + {0, sectionIndex, 1, 1} + }; + + const std::vector> itemPrefixes = { + {0, 1, sectionIndex}, + {0, sectionIndex} + }; + + const std::vector> namePaths = { + {0, 1, 1, 1, 2}, + {0, 1, 1, 1, 1, 2}, + {0, 1, 1, 2}, + {0, 1, 3, 2}, + {0, 1, 5, 1, 2}, + {1, 1, 1, 2}, + {1, 1, 2}, + {1, 3, 2} + }; + + for (const auto& countPath : countPaths) + { + tree* countNode = GetNodeByPath(root, countPath); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + continue; + + int delta = count - 2; + int collected = 0; + for (const auto& itemPrefix : itemPrefixes) + { + for (int i = 0; i < count; i++) + { + try + { + std::vector itemPath = itemPrefix; + itemPath.push_back(i + count - delta); + tree* itemNode = GetNodeByPath(root, itemPath); + if (!itemNode) + continue; + + String attributeName = L""; + for (const auto& namePath : namePaths) + { + tree* nameNode = GetNodeByPath(itemNode, namePath); + if (!nameNode) + continue; + + attributeName = Trim(nameNode->get_value()); + if (attributeName.IsEmpty()) + continue; + + break; + } + + if (attributeName.IsEmpty()) + attributeName = FindFirstMeaningfulString(itemNode); + + if (!attributeName.IsEmpty()) + { + attributes.push_back(std::make_unique(attributeName, "")); + collected++; + break; + } + } + catch (...) + { + } + } + + if (collected > 0) + return true; + } + } + + return false; + } + + bool TryCollectCatalogTabularAttributesByGuid(tree* root, std::vector>& attributes) + { + tree* node = find_metadata_node_by_guid(root, GUID_AttCatalogs); + if (!node) + return false; + + tree* countNode = node->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + int collected = 0; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String attributeName = FindFirstMeaningfulString(current); + if (attributeName.IsEmpty()) + continue; + + if (IsServiceTabularAttributeName(attributeName)) + continue; + + attributes.push_back(std::make_unique(attributeName, "")); + collected++; + if (collected >= count) + break; + } + + return collected > 0; + } + + bool TryCollectEmbeddedTabularAttributes(tree* root, std::vector>& attributes) + { + static const String EmbeddedTabularAttributeGuid = L"888744e1-b616-11d4-9436-004095e12fc7"; + + auto tryCollectFromContainer = [&](tree* container) -> bool + { + if (!container) + return false; + + for (int i = 0; i < container->get_num_subnode(); i++) + { + tree* sectionNode = container->get_subnode(i); + if (!sectionNode || sectionNode->get_num_subnode() < 2) + continue; + + String sectionGuid = Trim(sectionNode->get_subnode(0)->get_value()); + if (sectionGuid != EmbeddedTabularAttributeGuid) + continue; + + int count = sectionNode->get_subnode(1)->get_value().ToIntDef(0); + if (count <= 0) + return false; + + int collected = 0; + for (int itemIndex = 2; itemIndex < sectionNode->get_num_subnode(); itemIndex++) + { + String attributeName = FindFirstMeaningfulString(sectionNode->get_subnode(itemIndex)); + if (attributeName.IsEmpty()) + continue; + + if (IsServiceTabularAttributeName(attributeName)) + continue; + + attributes.push_back(std::make_unique(attributeName, "")); + collected++; + if (collected >= count) + break; + } + + return collected > 0; + } + + return false; + }; + + if (tryCollectFromContainer(root)) + return true; + + if (root->get_num_subnode() > 0 && tryCollectFromContainer(root->get_subnode(0))) + return true; + + tree* node = find_metadata_node_by_guid(root, EmbeddedTabularAttributeGuid); + if (!node) + return false; + + tree* countNode = node->get_next(); + int count = countNode ? countNode->get_value().ToIntDef(0) : 0; + if (count <= 0) + return false; + + int collected = 0; + tree* current = countNode; + while ((current = current->get_next()) != nullptr) + { + String attributeName = FindFirstMeaningfulString(current); + if (attributeName.IsEmpty()) + continue; + + if (IsServiceTabularAttributeName(attributeName)) + continue; + + attributes.push_back(std::make_unique(attributeName, "")); + collected++; + if (collected >= count) + break; + } + + return collected > 0; + } +} + __fastcall TTabular::TTabular() { @@ -22,3 +326,62 @@ __fastcall TTabular::~TTabular() { } + +void __fastcall TTabular::initializeFromTree(tree* root) +{ + attributes.clear(); + if (!root) + return; + + std::vector> parsedByGuid; + if (TryCollectCatalogTabularAttributesByGuid(root, parsedByGuid)) + { + attributes = std::move(parsedByGuid); + return; + } + + if (TryCollectEmbeddedTabularAttributes(root, parsedByGuid)) + { + attributes = std::move(parsedByGuid); + return; + } + + // У разных объектов 1С секция реквизитов табличной части может располагаться по + // разным индексам. Сначала пробуем наиболее вероятные секции, сохраняя первый + // успешный набор реквизитов. + const int candidateSections[] = {3, 2, 4, 5, 6, 7, 1}; + for (int sectionIndex : candidateSections) + { + std::vector> parsedAttributes; + if (TryCollectAttributesFromSection(root, sectionIndex, parsedAttributes)) + { + attributes = std::move(parsedAttributes); + break; + } + } + + if (attributes.empty()) + { + std::vector rawValues; + CollectMeaningfulStrings(root, rawValues); + for (const auto& rawValue : rawValues) + { + String value = Trim(rawValue); + if (value.IsEmpty() || value == name) + continue; + + bool alreadyExists = false; + for (const auto& attribute : attributes) + { + if (attribute->name == value) + { + alreadyExists = true; + break; + } + } + + if (!alreadyExists) + attributes.push_back(std::make_unique(value, "")); + } + } +} diff --git a/src/Tabular.h b/src/Tabular.h index 68fd869..336dfd1 100644 --- a/src/Tabular.h +++ b/src/Tabular.h @@ -3,14 +3,24 @@ #ifndef TabularH #define TabularH +#include +#include +#include + #include "MDO.h" +#include "Parse_tree.h" +#include "Requisite.h" //--------------------------------------------------------------------------- class TTabular : public TMDO { public: + std::vector> attributes; + __fastcall TTabular(); __fastcall TTabular(String _name, String _guid); __fastcall ~TTabular(); + + void __fastcall initializeFromTree(tree* root); }; #endif diff --git a/src/Tasks.cpp b/src/Tasks.cpp index fb6c5a3..41c8036 100644 --- a/src/Tasks.cpp +++ b/src/Tasks.cpp @@ -12,13 +12,13 @@ static MetadataTreePaths GetTasksPaths() MetadataTreePaths paths; paths.attIdx = 5; paths.attItemPath = {0, 1, 1, 1, 2}; - paths.tabIdx = 3; + paths.tabIdx = 7; paths.tabItemPath = {0, 1, 5, 1, 2}; - paths.formsIdx = 7; - paths.cmdIdx = 6; + paths.formsIdx = 4; + paths.cmdIdx = 8; paths.cmdItemPath = {0, 1, 3, 2, 9, 2}; - paths.moxIdx = 4; - paths.getFormNameFunc = GetNameFormCatalogs; + paths.moxIdx = 3; + paths.getFormNameFunc = GetNameFormDescriptor; paths.hasTabulars = true; return paths; } diff --git a/src/V8File.h b/src/V8File.h index ee49e28..22164cb 100644 --- a/src/V8File.h +++ b/src/V8File.h @@ -27,16 +27,11 @@ at http://mozilla.org/MPL/2.0/. #include #include +#include "v8_constants.h" + namespace v8unpack { -const size_t V8_DEFAULT_PAGE_SIZE = 512; -const uint32_t V8_FF_SIGNATURE = 0x7fffffff; - -// Для конфигурации старше 8.3.16, без режима совместимости -const uint64_t V8_FF64_SIGNATURE = 0xffffffffffffffff; -const size_t V8_OFFSET_8316 = 0x1359; // волшебное смещение, откуда такая цифра неизвестно... - const int V8UNPACK_OK = 0; const int V8UNPACK_ERROR = -50; const int V8UNPACK_NOT_V8_FILE = V8UNPACK_ERROR - 1; diff --git a/src/WSReferences.cpp b/src/WSReferences.cpp new file mode 100644 index 0000000..ca2e0b2 --- /dev/null +++ b/src/WSReferences.cpp @@ -0,0 +1,139 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "WSReferences.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } + + String FindReferenceName(tree* node) + { + if (!node) + return L""; + + if (node->get_type() == nd_list && node->get_num_subnode() >= 3) + { + tree* markerNode = node->get_subnode(0); + tree* possibleNameNode = node->get_subnode(2); + if (markerNode && possibleNameNode && + (markerNode->get_value() == L"2" || markerNode->get_value() == L"3") && + possibleNameNode->get_type() == nd_string && + !possibleNameNode->get_value().IsEmpty()) + { + return possibleNameNode->get_value(); + } + } + + for (int i = 0; i < node->get_num_subnode(); i++) + { + String result = FindReferenceName(node->get_subnode(i)); + if (!result.IsEmpty()) + return result; + } + + return L""; + } +} + +__fastcall TWSReferences::TWSReferences() : BaseMetadataObject() +{ + referenceName = ""; + root_data.reset(); +} + +__fastcall TWSReferences::TWSReferences(v8catalog* _parent, const String& _guid) + : BaseMetadataObject(_parent, _guid) +{ + referenceName = ""; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TWSReferences::TWSReferences(v8catalog* _parent, const String& _guid, const String& _name) + : BaseMetadataObject(_parent, _guid, _name) +{ + referenceName = _name; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TWSReferences::~TWSReferences() +{ +} + +String __fastcall TWSReferences::GetReferenceName() +{ + return referenceName; +} + +void __fastcall TWSReferences::SetReferenceName(String _name) +{ + referenceName = _name; + name = _name; +} + +std::vector>& TWSReferences::getAttributes() +{ + return attributes; +} + +std::vector>& TWSReferences::getCommands() +{ + return commands; +} + +std::vector>& TWSReferences::getLayouts() +{ + return layouts; +} + +std::vector>& TWSReferences::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TWSReferences::getForms() +{ + return forms; +} + +void __fastcall TWSReferences::initializeFromTree() +{ + tree* nameNode = GetNodeByPath(root_data.get(), {1, 2, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + referenceName = name; + return; + } + + String foundName = FindReferenceName(root_data.get()); + if (!foundName.IsEmpty()) + { + name = foundName; + referenceName = name; + return; + } + + if (referenceName.IsEmpty()) + referenceName = name; +} diff --git a/src/WSReferences.h b/src/WSReferences.h new file mode 100644 index 0000000..b886e5d --- /dev/null +++ b/src/WSReferences.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef WSReferencesH +#define WSReferencesH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TWSReferences : public BaseMetadataObject +{ +private: + String referenceName; + +public: + __fastcall TWSReferences(); + __fastcall TWSReferences(v8catalog* _parent, const String& _guid); + __fastcall TWSReferences(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TWSReferences(); + + String __fastcall GetReferenceName(); + void __fastcall SetReferenceName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif diff --git a/src/WebSocketClients.cpp b/src/WebSocketClients.cpp new file mode 100644 index 0000000..19a3436 --- /dev/null +++ b/src/WebSocketClients.cpp @@ -0,0 +1,101 @@ +//--------------------------------------------------------------------------- + +#pragma hdrstop + +#include "WebSocketClients.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) + +namespace +{ + tree* GetNodeByPath(tree* root, std::initializer_list indexes) + { + tree* current = root; + if (!current) + return nullptr; + + for (int index : indexes) + { + if (!current || index < 0 || index >= current->get_num_subnode()) + return nullptr; + + current = current->get_subnode(index); + } + + return current; + } +} + +__fastcall TWebSocketClients::TWebSocketClients() : BaseMetadataObject() +{ + clientName = ""; + root_data.reset(); +} + +__fastcall TWebSocketClients::TWebSocketClients(v8catalog* _parent, const String& _guid) : BaseMetadataObject(_parent, _guid) +{ + clientName = ""; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TWebSocketClients::TWebSocketClients(v8catalog* _parent, const String& _guid, const String& _name) : BaseMetadataObject(_parent, _guid, _name) +{ + clientName = _name; + initializeFromTree(); + root_data.reset(); +} + +__fastcall TWebSocketClients::~TWebSocketClients() +{ +} + +String __fastcall TWebSocketClients::GetClientName() +{ + return clientName; +} + +void __fastcall TWebSocketClients::SetClientName(String _name) +{ + clientName = _name; + name = _name; +} + +std::vector>& TWebSocketClients::getAttributes() +{ + return attributes; +} + +std::vector>& TWebSocketClients::getCommands() +{ + return commands; +} + +std::vector>& TWebSocketClients::getLayouts() +{ + return layouts; +} + +std::vector>& TWebSocketClients::getTabularSections() +{ + return tabularSections; +} + +std::vector>& TWebSocketClients::getForms() +{ + return forms; +} + +void __fastcall TWebSocketClients::initializeFromTree() +{ + tree* nameNode = GetNodeByPath(root_data.get(), {0, 1, 1, 2}); + if (nameNode && !nameNode->get_value().IsEmpty()) + { + name = nameNode->get_value(); + clientName = name; + return; + } + + if (clientName.IsEmpty()) + clientName = name; +} diff --git a/src/WebSocketClients.h b/src/WebSocketClients.h new file mode 100644 index 0000000..2e640d2 --- /dev/null +++ b/src/WebSocketClients.h @@ -0,0 +1,39 @@ +//--------------------------------------------------------------------------- + +#ifndef WebSocketClientsH +#define WebSocketClientsH + +#include "BaseMetadataObject.h" +//--------------------------------------------------------------------------- + +class TWebSocketClients : public BaseMetadataObject +{ +private: + String clientName; + +public: + __fastcall TWebSocketClients(); + __fastcall TWebSocketClients(v8catalog* _parent, const String& _guid); + __fastcall TWebSocketClients(v8catalog* _parent, const String& _guid, const String& _name); + virtual __fastcall ~TWebSocketClients(); + + String __fastcall GetClientName(); + void __fastcall SetClientName(String _name); + + std::vector>& getAttributes() override; + std::vector>& getCommands() override; + std::vector>& getLayouts() override; + std::vector>& getTabularSections() override; + std::vector>& getForms() override; + + void __fastcall initializeFromTree() override; + +private: + std::vector> attributes; + std::vector> commands; + std::vector> layouts; + std::vector> tabularSections; + std::vector> forms; +}; + +#endif diff --git a/src/guids.h b/src/guids.h index e4e7383..5692d2a 100644 --- a/src/guids.h +++ b/src/guids.h @@ -17,7 +17,7 @@ 46b4cd97-fd13-4eaa-aba2-3bddd7699218 // Хранилища настроек 4e828da6-0f44-4b5b-b1c0-a2b3cfe7bdcc // Подписки на события 58848766-36ea-4076-8800-e91eb49590d7 // Элементы стиля -6e6dc072-b7ac-41e7-8f88-278d25b6da2a // Неизвестный +6e6dc072-b7ac-41e7-8f88-278d25b6da2a // Боты 7dcd43d9-aca5-4926-b549-1842e6a4e8cf // Общие картинки 857c4a91-e5f4-4fac-86ec-787626f1c108 // Планы обмена 8657032e-7740-4e1d-a3ba-5dd6e8afb78f // Web-сервисы @@ -98,6 +98,7 @@ constexpr auto md_Subsystems = "Подсистемы"; constexpr auto md_Tasks = "Задачи"; constexpr auto md_WebServices = "Web-сервисы"; constexpr auto md_WSReferences = "WS-ссылки"; +constexpr auto md_WebSocketClients = "WebSocket-клиенты"; constexpr auto md_XDTOPackages = "XDTO-пакеты"; constexpr auto md_IntegrationServices = "Сервисы интеграции"; constexpr auto md_Sequences = "Последовательности"; @@ -129,6 +130,8 @@ constexpr const char* GUID_XDTOPackages = "cc9df798-7c94-4616-97d constexpr const char* GUID_WebServices = "8657032e-7740-4e1d-a3ba-5dd6e8afb78f"; constexpr const char* GUID_HTTPServices = "0fffc09c-8f4c-47cc-b41c-8d5c5a221d79"; constexpr const char* GUID_WSReferences = "d26096fb-7a5d-4df9-af63-47d04771fa9b"; +constexpr const char* GUID_WebSocketClients = "a7641777-7813-45c6-96ef-9d51587a6ac6"; +constexpr const char* GUID_IntegrationServices = "bf3420b0-f6f9-41a0-b83a-fe9d4ab0b65d"; constexpr const char* GUID_StyleItems = "58848766-36ea-4076-8800-e91eb49590d7"; constexpr const char* GUID_Styles = "3e5404af-6ef8-4c73-ad11-91bd2dfac4c8"; constexpr const char* GUID_Languages = "9cd510ce-abfc-11d4-9434-004095e12fc7"; @@ -151,7 +154,7 @@ constexpr const char* GUID_CalculationRegisters = "f2de87a8-64e5-45eb-a22 constexpr const char* GUID_BusinessProcesses = "fcd3404e-1523-48ce-9bc0-ecdb822684a1"; constexpr const char* GUID_Tasks = "3e63355c-1378-4953-be9b-1deb5fb6bec5"; constexpr const char* GUID_ExternalDataSources = "5274d9fc-9c3a-4a71-8f5e-a0db8ab23de5"; -constexpr const char* GUID_Bots = "a89b4a3c-01ea-4f0e-8541-05b97d19a7c6"; +constexpr const char* GUID_Bots = "6e6dc072-b7ac-41e7-8f88-278d25b6da2a"; //constexpr const char* GUID_SettingsStorages = "46b4cd97-fd13-4eaa-aba2-3bddd7699218"; // Макеты Справочника diff --git a/src/v8_constants.h b/src/v8_constants.h new file mode 100644 index 0000000..3d6750d --- /dev/null +++ b/src/v8_constants.h @@ -0,0 +1,21 @@ +// v8_constants.h +// Общие константы формата файлов 1С v8 +// Используется в APIcfBase.h и V8File.h (namespace v8unpack) + +#ifndef V8_CONSTANTS_H +#define V8_CONSTANTS_H + +// Размер страницы по умолчанию +const unsigned int V8_DEFAULT_PAGE_SIZE = 512; + +// Сигнатура конца списка (32-бит формат, до 8.3.16) +const unsigned int V8_FF_SIGNATURE = 0x7fffffff; + +// Сигнатура конца списка (64-бит формат, 8.3.16+) +const unsigned __int64 V8_FF64_SIGNATURE = 0xffffffffffffffffULL; + +// Смещение начала данных в файлах формата 8.3.16+ +// (волшебное смещение 0x1359 — происхождение неизвестно) +const int V8_OFFSET_8316 = 0x1359; + +#endif // V8_CONSTANTS_H