#include <wx/filename.h>
#include "mms.h"
#include "nametable.h"
#include "storage.h"
#include "commonfunctions.h"
#include "container.h"
#include "ordering.h"
#include "mms_filter.h"
#include "dll/gcomp.h"
#include "ui.h"
#include "rights.h"
#include "dialogform.h"
///////////////////////////////////////////////////////////////////////
/////////// class CMMSObject methods ////////////////////////////////
///////////////////////////////////////////////////////////////////////
void CMMSObject::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& SrcDir)
{
Msg(1, _U("INF: %s"), sID.c_str());
CNameTableRecord* nt_rec = NameTable.Find(MMS_Type);
if( nt_rec == NULL ) return;
if( !nt_rec->Dir.IsEmpty() )
{
wxString Dir = nt_rec->PrepareDirName(SrcDir);
ImportDescriptions(TypedTextStorage, Dir+_U("/"), true);
}
SendInfoMessage(InfoMsg_Progress, ++TotalObjectsProcessed);
}
void CMMSAttributes_SF::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& SrcDir)
{
CNameTableRecord* nt_rec = NameTable.Find(MMS_Type);
if( nt_rec == NULL ) return;
if( nt_rec->Dir.IsEmpty() ) return;
wxString Dir = nt_rec->PrepareDirName(SrcDir);
Msg(1, _U("INF: %s --> %s"), Dir.c_str(), nt_rec->Type1C.c_str());
ImportOrdering(Dir);
//Если у нас объекты раскиданы по каталогам, то и описания нужно собирать по каталогам
for( int i = 0; i < GetNChildren(); i++ )
{
CMMSObject* obj = GetChild(i);
wxString SubDir = obj->GetObjectDir(Dir);
obj->ImportDescriptions(TypedTextStorage, SubDir+_U("/"), true);
}
//А если всё в одном файле, то и описания будут в общей куче
ImportDescriptions(TypedTextStorage, Dir+_U("/"), true);
SendInfoMessage(InfoMsg_Progress, ++TotalObjectsProcessed);
}
void CMMSObject::ImportDescriptions(CStorage& TypedTextStor, const wxString& FNamePrefix, bool StdName)
{
if( MMS_Type == MMS_Property ) return; //Описания бывают только у объектов
CNameTableRecord* nt_rec_obj = NameTable.Find(MMS_Type);
CNameTableRecord* nt_rec = NameTable.Find(NT_UserHelpStor);
CNameTableRecord* nt_rec_file = NameTable.Find(NT_UserHelp);
MMS_Filter.Down();
if( MMS_Filter.Test(this, nt_rec_obj) || MMS_Filter.Test(NULL, nt_rec_file) )
{
wxString StorName = nt_rec->PrepareStorageName(ID);
wxString NewPrefix = FNamePrefix;
wxString Suffix;
if( ID_Type != IDT_NoID &&
(nt_rec_obj == NULL || nt_rec_obj->Type1C == _U("sID")) )
{
if( ID_Type == IDT_OnlyTextual )
Suffix.Printf(_U("%s."), sID.c_str());
else if( ID_Type == IDT_OnlyNumeric )
Suffix.Printf(_U("%s.%i."), nt_rec_file->FileName.c_str(), ID);
else if( sID.IsEmpty() || !IsValidFileName(sID) )
Suffix.Printf(_U("%s.%i."), nt_rec_file->FileName.c_str(), ID);
else
Suffix.Printf(_U("%s."), sID.c_str());
}
InplaceTranslit(Suffix);
NewPrefix += Suffix;
if( ID_Type == IDT_BothIDs &&
(!TypedTextStor.StorageExist(StorName) || !MMS_Filter.IsEmpty()) )
{
wxString FName;
if( StdName || Suffix.IsEmpty() )
FName.Printf(_U("%s%s.%s"), FNamePrefix.c_str(), nt_rec_file->FileName.c_str(), nt_rec_file->Ext.c_str());
else
FName.Printf(_U("%s%s"), NewPrefix.c_str(), nt_rec_file->Ext.c_str());
if( wxFileExists(FName) )
{
if( TypedTextStor.Create(StorName) )
{
Msg(2, _U("CPY: '%s'"), FName.c_str());
TypedTextStor.StreamFromFile(nt_rec_file->PrepareStorageName(ID), FName);
CContainer CC;
CC.CreateInTypedText(TypedTextStor);
TypedTextStor.Close();
}
}
}
for( int i = 0; i < GetNChildren(); i++ )
{
GetChild(i)->ImportDescriptions(TypedTextStor, NewPrefix, false);
}
}
MMS_Filter.Up();
}
///////////////////////////////////////////////////////////////////////
/////////// class CMMSObjectWithProps methods ///////////////////////
///////////////////////////////////////////////////////////////////////
bool CMMSObject::ImportMoxelPages(CStorage& Storage, const wxString& SrcDir, const wxString& ContCont)
{
bool HavePages = false;
wxString FName, Page, CC;
CObjectOrdering Order(4);
if( !Order.OpenFile(SrcDir) ) return false;
while( Order.ReadString() )
{
//Соберём имена
FName.Printf(_U("%s/%s"), SrcDir.c_str(), Order.GetValue(2).c_str());
Page.Printf(_U("Page.%s"), Order.GetValue(0).c_str());
if( TaskParameters.NoEmptyMxl ) //Поскипаем пустые шаблоны
{
long size = wxFileName::GetSize(FName).ToULong();
if( size == 147 || size == 139 ) continue;
}
Storage.StreamFromFile(Page, FName);
CC.Printf(_U(",{\"Moxcel.Worksheet\",\"%s\",\"%s\",\"\"}"), Page.c_str(), Order.GetValue(3).c_str());
((wxString)ContCont) += CC;
HavePages = true;
}
return HavePages;
}
void CMMSObject::ImportContainerProfile(CStorage& Storage, const wxString& SrcDir)
{
wxString ContProfName = SrcDir + _U("/Container.Profile");
wxString StreamName = _U("Container.Profile");
if( wxFileExists(ContProfName) )
{
Storage.StreamFromFile(StreamName, ContProfName);
return;
}
if( TaskParameters.NoProfiles ) return;
wxString CP = _U("{\n\
{\"MoxelName\",\"\",\"\"},\n\
{\"MoxelPos\",\"0\",\"\"},\n\
{\"UUID\",\"D41D8CD98F00B204E9800998ECF8427E\",\"\"},\n\
{\"Entry\",\"1\",\"\"},\n\
{\"MoxelNextMode\",\"1\",\"\"}}");
Storage.StreamFromString(StreamName, CP);
}
bool CMMSObject::ImportStreamByType(CStorage& Storage, MMSObjectType Type, const wxString& SrcDir)
{
CNameTableRecord* nt_rec = NameTable.Find(Type);
wxString FileName = nt_rec->PrepareFileName(SrcDir);
bool res;
MMS_Filter.Down();
if( MMS_Filter.Test(this, nt_rec) )
{
if( !wxFileExists(FileName) ) return false;
CStorage SubStorage(Storage);
res = SubStorage.StreamFromFile(
nt_rec->PrepareStorageName(ID),
FileName);
}
MMS_Filter.Up();
return res;
}
bool DialogInBeautyFormat(wxString FormFName)
{
wxFile * f = new wxFile(FormFName, wxFile::read);
char buf[16];
f->Read(buf, sizeof(buf)-1);
delete f;
wxString hdr = wxString(buf, wxConvLocal);
hdr.Trim();
hdr.Trim(true);
return ( wxStrcoll(_U("Диалог:"), hdr) == 0 );
}
bool CMMSObject::ImportWorkBook(CStorage& Storage, const wxString& SrcDir)
{
CNameTableRecord* nt_rec_wb = NameTable.Find(NT_Workbook);
CNameTableRecord* nt_rec;
wxString ContCont = _U("{\"Container.Contents\"");
bool StorageNotEmpty = false;
//Описание потока ММС для внешних отчетов
if( TaskParameters.CompoundType == external_report )
ContCont += _U(",{\"MetaDataHolderContainer\",\"Main MetaData Stream\",\"Main MetaData Stream\",\"\"}");
if( TaskParameters.CompoundType != external_report )
Storage.Create(nt_rec_wb->StorageName);
//Сама форма
bool dlg_form_imported = false;
nt_rec = NameTable.Find(NT_DialogForm);
MMS_Filter.Down();
if( MMS_Filter.Test(this, nt_rec) )
{
wxString FormFName = nt_rec->PrepareFileName(SrcDir);
if( wxFileExists(FormFName) )
{
if( DialogInBeautyFormat(FormFName) )
{
CDialogForm DlgForm(NULL);
DlgForm.ParseFile(FormFName);
CMMSString DlgAsString;
DlgForm.ToString(DlgAsString);
if( Storage.StreamFromString(nt_rec->StorageName, DlgAsString) )
{
dlg_form_imported = true;
StorageNotEmpty = true;
}
}
else
{
if( Storage.StreamFromFile(nt_rec->StorageName, FormFName) )
{
dlg_form_imported = true;
StorageNotEmpty = true;
}
}
}
if( dlg_form_imported )
{
ContCont += _U(",{\"DialogEditor\",\"Dialog Stream\",\"Dialog Form\",\"\"}");
}
}
MMS_Filter.Up();
//Модуль формы
nt_rec = NameTable.Find(NT_FormModule);
wxString ModuleFName = nt_rec->PrepareFileName(SrcDir);
if( dlg_form_imported || wxFileExists(ModuleFName) )
{
MMS_Filter.Down();
if( MMS_Filter.Test(NULL, nt_rec) )
{
if( !Storage.StreamFromFile(nt_rec->StorageName, ModuleFName) )
{
Storage.StreamFromString(nt_rec->StorageName, wxEmptyString); //создаём пустой модуль
StorageNotEmpty = true;
}
ContCont += _U(",{\"TextDocument\",\"MD Programm text\",\"Module text\",\"\"}");
}
MMS_Filter.Up();
}
//Для внешних отчетов описание складывается прямо в контейнер. Поток назвается "Inplace description"
if( TaskParameters.CompoundType == external_report )
{
if( !ImportStreamByType(Storage, NT_ErtUserHelp, SrcDir) )
{
nt_rec = NameTable.Find(NT_ErtUserHelp);
Storage.StreamFromString(nt_rec->PrepareStorageName(), wxString());
StorageNotEmpty = true;
}
ContCont += _U(",{\"MetaDataDescription\",\"Inplace description\",\"Описание\",\"\"}");
}
//Шаблоны таблиц
MMS_Filter.Down();
if( MMS_Filter.Test(wxString(_U("ШаблоныТаблиц"))) || MMS_Filter.Test(wxString(_U("MoxelPages"))) )
{
if( ImportMoxelPages(Storage, SrcDir, ContCont) )
StorageNotEmpty = true;
}
MMS_Filter.Up();
//Container.Contents и Container.Profile создаём только при полной компиляции
if( MMS_Filter.IsEmpty() )
{
ContCont += _U("}\n");
Storage.StreamFromString(_U("Container.Contents"), ContCont);
//Container.Profile
ImportContainerProfile(Storage, SrcDir);
}
if( TaskParameters.CompoundType != external_report )
{
Storage.Close();
if( !StorageNotEmpty )
Storage.Delete(nt_rec_wb->StorageName);
}
return StorageNotEmpty;
}
bool CMMSObject::ImportListForms(CFormDescrList& Forms, CStorage& Storage,
const wxString& SrcDir, wxString Prefix)
{
CNameTableRecord* nt_rec = NameTable.Find(NT_ListForm);
wxString StorName;
bool NotEmpty = false;
for( int i = 0; i < Forms.GetNChildren(); i++ )
{
CMMSObject* Form = Forms.GetChild(i);
MMS_Filter.Down();
if( MMS_Filter.Test(Form, nt_rec) || MMS_Filter.Test(wxString(_U("ФормыСписков"))) )
{
wxString FormDir;
FormDir.Printf(_U("%s/%s.%s"), SrcDir.c_str(), Translit(Form->sID).c_str(), nt_rec->Ext.c_str());
StorName.Printf(_U("%s%i"), Prefix.c_str(), Form->ID);
Storage.Create(StorName);
NotEmpty = ImportWorkBook(Storage, FormDir);
Storage.Close();
if( !NotEmpty )
Storage.Delete(StorName);
}
MMS_Filter.Up();
}
return NotEmpty;
}
void CMMSObject::ImportOrdering(wxString& SrcDir)
{
CObjectOrdering Order(1);
if( !Order.OpenFile(SrcDir) ) return;
int i = 0;
while( Order.ReadString() )
{
CMMSObject* obj = NULL;
wxString str_id = Order.GetValue(0);
if( str_id.IsNumber() )
obj = FindChild(wxAtoi(str_id), false);
else
obj = FindChild(str_id, false);
if( obj != NULL ) obj->Order = i++;
}
SortByOrder();
}
void CMMSTaskItem::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& Dir)
{
CMMSAttributes::Compile(Storage, TypedTextStorage, Dir);
CNameTableRecord* nt_rec = NameTable.Find(NT_UserHelpStor);
CNameTableRecord* nt_rec_file = NameTable.Find(NT_UserHelp);
wxString StorName = nt_rec->PrepareStorageName(Content.ID);
wxString FName = nt_rec_file->PrepareFileName(Dir);
if( wxFileExists(FName) )
{
if( TypedTextStorage.Create(StorName) )
{
Msg(2, _U("CPY: '%s'"), FName.c_str());
TypedTextStorage.StreamFromFile(nt_rec_file->PrepareStorageName(Content.ID), FName);
CContainer CC;
CC.CreateInTypedText(TypedTextStorage);
TypedTextStorage.Close();
}
}
}
///////////////////////////////////////////////////////////////////////
/////////// class CMMS methods //////////////////////////////////////
///////////////////////////////////////////////////////////////////////
bool CMMS::ImportStorage(CStorage& Storage, wxString& SrcDir, MMSObjectType Type)
{
CNameTableRecord* nt_rec = NameTable.Find(Type);
CStorage DestStor(Storage);
bool res;
MMS_Filter.Down();
if( MMS_Filter.Test(NULL, nt_rec) )
{
res = DestStor.StorageFromDir(nt_rec->PrepareStorageName(ID),
nt_rec->PrepareDirName(SrcDir));
}
MMS_Filter.Up();
return res;
}
void CMMS::ImportCommonMXL(CStorage& Storage, wxString& SrcDir)
{
CNameTableRecord* nt_rec_gd = NameTable.Find(NT_GlobalData);
CNameTableRecord* nt_rec = NameTable.Find(NT_CommonMXL);
MMS_Filter.Down();
if( MMS_Filter.Test(NULL, nt_rec) )
{
Msg(1, _U("INF: Общие таблицы"));
CStorage GDStorage(Storage);
GDStorage.Create(nt_rec_gd->StorageName);
CStorage MXLStorage(GDStorage);
MXLStorage.Create(nt_rec->StorageName);
if( !ImportWorkBook(MXLStorage, nt_rec->PrepareDirName(SrcDir)) )
{
MXLStorage.Close();
GDStorage.Delete(nt_rec->StorageName);
}
}
MMS_Filter.Up();
}
void CMMS::ImportGlobalModule(CStorage& Storage, wxString& Dir)
{
CNameTableRecord* nt_rec = NameTable.Find(NT_GlobalModuleStor);
CStorage GMStorage(Storage);
if( ImportStreamByType(Storage, NT_GlobalModule, Dir) && GMStorage.Open(nt_rec->StorageName) )
{
GMStorage.Open(nt_rec->StorageName);
CContainer CC;
CC.CreateInTypedText(GMStorage);
}
}
void CMMS::ImportMMS(CStorage& Storage)
{
CNameTableRecord* nt_rec = NameTable.Find(NT_MainMetadataStream);
CMMSString String;
//Изменим номер версии
MainDataContDef.MD_ver = 10009;
if( TaskParameters.CompoundType != external_report )
{
Storage.Create(wxString(_U("Metadata")));
}
ToString(String);
Storage.StreamFromString(nt_rec->StorageName, String);
if( TaskParameters.CompoundType == external_report )
{
Storage.AddZeroByte(); //Во внешнем отчёте в конце ММС обязан быть '\0'
}
if( TaskParameters.CompoundType != external_report )
{
Storage.Close();
}
}
void CMMS::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& Dir)
{
//firstly try to read name cache
if( MMS_Filter.IsEmpty() )
ReadObjNameCacheFromDir(Dir);
//Build names cache
BuildObjNameCache(ObjNameCache_compare_str, Dir, Storage);
if( TaskParameters.CompoundType == external_report )
{
ImportWorkBook(Storage, Dir);
ImportStorage(Storage, Dir, NT_PictureGallery);
ImportMMS(Storage);
CContainer CC;
CC.Create(Storage, true);
return;
}
SendInfoMessage(InfoMsg_Total, CountObjects());
//Глобальный модуль
ImportGlobalModule(TypedTextStorage, Dir);
for( int i = 0; i < GetNChildren(); i++ )
{
CMMSObject *obj = GetChild(i);
Msg(2, _U("%s:"), obj->sID.c_str());
obj->Compile(Storage, TypedTextStorage, Dir);
}
//Общие таблицы
ImportCommonMXL(Storage, Dir);
//Картинки
ImportStorage(Storage, Dir, NT_PictureGallery);
//Интерфейсы
CompileUI(Storage, Dir);
//Права
CompileUserRights(Storage, Dir);
//Служебные потоки
ImportStreamByType(Storage, NT_GUIDData, Dir);
ImportStreamByType(Storage, NT_TagStream, Dir);
//Container.Contents в каталоге UserDef
Storage.Open(wxString(_U("UserDef")));
wxString CC = _U("{\"Container.Contents\",{\"WorkPlaceType\",\"Page.1\",\"\",\"\"},{\"RigthType\",\"Page.2\",\"\",\"\"}}");
Storage.StreamFromString(_U("Container.Contents"), CC);
Storage.Close();
//Самое главное - Main Metadata Stream
Msg(1, _U("INF: Создание потока MainMetadataStream"));
if( MMS_Filter.IsEmpty() )
ImportMMS(Storage);
//Рекурсивный обход всех storage и создание Container.Contents там где его нет.
Msg(1, _U("INF: Создание потоков Container.Contents"));
CContainer ContainerContent;
ContainerContent.Create(Storage, true);
ContainerContent.Create(TypedTextStorage, true);
}
///////////////////////////////////////////////////////////////////////
/////////// class CMMSReport methods ////////////////////////////////
///////////////////////////////////////////////////////////////////////
void CMMSReport::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& SrcDir, wxString& SubStroragePrefix)
{
MMS_Filter.Down();
if( MMS_Filter.Test(this, NULL) )
{
wxString RptDir = GetObjectDir(SrcDir);
wxString StorName;
Msg(1, _U("INF: Отчёт.%s"), sID.c_str());
StorName.Printf(_U("%s%i"), SubStroragePrefix.c_str(), ID);
Storage.Create(StorName);
bool NotEmpty = ImportWorkBook(Storage, RptDir);
Storage.Close();
if( !NotEmpty )
Storage.Delete(StorName);
ImportDescriptions(TypedTextStorage, RptDir+_U("/"), true);
}
MMS_Filter.Up();
SendInfoMessage(InfoMsg_Progress, ++TotalObjectsProcessed);
}
///////////////////////////////////////////////////////////////////////
/////////// class CMMSReportList methods /////////////////////////////
///////////////////////////////////////////////////////////////////////
void CMMSReportList::Compile(CStorage& Storage, CStorage& TypedTextStorage, wxString& SrcDir)
{
CNameTableRecord* nt_rec = NameTable.Find(sID);
wxString ReportsDir = nt_rec->PrepareDirName(SrcDir);
MMS_Filter.Down();
if( MMS_Filter.Test(this, nt_rec) )
{
ImportOrdering(ReportsDir);
Storage.Create(nt_rec->StorageName);
wxString ReportStorName = nt_rec->StorageName + _U("_Number");
for( int i = 0; i < GetNChildren(); i++ )
{
((CMMSReport*)GetChild(i))->Compile(Storage, TypedTextStorage, ReportsDir, ReportStorName);
}
Storage.Close();
}
MMS_Filter.Up();
}