проект Zeta НЕФОРМАЛЬНАЯ документация

advertisement
Zeta 1.1, 1.6 Documentation
(проект Zeta НЕФОРМАЛЬНАЯ документация)
Update 2009: Создана версия для JRE 1.6 (см. добавления в конце)
Текущие версии документации и программных модулей находятся в системе контроля версий SVN:
http://zeta-cis.no-ip.org/svn/zeta_doc/ , логин/пароль test/test



Общие представления
Язык разметки интерфейсов
Макроподстановки и Zeta Script


Введение
Справочник
Построение новых конструкций (Java)
Распространенные ситуации и маленькие секреты
Настройка системы
Вопросы,примеры,известные баги
o
o
o
o
Данная система является мультиплатформенной средой для создания клиентских интерфейсов к базам
данных. Реализована эта среда на Java и поэтому теоретически работает на любой платформе, под
которую реализована JVM.
В данной документации приводятся примеры работы и настройки системы с СУБД Postgres 6.5
Общие представления
Задача решаемая данной системой - представление данных базы для пользователя в приемлемом виде и
возможность создавать/изменять/удалять данные. Например, бухгалтер работает с приходными и
расходными счет фактурами, тогда ему желательно видеть эти документы в виде максимально
приближенном к реальному.
Для построения таких форм служит язык разметки интерфейсов RML.
Но кроме предоставления доступа к данным через некоторую форму требуется реализовывать
некоторые процедурные расширения. Например, проверку на правильность введенных значений, в
простейшем случае, или поддерживать функциональность сложного иерархического справочника, в
более сложном.
Для этих целей служат макроподстановки и Script.
В системе как бы существует два слоя, несущих различную функциональную нагрузку. Слой
представления базы на клиенте (DATASTORE) и слой визуальных компонентов - форм которые видит и
с которыми работает пользователь. В DATASTORE описываются представления таблиц базы, и правила
сохранения измененных данных. Напротив, в визуальных компонентах указано, в какой DATASTORE
хранится редактируемая ими информация и как ее отображать.
Язык разметки интерфейсов.
Для описания интерфейса документа (далее просто документа) используется структурный язык
разметки следующего вида
KOI8_R
DOCUMENT
{FORM LEFT=1 RIGHT=1 WIDTH=200 HEIGHT=200
{FIELD ALIAS=FLD1 LEFT=10 TOP=10 WIDTH=100 HEIGHT=50 TARGET=A}
{FIELD ALIAS=FLD2 LEFT=10 TOP=100 WIDTH=100 HEIGHT=50 TARGET=B}
{DATASTORE ALIAS=DS
QUERY="select
'alfa'::varchar as a,
'beta'::varchar as b
from
dual"}
}
При открытии такого документа мы увидим два редактируемых поля, в первом будет текст alfa а во
втором beta. Теперь посмотрим, из чего состоит описание документа. Первая строчка - это кодировка, в
которой написан документ, вторая - тип документа (пока ни какого значения не имеет но необходима),
дальше идет иерархическое описание документа. В документе на верхнем уровне находится форма компонент FORM. У формы заданы размеры, местоположение и алиас, который позволяет обращаться к
одному компоненту из другого. В форме определены два поля и DATASTORE, которая содержит две
колонки а и b, которые являются результатом запроса к базе. В полях редактирования FLD1 и FLD2 в
атрибуте TARGET указано, из какого столбца строки результата запроса надо брать данные.
А вот более сложный, но интересный пример. Напишем документ, позволяющий выдавать любые
запросы к базе и просматривать результат запроса.
KOI8_R
DOCUMENT
{SPLITPANEL PERCENT = 30 TYPE = "HORIZONTAL"
{EDITOR
ALIAS = "ED"
FOREGROUND = "black"
BACKGROUND = "white"
EXP = "($try (
($DS@setsql ($ed@gettext))
($grid@retrieve))
$catch ('ANY') ())"
MULTIWINDOW = "YES"
FONT = "Courier,PLAIN,14"
}
{GRID
BUTTONBAR_FONT = "Courier,PLAIN,8"
ROWSIZE = 16
TITLEBAR_FONT = "Courier,PLAIN,8"
ALIAS = "grid"
FOREGROUND = "black"
BACKGROUND = "white"
FONT = "Times,PLAIN,12"
TITLEBAR_SIZE = 10
{DATASTORE
QUERY = "select
'empty'::varchar as empty
from
dual"
ALIAS = "DS"
}
}
}
Здесь пространство документа разделено на две части: в верхней находится редактор, в котором можно
набирать SQL запрос, а в нижней таблица с результатом запроса.
При выполнении запросов изменяется структура таблицы. Запросы выполняются через всплывающее
меню компонента EDITOR через пункт выполнить.
Этот пункт запускает на выполнение скрипт, написанный в атрибуте EXP, который устанавливает в
DATATASTORE новый запрос и вызывает команду перезачитывания данных, в результате чего
DATASTORE, а соответственно и таблица, содержат данные указанного запроса. Вообще документ
может содержать следующие компоненты
Справочник RML
Типичные выражения
<action>
<command>
<command>
<command>
<args>
<args>
<args>
<args>
<operation>
<op>
<expression>
<charset>
<container>
<color>
"<command>;<command>;..."
open[new][over] Doc.rml [<args>]
create[new][over] Doc.rml [<args>]
retrieve alias
<string>,[<args>]
<int>,[<args>]
<ident>,[<args>]
~alias~,[<args>]
"<op>;<op>;..."
alias=<expression>
as is (Zeta SCRIPT)
{CP1251,KOI8_R,CP866,ISO8859_5,...}
{FORM,SCROLLPANE,SPLITPANEL}
{#RGB, #RRGGBB, white, black,
lightgray, gray, blue, red, green, yellow}
Объекты RML.
BUTTON
CHART
CHECKBOX
CHECKGROUP
COLONTITUL
COLUMN
DATASTORE
DSCOLLECTION
EDITOR
FIELD
FORM
GRID
GROSSTAB
GROUP
GROUPREPORT
ITEM
LABEL
LINE
MENU
RADIOBUTTON
RADIOGROUP
REPORT
REPORTGRID
REPORTHEADER
REPORTTRAILER
SCROLPANEL
Кнопка
График
Переключатель
Группа переключателей
Колонтитул отчета
Столбец таблицы
Объект читающий/пишущий из базы данных, а также
хранящий выборку
Объект, собирающий Datastore, и обеспечивающий все
действия в базе в пределах одной транзакции.
Многострочный редактор с возможностью добавления
закладок
Редактируемое поле формы
Форма ввода
Таблица
Объект, потомок Datastore, на основе исходного
двумерного массива строит GrossTab
Объект, задающий группировку в отчетах
Объект, потомок Datastore, отличается от нее тем, что
хранит не двумерный массив, а дерево
Элемент меню
Нередактируемое поле формы
Линия в отчете
Всплывающее меню
Переключатель
Группа переключателей
Объект - отчет
Таблица отчета
Заголовок группы отчета
Trailer группы отчета
Контейнер, обеспечивающий прокрутку (скроллинг)
SPLITPANEL
TABSET
TOOLBAR
TREEVIEW
TVNAV
помещенного в него компонента
Контейнер, делящий свое пространство на две части по
горизонтали или по вертикали
Объект-контейнер с закладками
Объект содержащий в себе кнопки
Дерево
Специальный объект
Отношения объектов RML
Компонент
BUTTON
CHART
CHECKBOX
CHECKGROUP
COLONTITUL
COLUMN
DATASTORE
DSCOLLECTION
EDITOR
FIELD
FORM
GRID
GROSSTAB
GROUP
GROUPREPORT
ITEM
LABEL
LINE
MENU
RADIOBUTTON
RADIOGROUP
REPORT
REPORTGRID
REPORTHEADER
REPORTTRAILER
SCROLPANEL
SPLITPANEL
TABSET
TOOLBAR
TREEVIEW
DEFAULT SECTION
{Cp1251,KOI8-R, }
DOC
Может содержать
Ничего
DATASTORE
Ничего
CHECKBOX
FIELD, LABEL
DATASTORE
DATASTORE, GROUPREPORT
Ничего
Ничего
Ничего
FIELD, DATASTORE, MENU, RADIOGROUP,
CHECKGROUP, LABEL, BUTTON
COLUMN, DATASTORE, MENU
DATASTORE
REPORTHEADER, REPORTTRAILER, GROUP,
REPORTGRID
DATASTORE, GROUPREPORT
Ничего
Ничего
Ничего
ITEM, MENU
Ничего
RADIOBUTTON
REPORTHEADER, REPORTTRAILER, GROUP,
REPORTGRID, COLONTITUL, DATASTORE,
GROUPREPORT
COLUMN
FIELD, LABEL
FIELD, LABEL
SCROLLPANEL,
SPLITPANEL,FORM,GRID,TABSET,TREEVIEW
SCROLLPANEL,
SPLITPANEL,FORM,GRID,TABSET,TREEVIEW
SCROLLPANEL,
SPLITPANEL,FORM,GRID,TABSET,TREEVIEW
BUTTON
GROUPREPORT
кодировка документа
зарезервированное слово
document_title=название документа
style = файл стиля, применяемый к
данному документу
buttons = "d_ok,cancel,save,new,hand_ok"
Название, отображаемое в окне
заголовка
список типов кнопок, который будет
иметь документ
 d_ok кнопка закрыть - закрывает
