// aplClassifierMgr.cpp: implementation of the CaplClassifierMgr class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "aplClassifierMgr.h"
#include "apl_api.h"
#include "dictionary.h"
#include "ClassifierSystemDlg.h"
#include "ClassifierSelectDlg.h"
#include "DlgListInstances.h"
#include "SelectClassifierItemDlg.h"
#include "FindQueryDlg.h"
#include "ClassifierTreeView.h"
#include "ClassifierTableItemsView.h"
#include "ClassifierTreeFrame.h"
#include "ClassifierTableFrame.h"

#include "ClassifierChildFrame.h"

//////////////////////////////////////////////////////////////////////
// Переменная-указатель на функцию работы с форммами
CMDIChildWnd* aplCreateClassifiersFrame(CMDIFrameWnd *pMainFrame, CaplAPI* api, CaplInstance *Classifier, UINT nFrameResourceID)
{
	if(api==NULL) return NULL;
	if(Classifier==NULL) return NULL;
	if(!api->m_data.IsKindOf(Classifier, api->m_classifier_mgr.e_apl_classifier_system)) return NULL;

	CClassifierChildFrame* pFrame=(CClassifierChildFrame*)pMainFrame->CreateNewChild(RUNTIME_CLASS(CClassifierChildFrame), nFrameResourceID, NULL, NULL);
	if(pFrame)
		pFrame->Init(api, Classifier);
	return pFrame;
}

extern HINSTANCE CaplFormManagerDlgDLL;

int (*FShowForm1)(CaplAPI* pApi,CaplInstance* ciForm,
				  aplExtent& aeInInsts,aplExtent& aeOutInsts,
				  aplExtent* aeChars,LPCTSTR csInstChg,
				  CString csPath/*=_T("")*/,
				  BOOL bAutoSave/*=TRUE*/,BOOL bTst/*=FALSE*/,
				  BOOL bHideAdd/*=FALSE*/)=0;


// массив таблиц c фильтрами - чтобы память чистилась корректно
CaplTAggr<TArrElValChar*,TArrElValChar*,APLAGGR_UNIQUE_LIST_AUTOKILLREF> global_list_class_el_filters;
// карта - in - инстанс элемента классификатора, out - указатель на таблицу фильтров
CaplMap global_map__class_el_filters;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CaplClassifierMgr::CaplClassifierMgr()
{
	Detach();
	
	if(FShowForm1==0){
		if(CaplFormManagerDlgDLL!=0){
			(FARPROC&)FShowForm1= GetProcAddress(CaplFormManagerDlgDLL,"_ShowFormI");
		}
	}

}

CaplClassifierMgr::~CaplClassifierMgr()
{
}


//****************************************************************************
bool CaplClassifierMgr::Attach(CaplAPI *api)
{
	if(api==0)
	{
		Detach();
		return false;
	}
	CaplStepManager::Attach(api);
	e_apl_classifier_system = api->m_data.GetEntityBN(_T("apl_classifier_system"));
	a_apl_classifier_system_id = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("id"));
	a_apl_classifier_system_name = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("name"));
	a_apl_classifier_system_descr = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("description"));
	a_apl_classifier_system_parent = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("parent"));
	a_apl_classifier_system_childs = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("childs"));
	a_apl_classifier_system_is_concept_level_control = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_concept_level_control"));
	a_apl_classifier_system_is_concept_last_level = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_concept_last_level"));
	a_apl_classifier_system_concept_maxlevel = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("concept_maxlevel"));
	a_apl_classifier_system_concept_minlevel = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("concept_minlevel"));
	a_apl_classifier_system_can_store_object = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("can_store_object"));
	a_apl_classifier_system_is_object_level_control = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_object_level_control"));
	a_apl_classifier_system_is_object_last_level = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_object_last_level"));
	a_apl_classifier_system_object_maxlevel = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("object_maxlevel"));
	a_apl_classifier_system_object_minlevel = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("object_minlevel"));
	a_apl_classifier_system_is_type_control = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_type_control"));
	a_apl_classifier_system_forms = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("forms"));
	a_apl_classifier_system_stored_entity = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("stored_entity"));
	a_apl_classifier_system_list_characteristics = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("list_characteristics"));
	a_apl_classifier_system_esquisse = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("esquisse"));
	a_apl_classifier_system_esquisse_name = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("esquisse_name"));
	a_apl_classifier_system_template = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("item_id_template"));
	a_apl_classifier_system_is_multi_object = api->m_data.GetAttrDefinition(e_apl_classifier_system, _T("is_multi_object"));

	e_apl_classifier_level = api->m_data.GetEntityBN(_T("apl_classifier_level"));
	a_apl_classifier_level_id = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("id"));
	a_apl_classifier_level_code = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("code"));
	a_apl_classifier_level_name = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("name"));
	a_apl_classifier_level_name_eng = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("name_eng"));
	a_apl_classifier_level_descr = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("description"));
	a_apl_classifier_level_parent = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("parent"));
	a_apl_classifier_level_childs = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("childs"));
	a_apl_classifier_level_system = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("system"));
	a_apl_classifier_level_esquisse = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("esquisse"));
	a_apl_classifier_level_esquisse_name = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("esquisse_name"));
	a_apl_classifier_level_list_characteristics = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("list_characteristics"));
	a_apl_classifier_level_forms = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("forms"));
	a_apl_classifier_level_next_index = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("next_index"));
	a_apl_classifier_level_construction = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("only_construction"));
	a_apl_classifier_level_wiring = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("wiring"));
	a_apl_classifier_level_wiring_controls = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("wiring_near_controls"));
	a_apl_classifier_level_combustible_mat = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("combustible_materials"));
	a_apl_classifier_level_section_type = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("section_type"));
	a_apl_classifier_level_req_characts = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("required_characts"));
	a_apl_classifier_level_related_pdf = api->m_data.GetAttrDefinition(e_apl_classifier_level, _T("related_pdf"));
	a_apl_classifier_level_okpd_code = api->m_data.GetAttrDefinition(e_apl_classifier_level,_T("okpd_code"));
	CHECK_ZERO_ATTR(a_apl_classifier_level_is_system_level, m_data->GetAttrDefinition(e_apl_classifier_level, _T("is_system_level")));
		
	e_apl_classifier_association = api->m_data.GetEntityBN(_T("apl_classifier_association"));
	a_apl_classifier_association_item = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("item"));
	a_apl_classifier_association_classifier = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("classifier"));
	a_apl_classifier_association_index = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("index"));
	a_apl_classifier_association_id = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("id"));
	a_apl_classifier_association_system = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("system"));
	a_apl_classifier_association_pdf_count = api->m_data.GetAttrDefinition(e_apl_classifier_association, _T("pdf_count"));

	CHECK_ZERO_ATTR(a_apl_classifier_system_inner_label, m_data->GetAttrDefinition(e_apl_classifier_system,	_T("inner_label")));
	CHECK_ZERO_ATTR(a_apl_classifier_system_view_format, m_data->GetAttrDefinition(e_apl_classifier_system, _T("view_format")));
	CHECK_ZERO_ATTR(a_apl_classifier_level_inner_label, m_data->GetAttrDefinition(e_apl_classifier_level,	_T("inner_label")));
	CHECK_ZERO_ATTR(a_apl_classifier_association_inner_label, m_data->GetAttrDefinition(e_apl_classifier_association,	_T("inner_label")));

	return m_AllAttrDefined;
}//bool CaplClassifierMgr::Attach


//****************************************************************************
void CaplClassifierMgr::Detach()
{
	CaplStepManager::Detach();

	e_apl_classifier_system = NULL;
	a_apl_classifier_system_id = NULL;
	a_apl_classifier_system_name = NULL;
	a_apl_classifier_system_descr = NULL;
	a_apl_classifier_system_is_concept_level_control = NULL;
	a_apl_classifier_system_is_concept_last_level = NULL;
	a_apl_classifier_system_concept_maxlevel = NULL;
	a_apl_classifier_system_concept_minlevel = NULL;
	a_apl_classifier_system_can_store_object = NULL;
	a_apl_classifier_system_is_object_level_control = NULL; 
	a_apl_classifier_system_is_object_last_level = NULL;
	a_apl_classifier_system_object_maxlevel = NULL;
	a_apl_classifier_system_object_minlevel = NULL;
	a_apl_classifier_system_is_type_control = NULL;
	a_apl_classifier_system_forms = NULL;
	a_apl_classifier_system_stored_entity = NULL;
	a_apl_classifier_system_template = NULL;
	a_apl_classifier_system_is_multi_object = NULL;
	a_apl_classifier_system_view_format = NULL;

	e_apl_classifier_level = NULL;
	a_apl_classifier_level_id = NULL;
	a_apl_classifier_level_code = NULL;
	a_apl_classifier_level_name = NULL;
	a_apl_classifier_level_name_eng = NULL;
	a_apl_classifier_level_descr = NULL;
	a_apl_classifier_level_parent = NULL;
	a_apl_classifier_level_childs = NULL;
	a_apl_classifier_level_system = NULL;
	a_apl_classifier_level_list_characteristics = NULL;
	a_apl_classifier_level_forms = NULL;
	a_apl_classifier_level_next_index = NULL;
	a_apl_classifier_level_construction = NULL;
	a_apl_classifier_level_wiring = NULL;
	a_apl_classifier_level_wiring_controls = NULL;
	a_apl_classifier_level_combustible_mat = NULL;
	a_apl_classifier_level_section_type = NULL;
	a_apl_classifier_level_req_characts = NULL;
	a_apl_classifier_level_related_pdf = NULL;
	a_apl_classifier_level_okpd_code = NULL;
	a_apl_classifier_level_is_system_level = NULL;

	e_apl_classifier_association = NULL;
	a_apl_classifier_association_item = NULL;
	a_apl_classifier_association_classifier = NULL;
	a_apl_classifier_association_index = NULL;
	a_apl_classifier_association_id = NULL;
	a_apl_classifier_association_system = NULL;
	a_apl_classifier_association_pdf_count = NULL;

	global_list_class_el_filters.Clear();
	global_map__class_el_filters.Clear();
	
}//void CaplClassifierMgr::Detach


//****************************************************************************
bool CaplClassifierMgr::LoadDictionary()
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;

	CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
	ld.AddQuery(_T('e'), 0, e_apl_classifier_system, 0, true, true);
	ld.LoadEx();

	return true;
}


//****************************************************************************
bool CaplClassifierMgr::LoadClassifierInfo(CaplInstance *inst)
{
	aplExtent ext;
	if(inst==0)return false;
	ext.Add(inst);
	return LoadClassifierInfo(ext);
}


//****************************************************************************
bool CaplClassifierMgr::LoadClassifierInfo(aplExtent &ext)
{
	if(m_data==0) return false;
	if(!m_data->IsConnected()) return false;

	//разбиваем на различные массивы в зависимости от entity;
	CaplLoadData lde(m_data, DEF_SOURCE);
	CaplLoadData lds(m_data, DEF_SOURCE);
	for(int i=0; i<ext.Size; i++){
		if(ext[i]==0) continue;
		if(ext[i]->GetId()==0) continue;
		if(ext[i]->GetType()==0) continue;
		
		if(m_data->IsKindOf(ext[i], e_apl_classifier_system))lds.AddQuery(0, ext[i], true); //справочник 
		else if(m_data->IsKindOf(ext[i], e_apl_classifier_level))lde.AddQuery(0, ext[i], true);
		
		if(lds.m_queries.GetSize()>=m_MaxItemsLoad)
		{
			lds.AddQuery(_T('d'),0,0,a_apl_classifier_system_list_characteristics,true,true);
			lds.LoadEx();
			lds.ClearQuery();
		}
		if(lde.m_queries.GetSize()>=m_MaxItemsLoad)
		{
			lde.AddQuery(_T('d'),0,0,a_apl_classifier_level_list_characteristics,true,true);
			lde.AddQuery(_T('d'),0,0,a_apl_classifier_level_system,true,true);
			lde.LoadEx();
			lde.ClearQuery();
		}
	}
	if(lds.m_queries.GetSize()>0){
		lds.AddQuery(_T('d'),0,0,a_apl_classifier_system_list_characteristics,true,true);
		lds.LoadEx();
	}
	if(lde.m_queries.GetSize()>0){
		lde.AddQuery(_T('d'),0,0,a_apl_classifier_level_list_characteristics,true,true);
		lde.AddQuery(_T('d'),0,0,a_apl_classifier_level_system,true,true);
		lde.LoadEx();
	}

	return true;
}//bool CaplClassifierMgr::LoadClassifierInfo


