DevCon for OS/2 - Developer Connection |
Operating systems: ArcaOS, eComStation, IBM OS/2 Warp |
|
|
Конфигурация: используйте XObject
Вступление:Эта статья посвящена некоторым аспектам работы с файлами конфигурации (ini-файлам, профилям, registry и прочим). На фоне стандартных (распространенных) методов организации файлов настроек (конфигурации) описывается разработанный для конкретной задачи (Буровой тренажер под OS/2), но имеющий вполне универсальное значение язык описания информационных (неисполняемых) объектов, а также средства (API) использования его в среде OS/2. Всем известны самые примитивные средства описания в виде пар "параметр=значение", столь любимые программистами в среде различных *ix (автор конечно же не поднимет руку на охаивание синтаксиса правил разбора в sendmail.cf - сами знаете за что), от которых не слишком далеко ушли структуры (синтаксис) файлов config.sys и autoexec.bat, возможное содержание которых достаточно хорошо всем знакомо. Ниже, в качестве примера, приведен кусок моего config.sys файла:
SET EPMPATH=C:\OS2\APPS;C:\opendoc\BIN; PROTECTONLY=NO SHELL=C:\OS2\MDOS\COMMAND.COM C:\OS2\MDOS FCBS=16,8 RMSIZE=640 DEVICE=C:\OS2\MDOS\VEMM.SYS DOS=LOW,NOUMB DEVICE=C:\OS2\MDOS\VXMS.SYS /UMB DEVICE=C:\OS2\MDOS\VDPMI.SYS DEVICE=C:\OS2\MDOS\VDPX.SYS DEVICE=C:\OS2\MDOS\VWIN.SYS DEVICE=C:\OS2\MDOS\VW32S.SYS Критиковать такой синтаксис несложно - он не позволяет синтаксически отделять описания разных объектов в одном файле. Зато его использование примитивно реализуется программно и во многих случаях оправдано. Но не во всех случаях возможно. Незначительное расширение такой синтаксис получил в ini-файлах от Windows X.XX (например 3.11) за счет введения секций. Именованные секции позволяют структурировать описания и формулировать запросы на элементы описания уже по двум параметрам "имя секции"-"имя параметра", что гораздо удобнее. Вот пример из файла SYSTEM.INI для WIN-OS2 сессии: [keyboard] subtype= type=4 keyboard.dll=kbdru.dll oemansi.bin=xlat866.bin typeofswitch=2 secondkeyb.dll=kbdusx.dll [boot.description] keyboard.typ=Enhanced 101 or 102 key US and Non US keyboards mouse.drv=Microsoft, or IBM PS/2 network.drv=No Network Installed language.dll=Russian system.drv=MS-DOS System codepage=866 woafont.fon=Russian (866) К недостаткам этого метода можно отнести синтаксическую неопределенность при работе с переменным числом записей в рамках одной секции и отсутствие вложенности секций, что иногда полезно т.к. не все информационные объекты линейны. Конечно, все это можно так или иначе реализовать программно, но эта реализация не будет естественным следствием идеи заложенной в синтаксис, а лишь свидетельством изворотливости программиста. Здесь следует отметить, что критика и далее будет бить по одной, двум позициям намечающим путь к совершенству, не более того. Следующим шагом в развитии идеи скриптов-описателей стали registry от Windows9X и далее, а также ini-файлы в OS/2. Привести их примеры не представляется возможным в силу их непечатности. Отметим следующее - они подразумевают древовидную структуру элементов (развитие идеи вложенности) и позволяют хранить объекты любого типа за счет введения бинарных объектов трактуемых теми, кто их использует. Для критики существующих реализаций подобного ресурса (в OS/2 он реализован в WINPRF.DLL) необходимо уточнить требования к синтаксису файлов конфигурации вообще. Как отмечалось ранее, взгляды, здесь излагаемые, стали результатом работы над подсистемой сопровождения сценариев имитатора-тренажера для буровиков. Сценарий для подобного тренажера содержит в себе все параметры конфигурирующие начальное состояние имитатора буровой установки и скважины, т.е. не многим отличается от файлов конфигурации. Он содержит внутри себя описание множества совершенно независимых объектов - описателей различного оборудования, описателей пород и их сочетания в геологический разрез, описания различных аномалий раскиданных по стволу скважины (чтобы обучаемому было не скучно) и т.д. и т.п. Подобные сценарии должны были создаваться самими пользователями продукта. Отсюда возникало требование интуитивной понятности для непрограммиста самих описаний и средств их создающих. Поскольку описания одного и того же оборудования могли встречаться во многих сценариях, они должны были описываться отдельно от самого сценария и входить в него в виде ссылки. Хорошо продуманный сценарий становится методическим материалом, поэтому должны быть предусмотренны средства его печати в удобном и красивом виде. Эти требования повлекли за собой создание цепочки информационно связанных между собой программных средств:
Изменение описания любого объекта влекло за собой необходимость коррекции программных реализаций объектов в цепочке следующих за ним, что, естественно, очень неудобно. Это неудобство проявилось, как только технологи-разработчики решили, что напрасно они когда-то упростили ряд описаний и не худо бы было их дополнить. Выше описанные проблемы со сценарием и являются, по мнению авторов, вполне содержательной критикой использования Profile API для сопровождения сложных конфигураций. Все это подвигло нас на формулировку следующих требований к концепции конфигурирования:
Эти требования и были реализованы в предлагаемой подсистеме работы с файлами конфигурации. Она предлагает синтаксис, реализацию базовых объектов, WPS-объект визуализации и печати, а также API для записи и чтении их программно.
Неформальное описание:Любой файл конфигурации рассматривается как набор полей некоторых типов. Типы могут быть простыми и составными. Таким образом сам файл конфигурации является объектом некоего составного типа (класса). Предлагается синтаксис описания подобных классов, который оперирует ключевыми словами, литералами и коментариями. Литералы используются такие-же как в C++ : \xx, \\,\n,\t, etc, а также специальные литералы %.
Комментарии обозначаются сочетанием символов //, /*,*/ и правила их
использования аналогичны С++. Система оперирует следующими объектами:
Далее приведены их описания в предлагаемом синтакисе :
Класс ReferenceField позволяет использовать множество настроек в одной, если, например, программный продукт состоит из множества задач, каждая из которых имеет свою настройку с индивидуальной и общей частью, и наоборот, если настройки одного объекта используютсп во множестве других.
Класс ObjectListField позволяет создавать списки ссылочных объектов, если, например, список персоналий в группе или список различных сетевых соединений характеризующихся своими настройками.
ObjectListField list = { // пример списка объектов ReferenceField заданного класса
При выводе диалога ObjectListField в списке выводятся
значения элемента string title описания объектов, либо, значение
элемента name|value, если в описание ссылочного объекта
введен элемент StringField name. ColorMaskField = { string title = "" int fcolor = 0 // цвет переднего плана int bcolor = 0 // цвет фона Также можно заметить, что существуют и предустановленные данные:
На основе этих простых и сложных типов можно создавать свои балозые классы описаний. DEngine drill={ string title="Забойный двигатель" DoubleField diam_zd ={ title="Диаметр заб.двигателя" coef=0.001 decimals=1 delta=0.1 min=30 max=400} DoubleField leng_zd ={ title="Длина заб.двигателя" coef=1 decimals=2 delta=0.01 max=50} DoubleField q_zd ={ title="Расход заб.двигателя" coef=1000 decimals=1 delta=0.1 min=30 max=400} DoubleField dens_zd ={ title="Плотность жидкости" coef=1000 decimals=2 delta=0.01 min=0.8 max=2.5} DoubleField loss_px_zd ={ title="Потери давления на холостом ходу" coef=98100 min=1 max=200} DoubleField freq_nx_zd ={ title="Частота вращения на холостом ходу" coef=0.01666 min=10 max=999} DoubleField loss_pt_zd ={ title="Потери давления при торможении" coef=98100 min=1 max=200} DoubleField moment_t_zd={ title="Тормозной момент" coef=10 min=1 max=1500} ComboToggleField drop ={ string title ="Тип двигателя" group elements = { string = "турбобур с постоянной линией" string = "турбобур с падающей линией" string = "объемный двигатель" } } } А так выглядит описание конкретного забойного двигателя (/* комментарий */ в первой строке необходим для интерпретации текста как XObject): /* XObject */ DEngine = { diam_zd = {value = 30.0000} leng_zd = {value = 0.0000} q_zd = {value = 30.0000} dens_zd = {value = 0.8000} loss_px_zd = {value = 1.0000} freq_nx_zd = {value = 10.0000} loss_pt_zd = {value = 1.0000} moment_t_zd = {value = 1.0000} drop = {value = 0} } Данный синтаксис показывает возможность изменения в каждом конкретном объекте и вспомогательных полей: min, max и прочих. Как восклицала Алиса Кэрола - "Кому нужна книжка без картинок и диалогов!"
group pages = { namedgroup = { // описание страницы диалога title = "%MajorTab" // символ % означает MajorTab Вот как выглядит (и что порождает) часть описания класса забойного двигателя (DEngine) относящаяся к диалогу:
Обратите внимание на вторую закладку - Тип. Она создается всегда и дает возможность явно задать класс объекта и выбрать способ сохранения (текстовый/двоичный). Последнее позволяет легко подправить руками любое поле объекта с помощью текстового редактора. И наоборот, любой объект может быть создан в текстовм редакторе, а затем сохранен в двоичном виде. В случае хранения в двоичном виде, объект сохраняет лишь отличия от базового описания. Остальные элементы своего описания он наследует, поэтому размер двоичного файла XObject существенно меньше текстового.
Для описания печати объекта используется аналогично организованная group
sections и вот, что получается при печати:
Печать объекта производится либо из его меню либо простым натаскиванием его иконы на икону (фолдер) принтера. Выше приведен пример печати одного объекта. Тот же объект, как ReferenceField внутри сценария, при печати имеет следующий вид:
Как все это использовать: Для использования предлагаемой системы работы с конфигурациями необходимо в корне или каталоге указанном переменной окружения AMT_PATH создать файл config.ini следующего содержания (на примере тренажера): /* AMT */ group Config = { string customer = "ЗАО АМТ" int loglevel = 0 // -1 полный отладочный вывод в файл \xobject.log // 0 выводить только сообщения обошибках // 1 выводить предупреждения исообщения об ошибках group classes = { string = "classes.ini" // описание общих классов (обпзательно) string = "common.ini" // описание другой группы общих классов string = "DSTclass.ini" // описание классов бурового тренажера string = "KRSclass.ini" // описание классов тренажера для капитального ремонта скважин } }
Этот файл используется WPS-объектом AMTWPSXObject реализующем диалоги и
печать объектов конфигурации.
Этот объект ассоциирован с расширением AMT. /*********************************************************************/ /* XObject registration utility*/ /*********************************************************************/ Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs' Call SysLoadFuncs Say 'AMT XObjects to be registered' rc=SysRegisterObjectClass('AMTWpsObject', 'amtwpso') if rc then say 'AMTWpsObject registered' else say 'AMTWpsObject cannot be registered'
Программирование с помощью API XObject: #include "common.h" XObject *o_config; // для сценария // функция инициализирует подсистему предустановленных классов XObject // и возвращает кол-во классов в библиотеках int InitXClasses(void) { char buf[256]="", *str; char *amtPath = getenv(AMT_PATH); int num=0; XOBJECT_INITIALIZE // загрузка библиотек классов buf[0] = 0; if (amtPath) strcat(buf, amtPath); strcat(buf, "\\"); strcat(buf, AMT_CONFIG); o_config = XObject::loadObject(buf); if (!o_config) return 1; o_config = o_config->getGroupElement("classes"); for (int i = 0; i Cледующие строки дают представление о получении значений некоторых элементов класса сценария для тренажера: { ... o_main=XObject::loadObject(file_name); // загрузка файла конкретного сценарияЭто был пример чтения конфигурации. Доступ к элементам конфигурации (параметрам) может
производится по именам полей класса (name), по составным именам ("name|subname"),
а также по их порядковым номерам в group. В приведенном выше описании
забойного двигателя величина параметра Методы XObject позволяют также и сохранять в них программно полученную информацию. Это дает удобство последующей визуализации, печати и унифицированного сопровождения. Для заинтересовавшихся приведем описание public объектов класса XObject class _Export XObject {Если вам понравилась описанная идея, вы можете скачать комплект для разработчика здесь. Если вы хотите поспорить или просто поговорить с автором, пишите сюда: Joseph Shrago -- e:mail : LFer at rambler dot ru |
|
|||||||||||||||||||||
(C) OS2.GURU 2001-2024