Реализация полнотекстового поиска с SoftInform Search SDK

Источник материала:  
16.07.2010 — Новости Hi-Tech

Что ж, мы разобрали подробно практически все темы, касающиеся поискового "движка" от компании SoftInform. Сегодня, наконец, завершим этот длинный, но, думаю, достаточно полезный для многих наших читателей разговор. И завершится он рассмотрением той темы, которую мы подняли в предыдущем номере - то есть, завершим рассмотрение процесса создания собственных источников документов.

Напомню, в прошлый раз мы с вами успели увидеть интерфейсные части классов, реализующих интерфейсы, необходимые для создания внешнего источника данных, с которым сможет взаимодействовать SoftInform Search SDK. Но, сами понимаете, что для того, чтобы все нормально работало, одних интерфейсных частей нам явно не хватит. Так что давайте взглянем на то, что у нас в терминах Delphi имеет название Implementation. Думаю, что в разборе всех методов всех классов, которые были приведены в предыдущей части нашего разговора о SoftInform Search SDK, нет такой уж суровой необходимости, потому что в противном случае рассказ об этом программном продукте грозит затянуться ещё.

Для начала посмотрим в сторону метода Configure класса TDSSampleClass. Думаю, что количество разнообразных параметров, которые передаются данному методу при его вызове, способно смутить того, кто еще не слишком привык к работе с SoftInform Search SDK. Но, думаю, что после того, как вы взглянете на листинг 1, все встанет на свои места.

Листинг 1

function TDSSampleClass.Configure(hWnd: LongWord;  var AParameters, ACaption, ADescription: WideString;  const ATranslate: ISITranslate): WordBool; var  AValue: string; begin  Result := False;  AValue := AParameters;  if InputQuery('Delphi Sample DocumentSource config',   'Enter count', AValue) then  begin   AValue := Trim(AValue);   if StrToIntDef(AValue, 0) <= 0 then    Exit;   Result := True;   AParameters := AValue;   ACaption := 'Delphi SampleDS';   ADescription := '';  end; end;

В общем-то, код приведенного листинга достаточно прост, но мы с вами все-таки разберем подробнее, что именно там написано. Для начала стоит отметить, что этот метод должен присутствовать в классе только в том случае, если он вообще в принципе конфигурируем, что задается с помощью свойства Configurable. Конечно, в реальных приложениях окно с настройками, которое будет показывать программа, будет заметно отличаться от того предельно простого диалога, который она показывает в примере, приведенном в листинге 1.

Значение, возвращаемое рассмотренной нами функцией, определяет, успешно завершился процесс конфигурации или же изменения, которые были внесены пользователем, не должны быть в конечном итоге приняты (соответственно, и возвращаемое значение равно или не равно нулю). Из параметров, передаваемых функции, наиболее интересен AParameters. Как написано в справке, это "String where document source should store all options and parameters that was configurated". То есть, проще говоря, именно этот параметр фактически и есть результат работы всей функции. Что касается параметра ATranslate, то это просто указатель на экземпляр объекта, реализующего интерфейс ISITranslate и используемого в случае необходимости перевода содержимого окна конфигурации параметров источника документов. В большинстве же случаев трогать его нет никакой необходимости.

Что ж, давайте теперь обратимся к классу TSampleDocument и рассмотрим его конструктор. Его увидеть вы можете в листинге под номером 2.

Листинг 2

constructor TSampleDocument.Create(const ADate: TDateTime;  AType: Integer); var  SILibTlb: ITypeLib;  AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word;  ATitle: string; begin  OleCheck(LoadRegTypeLib(LIBID_SILib, SILibMajorVersion,   SILibMinorVersion, 0, SILibTlb));  inherited Create(SILibTlb, ISIDocument);  FDate := ADate;  FType := AType;  DecodeDateTime(FDate, AYear, AMonth, ADay, AHour, AMinute, ASecond,   AMilliSecond);  ATitle := '';  case FType of   0: ATitle := Format('%d days', [DaysBetween(FDate, 0)]);   1: ATitle := Format('%d hours', [HoursBetween(FDate, 0)]);   2: ATitle := Format('%d minutes', [MinutesBetween(FDate, 0)]);  end;  FHTML := '<HTML><HEAD>'#13#10 + '<TITLE>' + ATitle + '</TITLE>'#13#10   + '</HEAD><BODY><HR>'#13#10 + Format('<B>YEAR:</B> <I>%d</I><BR>'#13#10,   [AYear]) + Format('<B>MONTH:</B> <I>%d</I><BR>'#13#10, [AMonth])   + Format('<B>DAY:</B> <I>%d</I><BR>'#13#10, [ADay]);  if AType > 0 then   FHTML := FHTML + Format('<B>HOUR:</B> <I>%d</I><BR>'#13#10, [AHour]);  if AType > 1 then   FHTML := FHTML + Format('<B>MINUTE:</B> <I>%d</I><BR>'#13#10, [AMinute]);  FHTML := FHTML + '<HR></BODY></HTML>'#13#10; end;