//****************************************************************************
CaplInstance* CaplClassifierMgr::CreateClassifierSystem(CaplInstance *ParentElement,
									LPCTSTR id, LPCTSTR name, LPCTSTR descr, bool TestUnique)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	CaplInstance* system=0;
	if(ParentElement!=0){
		if(ParentElement->GetAccessmode()>ACCESS2SYSTEM_FOR_STRUCTURE){
			CString name;
			m_api->GetItemName(ParentElement,name);
			if(m_api->m_ModeInteractive)
			{
				CString buf=APL_T("Для редактирования структуры справочника нужен ");
				buf+=ACCESS2SYSTEM_FOR_STRUCTURE_DESCR;
				buf+= APL_T(" к родительскому справочнику!\n");
				buf+=APL_T("Родительский справочник: ");
				buf+=name;
				AfxMessageBox(buf);
			}
			return NULL;
		}
	}
	

	CString sId(id), sName(name), sDescr(descr);
	if((id==NULL || name==NULL) && TestUnique==true)
	{
		CaplSetResourceHandle setres(module_inst);

		CClassifierSystemDlg dlg;
		dlg.m_bSystem=true;
		dlg.m_api=m_api;
		dlg.m_sId = sId;
		dlg.m_sName = sName;
		dlg.m_sDescr = sDescr;
		dlg.m_parent = ParentElement;
		if(dlg.DoModal()!=IDOK){
			return NULL;
		}
		system=dlg.m_item;
	}else{
		if(TestUnique)//проверка на уникальность. если такая есть, то возвращаем её
		{
			aplExtent res;
			CaplAttrValue tst_val;
			tst_val.attr = a_apl_classifier_system_id;
			tst_val.value.Set(sId);
			if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_system, 1, &tst_val, res, false)>0)
			{
				//Нашли. теперь нужно проверить корневые справочники!
				CaplInstance* fSystem = res[0], *parent;
				if(fSystem)
				{
					m_api->m_data.GetAttr(fSystem, a_apl_classifier_system_parent, parent);
					if(parent!=ParentElement)
					{
						//По умолчанию переместим справочник в новый корневой справочник
						bool bReplace = true;
						if(m_api->m_ModeInteractive)
						{
							if(AfxMessageBox( APL_T("Справочник с таким обозначением уже существуетв БД, но входит в другой родительский справочник. Переместить данный справочник в новый?"),
								MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1)!=IDYES)
							{
								bReplace = false;
							}
						}
						if(bReplace)
						{
							aplExtent childs;
							if(parent)
							{
								m_api->m_data.GetAttr(parent, a_apl_classifier_system_childs, childs);
								childs.Remove(childs.Find(fSystem));
								m_api->m_data.PutAttr(parent, a_apl_classifier_system_childs, childs);
							}
							if(ParentElement)
							{
								m_api->m_data.GetAttr(ParentElement, a_apl_classifier_system_childs, childs);
								childs.Add(fSystem);
								m_api->m_data.PutAttr(ParentElement, a_apl_classifier_system_childs, childs);
							}
							m_api->m_data.PutAttr(fSystem, a_apl_classifier_system_parent, ParentElement);
						}
					}
					return res[0];
				}
			}
		}
		system = m_api->m_data.CreateInstance(e_apl_classifier_system);
		ASSERT(system);
		
		m_api->m_data.PutAttr(system, a_apl_classifier_system_id, sId);
		m_api->m_data.PutAttr(system, a_apl_classifier_system_name, sName);
		m_api->m_data.PutAttr(system, a_apl_classifier_system_descr, sDescr);
		m_api->m_data.PutAttr(system, a_apl_classifier_system_parent , ParentElement);
		if(ParentElement!=0)
		{
			aplExtent childs;
			m_api->m_data.GetAttr(ParentElement, a_apl_classifier_system_childs, childs);
			childs.Add(system);
			m_api->m_data.PutAttr(ParentElement, a_apl_classifier_system_childs, childs);
		}	
	}


	if(m_AutoSave) m_api->m_data.NET_SaveChanges();
	
	if(true==m_AutoUsurpire)
	{
		CaplEntity*	et	=NULL;
		aplExtent	aet;
		CString		csAccPat;

		et=e_apl_classifier_system;

		if(!m_AutoSave) m_api->m_data.NET_SaveChanges();
		if(NULL!=system)
			if(aplOWN==system->GetAccessmode())
				aet.Add(system);
		if(TRUE==m_api->m_options_mgr.GetDefPatern(et,csAccPat))
			apidata.NET_SetAccessFromPattern(&aet,csAccPat);
	}

	return system;
}//CaplInstance* CaplClassifierMgr::CreateClassifierSystem


//****************************************************************************
CaplInstance* CaplClassifierMgr::CreateClassifierLevel(CaplInstance *ClassifierSystem, CaplInstance *ParentElement, LPCTSTR id, LPCTSTR name, LPCTSTR descr, LPCTSTR code, bool TestUnique)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	CaplInstance* level=0;
	if(ClassifierSystem==0){
		return NULL;
	}else{
		if(ClassifierSystem->GetAccessmode()>ACCESS2SYSTEM_FOR_STRUCTURE){
			CString name;
			m_api->GetItemName(ClassifierSystem,name);
			if(m_api->m_ModeInteractive)
			{
				CString mes= APL_T("Для редактирования структуры справочника нужен ");
				mes+=ACCESS2SYSTEM_FOR_STRUCTURE_DESCR;
				mes+= APL_T(" к справочнику!\nСправочник: ");
				mes+=name;
				AfxMessageBox(mes);
			}
			return NULL;
		}
	}
	// Считаем уровни вложенности
//	При создании уровней контроль не ведется
//	if(!TestConceptLevelOfElement(ParentElement)){ 
//		return 0;
//	}
	
	CString sId(id), sName(name), sDescr(descr), sCode(code);
	if(sId.IsEmpty() && TestUnique==true)
	{
		CaplSetResourceHandle setres(module_inst);
		// предустанавливаем значение обозначения
		if(id==NULL){
			if(ParentElement!=0){
				m_data->GetAttr(ParentElement,a_apl_classifier_level_id,sId);
			}else{
				m_data->GetAttr(ClassifierSystem,a_apl_classifier_system_id,sId);
			}		
		}
		CClassifierSystemDlg dlg;
		dlg.m_api=m_api;
		dlg.m_bSystem=false;
		dlg.m_sId = sId;
		dlg.m_sName = sName;
		dlg.m_sCode = sCode;
		dlg.m_sDescr = sDescr;
		dlg.m_system = ClassifierSystem;
		dlg.m_parent = ParentElement;
		if(dlg.DoModal()!=IDOK){
			return NULL;
		}
		level=dlg.m_item;
	}else{
		if(TestUnique)//проверка на уникальность. если такой уровнь есть, то возвращаем его
		{
			aplExtent res;
			CaplAttrValue tst_val[2];
			tst_val[0].attr = a_apl_classifier_level_id;
			tst_val[0].value.Set(sId);
			tst_val[1].attr = a_apl_classifier_level_system;
			tst_val[1].value.Set(ClassifierSystem);
			if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_level, 2, &tst_val[0], res, false)>0)
				return res[0];
		}
		level = m_api->m_data.CreateInstance(e_apl_classifier_level);
		ASSERT(level);
		
		m_api->m_data.PutAttr(level, a_apl_classifier_level_id, sId);
		m_api->m_data.PutAttr(level, a_apl_classifier_level_system, ClassifierSystem);
		m_api->m_data.PutAttr(level, a_apl_classifier_level_name, sName);
		m_api->m_data.PutAttr(level, a_apl_classifier_level_descr, sDescr);
		m_api->m_data.PutAttr(level, a_apl_classifier_level_parent, ParentElement);
		if(ParentElement)
		{
			aplExtent childs;
			m_api->m_data.GetAttr(ParentElement, a_apl_classifier_level_childs, childs);
			childs.Add(level);
			m_api->m_data.PutAttr(ParentElement, a_apl_classifier_level_childs, childs);
		}
	}
	
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();

	if(true==m_AutoUsurpire)
	{
		CaplEntity*	et	=NULL;
		aplExtent	aet;
		CString		csAccPat;

		et=e_apl_classifier_level;

		if(!m_AutoSave) m_api->m_data.NET_SaveChanges();
		if(NULL!=level)
			if(aplOWN==level->GetAccessmode())
				aet.Add(level);
		if(TRUE==m_api->m_options_mgr.GetDefPatern(et,csAccPat))
			apidata.NET_SetAccessFromPattern(&aet,csAccPat);
	}

	return level;
}//CaplInstance* CaplClassifierMgr::CreateClassifierLevel


//****************************************************************************
bool CaplClassifierMgr::MoveClassifierSystem(CaplInstance* MovedSystem, CaplInstance *NewParent)
{
	CaplInstance* old_parent;
	aplExtent childs;
	int i;
	
	if(MovedSystem==0)return false;
	// точно справочник переносим?
	if(!m_data->IsKindOf(MovedSystem,e_apl_classifier_system)){return false;}
	// доступ на переносимый элемент структуры
	if(MovedSystem->GetAccessmode()>ACCESS2SYSTEM_FOR_STRUCTURE){
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на переносимый справочник!"));
		return false;
	}
	
	// проверим на совпадение систем и доступ на систему
	if(NewParent!=0){
		if(!m_data->IsKindOf(NewParent,e_apl_classifier_system)){return false;}
		if(NewParent->GetAccessmode()>ACCESS2LEVEL_FOR_STRUCTURE){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на новый родительский справочник!"));
			return false;
		}
		// Проверка рекурсии и самозамыкания
		if(NewParent==MovedSystem){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нельзя перенести справочник сам в себя!"));
			return false;
		}
		CaplInstance *inst0=NewParent,*inst1;
		bool found=false;
		while (1){
			if(inst0==0) break;
			m_api->m_data.GetAttr(inst0,a_apl_classifier_system_parent,inst1);
			if(inst1==MovedSystem){found=true; break;}
			inst0=inst1;
		}
		if(found){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нельзя создать цикл в иерархии элементов структуры справочника!"));
			return false;
		}
	}
	
	m_api->m_data.GetAttr(MovedSystem, a_apl_classifier_system_parent, old_parent);
	if(old_parent)
	{
		// если у переносимй системы есть родитель - нужен полный доступ
		if(old_parent->GetAccessmode()>ACCESS2LEVEL_FOR_STRUCTURE){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на исходный родительский справочник!"));
			return false;
		}

		//////////////////   переносим ////////////////
		m_api->m_data.GetAttr(old_parent, a_apl_classifier_system_childs, childs);
		for(i=0;i<childs.GetSize();i++){
			if(childs[i]==MovedSystem){
				childs.Remove(i);break;
			}
		}
		m_api->m_data.PutAttr(old_parent, a_apl_classifier_system_childs, childs);
		m_api->m_data.PutAttr(MovedSystem, a_apl_classifier_system_parent, (CaplInstance*)0);
	}
	
	if(NewParent!=0)
	{
		m_api->m_data.GetAttr(NewParent, a_apl_classifier_system_childs, childs);
		childs.Add(MovedSystem);
		m_api->m_data.PutAttr(NewParent, a_apl_classifier_system_childs, childs);
		m_api->m_data.PutAttr(MovedSystem, a_apl_classifier_system_parent, NewParent);
	}
	return true;
}//bool CaplClassifierMgr::MoveClassifierSystem


//****************************************************************************
bool CaplClassifierMgr::MoveClassifierLevel(CaplInstance* MovedElement, CaplInstance *NewParent, bool bMoveBetweenSystems /*= false*/)
{
	CaplInstance* old_parent,*system_moved,*system_new_parent;
	aplExtent childs;
	int i;

	if(MovedElement==0)return false;
	if(!m_data->IsKindOf(MovedElement,e_apl_classifier_level)){return false;}
	// доступ на переносимый элемент
	if(MovedElement->GetAccessmode()>ACCESS2LEVEL_FOR_STRUCTURE){
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на переносимый элемент структуры справочника!"));
		return false;
	}

	// проверим на совпадение систем и доступ на систему
	m_api->m_data.GetAttr(MovedElement,a_apl_classifier_level_system,system_moved);
	if(system_moved!=0){
		if(system_moved->GetAccessmode()>ACCESS2SYSTEM_FOR_STRUCTURE){
			if(m_api->m_ModeInteractive)
			{
				CString mes= APL_T("Для изменения элементов структуры справочника требуется иметь ");
				mes+=ACCESS2SYSTEM_FOR_STRUCTURE_DESCR;
				mes+= APL_T(" на справочник!");
				AfxMessageBox( mes );
			}
			return false;
		}
	}
	if(NewParent!=0){
		if(NewParent->GetAccessmode()>ACCESS2LEVEL_FOR_STRUCTURE){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на новый родительский элемент структуры справочника!"));
			return false;
		}
		if(m_data->IsKindOf(NewParent,e_apl_classifier_level)){
			m_api->m_data.GetAttr(NewParent,a_apl_classifier_level_system,system_new_parent);
		}else if(m_data->IsKindOf(NewParent,e_apl_classifier_system)){
			system_new_parent=NewParent;NewParent=0;
		}else{return false;}
		if(system_new_parent!=system_moved && system_moved!=0 && false==bMoveBetweenSystems){
			if(m_api->m_ModeInteractive)
			{
				//AfxMessageBox( APL_T("Элементы структуры можно переносить только внутри одного справочника!"));
				if(AfxMessageBox( APL_T("Вы хотите перенести элемент структуры в другой\nсправочник! Могут возникнуть конфликты между параметрами\nнового справочника и содержимым переносимого элемента.\nВы все равно хотите перенести элемент?"),
					MB_YESNO)==IDNO)return false;
			}
			
		}
		// Проверка рекурсии и самозамыкания
		if(NewParent==MovedElement){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нельзя перенести элементы структуры справочника самих в себя!"));
			return false;
		}
		
		CaplInstance *inst0=NewParent,*inst1;
		bool found=false;
		aplExtent ext_passed;
		int i_p;
		ext_passed.Unique=false;
		while (1){
			if(inst0==0) break;
			ext_passed.Add(inst0);
			m_api->m_data.GetAttr(inst0,a_apl_classifier_level_parent,inst1);
			for(i_p=0;i_p<ext_passed.GetSize();i_p++){
				if(ext_passed[i_p]==inst1){
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("В иерархии элементов структуры справочника обнаружен цикл!"));
					return false;
				}
			}
			if(inst1==MovedElement){found=true; break;}
			inst0=inst1;
		}
		if(found){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нельзя создать цикл в иерархии элементов структуры справочника!"));
			return false;
		}
//		При создании уровней контроль не ведется
//		if(!m_api->m_classifier_mgr.TestLevelCreateElement(NewParent)){
//			return false;
//		}
	}

	// если у переносимого уровня есть родитель - нужен полный доступ
	m_api->m_data.GetAttr(MovedElement, a_apl_classifier_level_parent, old_parent);
	if(old_parent)
	{
		if(old_parent->GetAccessmode()>ACCESS2LEVEL_FOR_STRUCTURE){
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа на исходный родительский элемент структуры справочника!"));
			return false;
		}
		// проверка переноса на родителя
		if(NewParent==old_parent){
			if(m_api->m_ModeInteractive){
				CString str1,str2;
				m_api->GetItemName(MovedElement,str1);
				m_api->GetItemName(NewParent,str2);
				AfxMessageBox( APL_T("Элемент ")+str1+ APL_T(" уже входит в элемент ")+str2+_T("!"));
			}
			return false;
		}

	}
	bool can_object,is_multi_object;
	bool is_object_control;
	bool is_last_level;
	int min_level;
	int max_level;
	GetObjectLevelParameters(MovedElement,can_object,is_object_control,is_last_level,min_level,max_level,is_multi_object);
	if(is_object_control && can_object){
		if(is_last_level){
			// проверяем нового родителя
			aplExtent ext;
			GetSubItems(NewParent,ext,0,false);
			if(ext.GetSize()>0){
				if(m_api->m_ModeInteractive){
					CString str;
					m_api->GetItemName(NewParent,str);
					if(AfxMessageBox(
						 APL_T("Внимание! После переноса текущего элемента справочника объекты,\nклассифицированые в элементе справочника ")
						+str
						+ APL_T("\nперестанут соответствовать ограничениям на уровень\nи будут недоступны из специализированных приложений.\nПеренести элемент справочника?"),
						MB_YESNO)==IDNO)
					{
						return false;
					}
				}
			}
			
		}else{
			int new_level=GetLevelClassifierLevel(NewParent);
			if(new_level<min_level || new_level>max_level){
				if(m_api->m_ModeInteractive){
					CString str;
					m_api->GetItemName(MovedElement,str);
					if(AfxMessageBox(
						 APL_T("Внимание! После переноса текущего элемента справочника объекты,\nклассифицированые в переносимом элементе справочника ")
						+str
						+ APL_T("\nперестанут соответствовать ограничениям на уровень\nи будут недоступны из специализированных приложений.\nПеренести элемент справочника?"),
						MB_YESNO)==IDNO)
					{
						return false;
					}
				}
			}
		}
	}
	
	//////////////////   переносим ////////////////
	if(old_parent)
	{
		m_api->m_data.GetAttr(old_parent, a_apl_classifier_level_childs, childs);
		for(i=0;i<childs.GetSize();i++){
			if(childs[i]==MovedElement){
				childs.Remove(i);break;
			}
		}
		m_api->m_data.PutAttr(old_parent, a_apl_classifier_level_childs, childs);
		m_api->m_data.PutAttr(MovedElement, a_apl_classifier_level_parent, (CaplInstance*)0);
	}

	if(NewParent!=0)
	{
		m_api->m_data.GetAttr(NewParent, a_apl_classifier_level_childs, childs);
		childs.Add(MovedElement);
		m_api->m_data.PutAttr(NewParent, a_apl_classifier_level_childs, childs);
		m_api->m_data.PutAttr(MovedElement, a_apl_classifier_level_parent, NewParent);
	}

	if(system_new_parent!=system_moved)  // Перенос в другой справочник
	{
		m_api->m_data.PutAttr(MovedElement, a_apl_classifier_level_system, system_new_parent);

		// короректировка ассоциаторов объектов с уровнем справочника - привязка к новому справочнику
		aplExtent ext_ok, ext_rel;
		GetSubItems(MovedElement,ext_ok, &ext_rel);
		for(i=0; i<ext_rel.GetSize(); i++)
		{
			m_api->m_data.PutAttr(ext_rel[i], a_apl_classifier_association_system, system_new_parent);
		}
	}

	return true;
}//bool CaplClassifierMgr::MoveClassifierLevel

