=head1 NAME

PowerBuilder::ORCA - Perl API для работы с .pbl и объектами PowerBuider

=head1 SYNOPSIS

    use PowerBuilder::ORCA qw/:const/;

    #открываем ORCA-сессию
    my $ses=new PowerBuilder::ORCA(['d:\WORK\C\xs\PowerBuilder\ORCA\pbtest.pbl'],
        'd:\WORK\C\xs\PowerBuilder\ORCA\pbtest.pbl',
        'pbtest');

    #теперь можно выполнять манипуляции с объектами
    my $rc=$ses->Export("pbtest.pbl","f_is_dir",PBORCA_FUNCTION,$buf);

    my %h;
    $ses->EntryInfo("pbtest.pbl","f_db_connect",PBORCA_FUNCTION,\%h);

    #закрываем сессию
    $ses->Close();

=head1 DESCRIPTION

Этот модуль дает возможность использовать Powersoft Open Library
API (ORCA) из Perl. ORCA представляет собой API для доступа к функциям
PowerBuilder Library Manager. Используя ORCA можно программно выполнять
те же операции по управлению объектами и библиотеками, что и в Powerbuilder
Libarary painter. ORCA API было разработано для
производителей CASE средств, которым необходим программный доступ к файлам
.pbl для создания и модификации объектов PowerBuilder. ERwin и S-Designor
работают через ORCA.

Для запуска программ использующих ORCA API необходима pborcNN.dll, которая
входит в состав professional и enterprise версий PB, где NN - номер версии PB.
Для PB 6 - pborc60.dll.

