воскресенье, 12 апреля 2026 г.

m3AttrIndexSearcher

{$IfDef FPC}{$CodePage cp1251}{$EndIf FPC}

unit m3AttrIndexSearcher;

// --------------------------------------------------------------------------
// Родители: "SearchByAttributes" <> MUID: (66C47D3E0363) :: "m3" <> MUID: (548712F60101) :: "Shared Delphi Low Level" <> MUID: (4ABCC25A0322)
// --------------------------------------------------------------------------
// Модуль: "w:\common\components\rtl\Garant\m3\m3AttrIndexSearcher.pas" GeneratorVersion: 1.0.0.883901
// Стереотип: "<>"
// Элемент модели: "Tm3AttrIndexSearcher" MUID: (66C47DB501FB)
// --------------------------------------------------------------------------

//#UC START# *66C47DB501FBbeforeDefines*
//#UC END# *66C47DB501FBbeforeDefines*
{$Include m3Define.inc}

interface

uses
 l3IntfUses
 , l3CProtoObject
 , m3AttrIndexInterfaces
 , m3SearcherInterfaces
 , l3Variant
 , m3DBInterfaces
 , m3DocumentStorageCacher
 , m3AttrIndexDumpersCache
 , l3CoreInterfaces
 , l3Interfaces
 , m3StorageInterfaces
 , l3Ranges
 , l3MarshalledTypes
 , l3StringsEnumerator
 , l3Enumerators
 , l3PrimString
 , l3Date
 //#UC START# *66C47DB501FBintf_uses*
 , k2Tags
;
const
 m3MandatoryAttributes = [
  k2_tiExternalHandle,
  k2_tiType,
  k2_tiUserType,
  k2_tiExternalVerLink,
  k2_tiRelExternalHandle,
  k2_tiRelInternalHandle,
  k2_tiExternalNextVerLink
 ]
 //#UC END# *66C47DB501FBintf_uses*
;