void CaplClassifierMgr::AddIfNotFound(aplExtent &base,aplExtent &added)
{
	int i,j;
	CaplInstance *charact_1,*type_1,*charact_2,*type_2;
	bool not_found;
	if(m_api==0)return;
	for(i=0;i<added.GetSize();i++){
		not_found=true;
		m_api->m_data.GetAttr(added[i],m_api->m_charact_mgr.a_apl_characteristic_and_type_characteristic,charact_1);
		m_api->m_data.GetAttr(added[i],m_api->m_charact_mgr.a_apl_characteristic_and_type_type,type_1);
		for(j=0;j<base.GetSize();j++){
			m_api->m_data.GetAttr(base[j],m_api->m_charact_mgr.a_apl_characteristic_and_type_characteristic,charact_2);
			m_api->m_data.GetAttr(base[j],m_api->m_charact_mgr.a_apl_characteristic_and_type_type,type_2);
			if(type_1==type_2 && charact_1==charact_2){
				not_found=false;
				break;
			}
		}
		if(not_found){
			base.Add(added[i]);
		}
	}
}

bool CaplClassifierMgr::GetClassifierElementFilters(CaplInstance* item,TArrElValChar** filters)
{
	if(filters==0)return false;
	long lval=global_map__class_el_filters.QGetByIn((long)item);
	if(lval!=-1){
		*filters=(TArrElValChar*)lval;
	}else{
		*filters=new TArrElValChar;
		if(*filters==0)return false;
		global_list_class_el_filters.Add(*filters);
		global_map__class_el_filters.Add((long)item,(long)*filters);
		global_map__class_el_filters.SortIn();
	}
	return true;
}

//****************************************************************************
bool CaplClassifierMgr::GetClassifierCharacteristic(CaplInstance* item,
								aplExtent &out_ext,bool all_level,bool chek_unique,bool load_from_bd)
{
	aplExtent ext_passed;
	int i_p;
	ext_passed.Unique=false;
	out_ext.Clear();
	if(item==0)return false;
	if(item==(CaplInstance*)-1)return false;
	if(item->GetType()==0)return false;
	if(load_from_bd)LoadClassifierInfo(item);
	if(m_api->m_data.IsKindOf(item, e_apl_classifier_system))
	{
		m_api->m_data.GetAttr(item,a_apl_classifier_system_list_characteristics,out_ext);
	}
	else if(m_api->m_data.IsKindOf(item, e_apl_classifier_level))
	{
		m_api->m_data.GetAttr(item,a_apl_classifier_level_list_characteristics,out_ext);
		if(all_level){
			CaplInstance *inst_p=item,*inst_c;
			aplExtent ext;
			m_data->GetAttr(inst_p,a_apl_classifier_level_parent,inst_c);
			while(inst_p!=0){
				ext_passed.Add(inst_p);
				m_data->GetAttr(inst_p,a_apl_classifier_level_parent,inst_c);
				if(inst_c==0)break;
				for(i_p=0;i_p<ext_passed.GetSize();i_p++){
					if(ext_passed[i_p]==inst_c){
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("В иерархии элементов структуры справочника обнаружен цикл!"));
						return false;
					}
				}
				if(load_from_bd)LoadClassifierInfo(inst_c);
				m_api->m_data.GetAttr(inst_c,a_apl_classifier_level_list_characteristics,ext);
				if(chek_unique){
					AddIfNotFound(out_ext,ext);
				}else{
					out_ext.Append(ext);
				}
				inst_p=inst_c;
			}
			m_data->GetAttr(item,a_apl_classifier_level_system,inst_p);
			if(inst_p!=0){
				if(load_from_bd)LoadClassifierInfo(inst_p);
				m_data->GetAttr(inst_p, a_apl_classifier_system_list_characteristics, ext);
				if(chek_unique){
					AddIfNotFound(out_ext,ext);
				}else{
					out_ext.Append(ext);
				}
			}
		}
	}
	return true;
}

//****************************************************************************
int CaplClassifierMgr::GetLevelClassifierLevel(CaplInstance* element)
{
	int level_current=0;
	if(element==0){return -1;}
	CaplInstance *inst_p=element,*inst_c;
	aplExtent ext_passed;
	int i_p;
	ext_passed.Unique=false;
	while(inst_p!=0){
		ext_passed.Add(inst_p);
		m_data->GetAttr(inst_p,a_apl_classifier_level_parent,inst_c);
		for(i_p=0;i_p<ext_passed.GetSize();i_p++){
			if(ext_passed[i_p]==inst_c){
				if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("В иерархии элементов структуры справочника обнаружен цикл!"));
				return -1;
			}
		}
		LoadClassifierInfo(inst_c);
		level_current++;
		inst_p=inst_c;
	}
	//level_current++;
	return level_current;
}//int CaplClassifierMgr::GetLevelClassifierLevel


//****************************************************************************
bool CaplClassifierMgr::TestConceptLevelOfElement(CaplInstance* element)
{
	CaplInstance *system;
	if(element==0){
		return true;
	}
	if(!m_data->IsKindOf(element,e_apl_classifier_level)){return false;}
	m_data->GetAttr(element,a_apl_classifier_level_system,system);
	if(system==0){
		return false;
	}
	int level_current=0;
	bool is_concept_control,is_last_level;
	int min_level,max_level;
	GetConceptLevelParameters(element,is_concept_control,is_last_level,min_level,max_level);
	if(!is_concept_control) return true;
	aplExtent childs;
	if(is_last_level){
		// последний ли уровень?
		m_data->GetAttr(element,a_apl_classifier_level_childs,childs);
		return childs.GetSize()==0;
	}else{
		// считаем уровни
		level_current=GetLevelClassifierLevel(element);
		return level_current>=min_level && level_current<=max_level;
	}

//	if(level_created>level_max && level_max!=-1){
//		if(m_ModeInteractive){
//			if(AfxMessageBox("Уровень создаваемого элемента структуры больше чем максимальный уровень справочника!\n"
//				"Продолжить создание элемента структуры?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//			{
//				return false;
//			}
//		}
//	}
	
	return false;
}//bool CaplClassifierMgr::TestConceptLevelOfElement


//****************************************************************************
bool CaplClassifierMgr::TestObjectLevelOfLevel(CaplInstance* element,bool supress_mesage)
{
	CaplInstance *system;
	if(element==0){
		return true;
	}
	if(element->GetType()==0){
		return true;
	}
	if(!m_data->IsKindOf(element,e_apl_classifier_level)){
		if(m_api->m_ModeInteractive){
			CString message;
			message.Format( APL_T("Объекты можно присоединить только к элементам структуры справочника!"));
			AfxMessageBox(message);
		}

		return false;
	}
	m_data->GetAttr(element,a_apl_classifier_level_system,system);
	if(system==0){
		return false;
	}
	int level_current=0;
	bool can_object,is_object_control,is_last_level,is_multi_object;
	int min_level,max_level;
	GetObjectLevelParameters(element,can_object,is_object_control,is_last_level,min_level,max_level,is_multi_object);
	if(!can_object){
		if(m_api->m_ModeInteractive && !supress_mesage){AfxMessageBox( APL_T("Справочник является справочником понятий а не объектов"));}
		return false;
	}
	if(!is_object_control) return true;
	aplExtent childs;
	if(is_last_level){
		// последний ли уровень?
		m_data->GetAttr(element,a_apl_classifier_level_childs,childs);
		if(childs.GetSize()>0){
			if(m_api->m_ModeInteractive && !supress_mesage){AfxMessageBox( APL_T("Объекты можно связывать только с последним уровнем данного справочника"));}
			return false;
		}
	}else{
		// считаем уровни
		level_current=GetLevelClassifierLevel(element);
		if(level_current<min_level || level_current>max_level){
			if(m_api->m_ModeInteractive && !supress_mesage){
				CString message;
				message.Format( APL_T("Уровень элементов структуры справочника не попадает в заданный диапазон (от %i до %i)"),
					min_level,max_level);
				AfxMessageBox(message);}
			return false;
		}
	}
	return true;

//	if(level_created>level_max && level_max!=-1){
//		if(AfxMessageBox("Уровень элемента структуры больше чем максимальный уровень справочника!\n"
//			"Занести объект в справочник?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//		{
//			return false;
//		}
//	}	
//	if(level_created<level_min && level_min!=-1){
//		if(AfxMessageBox("Уровень элемента структуры меньше чем минимальный уровень справочника!\n"
//			"Занести объект в справочник?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//		{
//			return false;
//		}
//	}	

}//bool CaplClassifierMgr::TestObjectLevelOfElement

bool CaplClassifierMgr::TestObjectType(CaplInstance* element,CaplInstance* object)
{
	if(m_api==0) return false;
	if(element==0) return false;
	if(object==0) return false;	
	bool is_object_type_control;
	CaplEntity* stored_entity;
	aplExtent form_instances;
//	int i,j;
	bool is_found=false;

	if(m_api->m_data.IsKindOf(object,m_api->m_prd_mgr.e_prd)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_prd_mgr.e_pdf)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_doc_mgr.e_apl_doc)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_prd_inst_mgr.e_prd_inst)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_prd_inst_mgr.e_lot)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_bp_mgr.e_bp)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_bp_mgr.e_apl_bp_inst)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_appr_mgr.e_org)){
	}else if(m_api->m_data.IsKindOf(object,m_api->m_folder_mgr.e_folder)){
	}else if (m_api->m_data.IsKindOfBN(object,_T("apl_appearance_requirement_limit"))){
	}else if (m_api->m_data.IsKindOfBN(object,_T("apl_composition_requirement"))){
	}else if (m_api->m_data.IsKindOf(object,m_api->m_charact_mgr.e_apl_unit)){
	}else if (m_api->m_data.IsKindOf(object,m_api->m_classifier_mgr.e_apl_classifier_system)){
	}else if (m_api->m_data.IsKindOf(object,m_api->m_project_mgr->e_project)){
	}else
	{
		if(m_api->m_ModeInteractive)
		{
			CString mess;
			if(object->GetType()!=0)
			{
				mess = APL_T("Объект типа ");
				mess += object->GetType()->name;
				mess += APL_T(" не может быть классифицирован!");
			}
			else
			{
				mess = APL_T("Объект, удаленный из БД, не может быть классифицирован.");
			}
			AfxMessageBox( mess );
		}
		return false;
	}



	GetObjectTypeParameters(element,is_object_type_control,&stored_entity,true);
	if(!is_object_type_control)return true;
	if(stored_entity==0)return true;
	bool retval=m_data->IsKindOf(object,stored_entity);
	if(m_api->m_ModeInteractive && !retval)
	{
		CString message;
		message.Format( APL_T("Тип вносимого объекта не совпадает с типом, заданным для справочника!"));
		AfxMessageBox(message);
	}

	return retval;
}
//****************************************************************************
bool CaplClassifierMgr::CheckItemInClassifierByOption(CaplInstance *item, LPCTSTR option, bool bShowMsg)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(0==option) return false;
	if(0==item) return false;

	CString sOptionValue;
	m_api->m_options_mgr.GetOptionValueBN( option, sOptionValue, _T(""));
	if(sOptionValue==_T("")) return true;

	bool b=CheckItemInClassifierById(item,LPCTSTR(sOptionValue));
	if(b) return true;
	if(bShowMsg) AfxMessageBox(APL_T("Объект не находится в разрещенных справочниках!"), MB_ICONSTOP|MB_OK);
	return false;
}


bool CaplClassifierMgr::CheckItemInClassifierById(CaplInstance *item, LPCTSTR classifiers_id)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(0==item) return false;
	if(0==classifiers_id) return false;


	CString buf,sSpravIds=classifiers_id;
	if(sSpravIds==_T("")) return true;

	CStringArray sa_sprav_id;
	int pos_prev=0;
	int pos=sSpravIds.Find(_T('|'));
	while(pos>=0)
	{
		if((pos-pos_prev)>1)
		{
			buf=sSpravIds.Mid(pos_prev,pos-pos_prev);
			if(buf!=_T(""))sa_sprav_id.Add(buf);
		}
		pos_prev=pos+1;
		pos=sSpravIds.Find(_T('|'),pos+1);
	}
	buf=sSpravIds.Right(sSpravIds.GetLength()-pos_prev); 
	if(buf!=_T(""))sa_sprav_id.Add(buf);

	CString sSql,sCond;

	int i;
	for(i=0;i<sa_sprav_id.GetSize();i++)
	{
		buf=_T(".id = '"); buf+=sa_sprav_id[i]; buf+=_T("'");
		if(sCond!=_T("")) sCond+=_T(" OR ");
		sCond+=buf;
	}
	sSql.Format(_T("SELECT ExtA FROM ExtA {apl_classifier_association(.system->apl_classifier_system(%s) AND .item = #%i)}	END_SELECT"), LPCTSTR(sCond), item->GetId());

	aplExtent aeItems;
	if(m_api->m_data.NET_QueryEditParse(sSql))
	{
		m_api->m_data.NET_QueryExecute(aeItems);
		if(aeItems.GetSize()>0) return true;
	}
	return false;
}


