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

Что ж, мы разобрали подробно практически все темы, касающиеся поискового "движка" от компании 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

Версия для печатиВерсия для печати

Номер: 

27 за 2010 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Владислав
Какая-то заказуха, уже который номер вижу эту статью, это что новый спонсор КВ?
Аватар пользователя Инкогнито
Не совсем так. Это старый спонсор Станкевича.
Аватар пользователя Al
А у меня вопросы к автору статьи:

1. На каком языке написаны листинги, приведенные в статье.

2. Где это может быть применено? В тексте я так этого и не увидел. Написано лишь "для полнотекстового поиска". Где? В программах, на сайте? На чем должны бить написаны эти программы?

Вообще создается впечатление, что статья написана для очень малой группы тех, кто понимает, о чём речь, или для тех, кто эту прогу (SDK, точнее) написал. И эти люди не являются читателями КВ.

Аватар пользователя Вадим Станкевич
1) Delphi. Это оговаривалось в первой статье цикла.

2) Это нужно было читать, опять-же, с первой статьи. А это уже седьмая.

3) Мой спонсор еще и а Apache, о проектах которого я писал шесть номеров подряд, и еще куча разных контор, о чьем софте я пишу. Да, и все мне платят. Пойду прокачусь на своем порше...

Аватар пользователя Инкогнито
когда будешь в порше садиться, не забудь штанину закатать, чтобы об цепь не испачкать
Аватар пользователя Al
Я не говорил ни разу про заказные статьи, я сказал, что эта тема интересна лишь малой части читателей. А вообще заказные статьи в таких газетах если и есть, то бюджет их не может быть большим, не та часть жизни. ))) Да и страна не та. )))
Аватар пользователя Первокурсник
а чем эта программа лучше гугловского поиска на своем компьютере - http://desktop.google.ru/ru/?ignua=1

поиск рулит!