type
 //#UC START# *66C47DB501FBci*
 //#UC END# *66C47DB501FBci*
 Tm3AttrIndexSearcher = class(Tl3CProtoObject, Im3AttrIndexSearcher)
  private
   f_BaseName: AnsiString;
   f_PrevDumper: Im3AttrIndexDumper;
   f_PrevAttr: Integer;
   f_PrevDirect: Boolean;
   f_DocumentHeaderData: Il3TagRef;
   f_PrevDocID: Integer;
   f_DB: Im3DB;
   f_DumpersCache: Tm3AttrIndexDumpersCache;
   {$If Defined(m3UseCacher)}
   f_Cacher: Tm3DocumentStorageCacher;
   {$IfEnd} // Defined(m3UseCacher)
  private
   function GetDocumentString(anAttrID: Integer;
    aDocID: Tm3DocID): Il3CString;
   procedure WriteDocumentString(anAttrID: Integer;
    aDocID: Tm3DocID;
    const aString: Il3CString);
   function OpenDocStream(aDocID: Tm3DocID;
    aMode: Tm3StoreAccess;
    aDocPart: Tm3DocPartSelector;
    aIndex: Integer): IStream;
  protected
   {$If Defined(m3UseCacher)}
   function pm_GetCacher: Tm3DocumentStorageCacher;
   {$IfEnd} // Defined(m3UseCacher)
   function MakeDumper(anAttrID: Integer;
    aDirect: Boolean): Im3AttrIndexDumper;
   function SearchByKey(anAttrID: Integer;
    aKey: Integer;
    aDirect: Boolean): Il3RangeEnumerable; overload;
    {* Ищет по ключу в индексе для атрнибута }
   function ExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
   function InternalHandleToExternalHandle(anID: Tm3DocID): Tm3DocID;
   function SearchFirstByKey(anAttrID: Integer;
    aKey: Integer;
    aDirect: Boolean): Integer;
   function RelExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
   function InternalHandleToRelExternalHandle(anID: Tm3DocID): Tm3DocID;
   function SearchByKeys(anAttrID: Integer;
    const aKeys: Il3IntegerEnumerable): Il3RangeEnumerable; overload;
   function NameByInternalHandle(anID: Tm3DocID): Il3CString;
   function TypeByID(anID: Tm3DocID): TDocType;
   function UserTypeByID(anID: Tm3DocID): TUserType;
   function NameByID(anID: Tm3DocID): Il3CString;
   function AllDocuments: Il3RangeEnumerable;
    {* Все документы базы }
   function IsRelated(anID: Tm3DocID): Boolean;
    {* Определяет - является ли документ справкой. }
   function ConstDocuments: Il3RangeEnumerable;
    {* Документы из постояной части }
   function ModifiedDocuments: Il3RangeEnumerable;
    {* Документы из переменной части }
   function IsSpravka(anID: Tm3DocID): Boolean;
   function DeletedDocuments: Il3RangeEnumerable;
    {* Удалённые документы }
   function AllRelated: Il3RangeEnumerable;
    {* Все справки }
   function ConstRelated: Il3RangeEnumerable;
    {* Справки в постоянной части }
   function ModifiedRelated: Il3RangeEnumerable;
    {* Справки в переменной части }
   function IsAnnoOnly(anID: Tm3DocID): Boolean;
    {* Документ содержит ТОЛЬКО аннотацию. Несколько "техническая" ручка. Обычно такой ситуации не должно быть. Но пусть будет }
   function SearcheableAttributesNames: Il3StringsEnumerable;
    {* Имена атрибутов для поиска }
   function SearchByKeyEx(const anAttrID: array of Integer;
    aKey: Integer;
    aDirect: Boolean): Il3RangeEnumerable;
    {* Ищет по ключу "иерархического" атрибута. Т.е. указывается "путь" в EVD. Сродни cAtomEx }
   function ContextAttributesNames: Il3StringsEnumerable;
   function SearchByKey(anAttrID: Integer;
    aKey: Tl3PrimString): Il3RangeEnumerable; overload;
   function SearchByKey(anAttrID: Integer;
    const aKey: AnsiString): Il3RangeEnumerable; overload;
   function SearchByKey(anAttrID: Integer;
    const aKey: Tl3WString): Il3RangeEnumerable; overload;
   function SearchByKeys(anAttrID: Integer;
    const aKeys: Il3StringsEnumerable): Il3RangeEnumerable; overload;
   function OutLinks(anID: Tm3DocID): Il3RangeEnumerable;
    {* Исходящие ссылки. Респонденты. }
   function InLinks(anID: Tm3DocID): Il3RangeEnumerable;
    {* Входящие ссылки. Корреспонденты. }
   function SearchByNumberType(aNumberType: TDNType): Il3RangeEnumerable;
   function SearchByNumber(const aNumber: AnsiString): Il3RangeEnumerable;
   function SearchBetweenKeys(const anAttrID: array of Integer;
    aLowKey: Integer;
    aHighKey: Integer;
    aDirect: Boolean): Il3RangeEnumerable;
   function SearchByDates(aFrom: TStDate;
    aTo: TStDate): Il3RangeEnumerable;
   function CommentByInternalHandle(anID: Tm3DocID): Il3CString;
   function CommentByID(anID: Tm3DocID): Il3CString;
   function Versions(anID: Tm3DocID): Il3IntegerEnumerable;
    {* Версии документа. Включая сам документ }
   function DocumentHeaderData(anID: Tm3DocID): Il3TagRef;
    {* Данные заголовка документа. Например ActiveIntervals и NumAndDates }
   function SearchByType(aDocType: TDocType): Il3RangeEnumerable;
   function SearchByMaskInKey(anAttrID: Integer;
    aMask: Integer): Il3RangeEnumerable;
    {* https://mdp.garant.ru/pages/viewpage.action?pageId=877071294 }
   function SearchByMaskInPriceLevel(aMask: Integer): Il3RangeEnumerable;
   function IndexTimeStamp(anAttrID: Integer;
    aDirect: Boolean): TDateTime;
   procedure Cleanup; override;
    {* Функция очистки полей объекта. }
   procedure ClearFields; override;
  public
   constructor Create(const aBaseName: AnsiString); reintroduce; overload;
   class function Make(const aBaseName: AnsiString): Im3AttrIndexSearcher; reintroduce; overload;
   constructor Create(const aDB: Im3DB); reintroduce; overload;
   class function Make(const aDB: Im3DB): Im3AttrIndexSearcher; reintroduce; overload;
   {$If Defined(m3UseCacher)}
   constructor Create(aCacher: Tm3DocumentStorageCacher); reintroduce; overload;
   {$IfEnd} // Defined(m3UseCacher)
   {$If Defined(m3UseCacher)}
   class function Make(aCacher: Tm3DocumentStorageCacher): Im3AttrIndexSearcher; reintroduce; overload;
   {$IfEnd} // Defined(m3UseCacher)
   {$If NOT Defined(l3NoSRT)}
   function SetRefTo(var thePlace: Tm3AttrIndexSearcher): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
   {$IfEnd} // NOT Defined(l3NoSRT)
  private
   {$If Defined(m3UseCacher)}
   property Cacher: Tm3DocumentStorageCacher
    read pm_GetCacher;
   {$IfEnd} // Defined(m3UseCacher)
 //#UC START# *66C47DB501FBpubl*
  private 
   {$IfDef FPC}
   class var f_SearcheableAttributesNames: Il3StringsEnumerable;
   class var f_ContextAttributesNames: Il3StringsEnumerable;
   {$EndIf FPC}
   f_WasException : Boolean;
  public 
   {$IfDef FPC}
   class destructor done;
   {$EndIf FPC}
   constructor CreateFromDumper(const aDumper: Im3AttrIndexDumper;
    anAttrID: Integer;
    aDirect: Boolean);
   class function MakeFromDumper(const aDumper: Im3AttrIndexDumper;
    anAttrID: Integer;
    aDirect: Boolean): Im3AttrIndexSearcher;
 //#UC END# *66C47DB501FBpubl*
 end;//Tm3AttrIndexSearcher

implementation

uses
 l3ImplUses
 , m3IndexDumper
 , m3DBHelper
 , m3DocumentInfoExtractor
 , m3DocumentsMap
 , m3DocumentsCache
 , m3AttrIndexDumperJoin
 , m3AttrIndexDumper
 , l3SharedConstString
 , k2DocumentHeaderBuffer
 , m3ExternalIDtoInternalIDMap
 //#UC START# *66C47DB501FBimpl_uses*
 {$IfNDef FPC}
 , Windows
 {$EndIf  FPC}
 , SysUtils
 , Classes
 , Math
 , DateUtils
 , l3Core
 , l3Types
 , l3Chars
 , l3CEmptyString
 , l3String
 , l3Bits
 , l3Except
 , l3StoreInterfaces
 , l3_String
 , l3StringList
 , l3LongintList
 , k2Attributes
 , k2TagGen
 , evdNativeReader
 , m2COMLib
 , m3Exceptions
 , m3DB
 , m3SplittedFileStream
 , m3RangedDocumentsList
 , m4SearchEx
 , m4SimpleExpression
 , m4Search
 , m4SearchResult
 , m3FirstTextExtractor
 , m3DBTools
 , m3CachersService
 {$IfDef Archi}
 {$IfDef AppClientSide}
 , ddClientBaseEngine
 {$EndIf AppClientSide}
 {$EndIf Archi}

{$Define m3UseHeaderForName}
{$Define m3UseTypeForAllRelated}
{$Define m3UseTypeForAllDocuments}

 //#UC END# *66C47DB501FBimpl_uses*
;

{$If Defined(m3UseCacher)}
function Tm3AttrIndexSearcher.pm_GetCacher: Tm3DocumentStorageCacher;
//#UC START# *68FF50220066_66C47DB501FBget_var*
//#UC END# *68FF50220066_66C47DB501FBget_var*
begin
//#UC START# *68FF50220066_66C47DB501FBget_impl*
 if (f_Cacher = nil) then
 begin
  if (f_DB = nil) then
   f_Cacher := Tm3DocumentStorageCacher.Create(Tm3DB.Make(f_BaseName), 0)
  else
   f_Cacher := Tm3DocumentStorageCacher.Create(f_DB, 0);
 end;//f_Cacher = nil
 Result := f_Cacher;
//#UC END# *68FF50220066_66C47DB501FBget_impl*
end;//Tm3AttrIndexSearcher.pm_GetCacher
{$IfEnd} // Defined(m3UseCacher)

constructor Tm3AttrIndexSearcher.Create(const aBaseName: AnsiString);
//#UC START# *66C47E91011E_66C47DB501FB_var*
//#UC END# *66C47E91011E_66C47DB501FB_var*
begin
//#UC START# *66C47E91011E_66C47DB501FB_impl*
 f_WasException := false;
 if (f_PrevDumper = nil) then
 begin
  f_PrevAttr := -1;
  f_PrevDirect := false;
  Assert(aBaseName <> '');
 end;//f_PrevDumper = nil
 f_PrevDocID := -1;
 f_DocumentHeaderData := nil;
 f_BaseName := aBaseName;
 f_BaseName := Tm3SplittedFileStream.NormalizeFileName(f_BaseName);
 f_BaseName := ChangeFileExt(f_BaseName, '');
 inherited Create;
//#UC END# *66C47E91011E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create

class function Tm3AttrIndexSearcher.Make(const aBaseName: AnsiString): Im3AttrIndexSearcher;
var
 l_Inst : Tm3AttrIndexSearcher;
begin
 l_Inst := Create(aBaseName);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3AttrIndexSearcher.Make

constructor Tm3AttrIndexSearcher.Create(const aDB: Im3DB);
//#UC START# *67A3B7240286_66C47DB501FB_var*
//#UC END# *67A3B7240286_66C47DB501FB_var*
begin
//#UC START# *67A3B7240286_66C47DB501FB_impl*
 Assert(aDB <> nil);
 Create(aDB.xBaseName);
 f_DB := aDB;
//#UC END# *67A3B7240286_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create

class function Tm3AttrIndexSearcher.Make(const aDB: Im3DB): Im3AttrIndexSearcher;
var
 l_Inst : Tm3AttrIndexSearcher;
begin
 l_Inst := Create(aDB);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3AttrIndexSearcher.Make

function Tm3AttrIndexSearcher.MakeDumper(anAttrID: Integer;
 aDirect: Boolean): Im3AttrIndexDumper;
//#UC START# *67AB413203A3_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;
 l_Key : Tm3AttrIndexDumperKey;
 l_Index : Integer;
//#UC END# *67AB413203A3_66C47DB501FB_var*
begin
//#UC START# *67AB413203A3_66C47DB501FB_impl*
 l_Key := Tm3AttrIndexDumperKey_C(anAttrID, aDirect);
 if (f_DumpersCache <> nil) then
  if f_DumpersCache.Has(l_Key, l_Index) then
  begin
   Result := f_DumpersCache.ValueByIndex(l_Index);
   Exit;
  end;//f_DumpersCache.Has(l_Key, l_Index)
 if (f_PrevDumper <> nil)
    AND (f_PrevAttr = anAttrID)
    AND (f_PrevDirect = aDirect)
    then
  l_Dumper := f_PrevDumper
 else
  l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
 try
  if (l_Dumper <> nil) then
  begin
   f_PrevAttr := anAttrID;
   f_PrevDirect := aDirect;
   f_PrevDumper := l_Dumper;
  end;//l_Dumper <> nil
  Result := l_Dumper;
 finally
  l_Dumper := nil;
 end;//try..finally
 if (f_DumpersCache = nil) then
  f_DumpersCache := Tm3AttrIndexDumpersCache.Create;
 f_DumpersCache.Add(l_Key, Result);
//#UC END# *67AB413203A3_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.MakeDumper

function Tm3AttrIndexSearcher.GetDocumentString(anAttrID: Integer;
 aDocID: Tm3DocID): Il3CString;
//#UC START# *68EF6D26029F_66C47DB501FB_var*
var
(* l_DB : Im3DB;
 l_Doc : Im3DBDocument;*)
 l_DocStream : IStream;
 l_Size : Int64;
 l_Len : Int64;
 l_S : Tl3_String;
//#UC END# *68EF6D26029F_66C47DB501FB_var*
begin
//#UC START# *68EF6D26029F_66C47DB501FB_impl*
 Result := nil;
(* if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(aDocID);
  if (l_Doc <> nil) then*)
  begin
   l_DocStream := Self.OpenDocStream(aDocID, m3_saRead, m3_dsNames, anAttrID);
   //l_DocStream := l_Doc.Open(m3_saRead, m3_dsNames, anAttrID);
   try
    if (l_DocStream <> nil) then
    begin
     l_Size := m2COMGetSize(l_DocStream);
     if (l_Size < 0) then
     begin
      Result := Tl3CEmptyString.Instance;
      Exit;
     end//l_Size < 0
     else
     if ((l_Size mod 2) <> 0) then
     begin
      Result := Tl3CEmptyString.Instance;
      Exit;
     end;//(l_Size mod 2) <> 0
     Assert((l_Size mod 2) = 0);
     if (l_Size = 0) then
      Result := Tl3CEmptyString.Instance
     else
     if (l_Size > 0) then
     begin
      l_Len := l_Size div 2;
      l_S := Tl3_String.Create;
      try
       l_S.CodePage := CP_Unicode;
       l_S.Len := l_Len;
       Assert(l_S.CodePage = CP_Unicode);
       m2COMReadBuffer(l_DocStream, l_S.St^, l_Size);
       l_S.CheckUnicode(true);
       Result := l_S.AsCStr;
      finally
       FreeAndNil(l_S);
      end;//try..finally
     end;//l_Size > 0
    end;//l_DocStream <> nil
   finally
    l_DocStream := nil;
   end;//try..finally
  end;//l_Doc <> nil
(* finally
  l_DB := nil;
 end;//try..finally*)
//#UC END# *68EF6D26029F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.GetDocumentString

procedure Tm3AttrIndexSearcher.WriteDocumentString(anAttrID: Integer;
 aDocID: Tm3DocID;
 const aString: Il3CString);
//#UC START# *68F0B95202A8_66C47DB501FB_var*
var
 l_DB : Im3DB;
 l_S : Tl3WString;
//#UC END# *68F0B95202A8_66C47DB501FB_var*
begin
//#UC START# *68F0B95202A8_66C47DB501FB_impl*
 if (aString = nil) then
  Exit;
 {$IfDef Archi}
 {$IfDef AppClientSide}
 //if false then
 if (g_BaseEngine <> nil) then
  if g_BaseEngine.WorkWithServer then
   Exit;
 {$EndIf AppClientSide}
 {$EndIf Archi}
 if (GetCurrentThreadID <> MainThreadID) then
  Exit;
 if f_WasException then
 // - guiard of deadlocks
  Exit;
 if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_S := aString.AsWStr;
  //if l3IsNil(l_S) then
  // Exit;
  m3WriteStringToDocument(l_DB, aDocID, anAttrID, l_S);
 finally
  l_DB := nil;
 end;//try..finally
//#UC END# *68F0B95202A8_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.WriteDocumentString

function Tm3AttrIndexSearcher.OpenDocStream(aDocID: Tm3DocID;
 aMode: Tm3StoreAccess;
 aDocPart: Tm3DocPartSelector;
 aIndex: Integer): IStream;
//#UC START# *68FF51A101F5_66C47DB501FB_var*
var
 {$IfDef m3UseCacher}
 l_Cacher: Tm3DocumentStorageCacher;
 {$EndIf m3UseCacher}
 l_Doc : Im3DBDocument;
//#UC END# *68FF51A101F5_66C47DB501FB_var*
begin
//#UC START# *68FF51A101F5_66C47DB501FB_impl*
 Result := nil;
 if (f_DB <> nil) then
 begin
  if f_DB.IsExclusive then
  begin
   l_Doc := f_DB.GetDocument(aDocID);
   if (l_Doc <> nil) then
    Result := l_Doc.Open(aMode, aDocPart, aIndex);
   Exit;
  end;//f_DB.IsExclusive
 end;//f_DB <> nil
 {$IfDef m3UseCacher}
 l_Cacher := Self.Cacher;
 l_Cacher.DocID := aDocID;
 try
  Result := l_Cacher.OpenDocStream(aMode, aDocPart, aIndex);
 except
  on Em3RegionLocked do
  begin
   if Tm3CachersService.Exists then
    Tm3CachersService.Instance.CloseCachers(aDocID);
   try
    Result := l_Cacher.OpenDocStream(aMode, aDocPart, aIndex);
   except
    on Em3RegionLocked do
    begin
     Result := nil;
    end;//on Em3RegionLocked
   end;//try..except
  end;//on Em3RegionLocked
  else
  // - maybe wrong sav
   Result := nil;
 end;//try..except
 {$Else  m3UseCacher}
 if (f_DB = nil) then
  l_Doc := Tm3DB.Make(f_BaseName).GetDocument(aDocID)
 else
  l_Doc := f_DB.GetDocument(aDocID);
 if (l_Doc <> nil) then
  Result := l_Doc.Open(aMode, aDocPart, aIndex);
 {$EndIf m3UseCacher}
//#UC END# *68FF51A101F5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.OpenDocStream

{$If Defined(m3UseCacher)}
constructor Tm3AttrIndexSearcher.Create(aCacher: Tm3DocumentStorageCacher);
//#UC START# *69020AF40205_66C47DB501FB_var*
//#UC END# *69020AF40205_66C47DB501FB_var*
begin
//#UC START# *69020AF40205_66C47DB501FB_impl*
 Assert(aCacher <> nil);
 aCacher.SetRefTo(f_Cacher);
 Create(aCacher.DB);
//#UC END# *69020AF40205_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create
{$IfEnd} // Defined(m3UseCacher)

{$If Defined(m3UseCacher)}
class function Tm3AttrIndexSearcher.Make(aCacher: Tm3DocumentStorageCacher): Im3AttrIndexSearcher;
var
 l_Inst : Tm3AttrIndexSearcher;
begin
 l_Inst := Create(aCacher);
 try
  Result := l_Inst;
 finally
  l_Inst.Free;
 end;//try..finally
end;//Tm3AttrIndexSearcher.Make
{$IfEnd} // Defined(m3UseCacher)

{$If NOT Defined(l3NoSRT)}
function Tm3AttrIndexSearcher.SetRefTo(var thePlace: Tm3AttrIndexSearcher): Boolean;
begin
 if (thePlace = Self) then
  Result := false
 else
 begin
  Result := true;
  thePlace.Free;
  thePlace := Self.Use;
 end;//thePlace = Self
end;//Tm3AttrIndexSearcher.SetRefTo
{$IfEnd} // NOT Defined(l3NoSRT)

function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
 aKey: Integer;
 aDirect: Boolean): Il3RangeEnumerable;
 {* Ищет по ключу в индексе для атрнибута }
//#UC START# *66C47C8F006F_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;

 function GetFromDoc: Boolean;
 var
  l_DocStream : IStream;
  l_DT, l_IdT : TDateTime;
  l_Size : Int64;
  l_S : Il3Stream;
 begin//GetFromDoc
  Result := false;
  if f_WasException then
  // - чтобы не долбиться головой об стену
  // https://mdp.garant.ru/pages/viewpage.action?pageId=902332536
   Exit;
  try
   l_DocStream := Self.OpenDocStream(aKey, m3_saRead, m3_dsAttrs, anAttrID);
  except
   f_WasException := true;
   Exit;
  end;//try..except
  try
   if (l_DocStream <> nil) then
   begin
    if (anAttrID in m3MandatoryAttributes) then
    begin
     SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
     Result := true;
     Exit;
    end//anAttrID in m3MandatoryAttributes
    else
    if (l_Dumper <> nil) then
    begin
     // - здесь будем timestamp проверять
     l_IdT := BadDateTime;
     l_DT := BadDateTime;
     l_IdT := l_Dumper.TimeStamp;
     l_Size := m2COMGetSize(l_DocStream);
     if SameValue(l_IdT, BadDateTime) then
     begin
      SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
      Result := true;
      Exit;
     end//SameValue(l_IdT, BadDateTime)
     else
     begin
      l_DT := BadDateTime;
      if Supports(l_DocStream, Il3Stream, l_S) then
       try
        l_DT := l_S.DateTime;
        if (CompareDateTime(l_DT, l_IdT) >= 0) then
        begin
         SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
         Result := true;
         Exit;
        end;//CompareDateTime(l_DT, l_IdT) >= 0
       finally
        l_S := nil;
       end;//try..finally
     end;//SameValue(l_IdT, BadDateTime)
    end//l_Dumper <> nil
    else
    begin
     SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
     Result := true;
     Exit;
    end;//l_Dumper <> nil
   end;//l_DocStream <> nil
  finally
   l_DocStream := nil;
  end;//try..finally
 end;//GetFromDoc

 procedure WriteToDoc;
 var
  l_DocStream : IStream;
 begin//WriteToDoc
  if not aDirect then
   Exit;
  if (aKey <= 0) then
   Exit;
  //if not (anAttrID in m3MandatoryAttributes) then
  begin
   if (GetCurrentThreadID <> MainThreadID) then
    Exit;
  end;//not (anAttrID in m3MandatoryAttributes)

  if not (anAttrID in m3MandatoryAttributes) then
  begin
   // if anAttrID IS NOT Mandatory then
   // we NEED to check previous version
   // and rewrite it or change its timestamp
   // but now we do not have needed functionaslity
   // so we simple exit at this point
   Exit;
  end;//not (anAttrID in m3MandatoryAttributes)

  if f_WasException then
  // - guiard of deadlocks
   Exit;

  {$IfDef Archi}
  {$IfDef AppClientSide}
  //if false then
  if (g_BaseEngine <> nil) then
   if g_BaseEngine.WorkWithServer then
    Exit;
  {$EndIf AppClientSide}
  {$EndIf Archi}

  l_DocStream := Self.OpenDocStream(aKey, m3_saReadWrite, m3_dsAttrs, anAttrID);
  try
   if (l_DocStream <> nil) then
    Il3RangeEnumerable_WriteTo(Result, l_DocStream);
  finally
   l_DocStream := nil;
  end;//try..finally
 end;//WriteToDoc

//#UC END# *66C47C8F006F_66C47DB501FB_var*
begin
//#UC START# *66C47C8F006F_66C47DB501FB_impl*
 Result := nil;

 if aDirect then
 begin
  if (aKey <= 0) then
  begin
  // -- заточка
   aKey := 0;
   Exit;
  end;//aKey <= 0
 end;//aDirect

 if aDirect then
 begin
  if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
  begin
   if (anAttrID in m3MandatoryAttributes) then
    if GetFromDoc then
     Exit;
  end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
 end;//aDirect

 l_Dumper := Self.MakeDumper(anAttrID, aDirect);
 try
  if aDirect then
  begin
   if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
   begin
    if not (anAttrID in m3MandatoryAttributes) then
     if GetFromDoc then
      Exit;
   end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
  end;//aDirect
  if (l_Dumper <> nil) then
  begin
   Result := l_Dumper.ValuesByKey(aKey);
   if aDirect then
   if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
   // - здесь будем писать в документ
   begin
    WriteToDoc;
   end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
  end;//l_Dumper <> nil
 finally
  l_Dumper := nil;
 end;//try..finally
//#UC END# *66C47C8F006F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey

function Tm3AttrIndexSearcher.ExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66C47CD2030A_66C47DB501FB_var*
//#UC END# *66C47CD2030A_66C47DB501FB_var*
begin
//#UC START# *66C47CD2030A_66C47DB501FB_impl*
 Result := Self.SearchFirstByKey(k2_tiExternalHandle, anID, false);
 if (Result <= 0) then
 begin
  if Tm3ExternalIDtoInternalIDMap.Exists then
   with Tm3ExternalIDtoInternalIDMap.Instance do
   begin
    Lock;
    try
     if Has(anID) then
     begin
      Result := ValueByKey(anID);
      if (Result = 0) then
       Result := -1;
     end;//Has(anID)
    finally
     Unlock;
    end;//try..finally
   end;//with Tm3ExternalIDtoInternalIDMap.Instance
 end;//Result <= 0
//#UC END# *66C47CD2030A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ExternalHandleToInternalHandle

function Tm3AttrIndexSearcher.InternalHandleToExternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66C4D5330179_66C47DB501FB_var*
var
 l_Header : Il3TagRef;
//#UC END# *66C4D5330179_66C47DB501FB_var*
begin
//#UC START# *66C4D5330179_66C47DB501FB_impl*
 if (anID < 0) then
 begin
  Result := -1;
  Exit;
 end;//anID < 0
 if (anID = 0) then
 begin
  Result := -1;
  Exit;
 end;//anID = 0
 Result := Self.SearchFirstByKey(k2_tiExternalHandle, anID, true);
 if (Result <= 0) then
 begin
  l_Header := Self.DocumentHeaderData(anID);
  if (l_Header <> nil) then
   if (l_Header.AsObject <> nil) then
    if l_Header.AsObject.IsValid then
    begin
     Result := l_Header.AsObject.IntA[k2_tiExternalHandle];
     if (Result = 0) then
      Result := -1;
    end;//l_Header.AsObject.IsValid
 end;//Result <= 0
 //Result := Self.SearchFirstByKey(k2_tiInternalHandle, anID, false);
//#UC END# *66C4D5330179_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InternalHandleToExternalHandle

function Tm3AttrIndexSearcher.SearchFirstByKey(anAttrID: Integer;
 aKey: Integer;
 aDirect: Boolean): Integer;
//#UC START# *66D9AB76035A_66C47DB501FB_var*
var
 l_E : Il3RangeEnumerable;
 l_It : Il3RangeEnumerator;
 //l_It : Il3IntegerEnumerator;
//#UC END# *66D9AB76035A_66C47DB501FB_var*
begin
//#UC START# *66D9AB76035A_66C47DB501FB_impl*
 Result := -1;
 l_E := Self.SearchByKey(anAttrID, aKey, aDirect);
 if (l_E <> nil) then
 begin
  l_It := l_E.GetEnumerator;
  if (l_It <> nil) then
   if l_It.MoveNext then
    Result := l_It.pCurrent^.rLow;
(*  l_It := Il3RangeEnumerable_GetIntegerEnumerator(l_E);
  if (l_It <> nil) then
   if l_It.MoveNext then
    Result := l_It.Current;*)
 end;//l_E <> nil
//#UC END# *66D9AB76035A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchFirstByKey

function Tm3AttrIndexSearcher.RelExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66F675CD0025_66C47DB501FB_var*
//#UC END# *66F675CD0025_66C47DB501FB_var*
begin
//#UC START# *66F675CD0025_66C47DB501FB_impl*
 Result := Self.SearchFirstByKey(k2_tiRelExternalHandle, anID, false);
//#UC END# *66F675CD0025_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.RelExternalHandleToInternalHandle

function Tm3AttrIndexSearcher.InternalHandleToRelExternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66F675E602D6_66C47DB501FB_var*
var
 l_Header : Il3TagRef;
//#UC END# *66F675E602D6_66C47DB501FB_var*
begin
//#UC START# *66F675E602D6_66C47DB501FB_impl*
 Result := Self.SearchFirstByKey(k2_tiRelExternalHandle, anID, true);
 if (Result <= 0) then
 begin
  l_Header := Self.DocumentHeaderData(anID);
  if (l_Header <> nil) then
   if (l_Header.AsObject <> nil) then
    if l_Header.AsObject.IsValid then
    begin
     Result := l_Header.AsObject.IntA[k2_tiRelExternalHandle];
     if (Result = 0) then
      Result := -1;
    end;//l_Header.AsObject.IsValid
 end;//Result <= 0
//#UC END# *66F675E602D6_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InternalHandleToRelExternalHandle

function Tm3AttrIndexSearcher.SearchByKeys(anAttrID: Integer;
 const aKeys: Il3IntegerEnumerable): Il3RangeEnumerable;
//#UC START# *66F6B0710210_66C47DB501FB_var*
var
 l_It : Il3IntegerEnumerator;
 l_Found : Il3RangeEnumerable;
//#UC END# *66F6B0710210_66C47DB501FB_var*
begin
//#UC START# *66F6B0710210_66C47DB501FB_impl*
 Result := nil;
 if (aKeys <> nil) then
 begin
  l_It := aKeys.GetEnumerator;
  if (l_It <> nil) then
  begin
   while l_It.MoveNext do
   begin
    l_Found := Self.SearchByKey(anAttrID, l_It.Current, false);
    if (l_Found <> nil) then
    begin
     Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
    end;//l_Found <> nil
   end;//while l_It.MoveNext
  end;//l_It <> nil
 end;//aKeys <> nil
//#UC END# *66F6B0710210_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeys

function Tm3AttrIndexSearcher.NameByInternalHandle(anID: Tm3DocID): Il3CString;
//#UC START# *66FFE0ED02C3_66C47DB501FB_var*
var
 l_ID : Integer;
{$IfDef m3UseHeaderForName}
 l_Header : Il3TagRef;
(* l_DB : Im3DB;
 l_Doc : Im3DBDocument;*)
 l_S : IStream;
 l_TextExtractor : Tm3FirstTextExtractor;
 l_Reader : TevdNativeReader;
 l_WasAbortLoad : Boolean;
 l_IsAnno : Boolean;
{$Else  m3UseHeaderForName}
 l_DB : Im3DB;
 l_Doc : Im3DBDocument;
 l_S : IStream;
 l_Extractor : Tm3DocumentInfoExtractor;
 l_Reader : TevdNativeReader;
 l_WasAbortLoad : Boolean;
 l_IsAnno : Boolean;
{$EndIf m3UseHeaderForName}
//#UC END# *66FFE0ED02C3_66C47DB501FB_var*
begin
//#UC START# *66FFE0ED02C3_66C47DB501FB_impl*
 Result := nil;
 Result := GetDocumentString(k2_tiName, anID);
 if not l3IsNil(Result) then
 //if (Result <> nil) then
  Exit;
 Result := GetDocumentString(k2_tiShortName, anID);
 if not l3IsNil(Result) then
 //if (Result <> nil) then
  Exit;
 Result := GetDocumentString(k2_tiText, anID);
 if not l3IsNil(Result) then
 //if (Result <> nil) then
  Exit;
 {$IfDef m3UseHeaderForName}
 l_Header := Self.DocumentHeaderData(anID);
 if (l_Header <> nil) then
  if (l_Header.AsObject <> nil) then
   if l_Header.AsObject.IsValid then
   begin
    Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiName]);
    WriteDocumentString(k2_tiName, anID, Result);
    if not l3IsNil(Result) then
     Exit;
    Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiShortName]);
    WriteDocumentString(k2_tiShortName, anID, Result);
    if not l3IsNil(Result) then
     Exit;
   end;//l_Header.AsObject.IsValid
 {$Else  m3UseHeaderForName}
 l_WasAbortLoad := false;
 if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(anID);
  if (l_Doc <> nil) then
  begin
   l_IsAnno := false;
   l_S := l_Doc.Open;
   try
    if (l_S <> nil) then
    begin
     if (m2COMGetSize(l_S) <= 0) then
     begin
      Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
      Exit;
     end;//m2COMGetSize(l_S) <= 0
    end;//l_S <> nil
    if (l_S = nil) then
    begin
     l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
     // - костылик для аннотаций
     if (l_S <> nil) then
      l_IsAnno := true;
    end;//l_S = nil
    if (l_S <> nil) then
    begin
     l_Extractor := Tm3DocumentInfoExtractor.Create;
     try
      l_Reader := TevdNativeReader.Create;
      try
       l_Reader.Generator := l_Extractor;
       l_Reader.Filer.Mode := l3_fmRead;
       l_Reader.Filer.COMStream := l_S;
       try
        l_Reader.Start;
        try
         try
          l_Reader.Execute;
         except
          on El3AbortLoad do
          begin
           l_WasAbortLoad := true;
          end;//on El3AbortLoad
         end;//try..except
        finally
         try
          if not l_WasAbortLoad then
           l_Reader.Finish;
         except
          on Ek2TagGeneratorBadFinishCall do
          begin
           if not l_WasAbortLoad then
            raise;
          end;//on Ek2TagGeneratorBadFinishCall
         end;//try..except
        end;//try..finally
       finally
        l_Reader.Filer.COMStream := nil;
       end;//try..finally
      finally
       FreeAndNil(l_Reader);
      end;//try..finally
      if not l3IsNil(l_Extractor.DocName) then
      begin
       if l_IsAnno then
        Result := l3Cat('Аннотация: ', l_Extractor.DocName)
       else
        Result := l_Extractor.DocName;
       Exit;
      end;//not l3IsNil(l_Extractor.DocName)
      if not l3IsNil(l_Extractor.DocShortName) then
      begin
       if l_IsAnno then
        Result := l3Cat('Аннотация: ', l_Extractor.DocShortName)
       else
        Result := l_Extractor.DocShortName;
       Exit;
      end;//not l3IsNil(l_Extractor.DocShortName)
     finally
      FreeAndNil(l_Extractor);
     end;//try..finally
    end;//l_S <> nil
   finally
    l_S := nil;
   end;//try..finally
  end;//l_Doc <> nil
 finally
  l_DB := nil;
 end;//try..finally
 {$EndIf m3UseHeaderForName}
 l_WasAbortLoad := false;