//****************************************************************************
bool CaplClassifierMgr::FindClassifiersContained(aplExtent &items, aplExtent &classifiers, aplExtent *assoc_ext)
{
	classifiers.Clear();
	if(m_data==0) return false;
	if(!m_data->IsDictLoad()) return false;

	int i;
	aplExtent ext;
	if(m_api->m_data.IsConnected())
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		bool bLoad = false;
		for(i=0; i<items.GetSize(); i++)
		{
			if(items[i]==NULL) continue;
			if(items[i]->GetId()==0) continue;

			ld.AddQuery(0, items[i], 0);
			bLoad = true;
		}
		if(bLoad)
		{
			int pos=ld.AddQuery(_T('r'), 0, e_apl_classifier_association, a_apl_classifier_association_item, true, true);
			ld.LoadEx(true, &ext);
		}
	}

	CaplInstance *inst;
	for(i=0;i<ext.GetSize();i++)
	{
		if(ext[i]==0) continue;
		if(!m_api->m_data.IsKindOf(ext[i],e_apl_classifier_association)) continue;
		m_api->m_data.GetAttr(ext[i], a_apl_classifier_association_item, inst);
		if(items.Find(inst)<0) continue;
		m_api->m_data.GetAttr(ext[i], a_apl_classifier_association_classifier, inst);
		if(inst)
		{
			classifiers.Add(inst);
			if(assoc_ext!=NULL) assoc_ext->Add(ext[i]);
		}
	}
	LoadExtentInfo(classifiers);
	return true;
}

bool CaplClassifierMgr::GetClassifierLevel4Items(CaplMap &map_item2level, bool bLoadClassifierInfo)
{
	if(0==map_item2level.Size)return true;	
	int i;
	for(i=0;i<map_item2level.Size;i++)map_item2level.Data[i].out=0;

	if(m_data==0) return false;
	if(!m_data->IsDictLoad()) return false;
	
	aplExtent ext;
	if(m_api->m_data.IsConnected())
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		bool bLoad = false;
		for(i=0; i<map_item2level.Size; i++)
		{
			CaplInstance *inst=(CaplInstance*)(map_item2level[i].in);
			if(inst==NULL) continue;
			if(inst->GetId()==0) continue;
			ld.AddQuery(0, inst, 0);
			bLoad = true;
		}
		if(bLoad)
		{
			int pos=ld.AddQuery(_T('r'), 0, e_apl_classifier_association, a_apl_classifier_association_item, true, true);
			if(bLoadClassifierInfo)
			{
				ld.AddQuery(_T('d'), pos, e_apl_classifier_association, a_apl_classifier_association_classifier, true, true);
				ld.AddQuery(_T('d'), pos, e_apl_classifier_association, a_apl_classifier_association_system, true, true);
			}
			if(!ld.LoadEx(true, &ext)) return false;
		}
	}
	
	for(i=0;i<ext.GetSize();i++)
	{
		CaplInstance *inst=ext[i];
		if(0==inst) continue;
		if(inst->GetAccessmode()>aplRO) continue;
		if(!m_data->IsKindOf(inst, e_apl_classifier_association)) continue;
		CaplInstance *item;
		m_api->m_data.GetAttr(inst, a_apl_classifier_association_item, item);
		int k=map_item2level.QFindByIn((long)item);
		if(k<0) continue;
		if(map_item2level.Data[k].out!=0) continue;
		m_api->m_data.GetAttr(inst, a_apl_classifier_association_classifier, inst);
		if(0==inst) continue;
		if(inst->GetAccessmode()>aplRO) continue;
		map_item2level.Data[k].out=(long)inst;
	}
	return true;
}


//****************************************************************************
bool CaplClassifierMgr::FindClassifiersContained(CaplInstance *item, aplExtent &classifiers, aplExtent *assoc_ext)
{
	aplExtent items;
	items.Add(item);
	return FindClassifiersContained(items, classifiers, assoc_ext);
}
//****************************************************************************
bool CaplClassifierMgr::TestClassifierAssociation(CaplInstance *Item, CaplInstance *ClassifierItem,pCaplInstance *association)
{
	bool retval;
	aplExtent ext;
	CaplAttrValue tst_val[2];
	tst_val[0].attr = a_apl_classifier_association_item;
	tst_val[0].value.Set(Item);
	tst_val[1].attr = a_apl_classifier_association_classifier;
	tst_val[1].value.Set(ClassifierItem);
	retval=(bool)(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_association, 2, &tst_val[0], ext, false)>0);
	if(association!=0){
		if(retval){
			*association=ext[0];
		}else{
			*association=0;
		}
	}
	return retval;
		
}
/************************************************************************/
bool CaplClassifierMgr::CreateClassifierAssociation(aplExtent &Items, CaplInstance* ClassifierLevel, bool TestUnique, aplExtent *Associators)
{
	CaplInstance* nInst=0;
	// массив инстанс - правильный ассоциатор (с нужным элементом справочника)
	CaplMap map_items;
	// массив инстанс - неправильный ассоциатор (с другим элементом того же справочника)
	CaplMap map_items_fault;
	int i;
	CaplInstance* Item_cur;
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Items.GetSize()==0) return false;
	if(!ClassifierLevel) return false;
	if(ClassifierLevel->GetAccessmode()>ACCESS2LEVEL_FOR_OBJECT){
		if(m_api->m_ModeInteractive) 
		{
			CString mes= APL_T("Для занесения объекта требуется ");
			mes+=ACCESS2LEVEL_FOR_OBJECT_DESCR;
			mes+= APL_T(" к элементу структуры!");
			AfxMessageBox( mes );
		}
		return false;
	}

	// Считаем уровни вложенности
	if(!TestObjectLevelOfLevel(ClassifierLevel)){
		return false;
	}
	bool is_multi_object;
	//берем справочник и следующий индекс связи
	CaplInstance* system;
	int index;
	CString query,id_item,id_system,tmp;

	aplExtent ext;
	int indx_in_map;
	bool has_fault = false;
	CaplInstance *test_level;
	int res;
	bool move = true;
	bool is_access=(ClassifierLevel->GetAccessmode()<=ACCESS2LEVEL_FOR_OBJECT);


	if(!m_api->m_data.IsKindOf(ClassifierLevel, e_apl_classifier_level))
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Чтобы занести объект в справочник, необходимо указать элемент справочника!"));
		return false;
	}
	m_api->m_data.GetAttr(ClassifierLevel, a_apl_classifier_level_system, system);

	if(system==0)
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Указанный элемент справочника не входит ни в один в справочник!"));
		return false;
	}

	m_api->m_data.GetAttr(ClassifierLevel, a_apl_classifier_level_next_index, index);

	m_data->GetAttr(system,a_apl_classifier_system_is_multi_object,is_multi_object);

	// проверяем на допустимость
	for(i=0;i<Items.GetSize();i++)
	{
		Item_cur = Items.GetAt(i);
	
		// контроль типов
		if(!TestObjectType(ClassifierLevel,Item_cur))
		{
			return false;
		}

		map_items.Add((long)Item_cur,0);
		if(TestUnique)
		{
			tmp.Format(_T(".item = #%i"),Item_cur->GetId());
			if(id_item!=_T(""))id_item+=_T(" OR ");
			id_item+=tmp;
			map_items_fault.Add((long)Item_cur,0);
		}
	}
	map_items.SortIn();
	if(TestUnique)
	{
		map_items_fault.SortIn();
		id_system.Format(_T("#%i"),system->GetId());

		query=_T("SELECT Ext FROM Ext{apl_classifier_association(.system = ")+id_system+_T(" AND (")+id_item+_T(" ) )} END_SELECT");
		if(m_data->NET_QueryEditParse(query))
		{
			m_data->NET_QueryExecute(ext);
			if(ext.GetSize()>0)
			{
				// Ага, что-то прохожее есть
				for(i=0;i<ext.GetSize();i++)
				{
					if (ext[i]->GetType() == NULL) continue;
					m_data->GetAttr(ext[i],a_apl_classifier_association_classifier,test_level);
					m_data->GetAttr(ext[i],a_apl_classifier_association_item,Item_cur);
					indx_in_map = map_items.QFindByIn((long)Item_cur);
					if(indx_in_map==-1)
					{
						if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Ошибка поиска ассоциаторов"));
						return false;
					}
					if(test_level==ClassifierLevel)
					{
						map_items.Data[indx_in_map].out = (long)ext[i];
					}
					else if(ClassifierLevel->GetAccessmode()<=ACCESS2LEVEL_FOR_OBJECT)
					{
						map_items_fault.Data[indx_in_map].out = (long)ext[i];
						has_fault = true;
					}
				}
				if(has_fault)
				{
					CString mes;
					if(m_api->m_ModeInteractive)
					{
						if(is_access)
						{
							if(is_multi_object)
							{
								mes = APL_T("Некоторые объекты уже включены в другой элемент структуры справочника.\n");
								mes+= APL_T("Перенести такие объекты в выбранный элемент структуры справочника?");
								CaplMessageBox dlg_mb(AfxGetMainWnd(),mes);
								dlg_mb.AddButton(ID_COPY_ASSOCIATION, APL_T("Копировать"),1);
								dlg_mb.AddButton(ID_MOVE_ASSOCIATION, APL_T("Перенести"),0);

								BOOL res=dlg_mb.DoModal();

								switch(res)
								{
								case ID_COPY_ASSOCIATION:
									move = false;
									break;
								case ID_MOVE_ASSOCIATION:
									break;
								}
							}
							else
							{
								mes = APL_T("Объект может быть классифицирован в выбранном справочнике только один раз.\n");
								mes += APL_T("Некоторые объекты уже включены в другой элемент структуры справочника.\n");
								mes += APL_T("Перенести такие объекты в выбранный элемент структуры справочника?");

								res=AfxMessageBox( mes,MB_YESNO |MB_ICONQUESTION);
								if(res==IDNO) return false;					
							}
						}
						else
						{
							if(is_multi_object)
							{
								mes = APL_T("Некоторые объекты уже включены в другой элемент структуры справочника.\n");
								mes += APL_T("Перенести объект в выбранный элемент структуры справочника невозможно:\n");
								mes += APL_T("Для перемещения объекта требуется ");
								mes += ACCESS2LEVEL_FOR_OBJECT_DESCR;
								mes += APL_T(" к старому справочнику!\n");
								mes += APL_T("Объекты будут скопированы в новый элемент справочника.\n");
								res=AfxMessageBox(mes,MB_ICONEXCLAMATION);
								move = false;
							}
							else
							{
								mes = APL_T("Некоторые объекты уже включены в другой элемент структуры справочника.\n");
								mes += APL_T("Объект может быть классифицирован в выбранном справочнике только один раз.\n");
								mes += APL_T("Перенести объект в другой элемент структуры справочника невозможно:\n");
								mes += APL_T("Для перемещения объекта требуется ");
								mes += ACCESS2LEVEL_FOR_OBJECT_DESCR;
								mes+= APL_T(" к старому справочнику!\n");
								res=AfxMessageBox(mes,MB_ICONEXCLAMATION);
								return false;					
							}
						}
					}
					else
					{
						return false;					
					}
				}
			}
		}
	}
	else
	{
		move = false;
	}

	for(i=0;i<Items.GetSize();i++)
	{
		Item_cur = Items.GetAt(i);
	
		indx_in_map = map_items.QFindByIn((long)Item_cur);
		nInst = (CaplInstance*)map_items[indx_in_map].out;

		if(nInst == 0)
		{
			if(index==0)
				index++;

			nInst = m_api->m_data.CreateInstance(e_apl_classifier_association);
			ASSERT(nInst);

			m_api->m_data.PutAttr(nInst, a_apl_classifier_association_item, Item_cur);
			m_api->m_data.PutAttr(nInst, a_apl_classifier_association_classifier, ClassifierLevel);
			m_api->m_data.PutAttr(nInst, a_apl_classifier_association_system, system);
			m_api->m_data.PutAttr(nInst, a_apl_classifier_association_index, index++);
			//Сохраняем следующий индекс связи
			m_api->m_data.PutAttr(ClassifierLevel, a_apl_classifier_level_next_index, index);

		}
		if(Associators!=0)
		{
			Associators->Add(nInst);
		}

		if(move)
		{
			// если такой ассоциатор уже был - с другим элементом того же справочника
			// и если объекты надо "переместить" - то удаляем старый ассоциатор
			nInst = (CaplInstance*)map_items_fault[indx_in_map].out;
			if(nInst!=0)m_data->DeleteInstance(nInst);
		}
	}

	if(m_AutoSave) m_api->m_data.NET_SaveChanges();

	return true;
}