документ с сохранением
 cancel кнопка отказ - закрывает
документ без сохранения
 save кнопка сохранить сохраняет документ
 new кнопка новый - создает
новый документ
 hand_ok кнопка применить передает выделенные в
справочнике строки в документ
BUTTON
LABEL
ACTION
AACTION
BACKGROUND
FONT
FOREGROUND
Надпись на кнопке
Action,
Выражение калькулятора, выполняемое
при нажатии кнопки
Цвет фона
Шрифт
Цвет текста
Методы - нет
CHART
ALIAS
STYLE
LEFT
TOP
WIDTH
FREE_SPACE
LEFT_OFFSET
BOTTOM_OFFSET
XCOLUMN
LEGENDA_X_OFFSET
LEGENDA_X_ASCEND
LEGENDA_Y_ASCEND
DATACOLUMNS
LEGENDA
LEGENDA_Y_OFFSET
HEIGHT
Имя объекта
Стиль графика (график – 0,
гистограмма – 1, …)
Координата х левого верхнего угла
Координата у левого верхнего угла
ширина
Пространство между столбцами
гистограммы
Смещение круговой диаграммы по х
Смещение круговой диаграммы по у
Индекс столбца выборки, размещаемы
по х
Смещение легенды по х
Отступ значений от границы легенды
по х
Отступ значений от границы легенды
по у
Индексы столбцов выборки, которые
будут использоваться при построении
диаграммы
{0,1} – определяет есть легенда или нет
Смещение легенды по у
высота
Методы -нет
CHECKBOX
ONVALUE
CHECK
LABEL
OFFVALUE
Методы
GetValue
Значение, возвращаемое при
положении «включен»
{yes, no} начальное положение
выключателя
Надпись около выключателя
Значение, возвращаемое при
положении «выключен»
Возвращает значение, ассоциированное
с данным положением переключателя
CHECKGROUP
ALIAS
LEFT
TOP
BG_COLOR
ALIGNMENT
Имя объекта
Координата x левого верхнего угла
Координата у левого верхнего угла
Цвет фона
{horizontal, vertical} расположение
переключателей в группе
Методы - нет
COLONTITUL
TYPE
{TOP, BOTTON} тип колонтитула
Методы – нет
COLUMN
font_face = <string>
font_family = {0,1,2,3}
font_size = <int>
font_color = <color>
title_font_face = <string>
title_font_family = {0,1,2,3}
title_font_size = <int>
title_font_color = <color>
bg_color = <color>
visible = {YES,NO}
exp = <operation>
dep = <list>
target = <alias>
value = <string>
начертание
тип шрифта
0 – PLANE
1 - BOLD
2 – ITALIC
3 - BOLD&ITALIC
размер шрифта
цвет шрифта
начертание
тип шрифта
размер шрифта
цвет шрифта
цвет фона
виден ли объект
вычисляемое поле
список алиасов объектов
зависимых от данного
имя ассоциированного объекта
в DATASTORE
значение по умолчанию
edit = <action>
editexp = <operation>
HALIGNMENT={LEFT,RIGHT,CENTER}
VALIGNMENT={TOP,BOTTOM,CENTER}
size = <int>
editable =
{HAND,HANDBOOK,READONLY,LIST,ALL}
title = <string>
действия для события
редактирования
выражение, вычисляемое после
события редактирования
выравнивание по горизонтали
выравнивание по вертикали
ширина столбца
тип допустимого
редактирования
название столбца
Примечания к свойству target.
SQL-парсер в ядре несовершенен.
Пример:
select distinct bank.id_bank, bank.name_bank
from settlement_account, bank
...
Названием столбца становится не "BANK.ID_BANK", а "DISTINCT BANK.ID_BANK".
Особенно несовершенство парсера заметно при использовании сложных названий
столбцов - функции, скобки, апострофы. Если нужно взять в грид данные из
столбца датастори примерно с таким именем: to_char(тырыпыры,
'dd.mm.yyyy'), то нужно использовать select from select, чтобы имя во
внешнем запросе было простым. Можно использовать и те имена, которые
отображаются при распознавании запроса в логе:
dbi.DATASTORE.tables query= DISTINCT BANK.ID_BANK, BANK.NAME_BANK
dbi.DATASTORE.tables colnam= DISTINCT BANK.ID_BANK
dbi.DATASTORE.tables colnam= BANK.NAME_BANK
Использование кавычек в target нужно, если решишь использовать плохо
распознанное парсером название столбца. Например при названии столбца
util.get(bank.name_bank) распознан он будет как
dbi.DATASTORE.tables colnam= UTIL.GET(BANK
И именно "UTIL.GET(BANK" надо поставить в свойство target, чтобы данные
передались в грид.
Методы - нет
DATASTORE
Alias
Query
Unique
Default
head
selaction
Имя объекта
Запрос, выполняемый объектом
Список столбцов, используемый в
качестве первичных ключей таблиц
Выражение калькулятора, выполняемое
при создании новой строки в объекте
{yes, no} определяет уровень объекта
Выражение калькулятора, выполняемое
SORTORDER
Методы
ITERATOR
SETVALUE
GETVALUE
RETRIEVE
SORT
CLEARSORT
FILTER
SUM
SIZE
UPDATE
NEWROW
CLEAR
SETSQL
DELROW
GETSQL
GETCURROW
SETCURROW
FASTSETCURROW
NOTIFYVIEWS
ADDCOLUMN
при смене текущей строки в объекте
Порядок сортировки
Возвращает итератор для объекта
Принимает индекс столбца и новое
значение, которое устанавливает в
текущую строку
Принимает индекс столбца, возвращает
значение этого столбца из текущей
строки
Выполняет запрос и заполняет объект
данными
Устанавливает параметры сортировки
и сортирует строки объекта
Сбрасывает сортировку объекта
Принимает выражение, возвращает
объект DATASTORE, все строки
которого удовлетворяют этому
выражению
Принимает индекс столбца, возвращает
сумму элементов в этом столбце
Возвращает количество строк
Сбрасывает изменения, накопленные в
объекте в базу данных
Добавляет новую строку в
DATASTORE
Удаляет из объекта все строки
Устанавливает запрос
Принимает номер строки и удаляет эту
строку
Возвращает запрос
Возвращает индекс текущей строки
Устанавливает текущую строку
(выполняя при этом скрипт selaction)
Устанавливает текущую строку (не
выполняя при этом скрипт selaction)
Уведомляет визуальный объект,
владеющий DATASTORE о том, что
данные объекта изменились
Принимает тип столбца и добавляет в
DATASTORE новый столбец
указанного типа
Пример
{datastore
query="select clbank.name_bank,
clbank.addr_bank,
clbank.id_clbank,
clbank.id_client,
clbank.bik_bank,
clbank.corr_account,
clbank.ku_bank
from clbank,client
where clbank.id_client = client.id_client and
clbank.id_client=~cl_head.client.id_client~"
alias=banks
editable = yes
default= "clbank.id_client=~cl_head.client.id_client~"
unique = "('clbank','clbank.id_clbank')"
}
В свойстве query определен запрос к БД, но не только. Дело в том, что к элементам DATASTORE
можно обращаться - их можно считывать и в них можно записывать значения. Любое обращение к
объекту в нашей системе возможно только по имени. Соответственно, если имя DATASTORE дс, то
обращение к ее элементу это дс.элемент. Тут возникает два вопроса.
Так как выборка, по сути, представляет собой двумерный массив, то, очевидно, в DATASTORE есть
текущая строка, кроме того, именем элемента строки (поля) DATASTORE будет имя поля, указанного в
запросе.
Например, в приведенной выше DATASTORE есть поля clbank.name_bank, clbank.addr_bank,
clbank.id_clbank, clbank.id_client, clbank.bik_bank, clbank.corr_account, clbank.ku_bank, но нет поля
ku_bank или id_client. Непонимание этого факта, как показала практика, порождает много ошибок,
которые трудно обнаружить.
Кроме того, обратите внимание на запись запроса. Все поля в нем указаны в нотации
<table_name>.<field_name>, и это не случайно. Дело в том, что когда приходит время сбрасывать
данные в базу DATASTORE необходимо знать, а к какой, собственно, таблице относится данный
столбец ( напомню, что в запросе могут соединяться несколько таблиц в которых есть столбцы С
ОДИНАКОВЫМИ ИМЕНАМИ ) никакого удовлетворительного способа кроме синтаксического
анализа запроса попросту не существует! Поэтому если вы хотите, чтобы измененный вами в
DATASTORE столбец попал в нужную таблицу, настоятельно РЕКОМЕНДУЕТСЯ указывать полные
имена столбцов.
Итак, свойство query определяет запрос, который будет выполнен при загрузке документа. Несложно
заметить, что в запросе выбираются данные из двух таблиц ( clbank,client), но при синхронизации
обьекта с базой реально будет изменена только одна таблица-'clbank', поскольку только она перечислена
в свойстве unique.
Рассмотрим свойство unique подробнее. Это свойство служит для указания списка 'Updateable' таблиц и
указания первичного ключа для каждой из таких таблиц (поскольку, не зная первичного ключа
таблицы, невозможно изменять конкретные строки данной таблицы). Формат свойства в общем виде
таков
('<table_name>','pk_column1',...,'pk_columnn')......('<table_name>','pk_column1',...,'pk_columnn').
Необходимо заметит, что все столбцы, перечисленные в unique, должны быть выбраны в операторе
SELECT свойства query.
Перейдем теперь к свойству default. Фактически, это свойство описывает, каким образом формировать
вновь введенную строку DATASTORE. Нужно это вот зачем представьте себе, что у вас есть документ,
в котором есть два DATASTORE ( например Шапка и Спецификация ) причем одна из DATASTORE
описывает главную таблицу, а вторая - подчиненную.
Очевидно, что для корректной записи описанной системы в базу, необходимо во всех вновь введенных
строках второй DATASTORE сформировать правильное значение внешнего ключа, указывающее на
первичный ключ строки первого DATASTORE. Как это сделать? Использовать default.
Default="fk=~ds.pk~,fildn=~param~...."
где fk - имя поля внешнего ключа в нашей DATASTORE, а pk- имя поля первичного ключа в
DATASTORE ds.
Итак, свойство default описывает, какие значения подставлять в поля вновь введенной строки. alias имя объекта, свойство очень важное, поскольку позволяет по этому имени производить операции с
объектом DATASTORE без имени не собирается в коллекцию
head - определяет порядок, в котором будут выполняться действия с объектом. Например, в документе
несколько DATASTORE, но одно из них самое важное, тогда insert/update/delete/retrieve будут делаться
сначала для него, а затем для всех остальных. Это бывает просто необходимо при работе с системами,
состоящими из одной основной таблицы и нескольких подчиненных.
selaction - описывает действие, которое выполняется при изменении в DATASTORE текущей строки
Это нужно, если, например, нужно при хождении по одному DATASTORE, перезачитывать другое
DATASTORE.
DSCOLLECTION
ALIAS
ALIASES
INITQUERY
SEQQUERY
SEQNAMES
INITACTION
Имя объекта
Алиасы,, присваемые столбцам
выборки INITQUERY
Запрос, выполняемый при СОЗДАНИИ
документа
Запрос, выполняемый КАЖДЫЙ РАЗ
при обращении к элементам
SEQNAMES
Алиасы,, присваемые столбцам
выборки SEQQUERY. Примечание:
после запятой не должно быть пробела,
есть некий глюк в ядре. Т.е. не
seqnames = "date,_user", а seqnames =
"date,user"
Выражение калькулятора, выполняемое
при СОЗДАНИИ документа
Методы
DELSTORE
ADDSTORE
Принимает объект DATASTORE и
удаляет его из коллекции, что
позволяет оперировать с этим объектом
в рамках особой транзакции
Принимает объект DATASTORE и
встраивает его в коллекцию. С этого
момента все операции с этим объектом
происходят в рамках общей транзакции
документа. Позволяет динамически
создавать объекты DATASTORE и
оперировать с ними как с объектами,
описанными в RML.
EDITOR
ALIAS
TABSELEXP
MULTIWINDOW
Методы
SETTEXT
Имя объекта
Выражение калькулятора, выполняемое
при смене текущей закладки
{yes, no} определяет возможность
создания в текущем редакторе новых
закладок (окон)
Принимает строку и устанавливает ее в
GETTEXT
ADDTAB
DELTAB
SETCURRENTTAB
GETCURRENTTAB
SETTABLABEL
качестве редактируемой для текущей
закладки
Возвращает редактируемую строку
принимает номер закладки и удаляет ее
Принимает номер закладки и делает ее
текущей
Возвращает номер текущей закладки
Принимает строку, которую
устанавливает в качестве названия
текущей закладки
FIELD
{left,top} = <int>
{width,height} = <int>
font_face = <string>
font_family = {0,1,2,3}
font_size = <int>
font_color = <color>
bg_color = <color>
visible = {YES,NO}
exp = <operation>
dep = <list>
target = <alias>
value = <string>
edit = <action>
editexp = <operation>
верхний левый угол
ширина, высота
начертание
тип шрифта
0 - PLANE
1 - BOLD
2 - ITALIC
3 - BOLD&ITALIC
размер шрифта
цвет шрифта
цвет фона
виден ли объект
вычисляемое поле
список алиасов объектов, зависимых от
данного
имя ассоциированного объекта в
DATASTORE
значение по умолчанию
действия для события редактирования
выражение, вычисляемое после
события редактирования
Методы - нет
FORM
ALIAS
LEFT
TOP
WIDTH
HEIGHT
FONT_FACE
FONT_FAMILY
FONT_SIZE
FONT_COLOR
BG_COLOR
Методы - нет
Имя объекта
Координата x левого верхнего угла
Координата у левого верхнего угла
Ширина компонента
Высота компонента
Имя шрифта
Тип шрифта
0 - PLANE
1 - BOLD
2 - ITALIC
3 - BOLD&ITALIC
Расмер шрифта
Цвет текста
Цвет фона
GRID
alias = name
editable = {Yes,No}
multiselect = {Yes,No}
{editexp,addexp,delexp} = <operation>
{edit,add,del} = <action>
button_size = <int>
titlebar_size = <int>
buttonbar_bg_color = <color>
titlebar_bg_color = <color>
vscrollsize = <int>
hscrollsize = <int>
rowsize = <int>
buttonbar_font_face = <string>
buttonbar_font_family = {0,1,2,3}
buttonbar_font_size = <int>
buttonbar_font_color = <color>
currow_color = <color>
currow_bg_color = <color>
Методы
CURRENTVALUE
GETVALUE
SELECTIONVALUES
RETRIEVE
SETDATASTORE
GETDATASTORE
GETALLDATASTORE
SUM
имя (алиас компонента)
тип редактирования
Yes - редактируемый
No - не редактируемый
тип выделения
Yes - можно выделять несколько строк
No - выделяется только одна строка
Действия, вызываемые соответственно
при выборе, добавлении, удалении
строчек объекта (если редактирование
осуществляется посредством
справочника)
Действия, вызываемые соответственно
при выборе, добавлении, удалении
строчек объекта (если редактирование
осуществляется вручную
пользователем)
Ширина панели Button_bar
Ширина панели заголовков столбцов
Цвет панели Button_bar
Цвет панели заголовков столбцов
Ширина полосы вертикальной полосы
прокрутки
Ширина полосы горизонтальной
полосы прокрутки
высота строки объекта
начертание шрифта
тип шрифта
размер шрифта
цвет шрифта
Цвет текста для текущей строки
Цвет текста фона для текущей строки
Принимает название столбца и
возвращает значение элемента данных
из этого столбца текущей строки
Принимает название столбца и номер
строки, возвращает соответствующий
элемент данных
Принимает название столбца и
возвращает массив значений этого
столбца, соответствующий
выделенным пользователям строкам
Вызывает метод retrieve подчиненной
DATASTORE
Принимает объект DATASTORE и
устанавливает ее для GRID в качестве
текущей
Возвращает DATASTORE GRID’а с
учетом наложенных фильтров
Возвращает DATASTORE GRID’а без
учета наложенных фильтров
Принимает имя столбца и возвращает
DUMPTOFILE
сумму его элементов с учетом
наложенных фильтров
Вызывает диалог сброса данных во
внешний файл
GROSSTAB
ALIAS
QUERY
ROWCONDITION
COLUMNCONDITION
EVAL
DATACONDITION
Имя объекта
Запрос, выполняемый объектом
Индекс столбца выборки, из которого
будут сформированы заголовки строк
объекта
Индекс столбца выборки, из которого
будут сформированы заголовки
столбцов строк объекта
{max,count,sum,…} функция,
применяемая к массиву, оказавшемуся
на пересечении строки и столбца
Индекс столбца выборки, из которого
будут сформированы ряды данных
объекта
GROUP
ALIAS
Методы
SUM
CURRENTROW
Имя объекта
Принимает индекс столбца и
возвращает сумму значений этого
столбца в данной группе
Возвращает текущую строку в группе
GROUPREPORT
ALIAS
QUERY
GROUPING
SORTING
TREEPARAM
Имя объекта
Запрос, выполняемый объектом
Параметры, задающие логическую
группировку (случай, когда
группировка строится по
ЗНАЧЕНИЯМ данных)
Параметр, задающий сортировку
Параметры, задающие физическую
группировку (случай, когда
группировка строится по связям между
строками таблицы – дерево лежит в
таблице)
Методы - нет
ITEM
ALIAS
LABEL
ACTION
EXP
Имя объекта
Название пункта меню
Действие, выполняемое при выборе
пункта меню
Выражение калькулятора, выполняемое
при выборе пункта меню
Методы - нет
LABEL
ALIAS
LEFT
TOP
WIDTH
HEIGHT
FONT_FACE
FONT_FAMILY
FONT_SIZE
FONT_COLOR
BG_COLOR
HALIGNMENT
VALIGNMENT
BORDER
MULTILINE
WORDWRAP
VALUE
Имя объекта
Координата хевого верхнего угла
Координата у левого верхнего угла
ширина
высота
Имя шрифта
Тип шрифта
0 - PLANE
1 - BOLD
2 - ITALIC
3 - BOLD&ITALIC
Расмер шрифта
Цвет текста
Цвет фона
{left,right,center} горизонтальное
выравнивание
{top,right,botton} вертикальное
выравнивание
{none, 3dlowered, box} тип рамки
{yes, no} определяет обычный текст,
или многострочный
{yes, no} – определяет, осуществлять
или нет перенос по словам
Текст
Методы
SETVALUE
Устанавливает значение для объекта
LINE
LEFT
TOP
SIZE
TYPE
Координата х
Координата у
длина
{horizontal, vertical} тип линии
Методы - нет
MENU
ALIAS
LABEL
Имя объекта
Текст меню (нужен при встраивании в
другое меню)
Методы - нет
RADIOBUTTON
VALUE
CHECK
Значение, возвращаемое компонентом,
при его выборе
{yes, no} начальное значение
компонента
LABEL
Текст около компонента
Методы - нет
RADIOGROUP
ALIAS
LEFT
TOP
BG_COLOR
ALIGNMENT
Имя объекта
Координата x левого верхнего угла
Координата у левого верхнего угла
Цвет фона
{horizontal, vertical} расположение
переключателей в группе
Методы
GETVALUE
Возвращает значение, ассоциированное
с выбранным переключателем
REPORT
BG_COLOR
ORIENTATION
Цвет фона для всего отчета
{landscape, portrait} ориентация по
умолчанию для отчета
Методы – нет
REPORTGRID
ALIAS
ROWSIZE
DRAWGRID
LEFT
TOP
Имя объекта
Размер строки в отчете
Параметр, определяющий способ
рисования сетки в отчете
Координата x левого верхнего угла
Координата у левого верхнего угла
Методы – нет
REPORTHEADER
LEFT
TOP
WIDTH
HEIGHT
BG_COLOR
ALIAS
Координата х левого верхнего угла
Координата у левого верхнего угла
ширина
высота
Цвет фона для компонента
Имя объекта
Методы – нет
REPORTTRAILER
LEFT
TOP
WIDTH
HEIGHT
BG_COLOR
ALIAS
Координата х левого верхнего угла
Координата у левого верхнего угла
ширина
высота
Цвет фона для компонента
Имя объекта
Методы – нет
SCROLPANEL
BG_COLOR
Цвет фона для компонента
Методы – нет
SPLITPANEL
ALIAS
TYPE
PERCENT
GAPSIZE
GAPCOLOR
Имя объекта
{horizontal,vertical} тип разбиения
Процентное соотношение между
размерами встроенных компонентов
Величина «зазора» между
компонентами
Цвет «зазора» между компонентами
Методы – нет
TABSET
ALIAS
FONT_FACE
FONT_FAMILY
FONT_SIZE
BG_COLOR
TABS_ON_TOP
LABELS
Имя объекта
Имя шрифта
Тип шрифта
0 - PLANE
1 - BOLD
2 - ITALIC
3 - BOLD&ITALIC
Расмер шрифта
Цвет фона
{yes, no} определяет положение
закладок компонента – вверху или
внизу
Перечисленные через запятую названия
закладок компонента
Методы
SETCUTTENTTAB
Устанавливает текущую закладку
TOOLBAR
ALIAS
ALIGN
VGAP
HGAP
BACKGROUND
Имя объекта
{left, top, center} определяет
выравнивание встроенных
компонентов
Расстояние между встраиваемыми
компонентами по вертикали
Расстояние между встраиваемыми
компонентами по горизонтали
Цвет фона
FOREGROUND
FONT
Цвет текста
Используемый шрифт
Методы – нет
TREEVIEW
Дерево для навигации по сложным структурам данных.
Источником данных является GROUPREPORT , TVNAV.
Alias = name
имя (алиас компонента)
action=<ACTION>
действие по щелчку мыши на листе
дерева
nodeaction=<ACTION>
действие по щелчку мыши+<CTRL> на
узле дерева
nodefont=<FONT>
фонт для узла дерева
pointfont=<FONT>
фонт для листа дерева
background=<COLOR>
цвет фона
hilite=<COLOR>,<COLOR>
подсветка фон/текст
node=<COLOR>
цвет текста для узла
point=<COLOR>
цвет текста для листа дерева
rootname="Текст в корне дерева"
Hiliting={ON,OFF}
Включает/выключает подсветку
Методы
GETLEVEL
Возвращает текущий уровень дерева
TVNAV
Навигатор для TREEVIEW по файлам специальной структуры.
Информация о структуре находится в файле следующего вида
файл node0
KOI8_R
N/узел 1/node1
N/узел 2/node2
P/файл 1/file1
файл node1
KOI8_R
P/файл 1/file1
P/файл 2/file2
файл node2
KOI8_R
N/узел 3/node3
P/файл 1/file1
P/файл 2/file2
файл node3
KOI8_R
P/файл 1/file1



Root
Узел1


Узел2
Узел3



Файл1
Файл2
Файл1

Файл1
Файл2

Файл1
Где
N - это узел дерева а P - его лист.
KOI8_R - кодировка текста
А общий формат записи для строки узла:
N/название узла/имяфайла_с_описанием
для листа дерева
P/название листа/управляющая_информация
параметры
root = "path for root-file on document server"
Макроязык Zeta SCRIPT
1. Введение
Данный язык вырос из калькулятора и изначально служил для макроподстановок и
вычисления значений в конструкциях RML. По этой причине простейшее выражение
записывается как для простого калькулятора, например
10+20*1000-2
Так же можно занести результат по алиасу объекта RML
STORE_ALIAS.FIELD=OTHER_STORE_ALIAS.FIELD*10
Где STORE_ALIAS и OTHER_STORE_ALIAS - алиасы некоторых объектов
DATASTORE, а FIELD это столбец соответствующего DATASTORE.
Но, допустим, вам надо вставить условное выражение в SQL запрос
select a,b from table_c where a='~($if (FILED1=='') ('UNKNOWN') $else (FIELD1))~'
Это называется макроподстановкой. Если поле редактирования с алиасом FIELD1
имеет значение, то это значение подставляется, иначе подставляется значение по
умолчанию.
Конечно, это можно сделать и средствами Oracle, но это более трудоемкий процесс. К
тому же операции связанные с правкой серьезной базы данных могут быть
неоправданным риском, в отличии от правки конкретного документа.
Вообще, конструкция IF записывается как
($if (логическое выражение)
(действия если выражение верно)
$if (альтернативное выражение)
(действия если выражение верно)
.......
$else (действие если не верно ни какое из выражений)
)
Например, если в обработке события вам надо в зависимости от содержимого базы
открывать разные документы то можно написать следующую макро подстановку
// в описании компонента GRID
edit="open ~($if ( ($($(''+DS.F1)@trim)@toUpperCase) == 'LIST') ('list.rml')
$if ( ($($(''+DS.F1)@trim)@toUpperCase) == 'WARE') ('ware.rml')
$if ( ($($(''+DS.F1)@trim)@toUpperCase) == 'CATALOG') ('catalog.rml')
$else (($alert 'Uncknown type of document '+DS.F1)
($throw 'IGNORE' '')))~ DS.CODE"
Здесь можно видеть использование функций ALTER и THROW (знак '$' означает
вызов функции, на самом деле IF это тоже функция), а также методов trim и
toUpperCase объекта STRING.
Теперь перейдем к более сложным моментам. При формировании отчетов часто
приходится считать различные суммы по строкам таблицы.
{label value="~($X
# создаем фильтр
filter = ($DS@filter 'DS.f1==ARGUMENTS.1')
# создаем итератор
t = ($filter@iterator)
($while ($t@next)
(
# здесь могут быть и более сложные операции
sum+= ($($t@value)@field 'field')
)
)
($ret sum)
)~"
}
Здесь представлены специализированные функции для работы с объектами из
DATASTORE и X-функция .
X-Функция это очень важная конструкция скрипта. Она используется для создания
пула локальных переменных (объект V) и все простые переменные (не содержащие
точки) считаются локальными и адресуются через объект V. То есть переменная а в
конструкции
($X a=10 )
реально адресуется через V.a
Значение X-функции это то значение, которое указано при вызове функции RET. На
вызове RET выполнение X-функции заканчивается.
Соответственно X-функция используется для определения новых функций на скрипте
($defun f<a,b> ($X ($ret a+b)))
определяет функцию, возвращающую сумму своих аргументов.
Определение собственных функций нужно в основном при использовании
рекурсивных алгоритмов. Например, для обхода дерева каталога товаров и подсчета
всех значений стоимостей товаров
KOI8_R
DOC // universal document
// секция значений по умолчанию
beginexpr="
#считаем значение как сумму значений всех листьев дерева
($defun f<a> ($X
## это вообще дерево ?
($if ($a@type == 'GROUP')
(
t = ($a@iterator)
($while ($t@next)
(sum+= ($f ($t@value)))
)
($ret sum)
)
$if ($a@type == 'DSROW') ## эта нода лист
($ret ($a@field 'SUM'))
$else ($throw 'UnknownType_in_F','object '+a+' must be Group')
)
))"
..............
{GroupReport Alias=GR
.........
}
.....
{label value="~($f(GR))~"}
.......
2. Справочник
Системные объекты
NUMBER
STRING
ARRAY
HASH
STACK
ITERATOR
*DATE
DSROW
GROUP
DATASTORE
GROUPREPORT
*VIEWR
*PAGE
*IMAGE
QEXPR
Конструкции/операторы
if/else
for
while
break/continue
X/Z/L/ret/goto
defun
try/catch/finally/throw
quote
alert - сообщение об ошибке
trace/notrace - информация о процессе исполнения
debugon/debugoff/debug - отладочная информация
Функции
Конструкторы системных объектов
@array
($@array n) создает массив из n элементов
($@array a,b,c,d,...) создает массив [a,b,c,d,...]
@hash
($@hash ) создает пустой хэш.
@number
($@number ($('10.2x')@substr 0,4) ) создает число по строке
@date
($@date) создает текущую дату
($@date sec) создает дату по количеству секунд прошедших с 1.1.1970
($@date day,month,year) -/- по дню, месяцу и году.
@image
($@image width,height)
($@image 'filename')
Системные объекты
Системные объекты обладают возможностью вызова методов применительно к
объекту
Пример с массивом
a=($@array 10,20,30,40)
($debug ($a@size))
#printed 4
($debug ($a@type))
#printed ARRAY
($debug ($a@ 0))
#printed 10
NUMBER
Число с плавающей запятой двойной точности
методы
type
Возвращает строку 'NUMBER'
int
Возвращает строку с целочисленным
значением
STRING
Строка
методы
type
trim
indexOf
lastIndexOf
substr
charAt
toUpperCase
toLowerCase
size/length
iterator
Возвращает строку 'STRING'
Удоляет лидирующие и завершающие
пробелы
Возвращает позицию, в которой
впервые встречен символ
Возвращает позицию, в которой в
последний раз встречен символ
Возвращает подстроку
($str@substr x) - начиная с позиции x
($str@substr x,y) - с позиции x до y
Возвращает символ в указаной
позиции.
Переводит строку в верхний регистр.
Переводит строку в нижний регистр.
Возвращает количество символов.
Возвращает итератор.
ARRAY
Массив
методы
type
i
size/length
sort/backsort
iterator
HASH
Возвращает строку 'ARRAY'
Индексация по массиву
Альтернативная запись ($a@ x1,x2,x3) индексов не больше, чем размерность
массивa
Бросает исключение IndexException
Возвращает количество элементов в
массиве
Сортировка по возрастанию и
убыванию
Возвращает итератор.
Хэш-таблица
методы
type
put
get
iterator
Возвращает строку 'HASH'
Помещает в таблицу ключ и объект
Возвращает по ключу объект
Возвращает итератор для ключей.
STACK
стек
методы
type
push
pop
empty
Возвращает строку 'STACK'
Помещает в стек
Берет из стека, если стек пуст бросает
исключение EmptyStackException
Проверяет пуст ли стек
ITERATOR
Итератор
методы
type
next
prev
last
first
value
setvalue
size
Возвращает строку 'ITERATOR'
позиционирует на следующий элемент,
если только создан и еще не
позиционировался то на первый
элемент
позиционирует на предыдущий
элемент, если только создан и еще не
позиционировался, то на последний
элемент
позиционирует на последний элемент
позиционирует на первый элемент
возвращает текущий элемент
записывает новое значение текущего
элемента, если это возможно, и
возвращает старое.
Если изменить значение невозможно
бросает ReadOnlyException
возвращает количество элементов
адресуемых итератором
DATE
дата
методы
type
ToNUMBER
ToSTRING
MM
YYYY
DD
next
iterator
возвращает строку 'DATE'
число секунд по Гринвичу
представление в виде строки
месяц
год
день
возвращает дату со смещением на
указанное число дней
создает итератор с указанным шагом (
в днях)
DSROW
Строка объекта DATASTORE
методы
type
field
Возвращает строку 'DSROW'
Возвращает значение поля по имени
($row@field 'fieldname')
GROUP
Группировка
методы
type
iterator
Возвращает строку 'GROUP'
Создает итератор по элементам
группировки
DATASTORE
Представление таблицы на стороне клиента
методы
type
Возвращает строку 'DATASTORE'
filter
Создает фильтр для строк таблицы
(полученный фильтр также является
DATASTORE)
($ds@filter ($quote (логическое
выражение фильтрации)))
iterator
Создает итератор по строкам таблицы
QEXPR
Вычислимое выражение
методы
type
eval
Возвращает строку 'QEXPR'
Вычисляет выражение
Конструкции/операторы
if/else
($if (логическое выражение)
(действия если выражение верно)
$if (альтернативное выражение)
(действия если выражение верно)
.......
$else (действие если не верно ни какое из выражений)
)
while
($while (логическое выражение)
(действия если выражение верно)
)
for
($for ((инициализация);(логическое выражение);(индексация))
(действия)
)
break/continue
($break) - выход из цикла
($continue) - переход на конец цикла
X/Z/L/ret/goto
($X
(действие)
.......
($if ......
($goto label2)
)
......
label1:
......
($ret anything)
......
label2:
......
($goto label1)
)
Z-функция отличается от X-функции только тем что не создает новой
таблицы локальных переменных
А отличие L-функции заключается в том, что она, во-первых, не создает свою
таблицу локальных переменных как и Z-функция ,а во-вторых, на ее работу
влияют вызовы функций CONTINUE и BREAK . Первая повторно выполняет
L-функцию, а вторая завершает выполнение со значением 0.
defun
($defun FunctionName
($X
......
($ret ....)
)
)
try/catch/finally/trow
($try
( ..... )
$catch ('ExceptionName') (действие)
$catch ('ExceptionName') (действие)
.....
$finally (действие)
)
Системные Исключения:
NullException
CastException
IndexException
FunctionNotFound
HasNotMethod
ReadOnlyException
Syntax
Any
quote
($quote (выражение)) возвращает объект QEXPR для выражения
3. Построение новых конструкций (Java)
Рассмотрим процесс разбора RML-документа. В процессе парсинга документ рассматривается как
вложенные друг в друга контейнеры. В начале сам документ рассматривается как контейнер и его
свойствами являются свойства в секции по умолчанию. Далее в нем последовательно находятся
компоненты следующего уровня и т.д.
В результате получается дерево из свойств компонентов, маркированных именами этих компонентов.
Далее, для класса реализующего компонент вершины дерева, вызывается функция doParsing(), которая
должна построить этот компонент, проинициализировать его параметрами компонента и вызвать
функцию парсера getContents(), если компонент может содержать другие компоненты. Функция
getContetnts создаст соответствующие объекты и вызовет для них doParsing() и т.д.
В результате будет построено представление документа, которое может быть отображено на экране.
public interface ParsedObject{
public Object doParsing(Proper prop,Hashtable aliases);
}
Пример реализации контейнерного компонента
package rml;
import views.*;
import java.util.*;
/**
* компонент, реализующий форму, наполняется другими компонентами ,
* например, полями ввода
*/
public class FORM implements ParsedObject{
public Object doParsing(Proper prop,Hashtable aliases){
// создадим визуальное представление формы
views.FORM frm = new views.FORM();
// поместить алиас обьекта в таблицу алиасов
String alias = (String)prop.get("ALIAS");
if (alias!=null){
aliases.put(alias.toUpperCase(),(Object)frm);
}
// проинициализировать обьект параметрами
frm.init(prop);
// получить компоненты, содержащиеся в форме
Object[] objs = Parser.getContent(prop,aliases);
// добавить их в форму
frm.addChildren(objs);
// вернуть построеную форму
return (Object)frm;
}
}
Основная прелесть SCRIPT'а в том что набор его языковых конструкций и/или
функций жестко не задан и поэтому может быть произвольно изменен и расширен.
Для этого достаточно построить класс, реализующий вашу конструкцию, и положить
его в пакет calc.functions для функций и calc.objects - для объектов.
Все функции скрипта создаются как классы пакета calc.functions реализующие
следующий интерфейс
Напишем простую функцию для определения максимума из двух чисел
package calc.functions;
import calc.*;
public class MAX implements ExternFunction{
// дерево для вычисления аргументов функции
OP args = null;
public Object eval() throws Exception{
// вычислим аргументы
Object o = OP.doHardOP(args); // вычисляем пока не получим константы
// должно быть два числовых аргумента
Object a1,a2;
if ( ( o instanceof Vector ) &&
( ((Vector)o).size()==2 ) &&
( (a1=((Vector)o).elementAt(0)) instanceof Double ) &&
( (a2=((Vector)o).elementAt(1)) instanceof Double ) ) {
// сравним арументы и вернем наибольший
return ( ((Double)a1).doubleValue() >
((Double)a2).doubleValue())? a1 : a2 ;
}else
// иначе бросим исключение системы
throw new RTException("CastException",
"Function MAX must have two number arguments");
}
public void init(String arg) throws Exception{
// построим дерево для вычисления аргументов
args = Parser.parse1(arg.toCharArray());
}
}
Здесь следует обратить внимание на то, что в функции init(String) происходит только
разбор выражения для аргументов , но не вычисление. Наоборот, в функции eval()
происходит только вычисление уже разобранного выражения. Разбор происходит
только один раз для каждого вызова функции (в каждом случае выражения для
аргументов функции разные), однако, вычисление может происходить много раз,
например, в цикле.
В приведенном выше примере используются следующие классы и интерфейсы из пакета calc.
interface ExternFunction - Этот интерфейс обязаны реализовать все конструкции-функции скрипта
методы:
Object eval() throws Exception - вычисление аргументов и функции
void init(String arg) throws Exception - разбор строки аргументов
class OP extends Tree - представление выражения в виде дерева
методы:
Object eval() throws Exception - вычисляет выражение
static Object doHardOP(OP) throws Exception - вычисляет выражение и пока результат есть
выражение вычисляет результат как новое выражение
static Object doSoftOP(OP) throws Exception - вычисляет выражение
class Parser - синтаксический анализатор
методы:
OP parse1(char[]) throws Exception - построение дерева для выражения
class RTException - RunTime Exception
конструктор:
RTException(String exception,String messag)
В сложных конструкциях, например IF, используется лексический анализатор
class Lexemator - лексический анализатор
конструктор:
Lexemator(char[] expression)
методы:
int next() throws Exception - прочитать следующую лексему
int type() throws Exception - тип лексемы
int args() throws Exception - аргументы для тега
int as_string() throws Exception - дать лексему как строку
int as_double() throws Exception - дать лексему как число
int as_op() throws Exception - дать лексему как операцию
константы:
int LDEF - идентификатор - алиас, тег, поле
int LSTR - строка
int LNUM - деествительное число
int LEND - конец потока лексем
int LOP - опкрация
int LEXPR - выражение
int LTAG - тег
Естественно можно писать функции с неизвестным количеством аргументов.
К примеру, перепишем нашу функцию так, чтобы она работала с количеством
аргументов не меньше двух.
package calc.functions;
import calc.*;
public class MAX implements ExternFunction{
// дерево для вычисления аргументов функции
OP args = null;
static final String except =
"Function MAX must have minimum two number arguments";
public Object eval() throws Exception{
// вычислим аргументы
Object o = OP.doHardOP(args); // вычисляем пока не получим константы
// должно быть не мение чем два аргумента
int size;
if ( ( o instanceof Vector ) &&
( (size=((Vector)o).size())>=2 ) &&
// сравним арументы и вернем наибольший
int i=0;
double x = Double.;
double y;
Vector v = (Vector)o;
try {
for (;i<size;++i){
y = ((Double)v.elementAt(i)).doubleValue();
x = (y>x)?y:x;
}
return new Double(x);
}catch(ClassCastException e){
throw new RTException("CastException",except+
",\n\tbut argument"+(i+1)+"is not NUMBER");
}
}else
// иначе бросим исключение системы
throw new RTException("CastException",except);
}
public void init(String arg) throws Exception{
// построим дерево для вычисления аргументов
args = Parser.parse1(arg.toCharArray());
}
}
Рассмотренные конструкции имеют одну очень важную особенность аргументы
функции рассматриваются как список обязательно вычисляемых выражений, что не
верно, например, для функции IF.
package calc.functions;
import calc.*;
public class IF implements ExternFunction {
OP expr = null;
OP doing = null;
OP elser = null;
public Object eval() throws Exception{
//вычисляем логическое выражение
Object result = expr.eval();
//если выражение истина вычисляем основное выражение
//лож - альтернативное выражение, если оно есть
if ( result instanceof Double ){
if ( ((Double)result).doubleValue() != 0 )
return doing.eval();
else if (elser!=null){
return elser.eval();
}
}else if ( result instanceof String ){
if (((String)result).trim().toUpperCase().equals("TRUE"))
return doing.eval();
else if (elser!=null){
return elser.eval();
}
}else throw new RTException("SYNTAX",
"RESALT of expression in IF is "+result);
return new Double(0);
}
public void init(String arg) throws Exception{
// создаем лексический анализатор для строки аргументов
Lexemator lex = new Lexemator(arg.toCharArray());
// читаем лексему
lex.next();
// лексема должна быть выражением
// это условное выражение
if (lex.type() == Lexemator.LEXPR){
expr = Parser.parse1(lex.as_string().toCharArray());
}else throw new RTException("SYNTAX",
"IF must have condition expression");
// читаем следующее выражение
// это основное выражение выполняемое если условное
// выражение истинно
lex.next();
if (lex.type() == Lexemator.LEXPR){
doing = Parser.parse1(lex.as_string().toCharArray());
}else throw new RTException("SYNTAX",
"IF must have main expression");
// далее следует конструкция
// например, еще один IF или ELSE или ни чего не следует.
lex.next();
switch (lex.type()){
case Lexemator.LEND:
break;
case Lexemator.LTAG:
elser = new Func(lex.as_string(),lex.args());
break;
default: throw new RTException("SYNTAX",
"IF can have any alternative as tag and ONLY tag");
}
}
}
Здесь видно, что для конструкций, в которых используются выражения, вычисляемые
при некоторых условиях необходимо самостоятельно производить разбор строки
аргументов, хотя и используя уже готовый лексический анализатор.
Новые объекты создаются как классы пакета calc.objects и могут реализовать
следующие интерфейсы
Реализация конструктора, позволяет создавать объект вызовом ($@имяобьекта)
public interface class_constructor {
// arg - результат вычисления строки аргументов
public Object constructor(Object arg) throws Exception;
}
Реализация методов обьекта
public interface class_method {
// method - имя метода
// arg - результат вычисления строки аргументов
public Object method(String method,Object arg) throws Exception;
}
Реализация метода size
public interface class_size {
public Double size() throws Exception;
}
Реализация метода type
public interface class_type {
public String type() throws Exception;
}
Реализация метода iterator
public interface class_iterator {
public iterator iterator() throws Exception ;
}
Как пример создания собственного объекта рассмотрим стек.
package calc.objects;
import calc.*;
import java.util.Vector;
public class STACK implements class_constructor,class_method,class_type{
class StackElement{
StackElement next;
Object value;
public StackElement(Object value,StackElement next){
this.next = next;
this.value = value;
}
}
StackElement stack = null;
public STACK(){}
public Object constructor(Object arg) throws Exception{
return this;
}
public Object method(String method,Object arg) throws Exception{
if ( method.equals("PUSH") ){
if ( arg instanceof Vector )
throw new RTException("CastException",
"STACK@PUSH must called with one argument");
stack = new StackElement(arg,stack);
return new Double(1);
}else if ( method.equals("POP") ){
if ( stack == null )
throw new RTException("EmptyStackException",
"Stack is Empty");
Object o = stack.value;
stack = stack.next;
return o;
}else if ( method.equals("EMPTY") ){
return (stack==null)?new Double(1):new Double(0);
}else throw new RTException("HasMethodException",
"object STACK has not method "+method);
}
public String type() throws Exception{
return "STACK";
}
public String toString(){
StackElement s = stack;
StringBuffer sb = new StringBuffer("<");
while ( s != null ){
if ( s.value instanceof Object[])
sb.append(OP.printArray((Object[])s.value));
else
sb.append(s.value);
sb.append(", ");
s = s.next;
}
sb.append("@>");
return sb.toString();
}
}
пример использования - файл test2
($notrace ($X
s = ($@stack)
($s@push 10)
($s@push 'text')
($s@push ($@array 1,2,3,4,5,6))
($debug s)
($while (!($s@empty))
($debug ''+($s@pop)))
))
а так выглядит процесс исполнения
[chen@wks5 zeta]$ java calc.test test2
#<[1.0,2.0,3.0,4.0,5.0,6.0], text, 10.0, @>
#[1.0,2.0,3.0,4.0,5.0,6.0]
#text
#10.0
result: 0.0
Настройка системы
Все настройки системы находятся в файле zeta.propers.
Основные параметры - это где база данных и где файлы системы ( *.class,*.rml,*.gif ).
база данных указывается через параметры
connect.type - тип базы данных с которой работает система
jdbc.diver - драйвер который будет использоваться для работы с базой
dbs.propto - строка подключения к базе
dbs.connect - действительно ли подключаться к базе (при отладке иногда это не нужно)
Для СУБД Postgres этим параметрам выставляются следующие значения
connect.type=postgres
jdbc.driver=postgresql.Driver
dbs.proto=jdbc:postgresql:test1
dbs.connect=yes
местоположение файлов системы задается через
doc.somthing=body.Snake
doc.server=file:///home/chen/java/zeta/rmlfiles/
class.server=file:///home/chen/java/zeta/
image.server=file:///home/chen/java/zeta/
Если вы работаете в Linux то необходимо разрешить поддержку перекодировки для компонентов AWT
это пофиксит баг JDK.
awt.locale=KOI8_R
enc.dtitle=on
enc.field=on
enc.ftitle=on
в других системах закомментируйте эти строчки.
Системные сообщения и надписи на специальных компонентах записываются через следующие
параметры
msg.OkButtonLabel=ОК
msg.CanscelButtonLabel=Отмена
msg.InputButtonLabel=Принять
msg.BadUsersCount1=В системе уже присутствует
msg.BadUsersCount2=пользователей!!!\nВам придется войти позже.
msg.BadLicense=Неправильный файл лицензии.
msg.BadUserOrPassword=Неправильно указано имя пользователя или пароль
msg.Blocked=Объект уже заблокирован другим пользователем
msg.Uncloseable=Невозможно выполнить операцию, т.к. присутствуют незакрываемые окна
msg.CantConnnectToDocumentServer=Нет связи с сервером документов
msg.CantConnectToDataBaseServer=Нет связи с базой данных
msg.CantLoadClass=Не могу загрузить класс
msg.ParsingError=Ошибка обработки документа
msg.UnknownFatalError=Неизвестная Ошибка
msg.ErrorReadNode=Ошибка чтения ноды
msg.ErrorLoadNode=Ошибка загрузки ноды
msg.RUSureExit=Вы действительно хотите нас покинуть?
msg.Retriving=Ждите... Идет запрос к базе данных...
msg.BadEditValuePrefix=Значение должно быть
msg.BadEditValuePostfix=типа
msg.BadEditValue=Вы можете продолжить редактирование \nили отменить ввод, вернув предыдущее значение
msg.BadEditValueHeader=Неверно введенное значение
msg.BadEditButtonEdit=Редактировать
msg.BadEditButtonUndo=Предыдущее значение
reg.create.msg = введите секретный ключ
reg.create.btn = регистрация
finddialog.caption = Поиск
finddialog.pattern = Образец
finddialog.direction = Направление
finddialog.direction_down = Вниз
finddialog.direction_up = Вверх
finddialog.case = С учетом регистра
finddialog.button_find = Найти
finddialog.button_close = Закрыть
filterdialog.caption = Параметры фильтра
filterdialog.button_ok = ok
filterdialog.button_cancel = Отмена
filterdialog.button_reset = Сброс
filterdialog.button_save = Сохранить
filterdialog.label_sort = Сорт.
filterdialog.label_filter = Фильтр
filterdialog.label_name = Наименование
filterdialog.label_bvalue = Нач. знач.
filterdialog.label_evalue = Кон. знач.
report.label.nextpage = ->
report.label.prevpage = <report.label.firstpage = <<report.label.lastpage = ->>
report.label.print = Печать
report.label.pages = Стр.
report.label.iz = из
report.label.numcopies = Копии
report.label.whatprint = Печатать
report.label.mashtab = Масштаб
report.label.onepage = Одну страницу
report.label.allpages = Все страницы
Вопросы, примеры, известные баги
1. Я описал форму и поле редактирования в ней, но не вижу его.
Поле редактирование ОБЯЗАТЕЛЬНО должно содержать описание положения и размера, а
также атрибут TARGET или TYPE.
2. В выражение на SCRIPT указан алиас компонента, компонент существует но возникает
исключительная ситуация по отсутствию компонента.
Если Вы обращаетесь к компоненту документа внутри X-функции и имя по которому вы
обращаетесь не содержит точку то поставьте перед именем префикс G, например так:
G.ALIASX
наоборот если вы обращаетесь к переменной описанной внутри X-функции но обращение
содержит точку то поставьте префикс V, например так:
V.HTABLE.KEY
3.
Доработки Zeta 1.6
-------------------------------------------------------------24.11.2008 Uglov Nikolay пишет:
-----------------------Новый релиз на SVN.
Что сделано:
Переработан механизм передачи фокуса между объектами. Исправлен механизм принудительной
постановки фокуса.
В данный момент времени можно задавать принудительно фокус для различных компонентов.
осуществляется это путем вызова функции FOCUS у объекта FOCUSER. В качестве параметра
передается указательна визуальный компонент (p.<alias>). Т.е. если требуется поставить фокус на
Field с альясом my_field:
$g.focuser@focus p.my_field
Как вы уже заметили из письма, появился новый идентификатор "p" суть его - взять адрес объекта.
Зачем он нужен? Затем, что бы была возможность получить адрес любого объекта, т.к. "g" в
случае его применения к такому объекту как field возвращал значение филда (т.е. то значение,
которое записано в филде).
Так же у объекта focuser реализованы 2 метода FOCUSNEXT и FOCUSPREVIOUS соответственно
передают фокус следующему или предыдущему элементам.
Что еще не сделано:
Не сделан механизм задания последовательности переходов фокуса. Тут я столкнулся с
некоторыми техническими сложностями, и сейчас мужественно с ними борюсь. Надеюсь
закончить на этой неделе.
Для тех кто не в теме: механизм задания последовательности фокуса из RML нужен для того,
чтобы ограничить переход фокуса между некоторым набором визуальных компонентов в
документе и задать порядок перехода фокуса в этом наборе, в данный момент он реализован в
ядре, но пока не работает, поэтому систаксис пока рассказывать не буду (да он еще наверное
претерпит некоторые изменения :)).
Серег, специально для тебя добавил метод документа loaddbf.
Кстати, отдельно наверное стоит уточнить, что метода FOCUS у документа больше не существует
т.е. конструкция g.self@focus вызовет ошибку.
Да, еще совсем забыл.
Убрана проверка лицензии. Вообще убрана. Т.е. файлик license можно удалить :) , собственно как
и mydll.dll (если эта dll еще у кого-то есть :))
-------------------------------------------------------------26.11.2008 Uglov Nikolay пишет:
-----------------------Новый релиз ядра на SVN.
Закончена фокусировка.
Систаксис объекта focuser на данным момент следующий:
{focuser
{focus_item target=p.component2}
{focus_item target=p.component1}
{focus_item target=p.component3}
{focus_item target=p.component4}
}
Если в RML встречается такая конструкция, то фокус будет переходить только среди описанных
компонентов (focus_item) в последовательность перехода - порядок объявления компонентов.
т.е. в данном примере фокус будет переходитьв следующей последовательности:
component2->component1->component3->component4->component2
Marina Vagapova:
Новый тип сообщений.
Было
sure "message" 0 – выдается окно с выбором ок, отмена, анализируется введенный ответ
sure "message" 1 – выдается окно с описанием ошибки
Стало
sure "message" 0 – выдается окно
sure "message" 1 – выдается окно
sure "message" 2 – выдается окно
input "message" - окно для ввода
input "message" "initialValue" –
с выбором ок, отмена, анализируется введенный ответ
с описанием ошибки
с предупреждением
с сообщением, возвращает введенное значение
окно для ввода + задается начальное значение
Combo пример
{column size=60
visible=yes
title="Код unit"
target=spc.id_unit
halignment=left
alias=idunit
font_size=12
editexp = "g.idunit=($g.unitDS@getValue 'id_unit')"
}
{column size=60
title="Ед. изм. Combo"
halignment=center
target=unit.symbol_rus
font_size=12
alias=name_unit
values = "DS:symbol_rus"
dep = "idunit"
{datastore
alias = unitDS
query = "SELECT id_unit, symbol_rus FROM unit"
editable = no
} // datastore
}
Download