(* if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(anID);
  if (l_Doc <> nil) then*)
  begin
   l_IsAnno := false;
   l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
   //l_S := l_Doc.Open;
   try
    if (l_S <> nil) then
    begin
     if (m2COMGetSize(l_S) <= 0) then
     begin
      Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
      WriteDocumentString(k2_tiText, anID, Result);
      Exit;
     end;//m2COMGetSize(l_S) <= 0
    end;//l_S <> nil
    if (l_S = nil) then
    begin
     l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsAnno, 0);
     //l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
     // - костылик для аннотаций
     if (l_S <> nil) then
      l_IsAnno := true;
    end;//l_S = nil
    if (l_S <> nil) then
    begin
     l_TextExtractor := Tm3FirstTextExtractor.Create;
     try
      l_Reader := TevdNativeReader.Create;
      try
       l_Reader.Generator := l_TextExtractor;
       l_Reader.Filer.Mode := l3_fmRead;
       l_Reader.Filer.COMStream := l_S;
       try
        l_Reader.Start;
        try
         try
          l_Reader.Execute;
         except
          on El3AbortLoad do
          begin
           l_WasAbortLoad := true;
          end;//on El3AbortLoad
         end;//try..except
        finally
         try
          if not l_WasAbortLoad then
           l_Reader.Finish;
         except
          on Ek2TagGeneratorBadFinishCall do
          begin
           if not l_WasAbortLoad then
            raise;
          end;//on Ek2TagGeneratorBadFinishCall
         end;//try..except
        end;//try..finally
       finally
        l_Reader.Filer.COMStream := nil;
       end;//try..finally
      finally
       FreeAndNil(l_Reader);
      end;//try..finally
      if not l3IsNil(l_TextExtractor.Text) then
      begin
       if l_IsAnno then
        Result := l3Cat('Аннотация: ', l_TextExtractor.Text)
       else
        Result := l_TextExtractor.Text;
       WriteDocumentString(k2_tiText, anID, Result);
       Exit;
      end;//not l3IsNil(l_TextExtractor.Text)
     finally
      FreeAndNil(l_TextExtractor);
     end;//try..finally
    end;//l_S <> nil
   finally
    l_S := nil;
   end;//try..finally
  end;//l_Doc <> nil