/************************************************************************/
CaplInstance* CaplClassifierMgr::CreateClassifierAssociation(CaplInstance *Item, CaplInstance *ClassifierLevel, bool TestUnique)
{
	CaplInstance* nInst=0;
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(!Item) return NULL;
	if(!ClassifierLevel) return NULL;
	if(ClassifierLevel->GetAccessmode()>ACCESS2LEVEL_FOR_OBJECT){
		if(m_api->m_ModeInteractive) 
		{
			CString mes= APL_T("Для занесения объекта требуется ");
			mes+=ACCESS2LEVEL_FOR_OBJECT_DESCR;
			mes+= APL_T(" к элементу структуры!");
			AfxMessageBox( mes );
		}
		return NULL;
	}

	// Считаем уровни вложенности
	if(!TestObjectLevelOfLevel(ClassifierLevel)){
		return 0;
	}
	// контроль типов
	if(!TestObjectType(ClassifierLevel,Item)){
		return 0;
	}

	bool is_multi_object;
	//берем справочник и следующий индекс связи
	CaplInstance* system;
	int index;

	if(!m_api->m_data.IsKindOf(ClassifierLevel, e_apl_classifier_level))
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Чтобы занести объект в справочник, необходимо указать элемент справочника!"));
		return 0;
	}
	m_api->m_data.GetAttr(ClassifierLevel, a_apl_classifier_level_system, system);

	if(system==0)
	{
		if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Указанный элемент справочника не входит ни в один в справочник!"));
		return 0;
	}

	m_api->m_data.GetAttr(ClassifierLevel, a_apl_classifier_level_next_index, index);

	m_data->GetAttr(system,a_apl_classifier_system_is_multi_object,is_multi_object);

	// проверка на уникальность. если такой ассоциатор есть, то возвращаем его
	// если есть ассоциация с другим элементом структуры текущего справочника -  спрашиваем, переклассифицировать ли
	if(TestUnique)
	{
		// проверяем, есть ли ассоциаторы с этим классификатором и с этим элементом ассоциирован или с другим
		// Если множественное вхождение объекта в справочник не допускается - то при ассоциации с другим элементом 
		//		будет выводиться предпреждение
		// Если разрешено множественное и ассоциатор с другим элементом - до просто вернет false
		//if(!FindClassifierAssociation(Item,ClassifierLevel,&nInst,!is_multi_object))

		CString query,id_item,id_system;
		CaplInstance *test_level;
		aplExtent ext;
		int i;
		int res;
		bool is_access=true;
		bool move = true;

		id_item.Format(_T("#%i"),Item->GetId());
		id_system.Format(_T("#%i"),system->GetId());
		query=_T("SELECT Ext FROM Ext{apl_classifier_association(.item = ")+id_item+_T(" AND ")
			_T(" .system = ")+id_system+_T(" )} END_SELECT");
		if(m_data->NET_QueryEditParse(query))
		{
			m_data->NET_QueryExecute(ext);
			if(ext.GetSize()>0)
			{
				// Ага, что-то похожее есть
				for(i=0;i<ext.GetSize();i++)
				{
					if (ext[i]->GetType() == NULL) continue;
					m_data->GetAttr(ext[i],a_apl_classifier_association_classifier,test_level);
					if(test_level==ClassifierLevel)
					{
						nInst = ext[i];
						ext.Remove(i);i--;
					}
					else if(ClassifierLevel->GetAccessmode()>ACCESS2LEVEL_FOR_OBJECT)
					{
						is_access = false;
					}
				}
			}
			if(ext.GetSize()>0)
			{
				CString mes;
				if(m_api->m_ModeInteractive)
				{
					if(is_access)
					{
						if(is_multi_object)
						{
							mes = APL_T("Объект уже включен в другой элемент структуры справочника.\n");
							mes+= APL_T("Перенести объект в выбранный элемент структуры справочника?");
							CaplMessageBox dlg_mb(AfxGetMainWnd(),mes);
							dlg_mb.AddButton(ID_COPY_ASSOCIATION, APL_T("Копировать"),1);
							dlg_mb.AddButton(ID_MOVE_ASSOCIATION, APL_T("Перенести"),0);

							BOOL res=dlg_mb.DoModal();

							switch(res)
							{
							case ID_COPY_ASSOCIATION:
								move = false;
								break;
							case ID_MOVE_ASSOCIATION:
								break;
							}
						}
						else
						{
							mes = APL_T("Объект может быть классифицирован в выбранном справочнике только один раз.\n");
							mes += APL_T("Перенести объект в выбранный элемент структуры справочника?");

							res=AfxMessageBox( mes,MB_YESNO |MB_ICONQUESTION);
							if(res==IDNO) return 0;					
						}
					}
					else
					{
						if(is_multi_object)
						{
							mes = APL_T("Объект будет скопирован в новый элемент справочника.\n");
							mes += APL_T("Перенести объект в выбранный элемент структуры справочника невозможно:\n");
							mes += APL_T("Для перемещения объекта требуется ");
							mes+=ACCESS2LEVEL_FOR_OBJECT_DESCR;
							mes+= APL_T(" к старому справочнику!");
							res=AfxMessageBox(mes,MB_ICONEXCLAMATION);
							move = false;
						}
						else
						{
							mes = APL_T("Объект может быть классифицирован в выбранном справочнике только один раз.\n");
							mes += APL_T("Перенести объект в выбранный элемент структуры справочника невозможно:\n");
							mes += APL_T("Для перемещения объекта требуется ");
							mes+=ACCESS2LEVEL_FOR_OBJECT_DESCR;
							mes+= APL_T(" к старому справочнику!");
							res=AfxMessageBox(mes,MB_ICONEXCLAMATION);
							return 0;					
						}
					}
				}
				else
				{
					return 0;					
				}
				if(move)
				{
					for(i=0;i<ext.GetSize();i++)
					{
						if (ext[i]->GetType() == NULL) continue;
						if(nInst ==0)
						{
							nInst = ext[i];
							m_api->m_data.PutAttr(nInst, a_apl_classifier_association_classifier, ClassifierLevel);
						}
						else
						{
							m_data->DeleteInstance(ext[i]);
							i--;
						}

						if(m_AutoSave){ m_api->m_data.NET_SaveChanges();}
					}
				}
				else
				{
					nInst = 0;
				}
			}
		}
	}
	if(nInst!=0)
	{
		return nInst;
	}
	
	if(index==0)
		index++;

	nInst = m_api->m_data.CreateInstance(e_apl_classifier_association);
	ASSERT(nInst);
	
	m_api->m_data.PutAttr(nInst, a_apl_classifier_association_item, Item);
	m_api->m_data.PutAttr(nInst, a_apl_classifier_association_classifier, ClassifierLevel);
	m_api->m_data.PutAttr(nInst, a_apl_classifier_association_system, system);
	m_api->m_data.PutAttr(nInst, a_apl_classifier_association_index, index++);
	//Сохраняем следующий индекс связи
	m_api->m_data.PutAttr(ClassifierLevel, a_apl_classifier_level_next_index, index);
	
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();
	
	return nInst;
}//CaplInstance* CaplClassifierMgr::CreateClassifierAssociation


//****************************************************************************
bool CaplClassifierMgr::DeleteClassifierAssociation(CaplInstance *Item, CaplInstance *ClassifierLevel)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	aplExtent res;
	CaplAttrValue tst_val[2];
	int num_attr=0;
	if(Item!=0 && ClassifierLevel !=0){
		tst_val[0].attr = a_apl_classifier_association_item;
		tst_val[0].value.Set(Item);
		tst_val[1].attr = a_apl_classifier_association_classifier;
		tst_val[1].value.Set(ClassifierLevel);
		num_attr=2;
	}else if(Item!=0){
		tst_val[0].attr = a_apl_classifier_association_item;
		tst_val[0].value.Set(Item);
		num_attr=1;
	}else if(ClassifierLevel!=0){
		tst_val[0].attr = a_apl_classifier_association_classifier;
		tst_val[0].value.Set(ClassifierLevel);
		num_attr=1;
	}else{
		return false;
	}

	if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_association, num_attr, &tst_val[0], res, false)==0)
		return true;

	//m_data->DeleteInstance(res[0]);
	for(int i=0;i<res.GetSize();i++){
		m_data->DeleteInstance(res[i]);
	}
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();

	return true;
}//bool CaplClassifierMgr::DeleteClassifierAssociation


//****************************************************************************
bool CaplClassifierMgr::LoadSubClassifierSystems(	CaplInstance *ClassifierSystem, aplExtent &SubElements,
													bool recursiv /*= false*/, bool bFromBase  /*= true*/)
{
	if(!m_api) return false;
	SubElements.Clear();
	if(ClassifierSystem!=0){
		if(ClassifierSystem->GetAccessmode()>aplRO) return true;
		if(ClassifierSystem->GetType()==0) return true;
	}

	if(ClassifierSystem==0 || m_api->m_data.IsKindOf(ClassifierSystem, e_apl_classifier_system))
	{
		aplExtent ext;
		CaplAttrValue tst_val[1];
		tst_val[0].attr = a_apl_classifier_system_parent;
		tst_val[0].value.Set(ClassifierSystem);

		if (bFromBase)
		{
			m_api->m_data.NET_FindInstancesWithAttrValues2(	e_apl_classifier_system,1,
															tst_val,ext,false,false,0,aplSBMiddle,false,DEF_SOURCE);
		}
		else
		{
			m_api->m_data.FindInstancesWithAttrValuesInLocalCache(	e_apl_classifier_system, NULL, 1,
																	tst_val, ext, false, false, false);
		}

		for(int i=0;i<ext.GetSize();i++){
			if(ext[i]->GetAccessmode()>aplRO){
				ext.Remove(i);i--;
			}
		}

		if (bFromBase && m_api->m_data.IsConnected())
		{
			LoadExtentInfo(ext);
		}

		SubElements.Append(ext);
		if(recursiv){
			for(int i=0;i<ext.GetSize();i++){
				aplExtent internal_ext;
				LoadSubClassifierSystems(ext[i],internal_ext,recursiv, bFromBase);
				SubElements.Append(internal_ext);
			}
		}	
	}
	else if(m_api->m_data.IsKindOf(ClassifierSystem, e_apl_classifier_level))
	{
		// ну это вообще нив какие ворота - у уровня искать вложенные системы!
		return false;
	}

	return true;
}//bool CaplClassifierMgr::LoadSubClassifierSystems


//****************************************************************************
bool CaplClassifierMgr::LoadSubClassifierLevels(CaplInstance *ClassifierItem, aplExtent &SubElements,
												bool recursiv /*= false*/, bool bFromBase /*= true*/)
{
	if(m_api==0) return false;
	if(ClassifierItem==0) return false;
	if(ClassifierItem->IsDeleted()) return false;
	if(ClassifierItem->GetType()==0)return false;

	SubElements.Clear();
	if(ClassifierItem->GetAccessmode()>aplRO) return true;

	aplExtent ext;
	int count=0;
	//система (читаем все. возвращаем или 0 уровень, или все)
	if(m_api->m_data.IsKindOf(ClassifierItem, e_apl_classifier_system))
	{
		CaplAttrValue tst_val[2];
		tst_val[0].attr = a_apl_classifier_level_system;
		tst_val[0].value.Set(ClassifierItem);
		if (recursiv)
			count = 1;
		else
		{
			count = 2;
			tst_val[1].attr = a_apl_classifier_level_parent;
			tst_val[1].value.Set((CaplInstance*)0);
		}
		if (bFromBase)
		{
			m_api->m_data.NET_FindInstancesWithAttrValues2(	e_apl_classifier_level,count,
															tst_val,ext,false,false,0,aplSBMiddle,false,DEF_SOURCE);
			if(m_api->m_data.IsConnected())
			{
				LoadExtentInfo(ext);
			}
		}
		else
		{
			m_api->m_data.FindInstancesWithAttrValuesInLocalCache(	e_apl_classifier_level, NULL, count,
																	tst_val, ext, false, false, false);
		}

		for(int i=0; i<ext.Size; i++)
		{
			if(ext[i]->GetAccessmode()>aplRO)continue;
			SubElements.Add(ext[i]);
		}
	}
	else if(m_api->m_data.IsKindOf(ClassifierItem, e_apl_classifier_level))
	{
		//m_api->m_data.GetEntityExtent(e_apl_classifier_level, ext);

		CaplAttrValue tst_val[1];
		tst_val[0].attr = a_apl_classifier_level_parent;
		tst_val[0].value.Set(ClassifierItem);

		if (bFromBase)
		{
			m_api->m_data.NET_FindInstancesWithAttrValues2(	e_apl_classifier_level,1,
															tst_val,ext,false,false,0,aplSBMiddle,false,DEF_SOURCE);
		}
		else
		{
			m_api->m_data.FindInstancesWithAttrValuesInLocalCache(	e_apl_classifier_level, NULL, 1,
																	tst_val, ext, false, false, false);
		}

		for(int i=0;i<ext.GetSize();i++){
			if(ext[i]->GetAccessmode()>aplRO){
				ext.Remove(i);i--;
			}
		}
		
		if (bFromBase && m_api->m_data.IsConnected())
		{
			LoadExtentInfo(ext);
		}

		SubElements.Append(ext);
		if(recursiv){
			for(int i=0;i<ext.GetSize();i++){
				aplExtent internal_ext;
				LoadSubClassifierLevels(ext[i],internal_ext,recursiv, bFromBase);
				SubElements.Append(internal_ext);
			}
		}	
	}

	return true;
}//bool CaplClassifierMgr::LoadSubClassifierLevels


//****************************************************************************
bool CaplClassifierMgr::ShowClassifierProperties(CaplInstance *Item)
{
	if(m_api==0) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0) return false;
	if(Item->GetType()==0) return false;
	if(Item->GetAccessmode()>aplRO){
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Нет доступа к атрибутам объекта!"));
		return false;
	}
	CClassifierSystemDlg dlg;
	dlg.m_api=m_api;
	dlg.m_item=Item;
	if(dlg.DoModal()!=IDOK) return false;
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();
	return true;
}//bool CaplClassifierMgr::ShowClassifierProperties