Возможно, сходу листинг может показаться перегруженным малозначительными деталями, особенно "наведением красоты" с помощью HTML-тегов, но на самом деле, мне кажется, здесь этот код не столько мешает, сколько позволяет более полно представить функционал данного метода в реальных приложениях, где, тем не менее, он наверняка будет значительно отличаться от нашего, если можно так сказать, модельного случая.

Для начала мы используем функции OleCheck и LoadRegTypeLib для того, чтобы загрузить библиотеку типов, необходимую для работы с SoftInform Search SDK, и в случае возникновения каких-то непредвиденных осложнений - вывести об этом осмысленную, с точки зрения пользователя, информацию об ошибке. После того, как библиотека типов таки загружена, мы вызываем "родительский" конструктор, ну а затем уже идет как бы логика работы класса, которая и будет отличаться от приведенной в реальных приложениях.

Теперь, я так думаю, будет не лишним поговорить об итераторах, которые мы также видели в прошлый раз. Здесь, опять-таки, рассмотрим именно конструктор, как наиболее ответственную часть всего класса, реализующего итератор для SoftInform Search SDK. Его вы можете увидеть в листинге 3.

Листинг 3

constructor TSampleDocumentItterator.Create(const ANow,  ASince: TDateTime; ACount, AType: Integer); var  SILibTlb: ITypeLib; begin  OleCheck(LoadRegTypeLib(LIBID_SILib, SILibMajorVersion,   SILibMinorVersion, 0, SILibTlb));  inherited Create(SILibTlb, ISIDocumentsItterator);  FItem := 0;  FNow := ANow;  FType := AType;  FCount := 0;  case FType of   0: begin      if DaysBetween(ANow, 0) <> DaysBetween(ASince, 0)       then FCount := ACount;      end;   1: begin      if HoursBetween(ANow, 0) <> HoursBetween(ASince, 0)       then FCount := ACount;      end;   2: begin      if MinutesBetween(ANow, 0) <> MinutesBetween(ASince, 0)       then FCount := ACount;      end;  end; end;

В самом начале этого листинга уже знакомый нам по прошлому листингу прием с загрузкой библиотеки типов и обработкой возможных ошибок, и с последующим вызовом inherited-конструктора. Затем идет инициализация всех возможных значений внутренних полей итератора (напомню, что посмотреть на список этих самых внутренних полей вы можете в предыдущей части нашего разговора о SoftInform Search SDK, где мы рассматривали интерфейс всех классов).

Напоследок просто необходимо сказать и о процедуре инициализации всего подключаемого к SoftInform Search SDK модуля. Для этого имеет смысл воспользоваться предоставляемой Delphi секцией инициализации модуля. Текст её (он, как видите, совсем небольшой - в буквальном смысле две строчки) вы можете увидеть в листинге 4.

Листинг 4

initialization TSIPluginClassFactory_Com.Create(ComServer, TDSSampleClass,  Class_DSSampleClass, 'DSSampleClass', 'Class of DSSample', ciMultiInstance, tmApartment);

Этот код содержит отсылку к одному достаточно простому классу, который мы с вами не разбирали в предыдущей статье, но который очень просто найти в примерах, идущих в стандартном комплекте поставки с SoftInform Search SDK, так что, думаю, в силу его простоты можно просто сказать, что это и есть инициализация COM-объектов, необходимых для взаимодействия нового источника документов и собственно поискового "движка".

Что ж, думаю, на этом разговор о SoftInform Search SDK можно считать успешно завершенным. Если кому-то он показался излишне подробным и затянутым, приношу свои извинения. Как, впрочем, и тем, кому, наоборот, показалось, что этот программный продукт заслуживает более подробного освещения на страницах "Компьютерных вестей". Так оно, конечно, и есть, но существует масса других интересных инструментов для разработчиков.

Еще раз хочу напомнить, что продукт SoftInform Search SDK имеет российские корни, а значит, если у вас возникнут какие-то вопросы по его использованию, на которые не смогут ответить ни примеры, ни справка (а я могу с уверенностью сказать, что так оно, скорее всего, и будет), вполне можно обращаться к создателям этого программного продукта с просьбой русским языком рассказать и показать, как его использовать. И тех трудностей, которые возникают по мере освоения этого продукта, не нужно пугаться - они неизбежны в любой сфере человеческой деятельности. Все эти сложности, которые на самом деле носят чисто технический характер, с лихвой искупаются теми преимуществами SoftInform Search SDK, которые я долго и методично перечислял в первых статьях, посвященных этому программному продукту. В общем, успешного вам освоения и внедрения SoftInform Search SDK в свои программные продукты!

Вадим СТАНКЕВИЧ,
dreamdrusch@tut.by

←Гуглофон Huawei U8230 как компьютер

Лента Новостей ТОП-Новости Беларуси
Яндекс.Метрика