(* finally
  l_DB := nil;
 end;//try..finally*)
 l_ID := Self.InternalHandleToExternalHandle(anID);
 if (l_ID < 0) then
  l_ID := anID;
 Result := l3Fmt('Документ №%d', [l_ID]);
 WriteDocumentString(k2_tiText, anID, Result);
//#UC END# *66FFE0ED02C3_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.NameByInternalHandle

function Tm3AttrIndexSearcher.TypeByID(anID: Tm3DocID): TDocType;
//#UC START# *6700586B00FE_66C47DB501FB_var*
var
 l_Header : Il3TagRef;
 l_Result : Integer;
//#UC END# *6700586B00FE_66C47DB501FB_var*
begin
//#UC START# *6700586B00FE_66C47DB501FB_impl*
 if (anID < 0) then
 begin
  Result := dtNone;
  Exit;
 end;//anID < 0
 if (anID = 0) then
 begin
  Result := dtNone;
  Exit;
 end;//anID = 0
 l_Result := Self.SearchFirstByKey(k2_tiType, anID, true);
 if (l_Result < 0) then
 begin
  l_Header := Self.DocumentHeaderData(anID);
  if (l_Header <> nil) then
   if (l_Header.AsObject <> nil) then
    if l_Header.AsObject.IsValid then
    begin
     l_Result := l_Header.AsObject.IntA[k2_tiType];
    end;//l_Header.AsObject.IsValid
 end;//l_Result < 0
 if (l_Result < Ord(Low(Result))) OR (l_Result > Ord(High(Result))) then
  Result := dtNone
 else
  Result := TDocType(l_Result);
//#UC END# *6700586B00FE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.TypeByID

function Tm3AttrIndexSearcher.UserTypeByID(anID: Tm3DocID): TUserType;
//#UC START# *6700588601FB_66C47DB501FB_var*
var
 l_Header : Il3TagRef;
 l_Result : Integer;
//#UC END# *6700588601FB_66C47DB501FB_var*
begin
//#UC START# *6700588601FB_66C47DB501FB_impl*
 if (anID < 0) then
 begin
  Result := utNone;
  Exit;
 end;//anID < 0
 if (anID = 0) then
 begin
  Result := utNone;
  Exit;
 end;//anID = 0
 l_Result := Self.SearchFirstByKey(k2_tiUserType, anID, true);
 if (l_Result >= Ord(Low(Result))) AND (l_Result <= Ord(High(Result))) then
 begin
  Result := TUserType(l_Result);
  Exit;
 end;//l_Result >= Ord(Low(Result))
 {$IfNDef Linux}
 if (l_Result < 0) then
 begin
  l_Header := Self.DocumentHeaderData(anID);
  if (l_Header <> nil) then
   if (l_Header.AsObject <> nil) then
    if l_Header.AsObject.IsValid then
    begin
     l_Result := l_Header.AsObject.IntA[k2_tiUserType];
    end;//l_Header.AsObject.IsValid
 end;//Result < 0
 {$EndIf  Linux}
 if (l_Result < Ord(Low(Result))) OR (l_Result > Ord(High(Result))) then
  Result := utNone
 else
  Result := TUserType(l_Result);
 // - here we need to save Result to DocStream
//#UC END# *6700588601FB_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.UserTypeByID

function Tm3AttrIndexSearcher.NameByID(anID: Tm3DocID): Il3CString;
//#UC START# *67005EDA000A_66C47DB501FB_var*
//#UC END# *67005EDA000A_66C47DB501FB_var*
begin
//#UC START# *67005EDA000A_66C47DB501FB_impl*
 Result := Self.NameByInternalHandle(anID);
//#UC END# *67005EDA000A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.NameByID

function Tm3AttrIndexSearcher.AllDocuments: Il3RangeEnumerable;
 {* Все документы базы }
//#UC START# *670679BD01C7_66C47DB501FB_var*
{$IfDef m3UseTypeForAllDocuments}
var
 l_T : TDocType;
 l_Found : Il3RangeEnumerable;
 l_Dumper : Im3AttrIndexDumper;
 l_TimeStamp : TDateTime;
 l_Key : Tm3DocumentMapKey;
 l_C : Tm3DocumentsCache;
{$EndIf m3UseTypeForAllDocuments}
//#UC END# *670679BD01C7_66C47DB501FB_var*
begin
//#UC START# *670679BD01C7_66C47DB501FB_impl*
 {$IfDef m3UseTypeForAllDocuments}
 Result := nil;
 l_Key := Tm3DocumentMapKey_C(f_BaseName, 'AllDocuments');
 l_C := Tm3DocumentsCache.Instance;
 l_TimeStamp := l3MinDateTime;
 l_Dumper := Self.MakeDumper(k2_tiType, false);
 if (l_Dumper <> nil) then
 begin
  l_TimeStamp := l_Dumper.TimeStamp;
 end;//l_Dumper <> nil
 if l_C.Get(l_Key, l_TimeStamp, Result) then
  Exit;
 for l_T := Low(TDocType) to High(TDocType) do
 begin
  if (l_T <> dtRelText) then
  begin
   l_Found := Self.SearchByType(l_T);
   Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
  end;//l_T <> dtRelText
 end;//for l_T
 l_C.Put(l_Key, l_TimeStamp, Result);
 {$Else  m3UseTypeForAllDocuments}
 Result := Self.ConstDocuments;
 Result := Il3RangeEnumerable_JoinWithOther(Result, Self.ModifiedDocuments);
 {$EndIf m3UseTypeForAllDocuments}
//#UC END# *670679BD01C7_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.AllDocuments

function Tm3AttrIndexSearcher.IsRelated(anID: Tm3DocID): Boolean;
 {* Определяет - является ли документ справкой. }
//#UC START# *670CEB0301D0_66C47DB501FB_var*
//#UC END# *670CEB0301D0_66C47DB501FB_var*
begin
//#UC START# *670CEB0301D0_66C47DB501FB_impl*
 Result := TypeByID(anID) = dtRelText;
//#UC END# *670CEB0301D0_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsRelated

function Tm3AttrIndexSearcher.ConstDocuments: Il3RangeEnumerable;
 {* Документы из постояной части }
//#UC START# *670CED2A00D5_66C47DB501FB_var*

var
 l_L : Tm3RangedDocumentsList;

 function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
 begin//DoElement
  Result := true;
  if not IsSpravka(anIndex) then
   l_L.Add(anIndex);
 end;//DoElement

var
 l_DB : Im3DB;
 l_Main : Im3IndexedStorage;
 l_Key : Tm3DocumentMapKey;
 l_C : Tm3DocumentsCache;
//#UC END# *670CED2A00D5_66C47DB501FB_var*
begin
//#UC START# *670CED2A00D5_66C47DB501FB_impl*
 l_Key := Tm3DocumentMapKey_C(f_BaseName, 'ConstDocuments');
 l_C := Tm3DocumentsCache.Instance;
 if l_C.Get(l_Key, Result) then
  Exit;
 l_L := Tm3RangedDocumentsList.Create;
 try
  if (Self.f_DB <> nil) then
   l_DB := Self.f_DB
  else
   l_DB := Tm3DB.Make(f_BaseName);
  try
   if (l_DB <> nil) then
   begin
    l_Main := l_DB.MainStorage(m3_saRead);
    if (l_Main <> nil) then
    begin
     l_Main.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
    end;//l_Main <> nil
   end;//l_DB <> nil
  finally
   l_DB := nil;
  end;//try..finally
  Result := l_L.AsEnumerable;
  l_C.Put(l_Key, Result);
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *670CED2A00D5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ConstDocuments

function Tm3AttrIndexSearcher.ModifiedDocuments: Il3RangeEnumerable;
 {* Документы из переменной части }
//#UC START# *670CF2F2034E_66C47DB501FB_var*

var
 l_L : Tm3RangedDocumentsList;

 function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
 begin//DoElement
  Result := true;
  if not IsSpravka(anIndex) then
   l_L.Add(anIndex);
 end;//DoElement

var
 l_DB : Im3DB;
 l_Versions : Im3IndexedStorage;
//#UC END# *670CF2F2034E_66C47DB501FB_var*
begin
//#UC START# *670CF2F2034E_66C47DB501FB_impl*
 l_L := Tm3RangedDocumentsList.Create;
 try
  if (Self.f_DB <> nil) then
   l_DB := Self.f_DB
  else
   l_DB := Tm3DB.Make(f_BaseName);
  try
   if (l_DB <> nil) then
   begin
    l_Versions := l_DB.GetVersionsStorage(m3_saRead);
    if (l_Versions <> nil) then
    begin
     l_Versions.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
    end;//l_Versions <> nil
   end;//l_DB <> nil
  finally
   l_DB := nil;
  end;//try..finally
  Result := l_L.AsEnumerable;
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *670CF2F2034E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ModifiedDocuments

function Tm3AttrIndexSearcher.IsSpravka(anID: Tm3DocID): Boolean;
//#UC START# *670CF548034A_66C47DB501FB_var*
//#UC END# *670CF548034A_66C47DB501FB_var*
begin
//#UC START# *670CF548034A_66C47DB501FB_impl*
 Result := Self.IsRelated(anID);
//#UC END# *670CF548034A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsSpravka

function Tm3AttrIndexSearcher.DeletedDocuments: Il3RangeEnumerable;
 {* Удалённые документы }
//#UC START# *670CF7F601C4_66C47DB501FB_var*
//#UC END# *670CF7F601C4_66C47DB501FB_var*
begin
//#UC START# *670CF7F601C4_66C47DB501FB_impl*
 Result := Self.SearchByKey(k2_tiDeleted, 1{true}, false);
//#UC END# *670CF7F601C4_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.DeletedDocuments

function Tm3AttrIndexSearcher.AllRelated: Il3RangeEnumerable;
 {* Все справки }
//#UC START# *671022280052_66C47DB501FB_var*
{$IfDef m3UseTypeForAllRelated}
var
 l_Dumper : Im3AttrIndexDumper;
 l_TimeStamp : TDateTime;
 l_Key : Tm3DocumentMapKey;
 l_C : Tm3DocumentsCache;
{$EndIf m3UseTypeForAllRelated}
//#UC END# *671022280052_66C47DB501FB_var*
begin
//#UC START# *671022280052_66C47DB501FB_impl*
 {$IfDef m3UseTypeForAllRelated}
 l_Key := Tm3DocumentMapKey_C(f_BaseName, 'AllRelated');
 l_C := Tm3DocumentsCache.Instance;
 l_TimeStamp := l3MinDateTime;
 l_Dumper := Self.MakeDumper(k2_tiType, false);
 if (l_Dumper <> nil) then
 begin
  l_TimeStamp := l_Dumper.TimeStamp;
 end;//l_Dumper <> nil
 if l_C.Get(l_Key, l_TimeStamp, Result) then
  Exit;
 Result := Self.SearchByType(dtRelText);
 l_C.Put(l_Key, l_TimeStamp, Result);
 {$Else  m3UseTypeForAllRelated}
 Result := Self.ConstRelated;
 Result := Il3RangeEnumerable_JoinWithOther(Result, Self.ModifiedRelated);
 {$EndIf m3UseTypeForAllRelated}
//#UC END# *671022280052_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.AllRelated

function Tm3AttrIndexSearcher.ConstRelated: Il3RangeEnumerable;
 {* Справки в постоянной части }
//#UC START# *6710223B00EB_66C47DB501FB_var*

var
 l_L : Tm3RangedDocumentsList;

 function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
 begin//DoElement
  Result := true;
  if IsSpravka(anIndex) then
   l_L.Add(anIndex);
 end;//DoElement

var
 l_DB : Im3DB;
 l_Main : Im3IndexedStorage;
 l_Key : Tm3DocumentMapKey;
 l_C : Tm3DocumentsCache;
//#UC END# *6710223B00EB_66C47DB501FB_var*
begin
//#UC START# *6710223B00EB_66C47DB501FB_impl*
 l_Key := Tm3DocumentMapKey_C(f_BaseName, 'ConstRelated');
 l_C := Tm3DocumentsCache.Instance;
 if l_C.Get(l_Key, Result) then
  Exit;
 l_L := Tm3RangedDocumentsList.Create;
 try
  if (Self.f_DB <> nil) then
   l_DB := Self.f_DB
  else
   l_DB := Tm3DB.Make(f_BaseName);
  try
   if (l_DB <> nil) then
   begin
    l_Main := l_DB.MainStorage(m3_saRead);
    if (l_Main <> nil) then
    begin
     l_Main.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
    end;//l_Main <> nil
   end;//l_DB <> nil
  finally
   l_DB := nil;
  end;//try..finally
  Result := l_L.AsEnumerable;
  l_C.Put(l_Key, Result);
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *6710223B00EB_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ConstRelated

function Tm3AttrIndexSearcher.ModifiedRelated: Il3RangeEnumerable;
 {* Справки в переменной части }
//#UC START# *6710224F0192_66C47DB501FB_var*

var
 l_L : Tm3RangedDocumentsList;

 function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
 begin//DoElement
  Result := true;
  if IsSpravka(anIndex) then
   l_L.Add(anIndex);
 end;//DoElement

var
 l_DB : Im3DB;
 l_Versions : Im3IndexedStorage;
//#UC END# *6710224F0192_66C47DB501FB_var*
begin
//#UC START# *6710224F0192_66C47DB501FB_impl*
 l_L := Tm3RangedDocumentsList.Create;
 try
  if (Self.f_DB <> nil) then
   l_DB := Self.f_DB
  else
   l_DB := Tm3DB.Make(f_BaseName);
  try
   if (l_DB <> nil) then
   begin
    l_Versions := l_DB.GetVersionsStorage(m3_saRead);
    if (l_Versions <> nil) then
    begin
     l_Versions.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
    end;//l_Versions <> nil
   end;//l_DB <> nil
  finally
   l_DB := nil;
  end;//try..finally
  Result := l_L.AsEnumerable;
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *6710224F0192_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ModifiedRelated

function Tm3AttrIndexSearcher.IsAnnoOnly(anID: Tm3DocID): Boolean;
 {* Документ содержит ТОЛЬКО аннотацию. Несколько "техническая" ручка. Обычно такой ситуации не должно быть. Но пусть будет }
//#UC START# *671A1D4B0365_66C47DB501FB_var*
var
(* l_DB : Im3DB;
 l_Doc : Im3DBDocument;*)
 l_S : IStream;
//#UC END# *671A1D4B0365_66C47DB501FB_var*
begin
//#UC START# *671A1D4B0365_66C47DB501FB_impl*
 Result := false;
(* if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(anID);
  if (l_Doc <> nil) then*)
  begin
   l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
   //l_S := l_Doc.Open;
   try
    if (l_S = nil) then
    // - нет текста
    begin
     l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsAnno, 0);
     //l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
     // - костылик для аннотаций
     if (l_S <> nil) then
      Result := true;
    end;//l_S = nil
   finally
    l_S := nil;
   end;//try..finally
  end;//l_Doc <> nil