//****************************************************************************
bool CaplClassifierMgr::DeleteClassifierItem(CaplInstance *Item, bool bCheckXmlReferences /*= true*/)
{
	if(m_api==0) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0) return false;
	
	LoadClassifierInfo(Item);
	
	if(Item->GetType()==0) return false;
	if(Item->GetAccessmode()!=aplOWN){
		if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Удаление невозможно - нет доступа!"),MB_OK |MB_ICONERROR);
		return false;
	}
	
	CaplInstance *parentLevel=0;  // Родитель удаляемого уровня. При удалении уровня сюда надо перенести все из extSubItems
	
	bool bMoveSubLevelsToParent=true; // при удалении уровня переносить подуровни в родителя если false удалять подуровни

	bool bMoveLevelsToTopSprav=false; // Преносить уровни в родительский справочник. В автоматическом режиме входящие уровни просто удаляются

	CaplInstance *SpravForMoveLevels=0; // Справочник в который бкдкт перенесены родительские уровни

	aplExtent DelExt; DelExt.Unique=false; // Полный список удаляемых объектов  // список удаляемых связанных объектов
	aplExtent extSubItems;   // Список подуровней на 1 уровень вниз (при удалении уровня)  
	aplExtent extDelLevels;  // Поный список удаляемых уровней

	aplExtent ext,ext_tmp;
	int i;
	
	bool is_in_level=false,is_in_content=false;
	CString buf,buf1;
	
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system))
	{
		m_api->m_data.GetAttr(Item,a_apl_classifier_system_childs,ext);
		if(ext.GetSize()>0){
			{
				if(!(ext.GetSize()==1 && ext[0]==Item))
				{
					if(m_api->m_ModeInteractive)
					{
						AfxMessageBox( APL_T("В удаляемый справочники входят другие справочники. Необходимо сначала удалить справочники нижнего уровня!"),MB_OK |MB_ICONERROR);
					}
					return false;
				}
			}
		}
		if(m_api->m_ModeInteractive)
		{
			if(IDNO==AfxMessageBox( APL_T("Вы действительно хотите удалить справочник?"),	MB_ICONSTOP |MB_YESNO|MB_DEFBUTTON2)) return false;
		}

		CaplInstance *inst, *system;

		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		ld.AddQuery(_T('b'), Item->GetId(), e_apl_classifier_level, a_apl_classifier_level_system, true,true);
		ld.LoadEx(true, &ext);
		
		for(i=0; i<ext.Size; i++)
		{
			inst = ext[i];
			if(inst==0) continue;
			if(inst->GetType()==0) continue;

			if(m_api->m_data.IsKindOf(inst, e_apl_classifier_level))
			{
				m_api->m_data.GetAttr(inst, a_apl_classifier_level_system, system);
				if(system!=Item) continue;
				extDelLevels.Add(inst);
			}
		}
		ld.ClearQuery();

		
		m_api->m_data.GetAttr(Item,a_apl_classifier_system_parent,SpravForMoveLevels);
		if(extDelLevels.Size>0)
		{
			if(m_api->m_ModeInteractive)
			{
				if(0!=SpravForMoveLevels)
				{
					if(IDYES==AfxMessageBox( APL_T("Перенести элементы структуры в справочник верхнего уровня?"),MB_YESNO |MB_ICONQUESTION))
					{
						bMoveLevelsToTopSprav=true;
					}
				}
				if(!bMoveLevelsToTopSprav)
				{
					if(IDYES!=AfxMessageBox( APL_T("Заданные в справочнике элементы структуры будут удалены вместе со справочником.\n\nПродолжить удаление справочника?"), MB_YESNO|MB_ICONSTOP|MB_DEFBUTTON2))
					{
						return false;
					}
				}
			}
		}

		m_api->m_data.GetAttr(Item, a_apl_classifier_system_list_characteristics, ext);
		for(i=0; i<ext.GetSize(); i++) DelExt.Append(ext);

		if (  !ValidateClassifierElsXmlRefs(DelExt) )return false;

	}
	else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level))
	{
		if(m_api->m_ModeInteractive)
		{
			if(IDYES!=AfxMessageBox( APL_T("Вы действительно хотите удалить элемент структуры справочника?"),
				MB_ICONSTOP |MB_YESNO|MB_DEFBUTTON2)) return false;
		}

		// проверка, есть ли элементы более низкого уровня

		LoadSubClassifierLevels(Item, extSubItems, false, true);
		if(extSubItems.GetSize()>0)
		{
			if(m_api->m_ModeInteractive)
			{
				if(IDYES==AfxMessageBox( APL_T("У элемента структуры справочника есть подэлементы.\n\n Удалить их? \n\nДа - подэлементы будут удалены.\nНет - подэлементы перейдут на уровеь выше (станут на место удаляемого)."),
					MB_ICONWARNING |MB_YESNO|MB_DEFBUTTON2))
				{
					if(IDYES!=AfxMessageBox( APL_T("Вы действительно хотите удалить все подэлементы структуры справочника?"),MB_ICONSTOP |MB_YESNO))
					{
						return false;
					}
					bMoveSubLevelsToParent=false;
				}
			}
		}

		if(!bMoveSubLevelsToParent)
		{
			LoadSubClassifierLevels(Item, extDelLevels, true, true);

			for(i=0; i<extDelLevels.GetSize(); i++)
			{
				CaplInstance *inst=extDelLevels[i];
				if(0==inst ) {extDelLevels.Remove(i); i--; continue;}
				if(inst->IsDeleted()) {extDelLevels.Remove(i); i--; continue;}

				if(inst->GetAccessmode()>aplOWN)
				{
					if(m_api->m_ModeInteractive)
					{
						m_api->GetItemName(inst,buf1);
						buf.Format( APL_T("На удаляемый объект\n%s\n нет полного доступа! Удаление невозможно!"),buf1);
						AfxMessageBox( buf,MB_OK |MB_ICONERROR);
					}
					return false;
				}
			}
		}
		extDelLevels.Add(Item);

		if (bCheckXmlReferences && !ValidateClassifierElsXmlRefs(extDelLevels) )return false;

	}


	// Обработка удаляемых уровней
 
	// Добавляем в список удаляемых связи с элементами структуры
	{
		m_api->LoadByParts(extDelLevels, m_api->m_MaxItemsLoad, false, &CaplClassifierMgr::FN_DeleteClassifierLevel, 0);
		
		aplExtent ext_ass;
		m_api->m_data.GetEntityExtent(e_apl_classifier_association, ext_ass);

		CaplInstance *ass, *level;
		for (i = 0; i < ext_ass.Size; ++i)
		{
			ass = ext_ass[i];
			m_api->m_data.GetAttr(ass, a_apl_classifier_association_classifier, level);
			if(extDelLevels.Find(level)<0) continue;
			DelExt.Add(ass);
		}
	}

	// Добавляем в список удаляемых характеристики
	{
		for(i=0 ; i<extDelLevels.GetSize(); i++)
		{
			m_api->m_data.GetAttr(extDelLevels[i], a_apl_classifier_level_list_characteristics, ext);
			if(ext.GetSize()>0) DelExt.Append(ext);
		}
	}

	if (bCheckXmlReferences && !ValidateClassifierElsXmlRefs(extDelLevels) ) return false;
	if (bCheckXmlReferences && !ValidateClassifierElsXmlRefs(DelExt) ) return false;

	// Само удаление
	{
		CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);

		if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system))
		{
			// Удаляем справочник

			if(bMoveLevelsToTopSprav && 0!=SpravForMoveLevels)
			{
				// Переносим уровни в родительский справочник
				for(i=0; i<extDelLevels.Size; i++)
				{
					m_api->m_data.PutAttr(extDelLevels[i], a_apl_classifier_level_system, SpravForMoveLevels);
				}
				extDelLevels.Clear(); // Чтобы они не удалились в дальнейшем
			}

			// удаляем справочник из родителя (если он есть)
			CaplInstance *parent;
			m_api->m_data.GetAttr(Item, a_apl_classifier_system_parent, parent);
			if(parent!=0)
			{
				m_api->m_data.GetAttr(parent, a_apl_classifier_system_childs, ext);
				for(i=0; i<ext.Size; i++)
				{
					if(ext[i]==Item) { ext.Remove(i); break;}
				}
				m_api->m_data.PutAttr(parent, a_apl_classifier_system_childs, ext);
			}

			CString sBlob;
			m_api->m_data.GetAttr(Item, a_apl_classifier_system_esquisse, sBlob);
			if(sBlob!=_T("")) m_api->m_data.NET_DeleteBlob(Item,a_apl_classifier_system_esquisse);

			m_api->m_data.DeleteInstance(Item);  
			Item=0;
		}
		else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level))
		{
			// корректировка родительского уровня - чистка и  и перенос в него подуровней
			CaplInstance *parent;
			m_api->m_data.GetAttr(Item, a_apl_classifier_level_parent, parent);
			aplExtent extParentChild;
			if(0!=parent)m_api->m_data.GetAttr(parent, a_apl_classifier_level_childs, extParentChild);


			// Удаляем из childs родителя
			for(i=0; i<extParentChild.GetSize(); i++)
			{
				if(Item==extParentChild[i]){ extParentChild.Remove(i);	break;}
			}

			if(bMoveSubLevelsToParent)
			{
				for(i=0;i<extSubItems.GetSize();i++) // Переносим входящие на уровень вверх
				{
					CaplInstance *inst=extSubItems[i];
					extParentChild.Add(inst);
					m_api->m_data.PutAttr(inst, a_apl_classifier_level_parent, parent);
				}
			}
			if(0!=parent) m_api->m_data.PutAttr(parent, a_apl_classifier_level_childs, extParentChild);
		}


		// Удаляем связанные объекты

		for(i=0;i<DelExt.GetSize();i++)
		{
			CaplInstance *inst=DelExt[i];
			if(0==inst) continue;
			if(inst->IsDeleted()) continue;
			m_api->m_data.DeleteInstance(inst);
		}

		CString sBlob;
		for(i=0;i<extDelLevels.GetSize();i++)
		{
			CaplInstance *inst=extDelLevels[i];
			if(0==inst) continue;
			if(inst->IsDeleted()) continue;

			m_api->m_data.GetAttr(inst, a_apl_classifier_level_esquisse, sBlob);
			if(sBlob!=_T("")) m_api->m_data.NET_DeleteBlob(inst,a_apl_classifier_level_esquisse);

			m_api->m_data.DeleteInstance(inst);
		}

	}
	if(m_AutoSave) m_api->m_data.NET_SaveChanges();

	return true;
}//bool CaplClassifierMgr::DeleteClassifierItem

//****************************************************************************
CaplInstance* CaplClassifierMgr::GetClassifierSystemById(LPCTSTR id, bool bFromBase)
{
	if(m_api==0) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;

	aplExtent ext;
	m_api->m_data.GetEntityExtent(e_apl_classifier_system, ext);
	CString sId;
	for(int i=0; i<ext.Size; i++)
	{
		CaplInstance *sys=ext[i];
		if(0==sys) continue;
		if(sys->IsDeleted()) continue;
		if(sys->GetAccessmode()>aplRO)continue;
		m_api->m_data.GetAttr(sys, a_apl_classifier_system_id, sId);
		if(sId.CompareNoCase(id)==0) return ext[i];
	}
	if(bFromBase && m_api->m_data.IsConnected())
	{
		CaplAttrValue tst_val;
		aplExtent ext;
		tst_val.attr = a_apl_classifier_system_id;
		tst_val.value.Set(id);
		if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_system, 1, &tst_val, ext, false)>0)
			return ext[0];
	}
	return NULL;
}//CaplInstance* CaplClassifierMgr::GetClassifierSystemById


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetClassifierSystemBN(LPCTSTR name, bool bFromBase)
{
	if(m_api==0) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	
	aplExtent ext;
	m_api->m_data.GetEntityExtent(e_apl_classifier_system, ext);
	CString sName;
	for(int i=0; i<ext.Size; i++)
	{
		CaplInstance *sys=ext[i];
		if(0==sys) continue;
		if(sys->IsDeleted()) continue;
		if(sys->GetAccessmode()>aplRO) continue;
		m_api->m_data.GetAttr(sys, a_apl_classifier_system_name, sName);
		if(sName.CompareNoCase(name)==0) return ext[i];
	}
	if(bFromBase && m_api->m_data.IsConnected())
	{
		CaplAttrValue tst_val;
		aplExtent ext;
		tst_val.attr = a_apl_classifier_system_name;
		tst_val.value.Set(name);
		if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_system, 1, &tst_val, ext, false)>0)
			return ext[0];
	}
	return NULL;
}//CaplInstance* CaplClassifierMgr::GetClassifierSystemBN


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetClassifierLevelById(LPCTSTR id, CaplInstance* ClassifierSystem, bool bFromBase)
{
	if(m_api==0) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(id==NULL) return NULL;
	if(ClassifierSystem==NULL) return NULL;

	aplExtent ext;
	CaplAttrValue tst_val[2];
	tst_val[0].attr = a_apl_classifier_level_id;
	tst_val[0].value.Set(id);
	tst_val[1].attr = a_apl_classifier_level_system;
	tst_val[1].value.Set(ClassifierSystem);
	if(bFromBase)
		m_api->m_data.NET_FindInstancesWithAttrValues2(e_apl_classifier_level, 2, &tst_val[0], ext, false, true,0,aplSBMiddle,false,DEF_SOURCE);
	else
		m_api->m_data.FindInstancesWithAttrValuesInLocalCache(e_apl_classifier_level, NULL, 2, &tst_val[0], ext, false, true, false);
	if(ext.Size>0)
		return ext[0];

	return NULL;
}//CaplInstance* CaplClassifierMgr::GetClassifierLevelById


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetClassifierLevelByName(LPCTSTR name, CaplInstance* ClassifierSystem)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(name==NULL) return NULL;
	if(ClassifierSystem==NULL) return NULL;
	
	aplExtent ext;
	CaplAttrValue tst_val[2];
	tst_val[0].attr = a_apl_classifier_level_name;
	tst_val[0].value.Set(name);
	tst_val[1].attr = a_apl_classifier_level_system;
	tst_val[1].value.Set(ClassifierSystem);
	m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_classifier_level, 2, &tst_val[0], ext, false);
	if(ext.Size>0)
		return ext[0];
	
	return NULL;
}//CaplInstance* CaplClassifierMgr::GetClassifierLevelByName

//****************************************************************************
bool CaplClassifierMgr::GetSubItems(aplExtent &ClassifierLevels, aplExtent &out_ext, aplExtent *rels,bool load_data,bool load_from_bd)
{
	out_ext.Clear();
	if(rels)
		rels->Clear();
	if(!m_api) return false;
	int i,j;
	if(ClassifierLevels.Size==0) return 0;
	if(m_api->m_data.IsConnected() && load_from_bd)
	{
		aplExtent ex_tmp;
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0;i<ClassifierLevels.Size;i++){
			if(ClassifierLevels[i]->GetId()==0)continue;
			if(ClassifierLevels[i]->GetAccessmode()>aplRO)continue;
			ld.AddQuery(0,ClassifierLevels[i],true);
		}
		if(ld.m_queries.GetSize()==0)return true;
		ld.AddQuery(_T('r'),0, e_apl_classifier_association, a_apl_classifier_association_classifier, true, true);
		ld.LoadEx(true,&ex_tmp);
	}
	aplExtent ext;
	CaplInstance *Item;
	CaplAttrValue tst_val[1];
	tst_val[0].attr = a_apl_classifier_association_classifier;

	for(i=0;i<ClassifierLevels.Size;i++){
		if(ClassifierLevels[i]->GetId()==0)continue;
		if(ClassifierLevels[i]->GetAccessmode()>aplRO)continue;
		tst_val[0].value.Set(ClassifierLevels[i]);
		
		m_api->m_data.FindInstancesWithAttrValuesInLocalCache(e_apl_classifier_association,0,1,tst_val,ext,true,true,false);
		
		for(j=0; j<ext.Size; j++)
		{
			if(ext[j]->GetAccessmode()>aplRO)continue;
			m_api->m_data.GetAttr(ext[j], a_apl_classifier_association_item, Item);
			if(Item)
			{
				out_ext.Add(Item);
				if(rels)
					rels->Add(ext[j]);
			}
		}
	}

	if(true==load_data)
		LoadExtentInfo(out_ext);
	return true;
}