Подробное описание идеологии и функций ORCA можно найти в документации по PB
(http://manuals.sybase.com/onlinebooks/group-pb/adt/orca/).

Соответствие имен функций ORCA API и функций предоставляемых ORCA.pm:

    ORCA API                        ORCA.pm
    ------------------------------  ------------------
    PBORCA_SessionClose             Close
    PBORCA_SessionGetError          GetError
    PBORCA_SessionOpen              new
    PBORCA_SessionSetCurrentAppl    SetAppl
    PBORCA_SessionSetLibraryList    SetLibList
    PBORCA_LibraryCommentModify     LibCommentModify
    PBORCA_LibraryCreate            LibCreate
    PBORCA_LibraryDelete            LibDel
    PBORCA_LibraryDirectory         LibInfo,LibDir,LibDirList
    PBORCA_LibraryEntryCopy         Copy
    PBORCA_LibraryEntryDelete       Del
    PBORCA_LibraryEntryExport       Export
    PBORCA_LibraryEntryInformation  EntryInfo
    PBORCA_LibraryEntryMove         Move
    PBORCA_CheckOutEntry            CheckOut
    PBORCA_CheckInEntry             CheckIn
    PBORCA_ListCheckOutEntries      ListCheckOutEntries
    PBORCA_CompileEntryImport       Import
    PBORCA_CompileEntryImportList   ImportList
    PBORCA_CompileEntryRegenerate   Regenerate
    PBORCA_ExecutableCreate         ExeCreate
    PBORCA_DynamicLibraryCreate     DllCreate
    PBORCA_ObjectQueryHierarchy     ObjectQueryHierarchy
    PBORCA_ObjectQueryReference     ObjectQueryReference

=head1 FUNCTIONS

Большинство функций возвращают ненулевой код ошибки в случае
неудачного завершения. Сообщение об ошибке можно получить ф-ей
GetError.

    Код  Описание
    ---  -----------------------------------
      0  Operation successful
     -1  Invalid parameter list
     -2  Duplicate operation
     -3  Object not found
     -4  Bad library name
     -5  Library list not set
     -6  Library not in library list
     -7  Library I/O error
     -8  Object exists
     -9  Invalid name
    -10  Buffer size is too small
    -11  Compile error
    -12  Link error
    -13  Current application not set
    -14  Object has no ancestors
    -15  Object has no references
    -16  Invalid # of PBDs
    -17  PBD create error
    -18  Source Management error

Для функций, в которые парметром передается тип объекта,
значением этого параметра должена быть одна из констант, описанных
в разделе L<Exported constants>.

=over 4

=head2 Начальная инициализация

Перед началом работы необходимо указать имя ORCA dll. Dll ORCA разных
версий PB имеют разные имена.

=item PowerBuilder::ORCA::LoadDll($dll_file);

=item PowerBuilder::ORCA::LoadDll();

Загружает для работы указанную dll. Если файл не существует и имя файла указано без пути
 - ищет его по PATH. Если имя файла не задано - проверяет
переменную среды ORCA_DLL, если она задана - загружает указаную в ней dll. Если
переменная среды не задана - ищет
по PATH dll версии 9,8,7,6 или 5 и загружает первую найденную. Если
ничего не помогло - умирает.

Имя загруженной dll сохраняется в переменной $PowerBuilder::ORCA::ORCA_Dll.

=head2 Управление сессией

=item $ses=new PowerBuilder::ORCA;

=item $ses=new PowerBuilder::ORCA(\@lib_list);

=item $ses=new PowerBuilder::ORCA(\@lib_list, $app_pbl, $app_name);

Создает новый объект, открывает ORCA сессию, возвращает указатель на объект.
Второй вариант вызова устанавливает также library list, последний
вариант устанавливает library list и текущее приложение. Часть функций ORCA требуют
установленного library list и текущего приложения (см. SetLibList и SetAppl).

=item $rc=$ses->SetLibList($pbl1,$pbl2,...)

Устанавливает library list для сессии. Library list используется для
поиска при разрешении ссылок м-ду объектами. При поиске библиотеки
просматриваются в заданном порядке. По возможности, следует указывать полный
путь к файлам. Ф-я может быть вызвана для сессии только один раз,
единственный способ изменить список, после того как он был установлен, -
закрыть текущую сессию и создать новую.

Следующие функции могут использоваться без установки library list:

    CommentModify
    LibCreate
    LibDel
    LibInfo,LibDir,LibDirList
    Copy
    Del
    Export
    EntryInfo
    Move
    CheckOut
    CheckIn

Функции выполняющие компиляцию и возвращающие информацию о связях м-ду
объектами требуют задания library list.

=item $rc=$ses->SetAppl($pbl,$obj)

Устанавливает текущее приложение. Перед вызовом этой ф-ии необходимо
установить library list ф-ей SetLibList(). Функции выполняющие
компиляцию и возвращающие информацию о связях м-ду объектами требуют
вызова этой ф-ии. Ф-я может быть вызвана для сессии только один раз.
Для переключения на другое приложение необходимо закрыть текущую
сессию и создать новую. Библиотеки, по возможности, следует указывать
с полным путем. Библиотека $pbl должна входить в Libarary list и ее
имя должно быть указано B<в точности> также, как при установке
Library list.

=item $ses->Close()

Закрывает сессию, освобождает ресурсы.

=item $errmsg=$ses->GetError()


Возвращает описание последней ошибки ORCA сессии. Может быть вызвана
в любой момент после того как какая-либо из ф-ий ORCA завершилась
с признаком ошибки. Все функции возвращают ненулевой код возврата
в случае ошибки. GetError возвращает полный текст сообщения об ошибке.
Если ошибок не было, возвращается пустая строка.

=back

=head2 Манипуляции объектами

=over 4

=item $rc=$ses->EntryInfo($pbl,$obj,$type,\%hbuf)

Возвращает информацию об объекте $obj типа $type из библиотеки $pbl. Информация
включает в себя комментарий, размер исходного текста, размер объекта и
время последнего изменения. Информация возвращается в хэше %hbuf. Ключи хэша
соответствуют параметрам структуры PBORCA_ENTRYINFO:

    Comments    Комментарий
    CreateTime  Время создания
    ObjectSize  Размер
    SourceSize  Размер исходного текста

Наблюдения: SourceSize ORCA возвращает некорректно.

=item $rc=$ses->Export($pbl,$obj,$type,$buf)

Помещает исходный текст объекта $obj типа $type из библиотеки pbl в буфер
$buf.

При экспорте исходного текста средствами PowerBuilder IDE в файл
помимо собственно исходного текста дописываются две строки заголовка.
Функция Export этого не делает, $buf содержит только исходный текст объекта.

=item $rc=$ses->Import($pbl,$obj,$type,$comment,$syntax,\$errbuf)

Импортирует исходный текст $syntax объекта $obj типа $type в библиотеку $pbl,
компилирует объект. $comment - комментарий к объекту (тот, что показывает
library painter). Если были ошибки компиляции $rc==-11, в $errbuf - сообщения
об ошибках. Библиотека $pbl должна входить в Libarary list и ее имя должно
быть указано B<в точности> также, как при установке Library list.

=item $rc=$ses->ImportList(\$errbuf,
        {
            Library=>'lib1.pbl',
            Name=>'f_func1',
            Type=>PBORCA_FUNCTION,
            Comment=>'comment 1',
            Syntax=>'source_code_of_f_func1'
        },
        {
            Library=>'lib2.pbl',
            Name=>'another_object_name',
            Type=>PBORCA_type_of_object,
            Comment=>'comment 2',
            Syntax=>'source_code_for_object'
        } ...
        );

Аналог Import, но за один вызов обрабатывается несколько объектов. Предназначена
для импорта нескольких взаимосвязанных объектов, например окна, его меню и
user_object-а, который они используют. Важно соблюдать правила последовательности
размещение информации об объектах в массивах. Предки должны размещаться
перед потомками, user_object-ы, на которые ссылаются другие объекты, должны
размещаться перед этими объектами. $errbuf - буфер для возврата информации об ошибках, может
быть скаляром или массивом (см. описание Regenerate).
Библиотека $pbl должна входить в Libarary list и ее имя должно быть указано
B<в точности> также, как при установке Library list.

=item $rc=$ses->Regenerate($pbl,$obj,$type,\$errbuf)

Компилирует объект $obj типа $type в библиотеке $pbl. Если были ошибки
компиляции $rc==-11, в $errbuf - сообщения об ошибках. $errbuf
может быть ссылкой на скаляр или ссылкой на массив. В первом случае
скаляр содержит все сообщения об ошибках, объединенные в строку.
Во втором случае возвращается массив сообщений, полученных от PB в хэшах,
повторяющих структуру pborca_comperr:

    Level
    MessageNumber
    MessageText
    ColumnNumber
    LineNumber

=item $rc=$ses->Copy($src_pbl,$dst_pbl,$obj,$type)

Копирует объект $obj типа $type из библиотеке $src_pbl в библиотеку $dst_pbl.

=item $rc=$ses->Move($src_pbl,$dst_pbl,$obj,$type)

Переносит объект $obj типа $type из библиотеке $src_pbl в библиотеку $dst_pbl.

=item $rc=$ses->Del($pbl,$obj,$type)

Удаляет объект $obj типа $type из библиотеки $pbl.

=back

=head2 Манипуляции библиотеками

=over 4

=item $rc=LibInfo($pbl,$comment,$n_obj)

Возвращает информацию о библиотеке $pbl. $comment - комментарий, $n_obj - число
объектов в библиотеке.

=item $rc=$ses->LibDir($pbl,\@objects);

Массив @objects заполняется информацией об объектах в библиотеке $pbl.
Каждый элемент @objects - ссылка на хэш со следующими ключами:

    Name    имя объекта
    Type    тип объекта
    Size    размер объекта
    CreateTime  время создания объекта
    Comment комментарий

=item =$ses->LibDirList($pbl[,$type])

Возвращает ссылку на массив с именами объектов заданного типа в библиотеке
$pbl. Если тип не задан - возвращаются имена всех объектов. Можно
непосредственно использовать в циклах:
    for my $obj_name ( LibDirList('lib1.pbl') ) {
        ...
    }

=item $rc=$ses->LibCreate($pbl,$comment)

Создает библиотеку с именем $pbl. Не требует установки library list.

=item $rc=$ses->LibDel($pbl)

Удаляет библиотеку с именем $pbl. Не требует установки library list.

=item $rc=$ses->LibCommentModify($pbl,$new_comment);

Устанавливает комментарий для библиотеки $pbl. Не требует установки
library list.

=back

=head2 VCS интерфейс

=over 4

=item $rc=$ses->CheckOut($obj,$type,$master_pbl,$work_pbl,$user_id,$copy)

Выполняет check out для объекта $obj типа $type из основной библиотеки
$master_pbl в рабочую библиотеку $work_pbl.  Значение $copy: 0 - установить
статус "check out" для объекта в master и work библиотеках, оставив объект
в work библиотеке без изменений; 1 - установить статус и скопировать
объект из master в work библиотеку. $user_id - id пользователя.

=item $rc=$ses->CheckIn($obj,$type,$master_pbl,$work_pbl,$user_id,$move)

Выполняет check in для объекта $obj типа $type из рабочей библиотеки
$work_pbl в основную библиотеку $master_pbl. $move: 0 - сбросить
check out статус объектов, не обновлять объект в master библиотеке и
не удалять копию объекта из work библиотеки; 1 - сбросить статус и
переместить копию объекта из work библиотеки в master. $user_id - id
пользователя, сделавшего check out.

=item $rc=$ses->ListCheckOutEntries($pbl,\@storage);

Помещает check out информацию об объектах в массив @storage. Каждый элемент
массива - хэш со следующими ключами:

    LibName имя библиотеки
    Name    имя объекта
    UserID  имя пользователя
    Mode    статус (s - source, r - registered, d - distanation)

Хэш соответствует структуре PBORCA_CHECKOUT.

=back

=head2 Ссылки и наследование

=over 4

=item $rc=$ses->ObjectQueryHierarchy($pbl,$obj,$type,\@storage);

Помещает информацию об иерархии предков объекта $obj типа $type из библиотеки $pbl
в массив @storage. Операция применима только к объектам типа window, menu
и user_object. Должен быть установлен library list, $pbl должна в него входить.

=item $rc=$ses->ObjectQueryReference($pbl,$obj,$type,\@storage);

Помещает информацию об объектах, на которые ссылается объект $obj типа $type
из библиотеки $pbl в массив @storage. Должен быть установлен library list,
$pbl должна в него входить. Каждый элемент массива - хэш со следующими ключами:

    LibName имя библиотеки
    Name    имя объекта
    Type    тип объекта
    RefType тип ссылки (o - open, s - simple) [недокументированно]

Хэш соответствует структуре PBORCA_REFERENCE.

=back

=head2 Построение исполняемых модулей

=over 4

=item $rc=$ses->DllCreate($pbl,$pbr,$options);

Создает PowerBuilder Dynamic Library (PBD) или PowerBuilder Dll из библиотеки
$pbl. $pbr - имя файла ресурсов или undef, если файла ресурсов нет. $options -
комбинация из флагов заданных в L<Параметры генерации кода>. Library list
и current application должны быть установлены. Если планируется
приложение с динамическими библиотеками, их необходимо построить перед
построением exe файла.

=item $rc=$ses->ExeCreate($exe,$ico,$pbr,\@pbd_flags,$options,\$errors);

Создает exe файл приложения в P-коде или в машинном коде. Для машинного кода
можно задавать тип оптимизации и включение отладочной информации. Приложение
создается в соответствии с library list. В массиве pbd_flags можно указать,
какие библиотеки будут динамическими и уже откомпилированы в pbd/dll, а какие
следует включить в exe файл. Library list и current application должны быть
установлены.

Параметры:
    $exe - имя исполняемого файла (не должно быть на диске, иначе - ошибка)
    $ico - иконка
    $pbr - файл ресурсов
    @pbd_flags - для каждой pbl в library list
        0 - включить объекты в .exe файл;
        1 - использовать уже построенную pbd/dll
        число элементов в массиве должно соответствовать числу
        библиотек в library list
    $options - параметры генерации кода (см. L<Параметры генерации кода>)
    $errors - буфер ошибок.

=back

=head1 Exported constants

Костанты экспортируются, если указан тэг const:

    use use PowerBuilder::ORCA qw/:const/;

=head2 Типы объектов

    PBORCA_APPLICATION
    PBORCA_DATAWINDOW
    PBORCA_FUNCTION
    PBORCA_MENU
    PBORCA_PIPELINE
    PBORCA_PROJECT
    PBORCA_PROXYOBJECT
    PBORCA_QUERY
    PBORCA_STRUCTURE
    PBORCA_USEROBJECT
    PBORCA_WINDOW

=head2 Параметры генерации кода

    PBORCA_P_CODE
    PBORCA_MACHINE_CODE
    PBORCA_MACHINE_CODE_NATIVE
    PBORCA_MACHINE_CODE_16
    PBORCA_P_CODE_16
    PBORCA_OPEN_SERVER
    PBORCA_TRACE_INFO
    PBORCA_ERROR_CONTEXT
    PBORCA_MACHINE_CODE_OPT
    PBORCA_MACHINE_CODE_OPT_SPEED
    PBORCA_MACHINE_CODE_OPT_SPACE
    PBORCA_MACHINE_CODE_OPT_NONE

=head1 HISTORY

=over 4

=item V0.03 10/11/2002

   	- полноценный тестовый пример, проверен на PB5, PB6 и PB8
	- доработки и исправления ошибок в EntryInfo,Import,ImportList
	- не была описана функция Del в документации
	- теперь модуль может работать с любой версией PB - dll ORCA линкуется 
	  динамически

=back

=head1 BUGS

Где-то внутри ORCA есть memory leak. В частности, этим грешна PBORCA_LibraryDirectory,
вызываемая с callback-ом. Соответственно, память утекает при вызове LibDir, хотя ее XS
код корректен, с точки зрения работы с памятью. Не думаю, что это создаст проблемы
в реальной жизни.

Все фунции были оттестированы но ошибки возможны, тем более, что это
первый релиз. Сообщайте по e-mail.

=head1 AUTHOR

Ilya Chelpanov, ilya@macro.ru, chelpanov@mail.ru
http://i72.narod.ru/

Этот модуль - свободное ПО. Вы можете использовать, распространять
и модифицировать ее на тех же условиях, что и сам Perl.

=head1 SEE ALSO

PowerBuilder online books, "ORCA Guide"
http://manuals.sybase.com/onlinebooks/group-pb/adt/orca/

=cut