(* finally
  l_DB := nil;
 end;//try..finally*)
//#UC END# *671A1D4B0365_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsAnnoOnly

function Tm3AttrIndexSearcher.SearcheableAttributesNames: Il3StringsEnumerable;
 {* Имена атрибутов для поиска }
//#UC START# *671A2BE300C2_66C47DB501FB_var*
var
 l_L : Tl3StringList;
//#UC END# *671A2BE300C2_66C47DB501FB_var*
begin
//#UC START# *671A2BE300C2_66C47DB501FB_impl*
 {$IfDef FPC}
 if (Self.f_SearcheableAttributesNames <> nil) then
 begin
  Result := Self.f_SearcheableAttributesNames;
  Exit;
 end;//Self.f_SearcheableAttributesNames <> nil
 {$EndIf FPC}
 l_L := Tl3StringList.CreateSorted;
 try
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiType));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiUserType));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiRelExternalHandle));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiRelInternalHandle));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalHandle));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiMaxHyperlinkHandle));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiGroups));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAccGroups));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSources));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiTypes));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiClasses));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiKeyWords));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAnnoClasses));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNorm));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiWarnings));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiPrefix));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSource));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiTerritory));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiServiceInfo));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));

  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiFinish));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));

  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiDocID));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiDeleted));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalVerLink));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalNextVerLink));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiInternalVerLink));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiInternalNextVerLink));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSortDate));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPriority));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiUrgency));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPriceLevel));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiOldNSRC));

  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiGroups) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAccGroups) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSources) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiTypes) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiClasses) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiKeyWords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAnnoClasses) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNorm) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiWarnings) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiPrefix) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiTerritory) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiServiceInfo) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));

  Result := l_L.AsEnumerable;
  {$IfDef FPC}
  Self.f_SearcheableAttributesNames := Result;
  {$EndIf FPC}
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *671A2BE300C2_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearcheableAttributesNames

function Tm3AttrIndexSearcher.SearchByKeyEx(const anAttrID: array of Integer;
 aKey: Integer;
 aDirect: Boolean): Il3RangeEnumerable;
 {* Ищет по ключу "иерархического" атрибута. Т.е. указывается "путь" в EVD. Сродни cAtomEx }
//#UC START# *671A571F021D_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;
//#UC END# *671A571F021D_66C47DB501FB_var*
begin
//#UC START# *671A571F021D_66C47DB501FB_impl*
 Result := nil;
 if (Low(anAttrID) = High(anAttrID)) then
  Result := Self.SearchByKey(anAttrID[Low(anAttrID)], aKey, aDirect)
 else
 begin
  l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
  try
   if (l_Dumper <> nil) then
    Result := l_Dumper.ValuesByKey(aKey);
  finally
   l_Dumper := nil;
  end;//try..finally
 end;//Low(anAttrID) = High(anAttrID)
//#UC END# *671A571F021D_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeyEx

function Tm3AttrIndexSearcher.ContextAttributesNames: Il3StringsEnumerable;
//#UC START# *671CD7E302F5_66C47DB501FB_var*
var
 l_L : Tl3StringList;
//#UC END# *671CD7E302F5_66C47DB501FB_var*
begin
//#UC START# *671CD7E302F5_66C47DB501FB_impl*
 {$IfDef FPC}
 if (Self.f_ContextAttributesNames <> nil) then
 begin
  Result := Self.f_ContextAttributesNames;
  Exit;
 end;//Self.f_ContextAttributesNames <> nil
 {$EndIf FPC}
 l_L := Tl3StringList.CreateSorted;
 try
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumber));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumber) + '_' + Tk2Attributes.Instance.NameByID(k2_tiPublishedIn));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiName));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiShortName));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiComment));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNameComment));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiName) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiShortName) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
  Result := l_L.AsEnumerable;
  {$IfDef FPC}
  Self.f_ContextAttributesNames := Result;
  {$EndIf FPC}
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *671CD7E302F5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ContextAttributesNames

function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
 aKey: Tl3PrimString): Il3RangeEnumerable;
//#UC START# *672B855300BE_66C47DB501FB_var*
var
 l_Name : TFileName;
 l_Searcher : Tm4SearchEngine;
 l_Expr : Tm4WordExpression;
 l_List : Tl3LongintList;
 //l_Res : Tm4SearchResult;
//#UC END# *672B855300BE_66C47DB501FB_var*
begin
//#UC START# *672B855300BE_66C47DB501FB_impl*
 Result := nil;
 l_Name := f_BaseName;
 l_Name := l_Name + '#';
 l_Name := l_Name + Tk2Attributes.Instance.NameByID(anAttrID);
 l_Name := l_Name + '_' + '(s)';
 l_Name := l_Name + '#';
 l_Searcher := Tm4SearchEngine.Create(l_Name, true);
 try
  l_Expr := Tm4WordExpression.Create(aKey.AsWStr, false);
  try
   l_List := l_Searcher.Search(l_Expr, nil);
   //l_List := l_Searcher.Search(l_Expr, @l_Res);
   try
    if (l_List <> nil) then
    begin
     Result := Il3RangeEnumerable_FromIntegerEnumerable(l_List.AsEnumerable);
    end;//l_List <> nil
   finally
    //FreeAndNil(l_Res);
    FreeAndNil(l_List);
   end;//try..finally
  finally
   FreeAndNil(l_Expr);
  end;//try..finally
 finally
  FreeAndNil(l_Searcher);
 end;//try..finally
//#UC END# *672B855300BE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey

function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
 const aKey: AnsiString): Il3RangeEnumerable;
//#UC START# *672B85E20020_66C47DB501FB_var*
var
 l_S : Tl3PrimString;
//#UC END# *672B85E20020_66C47DB501FB_var*
begin
//#UC START# *672B85E20020_66C47DB501FB_impl*
 l_S := Tl3SharedConstString.CreateShared(aKey);
 try
  Result := SearchByKey(anAttrID, l_S);
 finally
  FreeAndNil(l_S);
 end;//try..finally
//#UC END# *672B85E20020_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey

function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
 const aKey: Tl3WString): Il3RangeEnumerable;
//#UC START# *672B8A5E00CE_66C47DB501FB_var*
var
 l_S : Tl3PrimString;
//#UC END# *672B8A5E00CE_66C47DB501FB_var*
begin
//#UC START# *672B8A5E00CE_66C47DB501FB_impl*
 l_S := Tl3SharedConstString.CreateShared(aKey);
 try
  Result := SearchByKey(anAttrID, l_S);
 finally
  FreeAndNil(l_S);
 end;//try..finally
//#UC END# *672B8A5E00CE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey

function Tm3AttrIndexSearcher.SearchByKeys(anAttrID: Integer;
 const aKeys: Il3StringsEnumerable): Il3RangeEnumerable;
//#UC START# *672B98710207_66C47DB501FB_var*
var
 l_It : Il3StringsEnumerator;
 l_Found : Il3RangeEnumerable;