//****************************************************************************
bool CaplClassifierMgr::GetSubItems(CaplInstance *ClassifierLevel, aplExtent &out_ext, aplExtent *rels,bool load_data,bool load_from_bd)
{
	out_ext.Clear();
	if(rels)
		rels->Clear();
	if(!m_api) return false;
	if(ClassifierLevel==0) return false;
	if(ClassifierLevel->IsDeleted()) return false;
	if(ClassifierLevel->GetAccessmode()>aplRO) return true;

	CaplAttr *ref_attr=0;
	if(m_api->m_data.IsKindOf(ClassifierLevel,e_apl_classifier_level))
	{
		ref_attr=a_apl_classifier_association_classifier;
	}
	else if(m_api->m_data.IsKindOf(ClassifierLevel,e_apl_classifier_system))
	{
		ref_attr=a_apl_classifier_association_system;
	}
	else return false;


	if(m_api->m_data.IsConnected() && ClassifierLevel->GetId()!=0 && load_from_bd)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		ld.AddQuery(_T('b'), ClassifierLevel->GetId(), e_apl_classifier_association, ref_attr, true, true);
		ld.LoadEx();
	}
	aplExtent ext;
	m_api->m_data.GetEntityExtent(e_apl_classifier_association, ext);
	CaplInstance *tElem, *Item;

	// Временно убираем проверку уникальности
	bool bOld_unique_out_ext=out_ext.Unique;
	out_ext.Unique=false;

	bool bOld_unique_rels=true;
	if(rels)
	{
		bOld_unique_rels=rels->Unique;
		rels->Unique=false;
	}

	for(int i=0; i<ext.Size; i++)
	{
		CaplInstance *inst_i=ext[i];
		if(inst_i->GetAccessmode()>aplRO)continue;
		m_api->m_data.GetAttr(inst_i, ref_attr, tElem);
		if(tElem!=ClassifierLevel) continue;
		m_api->m_data.GetAttr(inst_i, a_apl_classifier_association_item, Item);
		if(Item)
		{
			out_ext.Add(Item);
			if(rels)
				rels->Add(inst_i);
		}
	}

	// Восстанвливаем проверку уникальности
	if(rels) rels->Unique=bOld_unique_rels;
	out_ext.Unique= bOld_unique_out_ext;
	CSortClass::MakeExtUnique(out_ext,true); // Для rels это ненужно


	if(true==load_data && load_from_bd)
		LoadExtentInfo(out_ext);
	return true;
}//bool CaplClassifierMgr::GetSubItems


//****************************************************************************
bool CaplClassifierMgr::MakeTable(CaplInstance *Item,bool is_hide_move_button,bool *redraw,bool show_subelements)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(redraw!=0){*redraw=false;}
	
	aplExtent ext,ext_tmp,ext_rel,ext_fld;
	// получаем содержимое
	if(Item==0){
		LoadDictionary();
		m_data->GetEntityExtent(e_apl_classifier_system, ext);
	}else{
		if(m_data->IsKindOf(Item,e_apl_classifier_system)){
			show_subelements=true;
		}
		GetSubItems(Item,ext,&ext_rel);
	}
	// добавляем документы, которые были ассоциированы с папкой ассоциаторами
	if(show_subelements){
		LoadSubClassifierLevels(Item, ext_tmp);
		ext.Append(ext_tmp);
	}
	m_api->LoadExtentInfo(ext);
	
	int res=0;
	CaplSetResourceHandle setres(module_inst);
	CDlgListInstances dlg;
	dlg.m_base_inst=Item;
	dlg.m_content=&ext;
	dlg.m_api=m_api;
	dlg.m_is_hide_move_button=false;//is_hide_move_button ;
	dlg.m_delete_message= APL_T("Вы действительно хотите удалить выделенные объекты из справочника?");
	dlg.m_ListObjects.m_create_assoc_doc=false;
//	if(Item->GetAccessmode()<=aplRW){
//		dlg.m_can_delete=true;
//	}
	dlg.m_can_delete=false;
	res=dlg.DoModal();
	if(dlg.m_changed){
//		if(m_AutoSave) m_data->NET_SaveChanges();
		if(redraw!=0){*redraw=true;}
	}
	return true;
}//bool CaplClassifierMgr::MakeTable


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetConceptLevelParameters(CaplInstance *Item,
					bool &is_concept_control,bool &is_last_level,int &min_level,int &max_level)
{
	is_concept_control=false;is_last_level=false;min_level=-1;max_level=-1;
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(Item==0)return 0;
	if(Item->GetType()==0)return 0;
	CaplInstance *active_system=0;

	if(m_api->m_data.IsKindOf(Item,e_apl_classifier_level)){
		m_api->m_data.GetAttr(Item,a_apl_classifier_level_system,active_system);
	}else if(m_api->m_data.IsKindOf(Item,e_apl_classifier_system)){
		active_system=Item;
	}else{
		return 0;
	}
	m_api->m_data.GetAttr(active_system,
						a_apl_classifier_system_is_concept_level_control,is_concept_control);

	if(is_concept_control){
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_is_concept_last_level,is_last_level);
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_concept_minlevel,min_level);
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_concept_maxlevel,max_level);
	}

	return active_system;
}//CaplInstance* CaplClassifierMgr::GetConceptLevelParameters


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetObjectLevelParameters(CaplInstance *Item,
					bool &can_object,bool &is_object_control,bool &is_last_level,
					int &min_level,int &max_level,bool &is_multi_object)
{
	can_object=false;is_object_control=false;is_last_level=false;min_level=-1;max_level=-1;
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(Item==0)return 0;
	if(Item->GetType()==0)return 0;
	CaplInstance *active_system=0;
	
	if(m_api->m_data.IsKindOf(Item,e_apl_classifier_level)){
		m_api->m_data.GetAttr(Item,a_apl_classifier_level_system,active_system);
	}else if(m_api->m_data.IsKindOf(Item,e_apl_classifier_system)){
		active_system=Item;
	}else{
		return 0;
	}
	m_api->m_data.GetAttr(active_system,
			a_apl_classifier_system_can_store_object,can_object);
//		if(!can_object){
//			// к уровням в этой системе нельзя присоединять объекты. И параметры контроля неактуальны
//			return 0;
//		}
	m_api->m_data.GetAttr(active_system,
			a_apl_classifier_system_is_object_level_control,is_object_control);
	if(is_object_control!=0)
	{
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_is_object_last_level,is_last_level);
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_object_minlevel,min_level);
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_object_maxlevel,max_level);
	}
	m_api->m_data.GetAttr(active_system,a_apl_classifier_system_is_multi_object,is_multi_object);

	return active_system;
}//CaplInstance* CaplClassifierMgr::GetObjectLevelParameters


//****************************************************************************
CaplInstance* CaplClassifierMgr::GetObjectTypeParameters(CaplInstance *Item,
					bool &is_object_type_control,CaplEntity **stored_entity,bool recursive)
{
	is_object_type_control=false;
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(Item==0)return 0;
	if(Item->GetType()==0)return 0;
	if(stored_entity!=0){*stored_entity=0;}


	CaplInstance *active_rule_inst=0,*active_system=0,*active_elment=0;
	
	if(m_api->m_data.IsKindOf(Item,e_apl_classifier_level)){
		m_api->m_data.GetAttr(Item,a_apl_classifier_level_system,active_system);
	}else if(m_api->m_data.IsKindOf(Item,e_apl_classifier_system)){
		active_system=Item;
	}else{
		return 0;
	}
	do{
		if(active_system==0)break;
		m_api->m_data.GetAttr(active_system,
			a_apl_classifier_system_is_type_control,is_object_type_control);
		if(is_object_type_control){
			active_rule_inst=active_system;
			break;
		}
		m_api->m_data.GetAttr(active_system,a_apl_classifier_system_parent,active_system);
	}while(!is_object_type_control && recursive);

	if(active_rule_inst!=0){
		if(stored_entity!=0){
			CString name_ent;
			m_api->m_data.GetAttr(active_rule_inst,a_apl_classifier_system_stored_entity,name_ent);
			*stored_entity=m_api->m_data.GetEntityBN(name_ent);
		}
		return active_rule_inst;
	}
	return 0;
}//CaplInstance* CaplClassifierMgr::GetObjectTypeParameters


bool CaplClassifierMgr::GetClassifierForms(CaplInstance *Item, aplExtent &list_forms, bool recursive, pCaplInstance *based_item)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0)return false;
	if(Item==(CaplInstance*)-1)return false;
	if(Item->GetType()==0)return false;

	CaplAttr* parent_attr;
	CaplAttr* forms_attr;
	CaplInstance *active_classifier=Item;
	CaplInstance *active_parent=0;
	if(based_item!=0){*based_item=0;}
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system))
	{
		parent_attr=0;// по формам по родителя не ходим - трудно отследить соответсвие формы и присоединенного типа
		forms_attr=a_apl_classifier_system_forms;
	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
		parent_attr=a_apl_classifier_level_parent;
		forms_attr=a_apl_classifier_level_forms;
	}else{
		return false;
	}
	aplExtent ext_passed;
	int i_p;
	ext_passed.Unique=false;
	do{
		m_api->m_data.GetAttr(active_classifier,forms_attr,list_forms);
		if(list_forms.Size>0){ break;}

		if(parent_attr==0){
			break;
		}else{
			ext_passed.Add(active_classifier);
			m_api->m_data.GetAttr(active_classifier,parent_attr,active_parent);
			for(i_p=0;i_p<ext_passed.GetSize();i_p++){
				if(ext_passed[i_p]==active_parent){
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("В иерархии элементов структуры справочника обнаружен цикл!"));
					return false;
				}
			}
		}
		if(active_parent==0 && m_api->m_data.IsKindOf(active_classifier, e_apl_classifier_level)){
			m_api->m_data.GetAttr(active_classifier,a_apl_classifier_level_system,active_parent);
			parent_attr=0;// по формам по родителям не ходим - трудно отследить соответсвие формы и присоединенного типа
			forms_attr=a_apl_classifier_system_forms;
		}
		active_classifier=active_parent;
	}while(active_classifier!=0 && recursive);
	if(based_item!=0){*based_item=active_classifier;}
	
	return true;
}


bool CaplClassifierMgr::SelectItem(CaplInstance **Item, CaplInstance *BaseClassifierSystem, UINT mode, LPCTSTR lpszTitle, CWnd **pWnd, aplExtent *extItems)
{
	if(!m_api) return false;
	if(mode==0) return false;

	// Непонятно из какого контрола выбирвать
	if(mode&APL_SELECT_CLASSIFIER_ITEM && ( mode&APL_SELECT_CLASSIFIER_LEVEL || mode&APL_SELECT_CLASSIFIER_SYSTEM) ) return false; 

	// Скидываем кривое задание флагов
	if(mode&APL_SHOW_ESQUISSE) mode&=~APL_HIDE_ESQUISSE; 
	if( (mode&(APL_SELECT_CLASSIFIER_SYSTEM | APL_SELECT_CLASSIFIER_LEVEL)) && (mode&APL_SHOW_ESQUISSE)) mode|=APL_HIDE_TABLE;

	bool bRes=  false;

	CaplSetResourceHandle setres(module_inst);

	if(mode&APL_CLASSIFIER_EDITOR || mode&APL_SELECT_CLASSIFIER_ITEM || mode&APL_SHOW_ESQUISSE )
	{
		CSelectClassifierItemDlg dlg(m_api, mode);
		dlg.m_extItems4Add=extItems;
		if(lpszTitle!=NULL)
			dlg.m_sTitle = lpszTitle;
		if(pWnd)
			*pWnd = &dlg;
		if(BaseClassifierSystem)
			dlg.m_BaseClassifierSystems.Add(BaseClassifierSystem);
		dlg.m_sTitle = lpszTitle;
		bRes = dlg.DoModal()==IDOK;
		if(bRes)
		{
			if(Item!=0)
				*Item=dlg.m_SelectedItem;
		}
	}
	else if(mode&APL_CLASSIFIER_EXE_EDITOR)
	{
		if(pWnd)
		{
			CRect rect(100, 50, 800, 700);
			CBaseFrame *pFrm = new CBaseFrame(mode);
			pFrm->Create(NULL, lpszTitle, WS_VISIBLE|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER|WS_CAPTION|WS_THICKFRAME, rect, NULL);
			pFrm->Init(m_api, BaseClassifierSystem);

			*pWnd = pFrm;
		}
		else
		{
			CSelectClassifierItemDlg dlg(m_api, mode, AfxGetMainWnd());
			if(lpszTitle!=NULL)
				dlg.m_sTitle = lpszTitle;
			if(BaseClassifierSystem)
				dlg.m_BaseClassifierSystems.Add(BaseClassifierSystem);
			dlg.m_sTitle = lpszTitle;
			bRes = dlg.DoModal()==IDOK;
			if(bRes)
			{
				if(Item!=0)
					*Item=dlg.m_SelectedItem;
			}
		}
	}
	else
	{
		CClassifierSelectDlg dlg(m_api);
		dlg.m_SelectMode = mode;
		dlg.m_BaseClassifierSystem = BaseClassifierSystem;
		dlg.m_sTitle = lpszTitle;
		bRes = dlg.DoModal()==IDOK;
		if(bRes)
		{
			if(Item)
				*Item = dlg.m_SelectedElement;
		}
	}
	return bRes;
}

bool CaplClassifierMgr::SelectItem(CaplInstance **Item, aplExtent &BaseClassifierSystems, UINT mode, LPCTSTR lpszTitle, SSelectItemFilter* filter)
{
	if(!m_api) return false;
	if(mode==0) return false;

	// Непонятно из какого контрола выбирвать
	if(mode&APL_SELECT_CLASSIFIER_ITEM && ( mode&APL_SELECT_CLASSIFIER_LEVEL || mode&APL_SELECT_CLASSIFIER_SYSTEM) ) return false; 

	// Скидываем кривое задание флагов
	if(mode&APL_SHOW_ESQUISSE) mode&=~APL_HIDE_ESQUISSE; 
	if( (mode&(APL_SELECT_CLASSIFIER_SYSTEM | APL_SELECT_CLASSIFIER_LEVEL)) && (mode&APL_SHOW_ESQUISSE)) mode|=APL_HIDE_TABLE;

	bool bRes=  false;
	CaplSetResourceHandle setres(module_inst);
	if(mode&APL_CLASSIFIER_EDITOR || mode&APL_CLASSIFIER_EXE_EDITOR || mode&APL_SELECT_CLASSIFIER_ITEM || mode&APL_SHOW_ESQUISSE)
	{
		CSelectClassifierItemDlg dlg(m_api, mode);
		if(lpszTitle!=NULL)
			dlg.m_sTitle = lpszTitle;
		dlg.m_BaseClassifierSystems.Append(BaseClassifierSystems);
		if(NULL != filter)
		{
			if(NULL != filter->search_entity)
			{
				dlg.m_filter = filter;
			}
		}
		bRes = dlg.DoModal()==IDOK;
		if(bRes)
		{
			if(Item!=0)
				*Item=dlg.m_SelectedItem;
		}
	}
	else
	{
		CClassifierSelectDlg dlg(m_api);
		dlg.m_SelectMode = mode;
		dlg.m_sTitle = lpszTitle;
		if(BaseClassifierSystems.GetSize()>0)
			dlg.m_BaseClassifierSystem = BaseClassifierSystems[0];
		bRes = dlg.DoModal()==IDOK;
		if(bRes)
		{
			if(Item)
				*Item = dlg.m_SelectedElement;
		}
	}
	return bRes;
}