//#UC END# *672B98710207_66C47DB501FB_var*
begin
//#UC START# *672B98710207_66C47DB501FB_impl*
 Result := nil;
 if (aKeys <> nil) then
 begin
  l_It := aKeys.GetEnumerator;
  if (l_It <> nil) then
  begin
   while l_It.MoveNext do
   begin
    l_Found := Self.SearchByKey(anAttrID, l_It.Current);
    if (l_Found <> nil) then
    begin
     Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
    end;//l_Found <> nil
   end;//while l_It.MoveNext
  end;//l_It <> nil
 end;//aKeys <> nil
//#UC END# *672B98710207_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeys

function Tm3AttrIndexSearcher.OutLinks(anID: Tm3DocID): Il3RangeEnumerable;
 {* Исходящие ссылки. Респонденты. }
//#UC START# *6733323601CE_66C47DB501FB_var*
//#UC END# *6733323601CE_66C47DB501FB_var*
begin
//#UC START# *6733323601CE_66C47DB501FB_impl*
 Result := Self.SearchByKey(k2_tiDocID, anID, true);
//#UC END# *6733323601CE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.OutLinks

function Tm3AttrIndexSearcher.InLinks(anID: Tm3DocID): Il3RangeEnumerable;
 {* Входящие ссылки. Корреспонденты. }
//#UC START# *6733327900E9_66C47DB501FB_var*
//#UC END# *6733327900E9_66C47DB501FB_var*
begin
//#UC START# *6733327900E9_66C47DB501FB_impl*
 Result := Self.SearchByKey(k2_tiDocID, anID, false);
//#UC END# *6733327900E9_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InLinks

function Tm3AttrIndexSearcher.SearchByNumberType(aNumberType: TDNType): Il3RangeEnumerable;
//#UC START# *6734A06300CD_66C47DB501FB_var*
//#UC END# *6734A06300CD_66C47DB501FB_var*
begin
//#UC START# *6734A06300CD_66C47DB501FB_impl*
 Result := Self.SearchByKeyEx([k2_tiNumANDDates, k2_tiType], Ord(aNumberType), false);
//#UC END# *6734A06300CD_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByNumberType

function Tm3AttrIndexSearcher.SearchByNumber(const aNumber: AnsiString): Il3RangeEnumerable;
//#UC START# *6735BE110028_66C47DB501FB_var*
//#UC END# *6735BE110028_66C47DB501FB_var*
begin
//#UC START# *6735BE110028_66C47DB501FB_impl*
 Result := Self.SearchByKey(k2_tiNumber, aNumber);
//#UC END# *6735BE110028_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByNumber

function Tm3AttrIndexSearcher.SearchBetweenKeys(const anAttrID: array of Integer;
 aLowKey: Integer;
 aHighKey: Integer;
 aDirect: Boolean): Il3RangeEnumerable;
//#UC START# *673F42AE005C_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;
 l_It : Im3AttrIndexElementEnumerator;
 l_Key : Integer;
 l_Values : Il3RangeEnumerable;
//#UC END# *673F42AE005C_66C47DB501FB_var*
begin
//#UC START# *673F42AE005C_66C47DB501FB_impl*
 Result := nil;
 Assert(aLowKey <= aHighKey);
 if (aLowKey = aHighKey) then
  Result := Self.SearchByKeyEx(anAttrID, aLowKey, aDirect)
 else
 if (aHighKey - aLowKey <= 200) then
 begin
  l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
  try
   if (l_Dumper <> nil) then
   begin
    for l_Key := aLowKey to aHighKey do
    begin
     l_Values := l_Dumper.ValuesByKey(l_Key);
     Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
    end;//for l_Key
   end;//l_Dumper <> nil
  finally
   l_Dumper := nil;
  end;//try..finally
 end//aHighKey - aLowKey <= 200
 else
 begin
  Assert(aLowKey < aHighKey);
  l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
  try
   if (l_Dumper <> nil) then
   begin
    l_It := l_Dumper.GetEnumerator;
    if (l_It <> nil) then
    begin
     while l_It.MoveNext do
     begin
      l_Key := l_It.Current.ID;
      if (l_Key < aLowKey) then
       continue
      else
      if (l_Key > aHighKey) then
       break
      else
      begin
       l_Values := l_It.Current.Values;
       Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
      end;//else
     end;//while l_It.MoveNext
    end;//l_It <> nil
   end;//l_Dumper <> nil
  finally
   l_Dumper := nil;
  end;//try..finally
 end;//aLowKey = aHighKey
//#UC END# *673F42AE005C_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchBetweenKeys

function Tm3AttrIndexSearcher.SearchByDates(aFrom: TStDate;
 aTo: TStDate): Il3RangeEnumerable;
//#UC START# *674046B103B1_66C47DB501FB_var*
//#UC END# *674046B103B1_66C47DB501FB_var*
begin
//#UC START# *674046B103B1_66C47DB501FB_impl*
 Result := Self.SearchBetweenKeys([k2_tiNumAndDates, k2_tiStart], aFrom, aTo, false);
//#UC END# *674046B103B1_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByDates

function Tm3AttrIndexSearcher.CommentByInternalHandle(anID: Tm3DocID): Il3CString;
//#UC START# *67484AAC0039_66C47DB501FB_var*
var
 {$IfDef m3UseHeaderForName}
  l_Header : Il3TagRef;
 {$Else  m3UseHeaderForName}
 //l_ID : Integer;
 l_DB : Im3DB;
 l_Doc : Im3DBDocument;
 l_S : IStream;
 l_Extractor : Tm3DocumentInfoExtractor;
 l_Reader : TevdNativeReader;
 l_WasAbortLoad : Boolean;
 l_IsAnno : Boolean;
 {$EndIf m3UseHeaderForName}
//#UC END# *67484AAC0039_66C47DB501FB_var*
begin
//#UC START# *67484AAC0039_66C47DB501FB_impl*
 Result := nil;
 Result := GetDocumentString(k2_tiNameComment, anID);
 if (Result <> nil) then
  Exit;
 Result := GetDocumentString(k2_tiComment, anID);
 if (Result <> nil) then
  Exit;
 {$IfDef m3UseHeaderForName}
 l_Header := Self.DocumentHeaderData(anID);
 if (l_Header <> nil) then
  if (l_Header.AsObject <> nil) then
   if l_Header.AsObject.IsValid then
   begin
    Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiNameComment]);
    WriteDocumentString(k2_tiNameComment, anID, Result);
    if not l3IsNil(Result) then
     Exit;
    Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiComment]);
    WriteDocumentString(k2_tiComment, anID, Result);
    if not l3IsNil(Result) then
     Exit;
   end;//l_Header.AsObject.IsValid
 {$Else  m3UseHeaderForName}
 l_WasAbortLoad := false;
 if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(anID);
  if (l_Doc <> nil) then
  begin
   l_IsAnno := false;
   l_S := l_Doc.Open;
   try
    if (l_S <> nil) then
    begin
     if (m2COMGetSize(l_S) <= 0) then
     begin
      Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
      Exit;
     end;//m2COMGetSize(l_S) <= 0
    end;//l_S <> nil
    if (l_S = nil) then
    begin
     l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
     // - костылик для аннотаций
     if (l_S <> nil) then
      l_IsAnno := true;
    end;//l_S = nil
    if (l_S <> nil) then
    begin
     l_Extractor := Tm3DocumentInfoExtractor.Create;
     try
      l_Reader := TevdNativeReader.Create;
      try
       l_Reader.Generator := l_Extractor;
       l_Reader.Filer.Mode := l3_fmRead;
       l_Reader.Filer.COMStream := l_S;
       try
        l_Reader.Start;
        try
         try
          l_Reader.Execute;
         except
          on El3AbortLoad do
          begin
           l_WasAbortLoad := true;
          end;//on El3AbortLoad
         end;//try..except
        finally
         try
          if not l_WasAbortLoad then
           l_Reader.Finish;
         except
          on Ek2TagGeneratorBadFinishCall do
          begin
           if not l_WasAbortLoad then
            raise;
          end;//on Ek2TagGeneratorBadFinishCall
         end;//try..except
        end;//try..finally
       finally
        l_Reader.Filer.COMStream := nil;
       end;//try..finally
      finally
       FreeAndNil(l_Reader);
      end;//try..finally
      if not l3IsNil(l_Extractor.DocNameComment) then
      begin
       if l_IsAnno then
        Result := l3Cat('Аннотация: ', l_Extractor.DocNameComment)
       else
        Result := l_Extractor.DocNameComment;
       Exit;
      end;//not l3IsNil(l_Extractor.DocNameComment)
      if not l3IsNil(l_Extractor.DocComment) then
      begin
       if l_IsAnno then
        Result := l3Cat('Аннотация: ', l_Extractor.DocComment)
       else
        Result := l_Extractor.DocComment;
       Exit;
      end;//not l3IsNil(l_Extractor.DocComment)
     finally
      FreeAndNil(l_Extractor);
     end;//try..finally
    end;//l_S <> nil
   finally
    l_S := nil;
   end;//try..finally
  end;//l_Doc <> nil
 finally
  l_DB := nil;
 end;//try..finally
 {$EndIf m3UseHeaderForName}
 //l_ID := Self.InternalHandleToExternalHandle(anID);
 //Result := nil;
//#UC END# *67484AAC0039_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.CommentByInternalHandle

function Tm3AttrIndexSearcher.CommentByID(anID: Tm3DocID): Il3CString;
//#UC START# *67484AC70170_66C47DB501FB_var*
//#UC END# *67484AC70170_66C47DB501FB_var*
begin
//#UC START# *67484AC70170_66C47DB501FB_impl*
 Result := Self.CommentByInternalHandle(anID);
//#UC END# *67484AC70170_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.CommentByID

function Tm3AttrIndexSearcher.Versions(anID: Tm3DocID): Il3IntegerEnumerable;
 {* Версии документа. Включая сам документ }
//#UC START# *67A089700158_66C47DB501FB_var*
var
 l_L : Tl3LongintList;
 l_Internal : Integer;
 l_External : Integer;
//#UC END# *67A089700158_66C47DB501FB_var*
begin
//#UC START# *67A089700158_66C47DB501FB_impl*
 l_L := Tl3LongintList.Create;
 try
  if (anID > 0) then
  begin
   l_L.Add(anID);
   // - добавляем себя
   l_Internal := anID;
   while true do
   // - тут ищем по прямому индексу
   begin
    l_External := Self.SearchFirstByKey(k2_tiExternalVerLink, l_Internal, true);
    if (l_External <= 0) then
     break;
    l_Internal := Self.ExternalHandleToInternalHandle(l_External);
    if (l_Internal <= 0) then
     break;
    if l_L.Has(l_Internal) then
    // - чтобы не зацикливаться
     break;
    l_L.Add(l_Internal);
   end;//while true

   l_Internal := anID;
   l_External := Self.InternalHandleToExternalHandle(l_Internal);
   while true do
   // - тут ищем по обратному индексу
   begin
    l_Internal := Self.SearchFirstByKey(k2_tiExternalVerLink, l_External, false);
    if (l_Internal <= 0) then
     break;
    if l_L.Has(l_Internal) then
    // - чтобы не зацикливаться
     break;
    l_L.Insert(0, l_Internal);
    l_External := Self.InternalHandleToExternalHandle(l_Internal);
   end;//while true
  end;//anID > 0

  Result := l_L.AsEnumerable;
 finally
  FreeAndNil(l_L);
 end;//try..finally
//#UC END# *67A089700158_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Versions

function Tm3AttrIndexSearcher.DocumentHeaderData(anID: Tm3DocID): Il3TagRef;
 {* Данные заголовка документа. Например ActiveIntervals и NumAndDates }
//#UC START# *67A3604E0118_66C47DB501FB_var*
var
 //l_ID : Integer;
(* l_DB : Im3DB;
 l_Doc : Im3DBDocument;*)
 l_S : IStream;
 l_Extractor : Tk2DocumentHeaderBuffer;
 l_Reader : TevdNativeReader;
 l_WasAbortLoad : Boolean;
 //l_IsAnno : Boolean;
//#UC END# *67A3604E0118_66C47DB501FB_var*
begin
//#UC START# *67A3604E0118_66C47DB501FB_impl*
 Result := nil;

 if (anID < 0) then
  Exit;

 if (anID = 0) then
  Exit;

 if (f_DocumentHeaderData <> nil) then
 begin
  if (f_DocumentHeaderData.AsObject <> nil) then
   if f_DocumentHeaderData.AsObject.IsValid then
   begin
    if (anID = f_PrevDocID) then
    begin
     Result := f_DocumentHeaderData;
     Exit;
    end;//anID = f_PrevDocID
   end;//f_DocumentHeaderData.AsObject.IsValid
 end;//f_DocumentHeaderData <> nil

 l_WasAbortLoad := false;
(* if (Self.f_DB <> nil) then
  l_DB := Self.f_DB
 else
  l_DB := Tm3DB.Make(f_BaseName);
 try
  l_Doc := l_DB.GetDocument(anID);
  if (l_Doc <> nil) then*)
  begin
   //l_IsAnno := false;
   l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
   //l_S := l_Doc.Open;
   try
    if (l_S <> nil) then
    begin
     if (m2COMGetSize(l_S) <= 0) then
     begin
      Result := nil;
      Exit;
     end;//m2COMGetSize(l_S) <= 0
    end;//l_S <> nil
(*    if (l_S = nil) then
    begin
     l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
     // - костылик для аннотаций
     if (l_S <> nil) then
      l_IsAnno := true;
    end;//l_S = nil*)
    if (l_S <> nil) then
    begin
     l_Extractor := Tk2DocumentHeaderBuffer.Create;
     try
      l_Reader := TevdNativeReader.Create;
      try
       l_Reader.Generator := l_Extractor;
       l_Reader.Filer.Mode := l3_fmRead;
       l_Reader.Filer.COMStream := l_S;
       try
        l_Reader.Start;
        try
         try
          l_Reader.Execute;
         except
          on El3AbortLoad do
          begin
           l_WasAbortLoad := true;
          end;//on El3AbortLoad
         end;//try..except
        finally
         try
          if not l_WasAbortLoad then
          begin
           if (l_Extractor.Root = nil) then
            l_Reader.Finish
           else
           begin
            Result := l_Extractor.Root.AsRef;
            try
             l_Reader.Generator := nil;
             l_Reader.Finish;
            except
             on Ek2TagGeneratorBadFinishCall do
             begin
             end;//on Ek2TagGeneratorBadFinishCall
            end;//try..finally
           end;//l_Extractor.Root = nil
          end;//not l_WasAbortLoad
         except
          on Ek2TagGeneratorBadFinishCall do
          begin
           if not l_WasAbortLoad then
            raise;
          end;//on Ek2TagGeneratorBadFinishCall
         end;//try..except
        end;//try..finally
       finally
        l_Reader.Filer.COMStream := nil;
       end;//try..finally
      finally
       FreeAndNil(l_Reader);
      end;//try..finally
      Assert(l_Extractor.Root <> nil);
      Result := l_Extractor.Root.AsRef;
      f_DocumentHeaderData := Result;
      f_PrevDocID := anID;
     finally
      FreeAndNil(l_Extractor);
     end;//try..finally
    end;//l_S <> nil
   finally
    l_S := nil;
   end;//try..finally
  end;//l_Doc <> nil
(* finally
  l_DB := nil;
 end;//try..finally*)
//#UC END# *67A3604E0118_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.DocumentHeaderData

function Tm3AttrIndexSearcher.SearchByType(aDocType: TDocType): Il3RangeEnumerable;
//#UC START# *67A48AB703AC_66C47DB501FB_var*
//#UC END# *67A48AB703AC_66C47DB501FB_var*
begin
//#UC START# *67A48AB703AC_66C47DB501FB_impl*
 Result := Self.SearchByKey(k2_tiType, Ord(aDocType), false);
//#UC END# *67A48AB703AC_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByType

function Tm3AttrIndexSearcher.SearchByMaskInKey(anAttrID: Integer;
 aMask: Integer): Il3RangeEnumerable;
 {* https://mdp.garant.ru/pages/viewpage.action?pageId=877071294 }
//#UC START# *67AB40480209_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;
 l_It : Im3AttrIndexElementEnumerator;
 l_Key : Integer;
 l_Values : Il3RangeEnumerable;
//#UC END# *67AB40480209_66C47DB501FB_var*
begin
//#UC START# *67AB40480209_66C47DB501FB_impl*
 Result := nil;
 l_Dumper := Self.MakeDumper(anAttrID, false);
 try
  if (l_Dumper <> nil) then
  begin
   l_It := l_Dumper.GetEnumerator;
   if (l_It <> nil) then
   begin
    while l_It.MoveNext do
    begin
     l_Key := l_It.Current.ID;
     if l3TestMask(l_Key, aMask) then
     begin
      l_Values := l_It.Current.Values;
      Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
     end;//l3TestMask(l_Key, aMask)
    end;//while l_It.MoveNext
   end;//l_It <> nil
  end;//l_Dumper <> nil
 finally
  l_Dumper := nil;
 end;//try..finally
//#UC END# *67AB40480209_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByMaskInKey

function Tm3AttrIndexSearcher.SearchByMaskInPriceLevel(aMask: Integer): Il3RangeEnumerable;
//#UC START# *67AB45FF015E_66C47DB501FB_var*
//#UC END# *67AB45FF015E_66C47DB501FB_var*
begin
//#UC START# *67AB45FF015E_66C47DB501FB_impl*
 Result := Self.SearchByMaskInKey(k2_tiPriceLevel, aMask);
//#UC END# *67AB45FF015E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByMaskInPriceLevel

function Tm3AttrIndexSearcher.IndexTimeStamp(anAttrID: Integer;
 aDirect: Boolean): TDateTime;
//#UC START# *68EA9627030F_66C47DB501FB_var*
var
 l_Dumper : Im3AttrIndexDumper;
//#UC END# *68EA9627030F_66C47DB501FB_var*
begin
//#UC START# *68EA9627030F_66C47DB501FB_impl*
 l_Dumper := Self.MakeDumper(anAttrID, aDirect);
 if (l_Dumper = nil) then
  Result := BadDateTime
 else
  Result := l_Dumper.TimeStamp;
//#UC END# *68EA9627030F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IndexTimeStamp

procedure Tm3AttrIndexSearcher.Cleanup;
 {* Функция очистки полей объекта. }
//#UC START# *479731C50290_66C47DB501FB_var*
//#UC END# *479731C50290_66C47DB501FB_var*
begin
//#UC START# *479731C50290_66C47DB501FB_impl*
 inherited;
 f_PrevDumper := nil;
 f_PrevAttr := -1;
 f_PrevDocID := -1;
 f_DocumentHeaderData := nil;
 f_PrevDirect := false;
 f_DB := nil;
 {$IfDef m3UseCacher}
 FreeAndNil(f_Cacher);
 {$EndIf m3UseCacher}
 FreeAndNil(f_DumpersCache);
 f_WasException := false;
//#UC END# *479731C50290_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Cleanup

procedure Tm3AttrIndexSearcher.ClearFields;
begin
 f_PrevDumper := nil;
 f_DocumentHeaderData := nil;
 f_DB := nil;
 inherited;
end;//Tm3AttrIndexSearcher.ClearFields

//#UC START# *66C47DB501FBimpl*
{$IfDef FPC}
class destructor Tm3AttrIndexSearcher.done;
begin
 f_SearcheableAttributesNames := nil;
 f_ContextAttributesNames := nil;
end;
{$EndIf FPC}

constructor Tm3AttrIndexSearcher.CreateFromDumper(const aDumper: Im3AttrIndexDumper;
 anAttrID: Integer;
 aDirect: Boolean);
begin
 f_PrevDumper := aDumper;
 f_PrevAttr := anAttrID;
 f_PrevDirect := aDirect;
 Create('');
end;

class function Tm3AttrIndexSearcher.MakeFromDumper(const aDumper: Im3AttrIndexDumper;
 anAttrID: Integer;
 aDirect: Boolean): Im3AttrIndexSearcher;
var
 l_Inst : Tm3AttrIndexSearcher;
begin
 l_Inst := Tm3AttrIndexSearcher.CreateFromDumper(aDumper, anAttrID, aDirect);
 try
  Result := l_Inst;
 finally
  FreeAndNil(l_Inst);
 end;//try..finally
end;

//#UC END# *66C47DB501FBimpl*


//#UC START# *66C47DB501FBforDiagramm*
(*
*)
//#UC END# *66C47DB501FBforDiagramm*

end.

Комментариев нет:

Отправить комментарий