bool CaplClassifierMgr::PutClassifierEsquisse(CaplInstance *Item, const TCHAR* name_file)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0)return false;
	if(Item==(CaplInstance*)-1)return false;
	if(Item->GetType()==0)return false;
	long blob_code;
	CString full_name=name_file,only_name;

	CaplAttr* worked_attr;
	CaplAttr* worked_attr_name;
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system))
	{
		worked_attr=a_apl_classifier_system_esquisse;
		worked_attr_name=a_apl_classifier_system_esquisse_name;
	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
		worked_attr=a_apl_classifier_level_esquisse;
		worked_attr_name=a_apl_classifier_level_esquisse_name;
	}else{
		return false;
	}
	int pos;
	pos=full_name.ReverseFind(_T('\\'));
	if(pos==-1){
		pos=full_name.ReverseFind(_T('/'));
	}
	if(pos!=-1){
		only_name=full_name.Right(full_name.GetLength()-pos-1);
	}else{
		only_name=full_name;
	}
	CString tmp;
	m_api->m_data.GetAttr(Item, worked_attr, tmp);
	if(tmp!=_T("")){
		m_api->m_data.NET_DeleteBlob(Item,worked_attr);
	}
	if(m_api->m_data.NET_SaveBlob(Item,worked_attr,name_file,blob_code,only_name)){
		m_api->m_data.PutAttr(Item,worked_attr_name,only_name);
		return true;
	}
	return false;
}

bool CaplClassifierMgr::GetClassifierEsquisse(CaplInstance *Item, CString &name_temp_file, CString *original_name)
{
	name_temp_file=_T("");
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0)return false;
	if(Item==(CaplInstance*)-1)return false;
	if(Item->GetType()==0)return false;
	CString blob_name,full_name,only_name;
	long blob_size;
	TCHAR lpTempFileName[MAX_PATH];
	TCHAR lpTempPath[MAX_PATH];
	UINT num;
	CaplAttr* worked_attr;
	CaplAttr* worked_attr_name;
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system)){
		worked_attr=a_apl_classifier_system_esquisse;
		worked_attr_name=a_apl_classifier_system_esquisse_name;
	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
		worked_attr=a_apl_classifier_level_esquisse;
		worked_attr_name=a_apl_classifier_level_esquisse_name;
	}else{
		return false;
	}
	m_api->m_data.GetAttr(Item,worked_attr,blob_name);
	if(blob_name==_T("")){return true;}// здесь блоба нет
	if(!m_api->m_data.NET_GetBlobSize(Item,worked_attr,blob_size)){
		return false;
	}
	m_api->m_data.GetAttr(Item,worked_attr_name,only_name);
	num=only_name.ReverseFind(_T('\\'));
	if(num==-1){
		num=only_name.ReverseFind(_T('/'));
	}
	if(num!=-1){
		only_name.Delete(0,num+1);
	}
	if(original_name!=0){
		*original_name=only_name;
	}
	// получаем уникальное имя временного файла в каталоге temp или аналогичном
	GetTempPath(MAX_PATH,lpTempPath);
	num=GetTempFileName(lpTempPath,_T("pss"),0,lpTempFileName);
	DeleteFile(lpTempFileName);
	full_name=lpTempFileName+CString(_T("."))+only_name;
	if(m_api->m_data.NET_LoadBlob(Item,worked_attr,full_name)){
		name_temp_file=full_name;
	}else{
		return false;
	}
	return true;
}

//bool CaplClassifierMgr::PutClassifierEsquisse(CaplInstance *Item, BYTE* buf_esquisse,long size_esquisse)
//{
//	if(!m_api) return NULL;
//	if(!m_api->m_data.IsConnected()) return NULL;
//	if(Item==0)return 0;
//	if(buf_esquisse==0 || size_esquisse==0)return 0;
//	long blob_code;
//	
//	CaplAttr* worked_attr;
//	CaplAttr* worked_attr_name;
//	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system)){
//		worked_attr=a_apl_classifier_system_esquisse;
//		worked_attr_name=a_apl_classifier_system_esquisse_name;
//	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
//		worked_attr=a_apl_classifier_level_esquisse;
//		worked_attr_name=a_apl_classifier_level_esquisse_name;
//	}else{
//		return false;
//	}
//
//	if(m_api->m_data.NET_SaveFileFromMemory(Item,worked_attr,buf_esquisse,size_esquisse,blob_code)){
//		return true;
//	}
//	return false;
//
//}

bool CaplClassifierMgr::GetClassifierEsquisse(CaplInstance *Item, BYTE** buf_esquisse,long &size_esquisse,CString &only_name, CString *original_name)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(Item==0)return false;
	if(Item==(CaplInstance*)-1)return false;
	if(Item->GetType()==0)return false;
	if(buf_esquisse==0)return 0;
	CString blob_name;
	
	CaplAttr* worked_attr;
	CaplAttr* worked_attr_name;
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system)){
		worked_attr=a_apl_classifier_system_esquisse;
		worked_attr_name=a_apl_classifier_system_esquisse_name;
	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
		worked_attr=a_apl_classifier_level_esquisse;
		worked_attr_name=a_apl_classifier_level_esquisse_name;
	}else{
		return false;
	}

	m_api->m_data.GetAttr(Item,worked_attr,blob_name);
	if(blob_name==_T("")){return true;}// здесь блоба нет
	
	if(!m_api->m_data.NET_GetBlobSize(Item,worked_attr,size_esquisse)){
		return false;
	}
	*buf_esquisse=new BYTE[size_esquisse];

	if(m_api->m_data.NET_LoadBlob2Memory(Item,worked_attr,*buf_esquisse,size_esquisse)){
		m_api->m_data.GetAttr(Item,worked_attr_name,only_name);
		if(original_name!=0){
			*original_name=only_name;
		}
		return true;
	}else{
		delete[] *buf_esquisse;
		size_esquisse=0;
	}
	return false;
}

bool CaplClassifierMgr::DelClassifierEsquisse(CaplInstance *Item)
{
	if(!m_api) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(Item==0)return 0;
	if(Item->GetType()==0)return 0;
	CString blob_name,only_name=_T("");
	
	CaplAttr* worked_attr;
	CaplAttr* worked_attr_name;
	if(m_api->m_data.IsKindOf(Item, e_apl_classifier_system)){
		worked_attr=a_apl_classifier_system_esquisse;
		worked_attr_name=a_apl_classifier_system_esquisse_name;
	}else if(m_api->m_data.IsKindOf(Item, e_apl_classifier_level)){
		worked_attr=a_apl_classifier_level_esquisse;
		worked_attr_name=a_apl_classifier_level_esquisse_name;
	}else{
		return false;
	}
	
	m_api->m_data.GetAttr(Item,worked_attr,blob_name);
	if(blob_name==_T("")){return true;}// здесь блоба нет

	if(m_api->m_data.NET_DeleteBlob(Item,worked_attr)){
		m_api->m_data.GetAttr(Item,worked_attr_name,only_name);
		return true;
	}
	return false;

}


int CaplClassifierMgr::GetNextLevelIndex(CaplInstance* instLevel, bool bRecalc)
{
	if(!m_api) return -1;
	if(!m_api->m_data.IsConnected()) return -1;
	if(instLevel==0)return -1;
	if(instLevel->GetAccessmode()>aplRO) return -1;

	int max_index = -1, tmp;
	if(bRecalc)
	{
		aplExtent ext, rels;
		GetSubItems(instLevel, ext, &rels);
		
		for(int i=0; i<rels.GetSize(); i++)
		{
			m_data->GetAttr(rels[i], a_apl_classifier_association_index, tmp);
			max_index = max_index>tmp?max_index:tmp>0?tmp:-1;
		}
		max_index++;
	}
	else
	{
		m_data->GetAttr(instLevel, a_apl_classifier_level_next_index, max_index);
	}
	return max_index;
}

bool CaplClassifierMgr::SetIndexToUnindexedAssociations(CaplInstance* instLevel)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(instLevel==0)return false;
	if(instLevel->GetAccessmode()>aplRW) return false;

	int index = GetNextLevelIndex(instLevel), tmp;
	aplExtent ext, rels;
	GetSubItems(instLevel, ext, &rels);
	
	for(int i=0; i<rels.GetSize(); i++)
	{
		m_data->GetAttr(rels[i], a_apl_classifier_association_index, tmp);
		if(tmp==0)
			m_data->PutAttr(rels[i], a_apl_classifier_association_index, index++);
	}
	m_data->PutAttr(instLevel, a_apl_classifier_level_next_index, index);

	return true;
}

bool CaplClassifierMgr::GetObjectCode(CaplInstance* instAssociation, CString &code)
{
	code=_T("");

	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(instAssociation==0)return false;
	if(instAssociation->GetAccessmode()>aplRO) return false;

	CaplInstance* system, *ClassifierLevel;
	CString buf, sTemplate, sys_id, level_id, index_buf;
	int index;
	m_data->GetAttr(instAssociation, a_apl_classifier_association_system, system);
	if(system==NULL) return false;
	if(system->GetAccessmode()>aplRO) return false;
	m_api->m_data.GetAttr(instAssociation, a_apl_classifier_association_classifier, ClassifierLevel);
	if(ClassifierLevel==NULL) return false;
	if(ClassifierLevel->GetAccessmode()>aplRO) return false;

	m_api->m_data.GetAttr(system, a_apl_classifier_system_template, sTemplate);
	m_api->m_data.GetAttr(system, a_apl_classifier_system_id, sys_id);
	m_api->m_data.GetAttr(ClassifierLevel, a_apl_classifier_level_id, level_id);
	m_api->m_data.GetAttr(instAssociation, a_apl_classifier_association_index, index);

	if(index<=0) return false;

	int ind = sTemplate.Find(_T("%i"));
	int cnt = 0;
	if(ind>-1)
	{
		if(ind<sTemplate.GetLength()-1)
		{
			index_buf = sTemplate.Mid(ind, 3);
			if(iswdigit(index_buf[2]))
			{
				cnt = _atoi(index_buf.Mid(2));
			}
		}
	}

	buf.Format(_T("%d"), index);
	if(cnt>0)
	{
		while(buf.GetLength()<cnt)
			buf = _T("0")+buf;
	}
	code = sTemplate;
	code.Replace(_T("%s"), sys_id);
	code.Replace(_T("%l"), level_id);
	if(!index_buf.IsEmpty())
		code.Replace(index_buf, buf);

	return true;
}

bool CaplClassifierMgr::GetObjectCode(CaplInstance* instSystem, CaplInstance* instObject, CString &code)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsConnected()) return false;
	if(instSystem==0)return false;
	if(instSystem->GetAccessmode()>aplRO) return false;

	CaplInstance *rel;
	if(!TestClassifierAssociation(instObject, instSystem,&rel)){
		return false;
	}
	return GetObjectCode(rel, code);
}

bool CaplClassifierMgr::CreateObjectWithForm(CaplInstance* ClassifierElement,aplExtent *created_objects,aplExtent *created_associations)
{
	CaplInstance *system,*new_inst,*new_ass;
	aplExtent ext_forms;
	aplExtent aeInInsts,aeOutInsts;
	CaplInstance* form;
	bool is_control;
	int i;
	CaplEntity *stored_entity;
	CString form_ent_name;
	m_api->m_data.GetAttr(ClassifierElement, m_api->m_classifier_mgr.a_apl_classifier_level_system, system);
	if(system)
	{
		m_api->m_classifier_mgr.GetClassifierForms(ClassifierElement,ext_forms);
		m_api->m_classifier_mgr.GetObjectTypeParameters(system,is_control,&stored_entity);
		if(ext_forms.GetSize()>0 && FShowForm1!=0)
		{
			form=ext_forms.GetAt(0);
			if(form==0){
				return false;
			}
			if(is_control && stored_entity!=0){
				// проверяем подходит ли форма под entity
				m_api->m_form_mgr.GetFormEntityName(form,form_ent_name);
				if(form_ent_name.CompareNoCase(stored_entity->name)!=0){
					if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Тип объекта формы не совпадает с типом объекта, разрешенным для справочника. Измените свойства справочника!"));
					return false;
				}
			}
			aplExtent aeChars;
			m_api->m_classifier_mgr.GetClassifierCharacteristic(ClassifierElement,aeChars,true);
			
			FShowForm1(m_api,form,aeInInsts,aeOutInsts,&aeChars,form_ent_name, _T(""), TRUE, FALSE, FALSE);
			
			for(i=0;i<aeOutInsts.GetSize();i++){
				new_inst=aeOutInsts.GetAt(i);
				if(new_inst!=0)
				{
					if(created_objects!=0){created_objects->Add(new_inst);}
					if(!m_api->m_classifier_mgr.TestClassifierAssociation(new_inst, ClassifierElement,&new_ass))
					{
						new_ass=m_api->m_classifier_mgr.CreateClassifierAssociation(new_inst, ClassifierElement, false);
					}
					else
					{
						if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Связь с данным объектом уже существует!"), MB_OK|MB_ICONINFORMATION);
					}
					if(created_associations!=0){created_associations->Add(new_ass);}
				}
			}
			
		}else{
			if(m_api->m_ModeInteractive)AfxMessageBox( APL_T("Для справочника не задана форма"));
			return false;
		}
	}

	return true;
}

void CaplClassifierMgr::FN_DeleteClassifierLevel( CaplAPI* api, CaplLoadData& loadData, DWORD dwData )
{
	loadData.AddQuery(_T('r'), 0, api->m_classifier_mgr.e_apl_classifier_association,
					api->m_classifier_mgr.a_apl_classifier_association_classifier, true, true);	
}

bool CaplClassifierMgr::ValidateClassifierElsXmlRefs( const aplExtent& exts )
{
	std::map<CaplInstance*, bool> outMap;
	if ( m_api->m_doc_mgr.IsUsedInXml(exts, outMap ) )
	{
		CString strTmp;
		CString names;

		for( std::map<CaplInstance*, bool>::iterator it = outMap.begin(); it != outMap.end(); it++ )
		{
			if (  it->second )
			{
				m_api->GetItemName( it->first, strTmp );

				names += strTmp + _T("\r\n");
			}
		}

		if ( !names.IsEmpty() )
		{
			if ( AfxMessageBox( APL_T("Удаляемый(-ые) объект(-ы) имеет(-ют) ссылки! Удалить? \r\n") + names 
				, MB_YESNO |MB_ICONERROR) == IDNO )
			{
				return false;
			}
		}
	}

	return true;
}

SSelectItemFilter::SSelectItemFilter()
{
	search_entity=0;
	search_entity_name=_T("");
	default_selection=0;
	default_relation=CaplQLQuery::aplLIKE;
	default_value=_T("");
	sorting_field=0;
}
