Предисловие В сборнике представлены статьи сотрудников Института системного программирования и некоторых других организаций, описывающие научные результаты исследований, полученные в 2003-2004 гг. В статьях обсуждаются как теоретические вопросы, так и проблемы реализации программных систем. Во второй части сборника представлены 10 статей. В статье П.М. Довгалюка «Анализ и оптимизация циклов с помощью производящих функций» представлены усовершенствования метода распространения констант, использующего GSA-представление (Gated Single Assignment), позволяющие алгоритму находить большее количество констант, чем исходный алгоритм. Во второй статье того же автора «Усовершенствованный алгоритм распространения констант с использованием GSA-представления» рассматривается метод анализа и оптимизации циклов с помощью производящих функций, состоящий в поиске выражений для конечных значений переменных, которые вычисляются в цикле и замене цикла вычислениями по формуле. Статья В.А. Семенова, С.В. Морозова и С.А. Пороха «Стратегии объектнореляционного отображения: систематизация и анализ на основе паттернов» посвящена методам отображения прикладных объектно-ориентированных данных в реляционную модель. Проводится систематизация этих методов, а также их анализ на основе введенной системы паттернов. Задача функционально полного отображения моделей данных рассматривается на примере EXPRESS-нотации, получившей распространение в качестве стандартного средства информационного моделирования научных и промышленных данных. В статье В.А. Семенова, С.В. Морозова и О.А. Тарлапана «Инкрементальная верификация объектно-ориентированных данных на основе спецификации ограничений» рассматриваются задачи полной и инкрементальной верификации объектно-ориентированных данных. На основе теории графов строится формальный аппарат, а также описываются разработанные методы инкрементальной верификации, использующие статический анализ спецификации ограничений и позволяющие локализовать область потенциальных нарушений при изменении данных. Результаты этой и предыдущей статей получены при поддержке РФФИ (грант N 04-01-00527) и Фонда содействия отечественной науке. В статье Д.А. Лизоркина «Оптимизация вычисления обратных осей языка XML Path при его реализации функциональными методами» предлагается алгоритм, позволяющий построить вычисление выражений XPath таким образом, что наличие указателей с дочерних узлов на родительские узлы в дереве документа 5
становится необязательным. Проводится обоснование алгоритма и рассматриваются его основные свойства. Во второй статье того же автора «Язык запросов к совокупности XMLдокументов, соединенных при помощи ссылок языка XLink» предлагается язык, который позволяет приложению прозрачным образом формулировать запросы к ссылкам XLink и осуществлять переходы по определяемым этими ссылками дугам. Язык инкапсулирует сложности синтаксиса XLink от приложения и предоставляет более высокий уровень абстракции при обработке совокупности XML-документов, соединенных ссылками языка XLink. В статье М.П. Рекуц «Виды ограничений целостности в базах XML-данных» на основе анализа потребностей современных приложений, работающих с XMLСУБД, выявляются виды ограничений целостности, которые должны поддерживаться XML-СУБД, и предлагаются средства определения этих видов ограничений с учетом специфики XML-модели данных и опыта, накопленного разработчиками реляционных СУБД. Работа выполнена при поддержке грантами РФФИ. В статье Г.И. Малашонка, А.И. Аветисяна, Ю.Д. Валеева и М.С. Зуева «Параллельные алгоритмы компьютерной алгебры» рассматривается разрабатываемая в рамках среды ParJava система компьютерной алгебры. Цель разрабатываемой системы – предоставить возможность эффективного использования параллельных вычислительных систем для проведения аналитических расчетов. В статье С.С. Гайсаряна и П.Н. Яковенко «К вопросу о генерации начальных данных, обеспечивающих заданную трассу SPMD-программы» исследуется проблема автоматизированной генерации входных данных для SPMDпрограммы на основании ее исходного текста. Вторую часть сборника завершает статья А.В. Инюхина «Открытая Т–система: распределённые вычисления в Internet», в которой рассмотрены возможности технологии автоматического динамического распараллеливания, реализованные в открытой Т–системе для выполнения распределённых вычислений в среде Internet, а также представлены результаты экспериментов, иллюстрирующие перспективы подобных вычислений. Член-корреспондент РАН
6
В.П. Иванников
7
2. Алгоритм распространения констант, использующий GSA-представление
Усовершенствованный алгоритм распространения констант с использованием GSA-представления П.М. Довгалюк (
[email protected]) Аннотация. В данной статье представлены усовершенствования метода распространения констант, использующего GSA-представление (Gated Single Assignment), позволяющие алгоритму находить большее количество констант, чем исходный алгоритм.
1. Введение Распространение констант – хорошо известная проблема глобального анализа потока данных. Цель распространения констант состоит в обнаружении величин, которые являются постоянными при любом возможном пути выполнения программы, и в распространении этих величин так далеко по тексту программы, как только это возможно. Выражения, чьи операнды являются константами, могут быть вычислены на этапе компиляции. Поэтому использование алгоритмов распространения констант позволяет компилятору выдавать более компактный и быстрый код. Хотя в общем случае проблема распространения констант является неразрешимой, существует множество проявлений этой проблемы, для которых существуют эффективные алгоритмы. Технологии распространения констант позволяют решить следующие задачи: - Выражения, вычисляемые на этапе компиляции не нужно вычислять в процессе выполнения программы; - Код, который никогда не выполняется, может быть удален, а недостижимый код может появляться в тех случаях, когда значение предиката в условном выражении неизменно и известно на этапе компиляции; - увеличение эффективности встраивания процедур. Распространение констант совместно со встраиванием процедур (когда многие параметры процедур являются константами) позволяет избежать разрастания кода, которое часто является результатом встраивания процедур в места из вызовов.
7
Алгоритм распространения констант, описанный в [8], использует SSAпредставление (Static Single Assignment) программы. В SSA-форму программа трансформируется таким образом, что только одно присваивание может достигнуть точки использования. Так как программы имеют ветвления и точки объединения нескольких путей, то в точках объединения необходимо добавить специальную форму присваивания, названную -функцией. -функция имеет форму V (R, S, …), где V, R, S, … – переменные. Количество операндов такой функции равняется количеству предшественников данного узла. Эти предшественники перечисляются в некотором определенном порядке, и j-й операнд -функции ассоциируется с j-м предшественником узла. Если путь выполнения программы лежит через j-го предка узла, то переменная V получает значение, связанное с j-м аргументом. Каждое исполнение -функции использует только один из аргументов, но который именно – зависит от того, из которого узла получил управление данный узел. В работе [8] алгоритмы распространения констант разделены на те, которые находят простые и условные константы. Алгоритм Sparse Conditional Constant Propagation находит все простые, а также некоторые условные константы. Время работы такого алгоритма пропорционально размеру SSA-графа, и каждое SSA-ребро обрабатывается максимум два раза. Когда необходимо классифицировать переменную в точке слияния, мы используем функцию meet для аргументов ее -функции. Но если в процессе своего выполнения программа всегда идет только по одной ветке, было бы лучше использовать то значение переменной, которое порождается именно в ней. В методе, описанном в предыдущем разделе, если значение предиката будет постоянным, то выполняемое ребро будет добавлено к рабочему списку. Поэтому в точке слияния выражения будут вычисляться с использованием информации о входящих выполняемых ребрах, что может приводить к неоднократному вычислению одних и тех же выражений. В методе, использующем GSA, если символ использует значение из точки слияния, то вычисляется значение предиката и определяется путь, из которого берется значение. При использовании -функции мы не можем определить, по какому пути шло выполнение программы. Но если снабдить -функцию предикатом, то если его значение является константой, можно выбрать нужный аргумент -функции, а если нет, то самое лучшее, что можно получить с помощью данного метода – это взять функцию meet от -аргументов. Чтобы выполнить данную задачу, необходимо расширить SSA-представление до GSA (Gated Single Assignment), введенное в работе [3], которое позволяет вычислять условные выражения, базирующиеся на предикатах. В данном представлении -функции заменяются на - и -функции. Большая часть -функций, расположенных в заголовках циклов переименовывается в -функции, тогда как 8
остальные преобразуются в -функции. -функция имеет вид: v = (P, v1, v2), что означает, что v принимает значение v1, если P=true, и v2, если P=false. В такой форме -функция представляет собой конструкцию if-then-else, но она может быть расширена для работы с более сложными условными конструкциями. Алгоритм для преобразования -функций в - и -функции представлен в работе [6]. В данном алгоритме используется представление программы в виде базовых блоков, состоящих из кортежей. Базовые блоки и кортежи внутри них связаны между собой и вместе образуют граф потока данных. Кортежи имеют следующие атрибуты: op, left, right, ssa_link, lattice, где op – код операции, left и right – два операнда, ssa_link – связь, порождаемая алгоритмом преобразования программы в SSA-форму. Поля left, right, ssa_link представляют собой указатели на соответствующие кортежи. Каждая операция (кортеж) также имеет ассоциированное значение – lattice, принадлежащее множеству значений из решетки и представляющее собой результат выполнения операции, который может быть получен на этапе компиляции.
3. Исходный алгоритм
if lattice(predicate) = C then lattice(t) = lattice value of -argument corresponding to C else lattice(t) = П of all -arguments of t endif -function: lattice(t) = -function: lattice(t) = lattice(-argument) default: lattice(t) = end case end propagate
4. Недостатки и предлагаемые изменения В работе [7] показано, что арифметические и логические выражения, включающие -функции, можно преобразовывать в несколько вложенных -функций и арифметических выражений, что позволяет получать константные выражения даже в тех случаях, когда аргументы исходного арифметического или логического выражения не являются константами. Это видно по следующему примеру: if P then a1 = 2 b1 = 1 else a2 = 4 b2 = 2 endif a3 = (P, a1, a2) b3 = (P, b2, b3) if a3 > b3 then ... endif
t tuples lattice(t) = T unvisited(t) = true Visit all basic blocks B in the program Visit all tuples t within B if unvisited(t) then propagate(t) propagate (tuple t) unvisited(t) = false if ssa_link(t) 0 then if unvisited(ssa_link(t)) then propagate(ssa_link(t)) lattice(t) = lattice(t) П lattice(ssa_link(t)) endif if unvisited(left(t)) then propagate(left(t)) if unvisited(right(t)) then propagate(right(t)) case on type (t) constant C: lattice(t) = C arithmetic operation: if all operands have constant lattice value then lattice(t) = arithmetic result of lattice values of operands else lattice(t) = endif store: lattice(t) = lattice(RHS) -function: lattice(t) = П of -arguments of t -function:
В данном случае переменные a3 и b3 будут всегда равны независимо от значения предиката P. Алгоритм, предложенный в [5], не сможет определить отношение значений переменных в данной ситуации. Предлагаемые изменения алгоритма привели бы предикат a3 > b3 к виду: (P, a1 > b1, a2 > b2) = (P, true, true) = true. Предлагаемые изменения алгоритма касаются обработки арифметических и логических выражений и состоят в следующем (E1, E2 – аргументы арифметического (логического) оператора): 1. E1 и E2 не содержат -функций, либо обе содержат -функции с разными предикатами. Используется обычное правило для вычисления арифмети-ческих и логических выражений. 2. Один из аргументов (E1 для определенности) содержит -функцию. Выполняется следующее преобразование: (P, V1, V2) op E2 = (P, V1 op E2, V2 op E2). 9
10
3. E1 и E2 содержат в себе -функции с одинаковыми предикатами. Выполняется следующее преобразование: (P, V1, V2) op (P, V3, V4) = (P, V1 op V3, V2 op V4).
if all operands have constant lattice value then lattice(t) = arithmetic result of lattice values of operands else lattice(t) = endif store: lattice(t) = lattice(RHS) -function: lattice(t) = lattice(left(t)) П lattice(right(t)) -function: propagate(predicate(t)) if lattice(predicate(t)) = C then lattice(t) = lattice value of -argument corresponding to C else lattice(t) = lattice(left(t)) П lattice(right(t)) endif -function: lattice(t) = -function: lattice(t) = lattice(-argument) default: lattice(t) = end case end propagate
5. Новый алгоритм t tuples lattice(t) = T unvisited(t) = true Visit all basic blocks B in the program Visit all tuples t within B propagate(t) propagate (tuple t) if not unvisited(t) return unvisited(t) = false label restart: if ssa_link(t) 0 then ssa_link(t) lattice(t) = lattice(t) П lattice(ssa_link(t)) endif if type(t) arithmetic operation propagate(left(t)) propagate(right(t)) endif case on type (t) constant C: lattice(t) = C arithmetic or logic operation: if type(left(t)) = -function or (type(right(t)) = -function then if type(left(t)) = -function and (type(right(t)) = -function or type(ssa_link(right(t))) = -function) and (predicate(left(t)) = predicate(right(t)) or type(ssa_link(left(t))) = -function) then join_common_predicate(t) goto restart else join_gamma_with_operand(t) goto restart endif else propagate(left(t)) propagate(right(t)) endif
11
Функция join_common_predicate объединяет две -функции с одинаковыми предикатами в одну: join_common_predicate (tuple t) tuple new_t = new -function predicate(new_t) = predicate(left(t)) left(new_t) = new operation node, same as t ssa_link(left(new_t)) = 0 unvisited(left(new_t)) = true lattice(left(new_t)) = T left(left(new_t)) = left(left(t)) right(left(new_t)) = right(left(t)) right(new_t) = new operation node, same as t ssa_link(right(new_t)) = 0 unvisited(right(new_t)) = true lattice(right(new_t)) = T left(right(new_t)) = left(right(t)) right(right(new_t)) = right(right(t)) t = new_t ssa_link(t) = 0 lattice(t) = T end join_common_predicate
Функция join_gamma_with_operand – объединяет -функцию и операнд, который не является -функцией:
12
join_gamma_with_operand (tuple t) tuple g, op tuple g_left = new operation node, same as t tuple g_right = new operation node, same as t if type(left(t)) = -function then g = left(t) op = right(t) left(g_left) = left(g) left(g_right) = right(g) right(g_left) = op right(g_right) = op else op = left(t) g = right(t) left(g_left) = op left(g_right) = op right(g_left) = left(g) right(g_right) = right(g) endif left(g) = g_left right(g) = g_right t = g
ветвления) или алгоритм классификации выражений, описанный в [2]. Первый вариант позволяет выполнить сравнения без значительных затрат времени. Второй позволяет найти одинаковые предикаты, которые не принадлежат одному оператору ветвления, но требует дополнительных затрат времени на классификацию предикатов. Литература 1. А. Ахо, Р. Сети, Д. Ульман. Компиляторы: принципы, технологии и инструменты.: Пер. с англ. – М.: Издательский дом «Вильямс», 2001. 2. B. Alpern, M. N. Wegman, F. K. Zadeck. Detecting equality of variables in programs, 1988. 3. R. A. Balance, A. B. Maccabe, and K. J. Ottenstein. The program dependence web: a representation supporting control-, data-, and demand-driven interpretation of imperative languages. In Proc. ACM SIGPLAN’90 Conf. on Programming Language Design and Implementation, June 1990. 4. S. Muchnick. Advanced compiler design and implementation, 1997. 5. E. Stoltz, M. Wolfe, M. P. Gerlek. Constant propagation: a fresh, demand-driven look, 1994. 6. E. Stoltz, M. Wolfe, and M. P. Gerlek. Demand-driven constant propagation. Technical Report 93-023, Oregon Graduate Institute, 1993. 7. P. Tu, D. Padua. Gated SSA-based demand-driven symbolic analysis for parallelizing compilers. ACM International Conference on Supercomputing, 1995. 8. M. N. Wegman, F. K. Zadeck. Constant propagation with conditional branches. ACM Trans. on Programming Languages and Systems, 13(2):181-210, July 1991.
unvisited(g_left) = true lattice(g_left) = T ssa_link(g_left) = 0 unvisited(g_right) = true lattice(g_right) = T ssa_link(g_right) = 0 end join_gamma_with_operand
6. Время работы алгоритма Т.к. в оригинальном алгоритме флаг unvisited для каждого узла не может измениться более одного раза, то это означает, что алгоритм посещает каждый узел единожды, поэтому время его работы может быть оценено как O(N), где N – количество узлов. Модифицированный алгоритм, как и исходный, посещает каждый узел представления программы единожды. В предельном (невозможном на практике) случае, однако, тип каждого узла может быть преобразован, поэтому время, необходимое для обработки одного узла, может увеличиться. Тем не менее, время работы алгоритма также представляет собой величину порядка O(N). Таким образом, улучшенный алгоритм обладает большими возможностями по обнаружению констант, чем исходный, лишь незначительно увеличивая время его работы (при том, что асимптотическая оценка времени работы остается той же). Для сравнения предикатов можно использовать сравнения указателей на них (т.е. предикаты эквивалентны, если они указывают на один и тот же оператор 13
14
2. Описание метода Производящая функция последовательности {an}, n>=0 – формальный степенной ряд:
Az a 0 a 1 z a 2 z 2 ... a n z n .
Анализ и оптимизация циклов с помощью производящих функций
n 0
П.М. Довгалюк (
[email protected]) Аннотация. В статье рассматривается метод анализа и оптимизации циклов с помощью производящих функций, состоящий в поиске выражений для конечных значений переменных, которые вычисляются в цикле и замене цикла вычислениями по формуле.
1. Введение Существует множество методов оптимизации циклов. Большинство методов только изменяют структуру цикла, оставляя его в программе. Среди них выделяется метод оптимизации циклов, которые не выполняют никаких действий, кроме изменения некоторых переменных. Для этого используется интерпретация циклов на этапе компиляции, если количество итераций невелико [3]. Если же число итераций превышает некоторое пороговое значение, то данный метод оказывается неэффективным. В данной статье рассматривается метод оптимизации циклов следующего вида с помощью производящих функций: для v V | v = v → C While (P) для v V | v = T(v, C) где: V – множество переменных, используемых в цикле, N – мощность этого множества; C – множество констант; V → C – множество начальных значений переменных, используемых в цикле; P – предикат, сигнализирующий об окончании цикла, представляющий собой результат применения логических и алгебраических операций к переменным из множества V и константам из множества C; T(V, C) – множество функций преобразования элементов множества V, используемых в цикле.
15
Переход от последовательностей к их производящим функциям позволяет заменить операции над последовательностями операциями над их производящими функциями. Идея метода производящих функций состоит в том, что рекуррентное соотношение, определяющее последовательность {an}, переписывают как уравнение для ее производящей функции, это уравнение решают и по найденной производящей функции получают зависимость общего члена последовательности {an} от n. Для того, чтобы получить алгебраические выражения для значения каждой переменной в зависимости от номера итерации, необходимо преобразовать операции, изменяющие значения переменных, в рекуррентные соотношения вида: v0 c v i t (V i 1 , V i , C ), где i – номер итерации; t – функция преобразования переменной v, принадлежащая множеству T; Vi-1 – значения переменных, полученные на предыдущей итерации; Vi – значения переменных, полученные на текущей итерации. Производящие функции (или выражения для vi) достаточно просто можно получить для присваиваний вида:
vi f V i 1 v, V i , C .
В этом случае для получения выражения для vi достаточно подставить выражения для всех остальных переменных в правую часть или найти производящую функцию для f. Пользуясь методикой из [2], каждый оператор присваивания вида vi f 0 vi 1 f V i 1 v, V i , C можно записать в виде алгебраического тождества, включающего производящие функции для переменных из множества V: Fv ( z ) G FV , C , z c , где Fv(z) – производящая функция для переменной v; FV – множество производящих функций для переменных, принадлежащих множеству V; G – некоторая алгебраическая функция. Найти алгебраическое выражение (возможно, содержащее в себе другие производящие функции) для производящей функции для f можно, пользуясь
16
линейностью производящих функций: производящая функция суммы равняется сумме производящих функций. Для каждого из слагаемых существует следующий выбор: 1. Производящую функцию можно определить непосредственно (например, если слагаемое представляет собой константу, умноженную на переменную) по таблице производящих функций из [2]. 2. Производящую функцию нельзя получить непосредственно. Например, ai bi . В этом случае необходимо подставить выражения для всех переменных (ai и bi), а затем найти производящую функцию для последовательности, которую генерирует это выражение при изменении i от 0 до бесконечности. 3. Производящую функцию нельзя получить непосредственно (как в случае 2), но выражения для ai и bi (см. случай 2) невозможно получить без знания выражения для vi+1. В этом случае предлагаемый метод не работает. Полученные выражения для переменных можно подставить в P, чтобы определить номер итерации, на которой произойдет выход из цикла. Если данную задачу удается решить, то цикл может быть заменен вычислениями по формуле или просто подстановкой констант в случае, когда все параметры, входящие в выражения для результирующих переменных известны на этапе компиляции. Рассмотрим несколько примеров: 1. Переменная, которая в каждой итерации умножается на константу и к результату прибавляется другая константа: v0 c0
vi c1 vi 1 c 2 Найдем производящую функцию для данной последовательности:
v z i
i0
i
z c v z z z c z v z
c0 c2
V z c0 c2
i
i 1
1
i 1
1
i0
i
vik
i
i0
c z V z c0 2 c1 z V z 1 z c0 c2 z V z 1 c1 z 1 z 1 c1 z
vij c j
j 1
N
v
j i 1
cj
j k
где k – номер переменной (переменные с номерами меньше k изменились в текущей итерации, с номером большим k – будут изменены позднее). Применяя манипуляции, подобные использованным в предыдущем пункте, можно получить следующий результат: k 1
Vk ( z )
N
V j ( z) c j z
j 1
V ( z) c j
j
c0
j k
Отсюда можно получить выражение для Vk(z), а из него – выражение для vki. 3. Многочлен от переменных, выражения для которых имеют вид (*): v0k c0
vik P v1i ,..., vik 1 , vik11 ,..., viN1 c1 vik1
Метод, применяемый в предыдущих примерах здесь не сработает, поэтому необходимо выполнить подстановку выражений для vji в данную формулу, что приведет к появлению многочлена от i: vik R (i ) c1 vik1
Производящая функция для in не существует в простой форме, однако ее можно выразить через производящие функции для числа сочетаний: i n i 1 z i 1 C nni z i n 1 n! 1 z i 0 i 0
I1 z Ci2 2
I 2 z
и так далее. 17
1 1 z
1 z i 2 i 1 2
2
c1i
1 c1 1
1
2! 2 2 2 1 i 2 C i: i 2 3 i 2 2 C i 2 3 C i 1 1
Отсюда можно получить алгебраическое выражение для v в зависимости от номера итерации: для c1 = 1: vi c0 c 2 i (*) для c1 1: vi c0 c1i c 2
k 1
Отсюда можно получить производящие функции для in: i 1 Ci11 1! 1 1 i : i C i 1 1
i 1
i
v 0k c 0
z i vi i 0 c0 z i i 0 c1 vi 1 c2 z i i
2. Линейная комбинация переменных:
18
2
1 z
3
3
1 z
2
1 1 z
Таким образом, производящая функция для vki будет иметь вид: z Vk z ri I i z c0 1 c1 z i 0
где ri – коэффициент при in в R(i), а Ii(z) – производящая функция для in.
3. Выводы В статье рассмотрен метод анализа циклов с помощью производящих функций. Несмотря на то, что не все циклы могут быть подвергнуты анализу с помощью данного метода, его можно применить для решения нижеперечисленных задач: 1. Данный метод выполняет задачу, обратную описанной в [3, разд. 14.1.1] – т.е. заменяет инкрементальные вычисления вычислениями по формуле. Кроме того, в процессе анализа цикла с помощью данного метода можно найти все его индуктивные переменные. 2. Компилятор, проделав все вышеприведенные вычисления, может либо заменить результат вычислений на константу (если все параметры являются постоянными), либо использовать вместо цикла соответствующую формулу. 3. Если цикл, подобный вышеприведенному, является вложенным в какойлибо другой, то производящие функции для переменных из V можно использовать описанным выше способом при оптимизации главного цикла. 4. Данный метод, как и многие другие методы алгебраической оптимизации, может быть использован только для целых чисел из-за возможной потери точности или переполнения чисел с плавающей точкой. 5. Полученные выражения для переменных могут быть использованы при анализе зависимостей между переменными, определении псевдонимов, устранении общих подвыражений (в том числе и полученных при выполнении аналогичных действий в различных циклах), при устранении незначимых вычислений, при определении индуктивных переменных. 6. Аналогичный подход может быть применен при оптимизации некоторых видов рекурсивных вычислений. Литература 1. А. Ахо, Р. Сети, Д. Ульман. Компиляторы: принципы, технологии и инструменты.: Пер. с англ. – М.: Издательский дом «Вильямс», 2001 2. Р. Грэхем, Д. Кнут, О. Паташник. Конкретная математика. Основание информатики: Пер. с англ. – М.: Мир, 1998 3. S. Muchnick. Advanced compiler design and implementation, 1997
19
Инкрементальная верификация объектно-ориентированных данных на основе спецификации ограничений1 В.А. Семенов, С.В. Морозов, О.А. Тарлапан Аннотация. Рассматриваются задачи полной и инкрементальной верификации объектно-ориентированных данных. На основе теории графов строится формальный аппарат, а также описываются разработанные методы инкрементальной верификации, использующие статический анализ спецификации ограничений и позволяющие локализовать область потенциальных нарушений при изменении данных. Методы предоставляют весомую альтернативу полной верификации прикладных данных при локальных изменениях, преобладающих в многопользовательских графических приложениях. Постановка задачи и методы описываются применительно к языку EXPRESS, предоставляющему универсальную нотацию для спецификации объектноориентированных моделей данных и ограничений на них.
1. Введение Обеспечение целостности является одним из фундаментальных ACID (atomicity, consistency, isolation, durability) принципов мультидоступа к данным на основе транзакций [1]. Для реализации данного принципа современные информационные системы должны предусматривать механизмы, которые бы гарантировали удовлетворение ограничений целостности сразу после завершения транзакции (integrity constraint enforcement). Наиболее распространенными являются подходы, связанные с проверкой ограничений (integrity constraint checking) и поддержкой целостности (integrity constraint maintenance). Первый консервативный подход предполагает проверку целостности всякий раз перед завершением транзакции и в случае выявленных нарушений отмену всех изменений, принятых в ее ходе. В рамках второго альтернативного подхода при изменениях, влекущих нарушение условий целостности, предпринимается попытка дополнительной модификации данных с тем, чтобы их окончательное состояние полностью им соответствовало. Оба подхода имеют известные преимущества и недостатки. Этим вопросам, применительно, прежде всего, к дедуктивной и реляционной метамоделям, посвящены обширные исследования. Достаточно упомянуть исчерпывающие обзоры работ [2–4].
В существенно меньшей мере внимание уделяется проблемам обеспечения целостности прикладных объектно-ориентированных данных, модели которых специфицированы, в частности, на популярных универсальных языках объектно-ориентированного моделирования EXPRESS [5] и UML/OCL [6]. Подобные модели предоставляют дополнительные возможности для статического и динамического анализа зависимостей между данными и учета локальности инкрементальных изменений, преобладающих в многопользовательских графических приложениях [7]. В разделе 2 вводится формальная объектно-ориентированная метамодель. Раздел 3 иллюстрирует ее на примере языка моделирования EXPRESS, предоставляющего нейтральную к реализации универсальную нотацию для спецификации объектно-ориентированных данных и ограничений на них. Особое внимание уделяется возможным видам ограничений, допускаемых конструкциями языка. В разделе 4 рассматривается общая постановка задачи верификации прикладных данных на основе спецификации ограничений. Вспомогательные понятия с привлечением аппарата теории графов вводятся в разделе 5. Здесь же приводятся конструктивные утверждения относительно зависимостей между данными и возможностей локализации нарушений целостности. Данные утверждения легли в основу разработанных методов инкрементальной верификации, которые детально описываются в разделе 6. В заключении даются общие рекомендации по их практическому применению и обозначаются направления для дальнейших исследований.
2. Объектно-ориентированная метамодель Рассмотрим сначала наиболее общие понятия, представляющие информационную объектно-ориентированную метамодель, подходящую для специфицирования произвольной предметной области. Используемая здесь формализация следует методу, применяемому в семантическом анализе языков [8, 9]. Определим объектно-ориентированную метамодель как информационную схему S T , , Rule со следующим значением: T T D T D C — множество типов данных информационной схемы, состоящее из основных типов TD , отображаемых в основную область семантики D, сложных типов TD , отображаемых в многозначную область семантики D , а также объектных типов (классов) C; — частичный порядок на T, отражающий отношения обобщения/специализации между типами данных и используемый в качестве основы для встраиваемого механизма полиморфизма; Rule RuleT Rule S — множество правил, налагающих ограничения целостности данных. Правила подразделяются на локальные RuleT ,
1 Работа поддержана грантами РФФИ (04-01-00527) и Фонда содействия отечественной науке (http://www.science-support.ru).
21
22
определяемые на отдельных типах данных, и глобальные Rule S , определяемые на некоторой совокупности типов информационной схемы. Важные свойства или характеристики объектов представляются их атрибутами. Имя атрибута определяет роль, играемую связанным с ним значением, в контексте того объекта, в котором оно появляется. Тип данных атрибута определяет область его возможных значений. Обозначим AttrC множество атрибутов информационной схемы или, точнее, множество сигнатур операций ac : C T , a c : C T C для функций доступа к значениям атрибутов. Объявление атрибута ac AttrC в объекте типа C устанавливает отношение между типом данных объекта и типом данных {m:n}
{ p:q}
атрибута T: C.a T , где 0 m n ограничивают количество элементов в прямом отношении от C к T, а 0 p q — в обратном отношении от T к C. Данную запись следует интерпретировать так: для каждого объекта типа C роль a играется не менее чем m и не более чем n экземплярами типа T, для каждого экземпляра типа T существует от p до q объектов типа C, в которых T играет роль a. Если в качестве типа атрибута выступает другой объектный тип, то данный атрибут представляет связь (ассоциацию) между двумя объектными типами. Состояние объектов определяется значениями их атрибутов. Поведение отдельных объектов характеризуется множеством локальных правил RuleC , которые могут определять количество, тип и организацию атрибутов, а также налагать ограничения на их значения. Формально, данные правила являются множеством сигнатур операций rulec : C logical . Ограничения на множество объектов (возможно, разных типов C1 , , C n ) налагают глобальные правила Rule S , представляющие собой сигнатуры операций rule S : C1 , C n logical .
описания моделируемых объектов реального мира. При создании языка EXPRESS ставилась задача избежать, насколько это возможно, влияния особенностей реализации. Таким образом, EXPRESS является декларативным объектно-ориентированным языком. В настоящее время он широко используется в качестве стандартного средства спецификации моделей данных для различных отраслей науки и промышленности. Рассмотрим вкратце семантику языка EXPRESS, используя описанную в предыдущем разделе метамодель.
3.1. Типы данных и операции над ними Язык EXPRESS определяет основные типы {Real, Integer, Number, Boolean, Logical, String, Binary} TD , соответствующие простым типам данных с общепринятой семантикой. Сложные типы {Aggregate, Bag, Set, List, Array, Enumeration, Select, Defined} TD соответствуют различным типам множеств, перечисляемым типам, выборкам и переопределенным типам, которые допускают определение производных и вложенных структур данных. Типы данных объектов C в языке EXPRESS определяются декларацией Entity. На Рис. 1 представлена общая классификация имеющихся в языке EXPRESS типов. Типы, отмеченные жирным курсивом, соответствуют его исходным типам. Стрелки показывают отношения наследования между ними. Виртуальные типы, отмеченные обычным шрифтом, используются только для того, чтобы единообразно классифицировать конструкции языка и представить типы, определяемые пользователем. GENERIC
SIMPLE
CONSTRUCTED
ENUMERATION
Способом, аналогичным алгебраической спецификации, предоставим сигнатуру S (TD TD C , , D D AttrC RuleT Rule S ) , где D , D
являются множествами операций, определенных над основными и
сложными типами. Сигнатура, сформированная подобным способом, описывает типы и символы операций, принадлежащие к объектноориентированной метамодели S, а также содержит исходное множество синтаксических элементов, над которыми могут быть определены выражения Expr ({ var T } T T D T C ) с переменными, индексируемыми данными типами.
STRING
NAMED
SELECT
DEFINED
LOGICAL
NUMBER
BINARY
BOOLEAN
REAL
SET OF GENERIC
INTEGER
SET
AGGREGATE
ENTITY
BAG OF GENERIC
LIST OF GENERIC
ARRAY OF GENERIC
BAG
LIST
ARRAY
D
3. Язык моделирования EXPRESS EXPRESS — это формальный язык информационного моделирования [5]. Он основан на определении объектов, представляющих формализованные 23
Рис. 1. Классификация исходных типов языка EXPRESS. Простыми типами данных являются Boolean, Logical, Number (включая конкретные подтипы Real и Integer), String и Binary. Интерпретация простых типов является обычной, но каждое множество расширяется специальной вели24
чиной ?, обозначающей неопределенное значение. Тип T TD отображается в область семантики D функцией I : T D следующим образом: I (Boolean) = {true, false} {?} , I (Logical) = {true, false, unknown} {?} , I (Real) = R {?} , I (Integer) = Z {?} , I (String) = A* {?} , где A — конечный алфавит, A* — множество всех последовательностей над алфавитом A , и I (Binary) = {0,1}* {?} . Длины строк и двоичных последовательностей могут быть неограниченными, ограниченными сверху или фиксированными. Над простыми типами определено множество операций. Существует несколько групп операторов: {+, -, *, /, **: Number Number Number; +, -, abs: Number Number} {div, mod: Integer Integer; odd: Integer Logical} {sin, cos, tan, asin, acos, atan, exp, log, log2, log10, sqrt: Number Real} {format: Number String String; value: String Number} {and, or, xor: Logical Logical Logical; not: Logical Logical} {+: String String String, like: String String Logical; length: String Integer; []: String Integer A, [:]: String Integer Integer String} {+: Binary Binary Binary; blength: Binary Integer; []: Binary Integer 0|1, [:]: Binary Integer Integer Binary} {=, , =, : Number Number Logical, Logical Logical Logical, String String Logical, Binary Binary Logical}. Семантику данных операций легко истолковать. В частности, это арифметические операции над числовыми операндами типов Number, Real, Integer и стандартные математические функции; преобразование чисел в строковое представление и обратно; логические операции над логическими операндами типов Logical или Boolean; конкатенация, сопоставление с образцом, индексация, выделение подмножества над операндами типов String и Binary, а также операции сравнения, определенные для всех простых типов. Некоторые операции имеют тот же самый перегруженный символ в качестве имени и могут различаться только по типам своих аргументов. Созданные типы, которыми могут являться перечисление либо выборка, расширяют множество основных типов. Область определения перечисляемого типа Enumeration задается упорядоченным множеством значений, представленных уникальными именами I ( Enumeration(ai , i 1, , n)) {ai A* , i 1, , n} {?} . На литералы перечисляемого типа ссылаются как на элементы перечисления. Порядок элементов перечисления предопределяется их относительными позициями. Данное упорядочение дает в результате операции сравнения, определенные между значениями, относящимися к одному и тому же перечисляемому типу: {=, , =, : Enumeration Enumeration Logical}. 25
Выбираемый тип данных Select определяет производный тип, представляемый списком других исходных типов. Экземпляр выбираемого типа данных является экземпляром одного из типов, заданных в списке выбора. Допускается, что экземпляр данных принадлежит одному из нескольких возможных типов. Другими словами, область определения значений для подобного типа является объединением областей определения типов в его I ( Select (Ti , i 1, , n)) I (T1 ) I (Tn ) {?} . Выбираемый тип списке является обобщением каждого из типов данных, перечисленных в его списке. К поименованным относятся типы данных, определяемые пользователем в конкретных информационных схемах. Так, определенный (Defined) тип данных является пользовательским расширением стандартных типов (простых, созданных или агрегатных), при этом он дает возможность определить дополнительные семантические ограничения, налагаемые на специфицируемые данные I ( Defined (T )) I (T ) {?} . Определенный тип является конкретизацией исходного типа данных, который используется при его объявлении. Объектные типы определяются пользователем с помощью конструкции ENTITY. При специфицировании объектного типа указываются его явные (EXPLICIT) атрибуты (в том числе ассоциативные связи с другими объектными типами), обратные ассоциации (INVERSE), а также производные вычисляемые свойства (DERIVED), определяемые типами и выражениями, которые могут включать в себя значения явных атрибутов, константы, исполняемые операторы, включая вызов функций и процедур, как стандартных, так и пользовательских. Язык EXPRESS предусматривает разнообразные модели простого и множественного наследования объектных типов. Объект производного типа наследует все атрибуты, определяемые в его родительских типах. При этом допускается переопределение отдельных атрибутов с целью специализации их типов, постановки более жестких ограничений на них или задания другого выражения для вычисляемых свойств. Кроме того, явные атрибуты базовых типов могут быть переопределены как вычисляемые в типах-наследниках. Над объектными типами определены следующие операции: {=, , :=:, :: : C C Logical} {rolesof: C Set(String), usedin: C String Bag(C)}. Операторы сравнения = и реализуют глубокий алгоритм сравнения объектов. В отличие от них, операторы :=: и :: проверяют лишь эквивалентность экземпляров (или совпадение идентификаторов объектов). Функция rolesof возвращает набор строк, содержащих имена ролей (ассоциативных атрибутов), играемых заданным объектом. Функция usedin возвращает множество объектов, которые используют указанный объект в заданной роли (под C здесь понимается некий обобщенный объектный тип). Вследствие наличия данной функции все связи между объектами в языке EXPRESS являются двунаправленными. Инверсные атрибуты используются лишь для именования ряда обратных связей, а также постановки ограничений 26
использования объектов в связях с другими, о чем будет упомянуто в следующем разделе. Многозначные выражения в языке EXPRESS описываются агрегатными типами. Агрегации используются для представления упорядоченных и неупорядоченных коллекций данных каких-либо основных, предопределенных сложных и объектных типов. Они конструируются путем указания типа для их элементов. Эти коллекции могут иметь фиксированные или переменные размеры, хранить уникальные или дублированные представления элементов, а также могут допускать неопределенные элементы, что дает в результате разреженные структуры данных. Как и любой другой тип данных языка EXPRESS, сами агрегации могут иметь неопределенное значение (это состояние следует отличать от пустой коллекции, не содержащей ни одного элемента). Так, тип данных Array (массив) представляет собой структуру с фиксированным размером, где существенной является индексация элементов. Опционально массивы могут допускать, что не все их элементы имеют значение. Свойство уникальности массивов означает, что каждый элемент отличается от любого другого в одном и том же экземпляре массива. Тип данных List (список) представляет упорядоченную коллекцию идентичных элементов. Список может хранить любое количество элементов, допуская или, опционально, не допуская их дублирование. Тип данных Bag (мультимножество) является коллекцией элементов, в которой порядок не является важным и допускается дублирование. И, наконец, Set (набор) является коллекцией элементов, в которой порядок не является важным и дублирование Количество элементов в списках, элементов не допускается. мультимножествах, наборах может изменяться в зависимости от определения их границ. Важно, что агрегатные типы могут быть вложенными, таким образом давая в результате многомерные структуры данных. Над агрегатными типами в языке EXPRESS определены следующие группы операций:
Aggregate( T2 ) Aggregate(T)} {=, , =, :=:, :: : Aggregate( T1 ) Aggregate( T2 ) Logical} {in, value_in: T Aggregate(T) Logical, value_unique: Aggregate(T) Logical, query: Aggregate(T) Logical Expression Aggregate(T)} {[]: Aggregate(T) Integer T} {sizeof, hiindex, loindex, hibound, lobound: Aggregate(T) Integer} {insert: List(T) T Integer List(T), remove: List(T) Integer List(T)}.
{+, -, *: Aggregate( T1 )
Операторы над множествами +, -, * определяются для объединения, вычитания и пересечения коллекций совместимых типов T1 , T2 (т.е. одинаковых типов или типов, один из которых является подтипом или конкретизацией другого). Операторы сравнения, включая операторы подмножества и надмножества =, предназначены для установления отношений равенства и общности между 27
совместимыми по типу коллекциями. Операторы сравнения экземпляров :=:, :: отличаются от операторов сравнения значений =, лишь для коллекций объектов, используя соответствующие вышеупомянутые операции, определенные над объектными типами. Для коллекций остальных типов данных операторы сравнения экземпляров эквивалентны соответствующим операторам сравнения значений. Операторы принадлежности in и value_in проверяют наличие в коллекции некоторого элемента, используя, соответственно, операции эквивалентности экземпляров и равенства значений. Функция value_unique проверяет уникальность по значению всех элементов коллекции. Выражение запроса query вычисляет логическое условие отдельно для каждого элемента коллекции и возвращает коллекцию, содержащую те элементы, для которых логическое выражение истинно. Оператор индексирования [] извлекает из коллекции отдельный элемент. Операции sizeof, hiindex, loindex, hibound, lobound возвращают, соответственно, количество элементов в агрегации, верхний и нижний индексы элементов массива, верхнюю и нижнюю границы списков, мультимножеств и наборов. Операции insert и remove определяются дополнительно, чтобы упростить манипулирование специфическими коллекциями — списками. Агрегации, выборки и определенные типы могут быть вложенными, поэтому в языке EXPRESS допустимо составление более сложных типов. В нетривиальных прикладных моделях данных невозможно избежать подобных сложных структур. Возможная дополнительная классификация типов не противоречит описанной в предыдущем разделе объектно-ориентированной метамодели. В частности, в языке EXPRESS в отдельную группу выделяются обобщенные типы данных Generic, Aggregate, Bag Of Generic, Set Of Generic, List Of Generic, Array Of Generic, которые используются для установления обобщения других типов данных и могут применяться в очень специфических контекстах (для представления формальных параметров, локальных переменных и результатов функций). Следующие операции, определенные над обобщенными типами, применимы к любому типу данных языка EXPRESS: {exists: Generic Boolean; nvl: T T T; typeof: Generic Set(String)}. Это функция проверки существования значения (возвращает true в случае фактического значения ее параметра или false в случае неопределенного значения), функция возврата альтернативного значения, если исходный параметр находится в неопределенном состоянии, а также функция, определяющая тип данных входного параметра (возвращает имена всех типов, членом которых является ее входной параметр).
3.2. Ограничения в языке EXPRESS Помимо декларативной части, содержащей описания типов данных, язык EXPRESS имеет и исполняемые операторы, связанные с проверкой правил и вычислением значений производных атрибутов. Правила налагают 28
ограничения на область определения значений специфицируемых типов данных. Помимо правил в языке EXPRESS существуют и другие виды ограничений, связанные со способом организации и типом атрибутов отдельных объектов. Ограничения являются критериями целостности данных, специфицируемых на языке EXPRESS. Можно выделить три группы ограничений в зависимости от места их определения (утверждения). К первой группе относятся ограничения, налагаемые на отдельные типы данных (и атрибуты соответствующих типов), а именно: длины в строковом типе данных: ограничение length( String ) n, n Z , n 0 для строк переменной длины или length( String ) n, n Z , n 0 для строк фиксированной длины (если n не указано в спецификации типа, ограничение отсутствует); длины в двоичном типе данных: ограничение blength( Binary ) n, n Z , n 0 для двоичных последовательностей переменной длины или blength( Binary ) n, n Z , n 0 для двоичных последовательностей фиксированной длины (если n не указано в спецификации типа, ограничение отсутствует); ограничение количества элементов в агрегатном типе данных: m sizeof ( Aggregate(T )) n, m Z , n Z , 0 m n для списков, мультимножеств и наборов (для данных разновидностей агрегатов ограничение отсутствует, если m=0 and n=?), sizeof ( Array (T )) n m 1, m Z , n Z , m n для массивов (в данном случае m, n указывают диапазон изменения индекса элементов); запрет на наличие повторяющихся элементов в агрегатном типе данных: elem i : : elem j , i 1, , sizeof ( Aggregate ( T )) 1, j i 1, ,
типа при проверке соответствующего правила; область значений определенного типа данных Defined(T) состоит из всех значений области определения значений исходного типа T, не нарушающих ни одно из данных правил); требование совместимости типов атрибута и присваиваемого ему значения: Tvalue Tattr — типы должны совпадать или тип присваиваемого значения должен быть специализацией типа, приписанного атрибуту (наиболее часто проверяют совместимость типа ассоциированного объекта с типом ассоциации). Во вторую группу входят локальные ограничения, которые устанавливаются в объектных типах данных и действуют для каждого объекта соответствующего типа. Локальные ограничения, определенные в базовом типе объекта, наследуются всеми его производными типами, как и атрибуты. К данной группе относятся: запрет на неопределенные значения для явных атрибутов объекта: exists(attri ) True, i 1, , k , где k — количество явных обязательных атрибутов (ограничение может быть снято указанием ключевого слова OPTIONAL в спецификации атрибута); ограничения использования объекта в ассоциативных связях с другими объектами, устанавливаемые через его инверсные атрибуты: m:n} { p:q} C1 .a { C 2 .inv _ a, p sizeof (inv _ a ) q, p Z , q Z , 0 p q , если инверсный атрибут имеет тип мультимножества или набора объектов C1 , причем в последнем случае дополнительно устанавливается ограничение уникальности инверсного отношения: inv _ a i :: inv _ a j ,
i 1, , sizeof (inv _ a ) 1, j i 1, , sizeof (inv _ a ) (т.е. объект типа C 2 не может играть роль a более одного раза в одном и том же объекте типа C1 ), sizeof (inv _ a ) 1 , если инверсный атрибут имеет тип объекта C1 ; уникальности экземпляров отдельного атрибута: ограничения oi .a :: o j .a, T (oi ) C , T (o j ) C — никакие два объекта совместимых
sizeof ( Aggregate (T )) для списков и наборов (для наборов ограничение устанавливается по умолчанию, для списков — если в спецификации типа elem i :: elem j , i m, , указано ключевое слово UNIQUE),
n 1, j i 1, , n для массивов (в данном случае ограничение установлено, если в спецификации типа указано ключевое слово UNIQUE); заметим, что здесь используется операция эквивалентности экземпляров, а не равенства значений; запрет на наличие необязательных элементов в массиве: exists(elemi ) True, i m, , n (ограничение может быть снято указанием ключевого слова OPTIONAL в спецификации типа массива); ограничения области определения значений в определенном типе данных: f i ( self ) : Defined (T ) Logical ( f i ( self ) — опционально указываемые в спецификации определенного типа логические выражения, в которых переменной self присваивается текущее значение атрибута определенного 29
типов не должны использовать тот же самый экземпляр для атрибута, имя которого указано в простом правиле уникальности; ограничения уникальности комбинации экземпляров атрибутов: oi .a1 :: o j .a1 and oi .a 2 :: o j .a 2 and oi .a k :: o j .a k , T (oi ) C , T (o j ) C — никакие два объекта совместимых типов не должны использовать ту же самую комбинацию экземпляров атрибутов, список имен которых указан в совместном правиле уникальности; ограничения области значений в типе данных объекта: f i ( AttrC ) : C Logical ( f i ( AttrC ) — опционально указываемые в спецификации объектного типа логические выражения над атрибутами самого объекта (собственными и унаследованными от его супертипов) и, 30
возможно, объектов, ассоциированных с ним; объект попадает в область значений, если он не нарушает ни одно из данных правил). Наконец, к третьей группе относятся глобальные ограничения, налагаемые на все объекты одного или нескольких типов: f ( Set (C1 ), , Set (C k )) : C1 , , C n Logical . Другими словами, глобальное ограничение является логической функцией над наборами объектов тех типов, на которых оно установлено. Наборы объектов, не нарушающие глобальные ограничения, считаются верными. Заметим, что любое ограничение является логической функцией. Ограничение считается нарушенным, если только соответствующая функция возвращает false. Ограничение считается выполненным, если функция возвращает true. Если функция возвращает unknown, ограничение ни выполнено, ни нарушено (такое возможно, если в выражениях участвуют необязательные явные атрибуты объектов с вероятными неопределенными значениями). Рассмотрим пример использования ограничений в языке EXPRESS на фрагменте спецификации геометрической модели (см. рис. 2). Во-первых, ограниченной является область определения значений ряда атрибутов в специфицируемых типах объектов. Так, в качестве значений атрибута Identifier в объектном типе GeometryObject должны использоваться строки фиксированной длины в 16 символов, диапазон значений размерности (Dim) точек (Point), кривых (Curve) и их сегментов (CurveSegment) ограничен целыми числами в интервале от 1 до 3, что определяется правилом WR1 в типе Dimension, а также недопустимыми являются неопределенные значения для явных атрибутов всех типов объектов, за исключением атрибута TextCommentary в типе GeometryObject. Используемые агрегатные типы данных налагают ограничения на количество элементов в коллекциях Coordinates, определяемых в типе Point, и Segments, определяемых в типе CompositeCurve, причем в последней ограничено только минимальное количество элементов. Дополнительные ограничения на отдельные объекты налагают правила и инверсные атрибуты, определенные в соответствующих объектных типах. Так, правило UR1 устанавливает уникальность значений атрибута Identifier в объектах типа GeometryObject. Правило DimCoincide в объектном типе CompositeCurve определяет требование совпадения размерностей ассоциированных объектов типа CurveSegment. Правило CheckTransition в объектном типе CompositeCurve устанавливает, что сопряжение сегментов составной кривой должно быть непрерывным, за исключением последнего сегмента незамкнутой кривой. Заметим, что в данных правилах используются не только локальные атрибуты, но и атрибуты ассоциированного объектного типа CurveSegment. Также, на объекты типа CurveSegment посредством инверсного атрибута UsingCurves налагается следующее ограничение: сегмент должен быть ассоциирован по крайней мере с одной составной кривой, причем с одной и той же кривой он не может быть ассоциирован многократно. 31
Наконец, глобальное правило CurveDimensionsCoincide устанавливает следующее ограничение: в правильном наборе данных должны совпадать размерности всех кривых. SCHEMA Geometry; TYPE Dimension = INTEGER; WHERE WR1: { 0 < SELF John Smith
[email protected] Paul Brown
2 years 500
[email protected]
В документе "purchase-orders.xml" на рис. 1 простыми ссылками XLink являются элементы языка XML с именами item и customer; первые указывают на элементы каталога, вторые — на клиентов. Идентификация конкретного клиента осуществляется с использованием имеющихся в XMLдокументе "clients.xml" атрибутов типа ID, и при данном способе идентификации может использоваться сокращенный синтаксис XPointer, напоминающий обращение к именованному якорю в HTML. Для идентификации элемента в каталоге (XML-документ "catalogue.xml") используется полный синтаксис XPointer. Из рассматриваемого примера легко видеть, что по сравнению с гиперссылками HTML простые ссылки XLink обладают более гибкими и мощными возможностями по связыванию ресурсов и описанию семантики этих связей.
2 2 1
Рис. 1. Набор связанных с помощью XLink XML-документов, выражающих систему заказа товаров. Документ "catalogue.xml" (слева вверху) содержит каталог товаров; документ "clients.xml" (справа вверху) — данные о клиентах; документ "purchase-orders.xml" (внизу) — сделанные клиентами заказы из каталога. Элемент языка XML, являющийся ссылкой XLink, может носить произвольное имя, а принадлежность элемента к языку XLink и ссылочный тип элемента устанавливаются глобальным атрибутом xlink:type, где префикс xlink связывается с пространством имен, зарезервированным языком XLink. По аналогии с гиперссылками HTML, удаленный ресурс, на который указывает простая ссылка XLink, определяется атрибутом xlink:href. Значением атрибута xlink:href служит Унифицированный Идентификатор URI, возможно, включающий в себя идентификатор фрагмента на языке XPointer — для целевых ресурсов, представляющих собой фрагмент XML-документа. 125
2. Расширенная ссылка (extended link) — это ссылка, которая выражает полную функциональность языка XLink. Расширенная ссылка может объединять произвольное количество участвующих в ней ресурсов, и участвующие ресурсы могут быть любой комбинацией локальных и удаленных. Использование или следование по ссылке с какой-либо целью называется переходом (traversal). Несмотря на то, что расширенные ссылки могут соединять произвольное количество ресурсов, переход всегда включает в себя ровно 2 ресурса [1]. Информация о том, как осуществлять переход между парой ресурсов, включающая в себя направление перехода и его семантику, задается при помощи дуги (arc). Ввиду того, что расширенная ссылка предоставляет мощные возможности по связыванию ресурсов, структура расширенной ссылки может быть достаточно сложной. В общем случае она включает в себя элементы типа локатор [2], которые указывают на удаленные ресурсы; элементы типа ресурс, содержащие локальные ресурсы; элементы типа дуга, которые определяют дуги и условия перехода по ним. Дуга в языке XLink является ориентированной, и 2 ресурса, соединяемые дугой, называются соответственно исходным (starting resource) и целевым (ending resource) [2]. Дугу называют входящей (inbound), если ее исходный ресурс является удаленным ресурсом, а целевой ресурс — локальным. Дуга называется сторонней (third-party), если ни один из соединяемых ею ресурсов не является локальным. Благодаря наличию в языке XLink входящих и сторонних дуг обеспечивается возможность соединять ресурсы без их модификации. Обычно элементы типа “расширенная ссылка” располагаются отдельно от тех ресурсов, которые они соединяют (например, в совершенно разных документах). Расширенные ссылки важны для ситуаций, когда соединяемые ресурсы доступны только для чтения; или когда модификация этих ресурсов является дорогостоящей и сложной операцией, тогда как модификация отдельно располагающейся ссылки 126
достаточно проста; или когда ресурсы имеют форматы, не поддерживающие встроенные ссылки (как для многих мультимедийных форматов). Пример расширенной ссылки будет рассмотрен в разделе 5. Хотя простые ссылки концептуально являются подмножеством расширенных ссылок, они синтаксически различны. В частности, простая ссылка определяет дугу неявным образом, и поэтому для преобразования простой ссылки в расширенную ссылку требуется осуществить несколько структурных преобразований. Можно говорить о том, что предназначением простой ссылки является удобная короткая форма записи для эквивалентного случая расширенной ссылки [1]. Один элемент вида “простая ссылка” объединяет в себе базовую функциональность элементов типа “расширенная ссылка”, “локатор”, “дуга” и “ресурс”. В том случае, когда реально требуется лишь подмножество свойств этих элементов, простая ссылка удобна как альтернатива расширенной ссылке.
3. Родственные работы по предметной области В данном разделе рассматриваются работы, в которых делается попытка обеспечить язык запросов к совокупности XML-документов, связанных ссылками языка XLink, или предоставляются высокоуровневые возможности переходов по дугам XLink.
3.1. XQuery В качестве языка запросов, применимого к источникам XML-данных разнообразных типов, Консорциум Всемирной Сети [2] позиционирует язык Xquery [5]. Хотя на момент написания настоящей статьи язык XQuery еще не был переведен из чернового статуса в статус официальной Рекомендации Консорциума, уже можно с уверенностью говорить о том, что в своей текущей версии XQuery не предоставляет средств по обработке ссылок языка XLink в соответ-ствии со Спецификацией XLink, что подтверждается следующими соображениями: Описания ссылок языка XLink строятся на сложном и многословном синтаксисе, базирующемся на пространстве имен и иерархической взаимосвязи элементов языка XLink. При написании на XQuery запросов к XML-документам, содержащим элементы языка XLink, вся работа по распознаванию ссылок XLink и интерпретации их семантики целиком ложится на разработчика запросов. Необходимо также заметить, что получение информации о дугах, описанных в единственной расширенной ссылке языка XLink, требует написания на XQuery нескольких операций естественного соединения (join), выполнение которых дает значительную нагрузку на вычислитель языка XQuery. При соединении с помощью ссылки XLink удаленного ресурса, представляющего собой фрагмент некоторого XML-документа, идентификация данного фрагмента внутри документа осуществляется 127
с помощью языка XPointer, и идентификатор фрагмента включается в значение одного из глобальных атрибутов языка XLink. При обработке ссылок XLink с помощью XQuery для определения ресурсов, соединяемых с помощью ссылки, необходимо динамически вычислить идентификатор фрагмента на языке XPointer, полученный в качестве значения атрибута. В Библиотеке базовых функций XQuery [11] не существует функции, позволяющей интерпретировать идентификатор фрагмента, записанный на языке XPointer. Автору также не известна ни одна реализация XQuery, которая бы предоставляла интерпретатор языка XPointer внутри вычислителя запросов. Предлагаемый в настоящей статье язык запросов к совокупности XMLдокументов, связанных ссылками XLink, базируется на подмножестве XQuery — языке XPath, назначением которого является адресация структурных частей XML-документа. В настоящей статье предлагается расширение XPath высокоуровневой поддержкой XLink, функциональность языка запросов достигается благодаря возможности тесной интеграции XPath с функциональным языком программирования общего назначения Scheme.
3.2. Браузеры с поддержкой XLink Под поддержкой языка XLink браузером будем понимать способность браузера распознавать элементы языка XLink в XML-документе и обеспечивать пользовательский интерфейс для переходов между ресурсами по дугам XLink. Среди браузеров, обеспечивающих поддержку языка XLink, следует упомянуть такие, как Amaya, Mozilla и DocZilla. Первые два реализуют поддержку языка XLink лишь в масштабе простых ссылок XLink, браузер DocZilla обеспечивает также навигацию по расширенным ссылкам. Наличие лишь одного известного автору браузера, поддерживающего ссылки языка XLink в полном объеме (DocZilla), мотивируется сформулированными Консорциумом Всемирной Сети требованиями к языку XLink [4]. В то время как простые ссылки XLink явным образом ориентированы на внешнее представление, презентационный аспект расширенных ссылок XLink многими аналитиками ставится под сомнение [12]. Необходимо заметить, что браузеры с поддержкой языка XLink по своей природе нацелены на наглядное представление документов со ссылками XLink человеку. Поскольку браузеры являются прикладным программным продуктом, при их разработке не ставятся задачи обеспечения других приложений средствами высокоуровневой обработки XML-документов со ссылками XLink. В настоящей статье решается системная задача, и язык запросов к совокупности XML-документов, связанных ссылками XLink, разрабатывается из расчета на то, чтобы быть использованным другими приложениями.
128
3.3. Интерфейсы прикладного программирования
4.1. Обзор XPath
Интерфейсы прикладного программирования для обработки XML-документов, соединенных ссылками языка XLink, предоставляют системы XLip, X2X и ExtremeKnit. Все 3 обозначенные системы предоставляют интерфейсы прикладного программирования на языке объектно-ориентированного программирования Java. Ввиду использования объектно-ориентированного языка программирования для обработки XML-документов, все 3 системы — XLip, X2X и ExtremeKnit — страдают от проблемы несоответствия импеданса [13]. Так, в интерфейсах прикладного программирования, предоставляемых каждой из рассматриваемых 3 систем, для представления и обработки XML-документов со ссылками XLink разработана своя собственная система классов, и каждая из этих систем классов достаточно далека от древовидной структуры Информационного Пространства XML [14]. Помимо показанной проблемы несоответствия импеданса, все 3 интерфейса прикладного программирования являются достаточно низкоуровневыми. С различными вариациями отдельные методы языка Java используются для таких базовых операций, как загрузка отдельного XML-документа, получения набора ссылок, нахождения исходного или целевого ресурса для данной ссылки и т.п. Упомянутые методы связаны друг с другом только по их аргументам и возвращаемым результатам, что вынуждает разработчиков приложений вводить много локальных переменных и прослеживать сложные взаимосвязи между классами языка Java. Приложению приходится проводить много низкоуровневой рутинной работы, прежде чем будут получены все необходимые данные для переходов по ссылкам XLink и обработки связанных этими ссылками XML-документов. Язык запросов, предлагаемый в настоящей статье, обеспечивает более высокий уровень абстракции над синтаксисом языка XLink по сравнению с рассмотренными интерфейсами прикладного программирования. Использование функциональных методов программирования для сделанной реализации обеспечивает интеграцию предлагаемого языка запросов с языком программирования общего назначения Scheme на уровне узлов обрабатываемых документов (как списковых структур данных языка Scheme) и функций Scheme, что позволяет избежать проблемы несоответствия импеданса [15].
Назначение языка XPath — адресация структурных частей XML-документа. Ввиду того, что XML-документ является, в сущности, древовидной структурой, модель данных языка XPath [6] представляет документ как дерево узлов. Вычисление любого выражения XPath осуществляется относительно контекста. Основными составляющими контекста являются: Узел XML-документа (называемый также контекстным узлом); Контекстная позиция и контекстный размер, которые используются при определении взаимоотношения контекстного узла с остальными узлами. Основной конструкцией языка XPath является путь доступа (location path) [6]. Путь доступа применяется к контекстному узлу, и результатом вычисления является набор узлов (node-set) [2], состоящий из (возможно, нескольких) узлов, выбранных с помощью данного пути доступа относительно контекстного узла. Выбранные узлы соответствуют элементам, атрибутам, текстовым данным и другим частям XML-документа [16]. Путь доступа состоит из последовательности одного или более шагов доступа (location step), синтаксически отделяемых друг от друга символом косой черты (“/”). Шаг доступа включает в себя 3 составляющие: Ось (axis), определяющую соотношение в дереве между узлами, в контексте которых вычисляется шаг доступа, и узлами, которые выбирает шаг доступа. Ось можно считать направлением движения по дереву, представляющему XML-документ [16]. Спецификация XPath определяет 13 различных осей. Они включают в себя оси для спуска к листьям дерева, для подъема в сторону корня, для выбора соседних узлов и т.п. Синтаксически имя оси отделяется от остальной части шага адресации с помощью двойного двоеточия (“::”); Тест узла (node test), который определяет тип и, возможно, имя узлов, выбираемых шагом доступа. В то время как ось определяет направление движения, тест узла определяет желаемые узлы, которые должны быть выбраны; Ноль или более предикатов (predicates). Каждый предикат синтаксически записывается в квадратных скобках и используется для дальнейшего просеивания набора узлов, выбираемых шагом доступа. Шаги в пути доступа вычисляются по очереди слева направо. Самый левый шаг вычисляется первым, обычно по отношению к контекстному узлу — корню дерева XML-документа. Каждый последующий шаг доступа выбирает набор узлов, который вычисляется по отношению к набору узлов, выбранному предыдущим шагом доступа. Набор узлов, выбранный самым правым шагом доступа — это результат всего пути доступа для данного XML-документа. Пример пути доступа языка XPath приведен на рис. 2. Данный путь доступа состоит из 4 шагов доступа, во 2-м шаге доступа имеется один предикат, остальные шаги доступа предикатов не содержат. Если вернуться к рис. 1 и рассмотреть показанный на рис. 2 XML-документ "clients.xml", то нетрудно
4. Язык XPath и переходы по дугам языка XLink Предлагаемый в статье язык запросов к XML-документам, связанным между собой с помощью ссылок XLink, будет базироваться на языке адресации частей XML-документа XPath. В данном разделе сначала дается обзор языка XPath, затем рассматривается предлагаемое расширение функциональности XPath, обеспечивающее переходы по дугам языка XLink. 129
130
видеть, что путь доступа на рис. 2 для данного документа выбирает имя (name) человека (person), у которого имеется атрибут person-id со значением "per2". Специальный тест узла языка XPath text() используется в данном шаге доступа для адресации к текстовому узлу с целью получения имени. /child::clients/child::person[attribute::person-id = "per2"]/child::name/child::text()
Рис. 2. Пример пути доступа, который выбирает имя клиента, имеющего атрибут person-id со значением "per2" Помимо рассмотренного синтаксиса для записи путей доступа (называемого также полным синтаксисом), Спецификацией XPath определяется также укороченный синтаксис (abbreviated syntax) для наиболее употребительных конструкций языка. При дальнейшем изложении мы будем пользоваться двумя такими правилами укороченного синтаксиса: Ось child используется в шаге доступа по умолчанию, т.е. спецификатор child:: может опускаться; Разделитель в две идущие подряд косые черты (“//”) символизирует шаг доступа /descendant-or-self::node()/, выбирающий контекстный узел и всех его узлов-потомков. В виде сокращенного синтаксиса путь доступа, рассмотренный на рис. 2, может быть переписан так: //person[attribute::person-id = 'per2']/ name/text()
Мы будем пользоваться сокращенным синтаксисом для компактной записи рассматриваемых далее примеров.
4.2. Расширение XPath переходами по дугам языка XLink Заметим, что термин ось (axis) в XPath очень близок термину переход (traverse) в XLink, поскольку и тот, и другой подразумевают перемещение с одного места в документе на другое. Данное наблюдение убеждает нас в том, что при построении на основе XPath языка запросов к совокупности связанных XMLдокументов операции перехода по дуге XLink в языке XPath должна соответствовать ось. По аналогии с англоязычным названием для перехода в XLink назовем эту ось “traverse”. На содержательном уровне, если имеются узлы A и B, такие, что для некоторой дуги XLink узел A является исходным ресурсом, а узел B целевым, то при применении оси traverse к узлу A как к контекстному узлу результатом будет узел B. Если следовать общему стилю, принятому в Спецификации XPath при определении осей, то более строгое определение оси traverse будет выглядеть так:
131
Определение 1. Ось traverse содержит все узлы, являющиеся целевыми ресурсами для всех дуг XLink, для которых контекстный узел служит исходным ресурсом. Из определения следует, что ось traverse возвращает непустой набор узлов только тогда, когда контекстный узел является исходным ресурсом хотя бы для одной дуги языка XLink. Необходимо отметить, что осью traverse могут быть выбраны узлы, находящиеся в другом XML-документе, нежели контекстный узел; т.к. дуги языка XLink могут соединять ресурсы, находящиеся в разных XMLдокументах. Также в результате применения к контекстному узлу оси traverse может быть получен набор узлов из нескольких разных XMLдокументов, поскольку контекстный узел может быть исходным ресурсом для нескольких дуг XLink, и целевые ресурсы этих дуг могут располагаться в нескольких разных XML-документах. Если целевой ресурс является удаленным ресурсом в терминах XLink и представляет собой целиком XML-документ (т.е. при адресации к данному ресурсу не используется идентификатор фрагмента на языке XPointer), то осью traverse будет выбран элемент документа. Если при адресации к удаленному целевому ресурсу Унифицированный Идентификатор Ресурса (URI) используется совместно с идентификатором фрагмента на языке XPointer и данный идентификатор фрагмента вычисляется в некоторый набор узлов, то осью traverse будет выбран весь этот набор узлов. Выражение на языке XPath, расширенном предлагаемой осью traverse, позволяет прикладному приложению оперировать не с одним деревом XMLдокумента, а уже с деревьями нескольких документов, соединенных между собой с помощью ссылок языка XLink. При этом оси, определяемые Спецификацией XPath, замкнуты внутри отдельного дерева документа, а ось traverse позволяет осуществить переход между деревьями. Необходимо отметить, что хотя совокупность XML-документов, соединенных ссылками XLink, представляет собой граф, вычисление любого выражения XPath, расширенного предлагаемой осью traverse, всегда будет конечным по времени. Данное свойство предлагаемого расширения языка XPath объясняется тем, что все оси, являющиеся транзитивным замыканием других осей, не могут зациклиться, поскольку замкнуты внутри конкретного дерева XML-документа, где циклы отсутствуют по определению дерева. Вычисление оси traverse также всегда конечно, поскольку для любого набора узлов существует лишь конечное число дуг XLink, исходными ресурсами которых являются узлы из данного набора. Предложенная ось органичным образом вписывается в язык XPath, и при использовании данной оси в шаге доступа XPath полностью сохраняется семантика остальных составляющих шага доступа — теста узла и предикатов. Ввиду того, что по оси traverse можно перейти на узлы произвольного типа, 132
тест узла помогает конкретизировать тип и, возможно, имя узлов, выбираемых шагом доступа. Предикаты могут быть использованы для дальнейшего просеивания получаемого набора узлов в соответствии с некоторыми более сложными условиями. Как и для других осей, определенных спецификацией XPath, при применении предикатов к результату оси traverse контекстный размер равен количеству узлов в наборе, подлежащему фильтрации. Что касается контекстной позиции каждого узла, то для неупорядоченных наборов узлов — таких как атрибуты и объявления пространств имен — в Спецификации XPath сопоставление каждого узла с контекстной позицией объявляется зависящим от реализации [6]. Аналогичный подход может быть применен и для набора узлов, получаемый в результате оси traverse, т.к. по этой оси в общем случае осуществляется переход сразу по нескольким дугам XLink, которые не упорядочены между собой. Альтернативным подходом к сопоставлению узла с контекстной позицией может быть подход, принятый в языке XQuery: узлы в пределах одного XML-документа упорядочиваются в порядке обхода дерева документа, узлы из разных документов упорядочиваются произвольным, но единообразным образом для конкретной реализации [5]. Предлагаемая дополнительная ось traverse позволяет прикладному приложению осуществлять переходы по дугам языка XLink полностью прозрачным образом, без необходимости распознавать элементы XLink в XML-документе и разбирать их в соответствии с синтаксисом языка XLink с целью извлечения семантики дуг. Вне зависимости от того, где была определена дуга — в простой ссылке, или в расширенной ссылке, располагающейся в том же документе, или даже в отдельном документе, — переход по дуге осуществляется унифицированным образом. Для иллюстрации предлагаемого расширения языка XPath осью traverse вернемся к рисунку 1, выражающему систему заказа товаров в виде 3 связанных XML-документов, и рассмотрим несколько примеров написания практических запросов к данной системе связанных документов. Пример 1. Найдем имена всех клиентов, заказавших принтеры. Для получения ответа на этот запрос требуется соединить данные изо всех 3 XML-документов на рис. 1, и соединение должно проводиться на основе ссылок XLink, связывающих части этих документов. Поскольку в рассматриваемой системе связанных XML-документов все ссылки языка XLink исходят из документа "purchase-orders.xml", описывающего сделанные заказы, то запрос будет адресоваться именно к этому документу, и наличие ссылок XLink позволит выбрать необходимую информацию из остальных документов с помощью оси traverse. Путь доступа, реализующий требуемый запрос, может быть записан следующим образом: //order[entry/item/traverse::printer]/ customer/traverse::person/name/text() 133
Шаг доступа, содержащий предикат и записанный в первой строке пути доступа, выбирает те выполненные заказы, в которых имеется хотя бы одно вхождение (entry) принтера среди заказанных товаров. Ось traverse внутри предиката осуществляет переход из каждого вхождения в заказе на каталог товаров; и тест узла printer позволяет указать, что из всех заказанных элементов каталога нас интересуют принтеры. Во второй строке пути доступа, после того, как заказы были выбраны, осуществляется адресация к именам клиентов, сделавших соответствующие заказы. При адресации к именам клиентов снова используется ось traverse, и в этом случае она осуществляет переход уже на конкретного человека в документе "clients.xml", т.к. переход осуществляется по ссылке, ведущей от заказа к покупателю. Результат вычисления запроса выбирает имя искомого клиента: John Smith Пример 2. Найдем список товаров, заказанных важным клиентом (в описании которого имеется вложенный элемент ). С помощью языка XPath, расширенного осью traverse, данный запрос может быть реализован в виде следующего пути доступа: //order[customer/traverse::person/VIP]/ entry/item/traverse::* В отличие от примера 1, здесь заказы фильтруются в соответствии с условием, накладываемым уже на клиента. Результат запроса состоит из двух элементов каталога, и в соответствии с нотацией, принятой в XQuery для записи последовательности из нескольких узлов [5], мы записываем результат в круглых скобках, отделяя узлы друг от друга при помощью запятых: ( 001 Ink jet 450 , 003 Color, Digital 2 years 500 )
5. Адресация к дугам языка XLink В предыдущем разделе было предложено простое и органичное расширение языка XPath осью traverse, которая предоставляет возможность осуществлять 134
переходы по дугам XLink, и на основе практических примеров была проиллюстрирована гибкость предложенного расширения. Необходимо заметить, что расширение языка XPath лишь осью traverse обеспечивает ограниченные функциональные возможности для адресации структурных частей XML-документов, связанных между собой ссылками XLink. Данное наблюдение мотивируется тем, что ось traverse осуществляет переход сразу по всем дугам XLink, для которых контекстный узел является исходным ресурсом, а таких дуг может быть несколько. Для шага доступа со спецификатором оси traverse присутствующие в шаге доступа тест узла и предикаты позволяют приложению наложить условия на интересующие целевые ресурсы, но не на дуги, по которым осуществляется переход в данном шаге доступа. В практических задачах обработки XML-документов, связанных ссылками XLink, может быть желательно выбирать только некоторые из дуг, по которым необходимо осуществить переход из контекстного узла, а также формулировать запросы непосредственно к дугам и их семантическим атрибутам. В соответствии с обозначенными в разделе 1 пожеланиями к языку, который бы позволил приложению формулировать запросы к XML-документам, связанным при помощи ссылок XLink, необходимо инкапсулировать сложности синтаксиса языка XLink и предоставить приложению прозрачное представление для имеющихся в XML-документах ссылок. Для достижения поставленной цели в настоящей статье предлагается представление каждой дуги XLink в виде информационной единицы (information item) Информационного Пространства XML [14], которое может рассматриваться как представление (view) в терминах реляционных баз данных и позволяет формулировать запросы к дуге XLink единообразно с другими структурными частями XML-документа. В данном разделе рассматривается предлагаемый способ представления дуги XLink как информационной единицы; затем в качестве дальнейшего расширения к языку XPath вводятся 2 дополнительные оси, позволяющие приложению формулировать запросы к дугам XLink как к самостоятельным сущностям.
5.1. Дуга XLink как слабоструктурированные данные Для наглядности предлагаемого представления дуги XLink в виде информационной единицы в данном разделе для записи примера будет использоваться синтаксис XML. При этом необходимо отметить, что XML является не единственным синтаксисом для записи дуги XLink в виде информационной единицы: в частности, как будет показано в разделе 6, при реализации предложенного языка запросов XPathLink функциональными методами для представления дуги XLink использовался формат SXML [17]. В данном разделе мы будем оперировать терминами Информационного Пространства XML с целью подчеркнуть независимость предлагаемого представления дуги XLink от конкретного внешнего синтаксиса. 135
Каждой дуге XLink будет соответствовать информационная единица типа “элемент” (element information item). С каждой дугой XLink сопоставим имя, которое будет содержаться в локальном имени информационной единицы, представляющей дугу. Имена дуг не представлены в явном виде в синтаксисе языка XLink и в настоящей статье предлагаются для удобной классификации дуг приложением. Наличие имени у дуги предоставляет приложению удобный способ выбрать группу дуг, обладающих общими свойствами, без необходимости проводить детальный анализ внутренней структуры информационных единиц. Предлагается сопоставлять с каждой дугой XLink одно из следующих 6 имен: Дуге, определяемой простой ссылкой XLink, сопоставим имя simple (простая). Спецификация XLink определяет, что описание простой ссылки XLink содержит дугу неявным образом, и эта дуга обеспечивает переход от локального ресурса простой ссылки к ее удаленному ресурсу. Дуге, определяемой внутри расширенной ссылки XLink, сопоставим одно из имен outbound (исходящая), inbound (входящая), third-party (сторонняя) или local-to-local (от локального к локальному), в зависимости от типа дуги. Определения первых трех типов дуг введены Спецификацией XLink и уже обсуждались в разделе 2. Спецификация XLink не предусматривает какого-либо специального названия для дуги, и исходный, и целевой ресурсы которой являются локальными, ввиду редкой практической потребности для дуги данного типа. Для полноты рассмотрения возможных вариантов определяемых внутри расширенной ссылки типов дуг, для дуги, соединяющей 2 локальных ресурса, выбрано имя local-to-local. Дуге, семантическая роль которой состоит в указании на ссылочную базу (linkbase), сопоставим имя linkbase. Ссылочная база — это отдельный XML-документ, содержащий описания входящих и сторонних ссылок. Дуга, описанная как указывающая на ссылочную базу, позволяет приложению идентифицировать обрабатываемые ресурсы как исходные ресурсы для входящих и сторонних ссылок, которые описаны в ссылочной базе. По сравнению с остальными дугами, дуга, указывающая на ссылочную базу, должна обрабатываться особым образом: вместо перехода по дуге приложение должно загрузить ссылочную базу и извлечь описанные в ней ссылки для последующего использования. Для описания дуги как указывающей на ссылочную базу в языке XLink используется предопределенное значение глобального атрибута с семантикой роли дуги. При представлении дуги, указывающей на ссылочную базу, в виде информационной единицы, предлагается иметь для такой дуги особое имя с целью облегчения ее обработки приложением. Представляющая дугу XLink информационная единица типа элемент имеет дочерние информационные единицы, которые содержат необходимые данные о соединяемых дугой ресурсах и семантических параметрах дуги. 136
5.1.1. Исходный и целевой ресурсы дуги Для хранения данных об исходном и целевом ресурсах дуги Xlink предлагается использовать при ее представлении в виде информационной единицы дочерние информационные единицы типа “элемент”. По аналогии с синтаксисом языка XLink для записи исходного и целевого ресурса дуги информационной единице, представляющей исходный ресурс, дадим локальное имя from, а информационной единице, представляющей целевой ресурс — локальное имя to. Заметим, что при представлении дуги XLink в виде информационной единицы не требуется использование пространств имен XML [18]. Как отмечается в [19], пространства имен в XML используются для того, чтобы позволить прило-жению однозначным образом распознать имя элемента или атрибута в XML-документе [20]. В частности, Спецификация XLink использует собственное глобальное пространство имен, чтобы элементы языка XLink могли быть распознаны среди прочих элементов XML-документа. В предлагаемом в настоящей статье представлении дуги XLink в виде информационных единиц ситуация иная: про все информационные единицы данного представления известно, что они служат для описания дуги, и поэтому использования в именах информационных единиц какого-либо пространства имен не требуется. В синтаксисе языка XLink дуги и соединяемые ими ресурсы описываются отдельно друг от друга, а исходный и целевой ресурс дуги специфицируются опосредованным образом — при помощи меток. Для того, чтобы избавить приложение от необходимости самостоятельно сопоставлять метки языка XLink при определении соединяемых дугой ресурсов, предлагается при представлении дуги в виде информационной единицы использовать полные описания ее исходного и целевого ресурса, явным образом включенные внутрь описания дуги. Дополнительно, для обеспечения прозрачности межресурсных связей, предлагается единообразное представление как для локальных, так и для удаленных ресурсов языка XLink. Данное единообразие достигается за счет наличия у информационной единицы, представляющей исходный (аналогично — целевой) ресурс дуги, любых из следующих 3-х дочерних информационных единиц типа “элемент”: Информационная единица с именем uri, которая содержит последовательность символов, представляющих унифицированный идентификатор URI данного ресурса. Для удаленного ресурса XLink его унифицированный идентификатор явным образом задается в описании ресурса на языке XLink. Для локального ресурса XLink его идентификатором является унифицированный идентификатор XMLдокумента, в котором описан данный локальный ресурс. Информационная единица с именем nodes, которая содержит сам ресурс — узел XML-документа или набор узлов — в качестве своих дочерних информационных единиц. Для локального ресурса XLink таким 137
узлом является сам этот ресурс, т.к. только узел XML-документа может выступать в качестве локального ресурса. Информационная единица с именем xpointer, которая содержит последовательность символов, представляющих идентификатор фрагмента на языке XPointer для данного ресурса. Идентификатор фрагмента может использоваться для определения удаленного ресурса XLink и задается явным образом в описании ресурса. Необходимо отметить, что в зависимости от способа обработки XMLдокументов со ссылками языка XLink конкретным приложением, при описании дуги XLink в виде информационной единицы для данного приложения могут быть предпочтительными различные способы представления соединяемых дугой ресурсов. Так, если по семантике приложения предполагается осуществлять переходы по дуге многократно, то для обеспечения быстроты переходов разумно заранее вычислить удаленный целевой ресурс дуги и хранить полученный в результате вычисления набор узлов в описании дуги — как дочерние для информационной единицы nodes. Напротив, если предполагается долговременное хранение предлагаемого представления дуги XLink на диске, то с целью поддержания взаимосвязи между дугой и соединяемыми ею ресурсами, предпочтительно описывать эти ресурсы не “по значению” — с использованием информационной единицы nodes, — а “по ссылке” — с использованием совокупной семантики информационных единиц uri и xpointer.
5.1.2. Семантические параметры дуги В соответствии со Спецификацией XLink, описание дуги может сопровождаться необязательными семантическими и поведенческими атрибутами. Семантические атрибуты включают в себя машинно-понимаемую роль дуги (arcrole) в системе межресурсных связей и понимаемый человеком заголовок (title). Поведенческие атрибуты определяют момент активизации дуги (actuate) и способ демонстрации целевого ресурса (show). Каждый из упомянутых атрибутов языка XLink в предлагаемом представлении дуги XLink выражается информационной единицей типа “элемент”, которая носит локальное имя, совпадающее с локальным именем соответствующего атрибута. Каждая из информационных единиц содержит последовательность дочерних символов, которые выражают значение атрибута. По уже обсуждавшимся в предыдущем пункте причинам, для информационных единиц в предлагаемом представлении дуги XLink не требуется использование какого-либо пространства имен. Использование информационных единиц типа “элемент” для выражения атрибутов языка XLink используется из соображений единообразного дизайна предлагаемого представления дуги XLink.
5.1.3. Пример На рис. 3 приведен пример расширенной ссылки языка XLink, которая соединяет несколько ресурсов о джазовом музыканте Луисе Армстронге. Из 138
рисунка легко видеть, что Спецификация XLink не накладывает ограничений на имя элемента, являющегося расширенной ссылкой, а принадлежность этого элемента языку XLink и его ссылочный тип задаются глобальным атрибутом xlink:type. Расширенная ссылка на рис. 3 соединяет 3 ресурса, а именно: Описание биографии Луиса Армстронга. Это локальный ресурс языка XLink, т.е. всё содержимое ресурса целиком располагается внутри ссылочного элемента. Элемент языка XML специфицируется как локальный ресурс XLink с помощью наличия у данного элемента глобального атрибута xlink:type со значением "resource". Песни Луиса Армстронга, которые располагаются в некотором XMLдокументе "louis-songs.xml". Относительно рассматриваемой на рис. 3 расширенной ссылки этот ресурс является удаленным, поскольку к нему адресуются по его Унифицированному Идентификатору Ресурса. Удаленный ресурс описывается элементом языка XLink типа локатор [2], который специфицируется на языке XLink с помощью глобального атрибута xlink:type со значением "locator". Упоминания о Луисе Армстронге в прессе. Данный ресурс также является удаленным, и представляет собой набор узлов — набор статей о музыканте, — выбираемых из документа "www.press.com/archive.xml" идентификатором фрагмента языка XPointer. Louis Daniel Armstrong August 4, 1901 ...
Рис. 3. Расширенная ссылка XLink, соединяющая различные ресурсы о музыканте Луисе Армстронге. (
139
louis-songs.xml Louis Daniel Armstrong August 4, 1901 ... onRequest , louis-songs.xml www.press.com/archive.xml xpointer(paper[keyword='Armstrong']) )
(а)
(б)
Рис. 4: Представленные в виде информационных единиц и записанные в синтаксисе XML дуги языка XLink, которые были определены в расширенной ссылке на рис. 3 Каждый из описанных в расширенной ссылке ресурсов помечен собственной меткой, задаваемой значением атрибута xlink:label. Эти метки используются для описания дуг. В расширенной ссылке на рис. 3 определяются 2 дуги: от песен Луиса Армстронга к его биографии и от песен к упоминаниям о музыканте в прессе. Заметим, что последняя дуга соединяет два удаленных ресурса. На рис. 4 для обеих дуг приведено их представление в виде информационных единиц, предложенное в рамках настоящей статьи и описанное выше в данном разделе. Буквой (а) на рис. 4 помечена дуга, ведущая от песен к биографии; буквой (б) — дуга, ведущая от песен к упоминаниям о музыканте в прессе. Для наглядности визуального восприятия предлагаемого представления дуг XLink в виде информационных единиц на рис. 4 используется синтаксис XML; альтернативно может использоваться любой другой синтаксис, который соответствует аналогичному набору информационных единиц Информационного Пространства XML. Заметим, что поведенческий атрибут способа активизации дуги, ведущей к биографии Луиса Армстронга, на рис. 4 (а) находит свое выражение в виде элемента с одноименным локальным именем. Рассмотренный пример будет использоваться в ходе последующего изложения — при определении языковых средств для формулирования запросов к дугам XLink. 140
5.2. Оси для адресации к дугам XLink Теперь, когда определен способ представления каждой дуги XLink в виде информационной единицы Информационного Пространства XML, рассмотрим предлагаемое в данной статье дальнейшее расширение языка XPath, предоставляющее приложению возможность прозрачным образом формулировать запросы к дугам XLink. Расширим функциональность языка XPath возможностью получить информацию обо всех дугах XLink, по которым можно осуществить переход из контекстного узла, т.е. таких, для которых контекстный узел является их исходным ресурсом. Следуя единообразию в дизайне предлагаемого расширения языка XPath поддержкой языка XLink, естественно оформить данную операцию получения всех дуг, исходным ресурсом которых является контекстный узел, в виде новой оси XPath. По аналогии с англоязычным термином для дуги, введенным Спецификацией XLink, данную ось назовем "arc". Определение 2. Ось arc содержит все узлы, являющиеся в терминах Информационного Пространства XML представлением в виде информационных единиц всех дуг XLink, для каждой из которых контекстный узел служит исходным ресурсом. Из определения следует, что ось arc возвращает непустой набор узлов только для такого контекстного узла, который является исходным ресурсом хотя бы для одной дуги XLink. Каждый из узлов, возвращаемый осью arc, имеет тип “элемент”, и его имя и внутренняя структура служат представлением для дуги XLink, которую этот элемент выражает. При использовании в шаге доступа XPath спецификатора оси arc полностью сохраняется семантика остальных составляющих шага доступа — теста узла и предикатов. Например, тест узла позволяет выбрать дуги XLink по их именам — в соответствии с одним из 6 имен, предложенных для дуг в пункте 5.1. Необходимо подчеркнуть, что каждый из узлов, возвращаемый предложенной осью arc, полностью соответствует Модели данных XPath [6], и поэтому к этим узлам далее могут применяться произвольные выражения XPath, с полным сохранением семантики этих выражений. В частности, предикаты могут использоваться для фильтрации дуг в соответствии со структурой представляющих их информационных единиц: например, выбрать дуги с конкретным значением некоторого семантического параметра XLink или наложить условие на тип целевого ресурса дуги. Заметим, что в Модели Данных XPath [6], являющейся частью стандарта языка XPath Консорциума Всемирной Сети, узел типа “элемент” имеет ассоциированный с ним набор узлов типа “атрибут” и набор узлов типа “объявление пространства имен”, и относительный порядок узлов в каждом из наборов считается зависимым от конкретной реализации. В полной аналогии с 141
наборами атрибутов и объявлениями пространств имен можно говорить, что предлагаемое в данной статье расширение языка XPath поддержкой XLink дополняет Модель Данных XPath наличием ассоциированного с узлом любого типа набора выходящих из него дуг XLink. Каждая дуга реализуется в Модели Данных XPath узлом типа “элемент” и является представлением дуги в виде информационной единицы, как было описано в данном разделе. Вернемся к расширенной ссылке на рис. 3 и представлению определяемой этой ссылкой дуг на рис. 4 и рассмотрим несколько кратких примеров использования предложенной оси arc. Необходимо отметить, что в соответствии с описаниями ресурсов и дуг, имеющимися в рассматриваемой расширенной ссылке, элемент документа (document element) [2] XML-документа "louissongs.xml" является исходным ресурсом сразу для 2 дуг языка XLink. (На рис. 3 документ "louis-songs.xml" опущен ввиду того, что его структура не важна для последующих рассматриваемых примеров). Пример 3. Пусть контекстным узлом является элемент документа XMLдокумента "louis-songs.xml". Выберем все сторонние дуги (third-party arcs), которые выходят из данного узла. С использованием предлагаемой оси arc интересующие сторонние дуги могут быть получены с помощью выражения XPath — шага доступа: arc::third-party Результатом данного шага доступа является узел — приведенное на рис. 4 (б) представление дуги XLink в виде информационной единицы, записанное на данном рисунке в синтаксисе языка XML. Заметим, что для получения данного результата приложению не требуется осуществлять разбор разметки языка XLink, поскольку эта работа полностью инкапсулирована предлагаемым в настоящей статье языком XPathLink. Пример 4. Рассмотрим тот же контекстный узел, что и в примере 3. Выберем теперь все выходящие из данного контекстного узла дуги, имеющие поведенческий атрибут активизации со значением "onRequest". Интересующие дуги могут быть получены с помощью следующего шага доступа: arc::*[actuate="onRequest"] Результатом данного шага доступа является узел — представление дуги, приведенное на рис. 4 (а). Необходимо отметить, что вычисление используемого в шаге доступа предиката осуществляется с полным сохранением семантики языка XPath, т.к. предложенное представление дуг XLink, подлежащих фильтрации по условию предиката, унифицировано с другими узлами XML-документа. Наличие оси arc позволяет приложению формулировать запросы к дугам XLink и накладывать условия на интересующие дуги с помощью предикатов XPath. Когда интересующие приложение дуги XLink выбраны, приложению может потребоваться осуществить по ним переход. Для обеспечения данной функциональности можно было бы использовать введенную в разделе 4 ось 142
traverse, расширив ее и для узлов, представляющих дуги XLink в виде
информационных единиц. Однако в данной статье предлагается не перегружать ось traverse излишне сложной функциональностью, поскольку негативным примером подобной перегруженности служит ось parent (родитель) в Стандарте языка XPath. Так, для контекстного узла типа атрибут ось parent выбирает содержащий его элемент (owner element) [14], а для контекстного узла любого другого типа — его родительский узел. Данная функциональная перегруженность оси parent приводит к тому, что транзитивное замыкание оси parent — ось ancestor-or-self — выбирает узлы нескольких разных типов, будучи примененная к контекстному узлу типа “атрибут”. Для сохранения простоты семантики предлагаемого языка XPathLink, являющегося расширением языка XPath поддержкой языка XLink, в настоящей статье используется отдельная дополнительная ось для перехода к целевому ресурсу дуги XLink из информационной единицы, представляющей дугу. Данная ось получила название traverse-arc, т.е. “переход из дуги”. Определение 3. Ось traverse-arc содержит все узлы, являющиеся целевыми ресурсами для контекстного узла, представляющего в виде информационной единицы дугу XLink. Для любого другого контекстного узла ось traverse-arc содержит пустой набор узлов. Как отмечалось выше, семантика оси traverse-arc во многом напоминает семантику оси traverse, и области определения этих осей дополняют друг друга. Общность осей traverse-arc и traverse позволяет нам сразу перейти к рассмотрению примера. Пример 5. Вернемся к примеру 3 и дополним его переходом по дуге. Пусть контекстным узлом снова является элемент документа XML-документа "louissongs.xml". Осуществим переход по всем сторонним дугам, для которых контекстный узел является исходным ресурсом. При наличии предлагаемых в статье дополнительных осей XPath искомая последовательность действий может быть оформлена в виде следующего пути доступа: arc::third-party/traverse-arc::* Результатом вычисления данного пути доступа является набор узлов — ресурс, описанный расширенной ссылкой на рис. 3 и содержащий упоминания о Луисе Армстронге в прессе. Предложенные в настоящей статье 3 дополнительные оси для языка XPath связаны следующим отношением: для произвольного теста узла NodeTest справедливо traverse::NodeTest arc::*/traverse-arc::NodeTest , где символ тождественного равенства обозначает совпадение наборов узлов, выбираемых путями доступа в левой и правой частях тождества, для любого контекстного узла. Справедливость данного утверждения следует из того 143
очевидного наблюдения, что последовательное применение осей arc и traverse-arc реализует те же действия, что и ось traverse, если не требуется накладывать условие на интересующие дуги XLink, по которым следует осуществить переход.
6. Реализация В данном разделе рассматривается реализация предлагаемого языка XPathLink при помощи функциональных методов программирования. В основе подхода к обработке XML-данных функциональными методами лежит SXML — представление Информационного Пространства XML в виде Sвыражений [21]. Функциональный язык программирования Scheme, использованный для реализации, естественным образом обрабатывает Sвыражения и, таким образом, SXML. В данном разделе дается краткий обзор SXML, затем рассматриваются ключевые моменты сделанной в рамках настоящей статьи реализации предлагаемого языка XPathLink.
6.1. Обзор SXML SXML — это абстрактное синтаксическое дерево XML-документа в форме Sвыражения. Языки SXML и XML могут рассматриваться как два синтаксически различных представления Информационного Пространства XML [14]. Язык XML использует язык разметки SGML для представления информационных единиц Информационного Пространства XML и их свойств. Древовидная структура документа (свойства родитель и ребенок информационных единиц Информационного Пространства XML) выражается при помощи вложенных тегов разметки [13]. Язык SXML использует для представления информационных единиц Информационного Пространства XML и их свойств S-выражения языка Scheme. Древовидная структура документа выражается при помощи вложенных списков. Каждая из информационных единиц Информационного Пространства XML представляется в виде S-выражения, первым членом которого является либо имя информационной единицы (для типов “элемент” и “атрибут”), либо служебное имя, предусмотренное для информационной единицы данного типа в грамматике SXML [17]. Пример простого XML-документа и его представления на SXML приведены на рис. 5, наглядно демонстрирующем соответствие между вложенными тегами XML и вложенными списками SXML. Text node
144
(*TOP* (*PI* xml "version='1.0'") (doc (tag (@ (attr1 "value1") (attr2 "value2")) (nested "Text node") )
(empty) ))
Рис. 5. XML-документ (левый столбец) и его представление в SXML.
6.2. Разбор разметки языка XLink При реализации предлагаемого языка запросов к совокупности XMLдокументов, связанных при помощи ссылок XLink, важным моментом технического характера является разбор элементов языка XLink в соответствии со спецификацией этого языка и инкапсуляция сложностей синтаксиса XLink от пользовательского приложения. С целью создания единообразной среды для работы приложения как с SXMLдокументом, так и с дугой XLink последняя также записывается в формате SXML. Для разбора XML-документа, содержащего ссылки языка XLink, и представления документа и дуг XLink на SXML была реализована специализированная разновидность парсера SSAX [22]. SSAX — это парсер для разбора XML-документов, написанный на языке Scheme в чисто функциональном стиле и предоставляющий Простой Интерфейс Прикладного Программирования для XML (Simple API for XML — SAX). Интерфейс парсера SSAX основан на событиях, и в рамках данной статьи специализированные обработчики событий были реализованы для конструирования представления на SXML описанных в XML-документе дуг XLink, одновременно с конструированием представления на SXML самого разбираемого XMLдокумента. Реализованная архитектура специализированного парсера обеспечивает построение представления на SXML для документа и всех описанных в нем дуг XLink за один проход по документу. Узел SXML-документа, являющийся исходным ресурсом для некоторой дуги XLink, соединяется со сконструированным представлением этой дуги при помощи концепции так называемых вспомогательных списков грамматики SXML. Вспомогательный список — это S-выражение, первым членом которого является служебный символ '@@. Вспомогательный список не может быть перепутан ни с одной другой информационной единицей SXML-документа, поскольку служебный символ '@@ не может быть корректным именем языка XML. Хранение предлагаемого представления дуг XLink внутри вспомогательного списка подчеркивает близость относительно Модели данных XPath между набором выходящих из данного узла дуг и набором атрибутов данного узла, поскольку атрибуты на SXML синтаксически записываются внутри списка со служебным именем '@. Необходимо отметить, что соединяемые ссылками XLink удаленные ресурсы, являющиеся фрагментами XML-документа, на языке XPointer могут специфицироваться по уникальному идентификатору — значению атрибута типа ID. Например, на рассмотренном ранее рис. 1, выражающем систему заказа товаров, по атрибутам типа ID определяются ресурсы внутри документа 145
"clients.xml". Тип атрибута описывается не в самом XML-документе, но в его схеме; и поэтому разбор схемы XML-документа необходим для идентификации ресурсов, представляющих собой фрагменты внутри данного документа. Сделанная в рамках данной статьи реализация обеспечивает извлечение описаний атрибутов типа ID из схемы на языке Определения Типа Документа (Document Type Definition — DTD) [2]. Заметим, что документы на HTML также представляют собой слабоструктурированные данные, а семантика гиперссылок HTML, задаваемых при помощи элемента A, может рассматриваться как частный случай семантики дуг XLink. Из сделанного наблюдения следует, что применение предлагаемого в настоящей статье языка XPathLink может быть без изменений расширено на случай формулирования запросов к совокупности документов на HTML, связанных гиперссылками. Парсер HtmlPrag, позволяющий сконструировать представление в виде S-выражений для практических HTML-документов [23], в рамках данной статьи был дополнен обработкой гиперссылок HTML по аналогии с дугами XLink. На высоком уровне, для получения в виде SXML набора связанных документов, прикладному приложению предоставляется функция xlink:documents (имя documents выбрано по аналогии с языками XSLT и XQuery, а префикс xlink подчеркивает связь данной функции с языком XLink). Функция принимает в качестве аргументов один или более Унифицированный Идентификатор Ресурса (URI) для интересующих приложение документов. По предоставленным Унифицированным Идентификаторам Ресурсов функция получает соответствующие документы, конструирует их представление на SXML и связывает все узлы SXMLдокументов, являющиеся исходными ресурсами для дуг языка XLink, с представлением этих дуг на SXML. Семантика функции xlink:documents объединяет в себе следующие действия: Получение документов по их Унифицированным Идентификаторам Ресурса, определение типа каждого документа: XML или HTML; Конструирование с помощью соответствующего парсера (специализированная реализация SSAX или HtmlPrag) представления документа на SXML и построение представления на SXML описанных в данном документе дуг XLink или гиперссылок HTML; Загрузка ссылочных баз языка XLink с целью получения тех дуг XLink, исходные и/или целевые ресурсы которых располагаются в интересующих приложение документах; Ассоциирование исходных ресурсов с соответствующими дугами XLink (учитывая ту специфику языка XLink, что дуги в общем случае описываются в другом месте относительно местоположения их исходных ресурсов).
146
Наличие единой функции xlink:documents, обеспечивающей проведение всех описанных выше действий за один высокоуровневый вызов, способствует простоте использования сделанной реализации прикладным приложением.
Результат вычисления данного кода на языке Scheme представляет собой список — набор узлов, состоящий из единственного текстового узла:
6.3. Реализация SXPath
Пример 7. Вычислим пример 2 с помощью SXPath, расширенного поддержкой языка XLink.
предложенных
осей
как
расширения
к
SXPath — это реализация XPath на языке функционального программирования Scheme, предоставляющая язык запросов к документам на SXML. Реализация SXPath трактует путь доступа как составной запрос к дереву документа или его ветви. Отдельный шаг доступа представляет собой комбинацию проекции, выборки или транзитивного замыкания [24]. Несколько шагов доступа комбинируются с помощью операций последовательного применения или объединения. Библиотека SXPath состоит из набора низкоуровневых предикатов, фильтров, операций выборки и комбинаторов; и функций высокого уровня, реализованных в терминах низкоуровневых функций. В рамках данной статьи предложенные 3 дополнительные оси, обеспечивающие поддержку в XPath языка XLink, были реализованы в качестве расширения к SXPath. Примечательно, что оси traverse и traverse-arc, осуществляющие переход по дугам, прозрачным для приложения образом вызывают вычислитель языка XPointer, когда требуется разыменовать (resolve) идентификатор фрагмента на XPointer для целевого ресурса дуги. Упомянутые оси также могут прозрачным для приложения образом загружать по Унифицированным Идентификаторам Ресурса те документы, в которых располагаются целевые ресурсы перехода и которые ранее не были загружены с помощью функции xlink:documents. Данное свойство сделанной реализации делает ее мощным инструментом для работы с ресурсами в масштабах Всемирной Сети. Для иллюстрации сделанной реализации вернемся к некоторым рассмотренным ранее примерам и посмотрим их вычисление с помощью предложенного расширения SXPath поддержкой языка XLink. Пример 6. Вычислим пример 1 с помощью SXPath, расширенного поддержкой языка XLink: ((sxpath/c "//order[entry/item/traverse::printer]/ customer/traverse::person/name/text()") (xlink:documents "purchase-orders.xml")) Высокоуровневая функция sxpath/c получает на вход выражение XPath и конструирует реализацию этого выражения в виде комбинации низкоуровневых примитивов библиотеки SXPath. Сконструированная реализация выражения XPath имеет сигнатуру функции, которая затем применяется к набору узлов. В данном примере этот набор состоит из единственного узла — представленного на SXML документа "purchase-orders.xml". 147
("John Smith")
((sxpath/c "//order[customer/traverse::person/VIP]/ entry/item/traverse::*") (xlink:documents "purchase-orders.xml")) Результатом вычисления данного кода представляющий собой набор узлов на SXML:
является
следующий
список,
((printer (lot "001") (descr "Ink jet") (price "450")) (display (lot "003") (descr "Color, Digital") (warranty "2 years") (price "500")))
6.4. Язык запросов Тесная интегрированность SXPath с языком программирования общего назначения Scheme предоставляет функциональность языка запросов к SXMLдокументам. Проводя аналогии с языком запросов к XML-документам XQuery, можно обозначить следующие соответствия между конструкциями XQuery и возможностями Scheme: Итерация по членам последовательности for-return языка XQuery реализуется на Scheme функцией map. Функция map получает на вход функцию от одного аргумента и список, и формирует новый список, последовательно применяя полученную в качестве аргумента функцию к каждому из членов аргумента-списка. Функции и операторы XQuery [11], а также функции XQuery, определяемые пользователем, реализуются на Scheme также функциями — стандартными, библиотечными или определяемыми пользователем. Дополнительно, в языке Scheme функции могут использоваться как объекты первого класса, что не поддерживается в XQuery. Конструкторы различных типов узлов в языке XQuery реализуются на Scheme конструкторами списков. Более того, наличие в языке Scheme выражений квази-цитирования (quasiquote) и снятия цитирования 148
(unquote) позволяет компактным и наглядным образом комбинировать константные выражения и фрагменты вычисляемых выражений. Аналогичные идеи используются в синтаксисе XSLT для комбинирования литеральных элементов результата [2] и исполняемых инструкций. Рассмотрим совместное использование SXPath и Scheme как языка запросов к SXML-документам на конкретном примере. Пример 8. Вновь обратимся к рисунку 1 и подведем счет для каждого сделанного заказа. Счет будет включать в себя имя клиента и общую цену с учетом количества единиц каждого заказанного товара. Получение желаемого результата требует использования языка запросов, поскольку требуется не просто выбрать некоторые узлы из XML-документов, но также сконструировать новые узлы, которых в самих документах нет. На рис. 6 показано решение поставленного запроса в двух вариантах: На языке XQuery, расширенном предлагаемыми в настоящей статье дополнительными осями XPath; На Scheme, благодаря тесной интеграции SXPath с языком программирования. for $order in document("purchase-orders.xml")//order return { fn:sum( for $entry in $order/entry return item/traverse::*/price * quantity ) } {$order/customer/traverse::person/name} (map (lambda (order) `(bill (total-price ,(apply + (map (sxpath/c "item/traverse::*/price * quantity") ((sxpath/c "entry") order)))) ,@((sxpath/c "customer/traverse::person/name") order))) ((sxpath/c "//order") (xlink:documents "purchase-orders.xml"))) Рис. 6. Вычисление счета для каждого заказа: с помощью XQuery, расширенного поддержкой XLink, (вверху) и с помощью Scheme (внизу). См. также пример 8. Из рис. 6 легко видеть, что соответствие между выражениями языка XQuery и вызовами функций языка Scheme является достаточно прямолинейным, и многие конструкции языка XQuery имеют свое наглядное отражение в виде примитивов языка Scheme над деревьями SXML-документов.
149
Результатом вычисления представленного на рис. 6 кода на Scheme является набор узлов, выражающих на SXML искомые счета для сделанных заказов: ((bill (total-price 1900) (name "John Smith")) (bill (total-price 20) (name "Paul Brown")))
7. Ограничения предлагаемого языка запросов Предложенный в данной статье язык XPathLink не предоставляет средств по работе с ресурсами XLink, которые не являются узлами или наборами узлов. Такими ресурсами могут быть только удаленные ресурсы (т.е. те, которые участвуют в ссылке XLink благодаря тому, что к ним адресуются с помощью унифицированного идентификатора URI), и к их числу относятся: Ресурсы, которые имеют формат, отличный от XML и XHTML, например, мультимедийные форматы; Ресурсы, при адресации к которым используется идентификатор фрагмента на языке XPointer, вычисляющийся в интервал (range) или последовательность символов внутри текстового узла. Введенные ограничения мотивированы требованием обеспечить замкнутость всех операций языка запросов относительно сущности набор узлов. Так, интервалы языка XPointer нарушают иерархическую структуру документа, поскольку разрывают границы разметки, и поэтому не могут быть представлены в виде набора узлов модели данных XPath. Заметим, что идентичные ограничения приняты и в Спецификации Языка Преобразований XSL при обеспечении доступа к документам, отличным от обрабатываемого XML-документа [25]. Данная аналогия подтверждает, что введенные ограничения предложенного в настоящей статье языка XPathLink являются оправданными.
8. Заключение Данная статья посвящена вопросу обработки совокупности XML-документов как системы связанных ресурсов, описанной с помощью языка XLink. На основе анализа существующих работ в области обработки XML-документов, связанных ссылками XLink, была отмечена потребность в наличии языка высокого уровня, который бы инкапсулировал сложности синтаксиса XLink и обеспечивал приложение возможностями формулировать запросы к ссылкам XLink и осуществлять переходы по определяемым этими ссылками дугам. Был проведен обзор языка адресации структурных частей XML-документа Xpath, и было замечено непосредственное семантическое соответствие между 150
переходом по дуге в терминах языка XLink и осью в XPath. Было предложено ввести в XPath дополнительную ось traverse, которая осуществляет переход из контекстного узла как из исходного ресурса дуги XLink на ее целевой ресурс. Были рассмотрены свойства предложенной дополнительной оси, и сценарии ее использования были проиллюстрированы практическими примерами. Для обеспечения прикладного приложения возможностью прозрачным образом формулировать запросы к дугам XLink как к самостоятельным сущностям было разработано представление для дуг в виде информационной единицы Информационного Пространства XML. В язык XPath была добавлена ось arc, позволяющая приложению для данного контекстного узла получить все дуги XLink, для которых контекстный узел служит исходным ресурсом. Было отмечено единообразие предложенного слабоструктурированного представления дуг XLink и других узлов XML-документа, и рассмотрено место дуг XLink в Модели Данных языка XPath. Обсуждались преимущества наличия двух различных осей для перехода по дуге XLink из узла XML-документа и из слабоструктурированного представления дуги. Рассматривались детали сделанной в рамках данной статьи реализации функциональными методами предложенного расширения XPath. Тесная интеграция сделанной реализации с языком программирования общего назначения Scheme обеспечивает прикладное приложение функциональностью языка запросов. Предложенный в статье язык запросов и его реализация функциональными методами являются мощным и гибким инструментом для обработки совокупности XML-документов, связанных ссылками XLink. Литература 1. S. DeRose, E. Maler and D. Orchard (editors). XML Linking Language (XLink) Version 1.0. W3C Recommendation 27 June 2001. http://www.w3.org/TR/xlink/ 2. Когаловский М.Р. Глоссарий по технологиям платформы XML. Версия 4 (25-11-2003). http://www.elbib.ru/index.phtml?page= elbib/rus/methodology/xmlbase/glossary_XML 3. T. Bray and S. DeRose (editors). Extensible Markup Language (XML): Part 2. Linking. W3C Working Draft April-06-97. http://www.w3.org/TR/WD-xml-link-970406.html 4. S. J. DeRose (editor). XML XLink Requirements Version 1.0. W3C Note 24-Feb-1999. http://www.w3.org/TR/NOTE-xlink-req 5. S. Boag, D. Chamberlin, M. Fernandez, D. Florescu, J. Robie and J. Simeon (editors). XQuery 1.0: An XML Query Language. W3C Working Draft, 12 November 2003. http://www.w3.org/TR/2003/WD-xquery-20031112/ 6. J. Clark и S. DeRose (редакторы). Язык XML Path (XPath) Версия 1.0. Рекомендация Консорциума Всемирной Сети от 16 Ноября 1999. http://citforum.ru/internet/xpath/index.shtml 7. Лизоркин Д.А. и Лисовский К.Ю. Языки XSLT и XLink и их реализация функциональными методами. Электронные Библиотеки, 2003, Том 6, Выпуск 5. http://www.elbib.ru/index.phtml?page= elbib/rus/journal/2003/part5/LL 8. T. Berners-Lee, R. Fielding, U.C. Irvine and L. Masinter. Request for Comments: 2396. Uniform Resource Identifiers (URI): Generic Syntax. Network Working Group, August 1998. http://www.cse.ohio-state.edu/cgi-bin/rfc/rfc2396.html
151
9. P. Grosso, E. Maler, J. Marsh and N. Walsh (editors). XPointer Framework. W3C Recommendation 25 March 2003. http://www.w3.org/TR/2003/REC-xptr-framework-20030325/ 10. Лизоркин Д.А. и Лисовский К.Ю. Реализация XLink — языка ссылок XML — с помощью функциональных методов. Принята к публикации в журнал ``Программирование'', 2005, номер 1. http://www.maik.rssi.ru/cgi-bin/journal.pl?name=procom&page=main 11. A. Malhotra, J. Melton and N. Walsh (editors). XQuery 1.0 and XPath 2.0 Functions and Operators. W3C Working Draft 23 July 2004. http://www.w3.org/TR/2004/WD-xpath-functions-20040723/ 12. B. DuCharme. XLink: Who Cares? XML.com, O'Reilly Media. http://www.xml.com/pub/a/2002/03/13/ xlink.html 13. Лисовский К.Ю. Разработка XML-приложений на языке Scheme. Программирование, выпуск 28, номер 4, 2002. http://www.maik.rssi.ru/journals/procom.htm 14. J. Cowan and R. Tobin (editors). XML Information Set (Second Edition). W3C Recommendation 4 February 2004. http://www.w3.org/TR/xml-infoset/ 15. Лизоркин Д.А. и Лисовский К.Ю. SXML: XML-документ как S-выражение. Электронные библиотеки, 2003, Том 6, Выпуск 2. http://www.elbib.ru/index.phtml?page= elbib/rus/journal/2003/part2/LK 16. Лизоркин Д.А. и Лисовский К.Ю. Язык XML Path (XPath) и его функциональная реализация SXPath. Электронные Библиотеки, 2003, Том 6, Выпуск 4. http://www.elbib.ru/index.phtml?page= elbib/rus/journal/2003/part4/LL 17. O. Kiselyov. SXML, revision 3.0, March 12, 2004. http://okmij.org/ftp/Scheme/SXML.html 18. T. Bray, D. Hollander and A. Layman (editors). Namespaces in XML. World Wide Web Consortium 14-January-1999. http://www.w3.org/TR/REC-xml-names/ 19. J. Clark. XML Namespaces. February 4, 1999. http://www.jclark.com/xml/xmlns.htm 20. Лизоркин Д.А. и Лисовский К.Ю. Пространства имен в XML и SXML. Электронные библиотеки, 2003, Том 6, Выпуск 3. http://www.elbib.ru/index.phtml?page= elbib/rus/journal/2003/part3/LL 21. O. Kiselyov and K. Lisovsky. XML, XPath, XSLT Implementation as SXML, SXPath and SXSLT. International Lisp Conference ILC 2002, San Francisco. October, 2002. http://www.okmij.org/ftp/papers/SXs.pdf 22. O. Kiselyov. A better XML parser through functional programming. Practical Aspects of Declarative Languages: 4th International Symposium, PADL 2002. Springer-Verlag Heidelberg, ISSN: 0302-9743. http://www.okmij.org/ftp/papers/XML-parsing.ps.gz 23. Neil W. Van Dyke. HtmlPrag: Pragmatic Parsing of HTML to SHTML and SXML. July 2004. http://www.neilvandyke.org/htmlprag/ 24. K. Lisovsky. STX: Scheme-enabled XSLT processor. http://www.pair.com/lisovsky/transform/stx/ 25. J. Clark (редактор). Язык преобразований XSL (XSLT) Версия 1.0. Рекомендация Консорциума Всемирной Сети от 16 ноября 1999. http://www.rol.ru/news/it/helpdesk/ xslt01.htm
152
Виды ограничений целостности в базах XML-данных
включают адрес, возраст студента, его имя, номер студенческого билета и любое количество курсов, которые он посещает (номера курсов). Данные для каждого курса лекций включают номер курса и его название. Возраст студентов не должен превышать 30 лет. Номера студенческих билетов и номера курсов уникальны. Для каждого номера курса лекции, содержащегося в данных студента, должны существовать данные о курсе лекций с таким номером. На рис. 1 представлена структура XML-данных университета.
М.П. Рекуц Аннотация. Исследовательская группа MODIS (www.modis.ispras.ru) ИСП РАН на протяжении последних двух лет работает над проектом по созданию полнофункциональной системы управления XML-данными (XML-СУБД) Sedna1. Одним из основных требований к любой полнофункциональной СУБД является полноценная поддержка ограничений целостности. В этой статье на основе анализа потребностей современных приложений, работающих с XML-СУБД, выявляются виды ограничений целостности, которые должны поддерживаться XML-СУБД, и предлагаются средства определения этих видов ограничений с учетом специфики XMLмодели данных и опыта, накопленного разработчиками реляционных СУБД.
1. Введение За последние несколько лет XML [1] стал если не повсеместным, то, по крайней мере, весьма популярным форматом данных, что привело к тому, что XML-СУБД все чаще становится ключевым компонентом в сложных решениях. Это, в свою очередь, требует от XML-СУБД широкого набора функциональности, эквивалентного тому, что мы привыкли ожидать от традиционных СУБД. Одним из примеров такой функциональности является развитая поддержка ограничений целостности – важнейший элемент СУБД, без которого, в частности, невозможна поддержка полноценного механизма транзакций. В этой работе мы ставим перед собой цель проанализировать, какие ограничения целостности могут и должны поддерживаться полнофункциональными XML-СУБД, определить виды ограничений целостности, исходя из специфики XML-модели данных, потребностей современных приложений, работающих с XML-данными, и учитывая опыт, накопленный разработчиками реляционных СУБД. Для начала рассмотрим проблему на примере. Приложение работает с данными некоторого университета. Пусть имеется следующее описание данных: данные университета представлены в формате XML и включают информацию о студентах университета и курсах лекций, проводящихся в университете. Данные для каждого студента 1
Проект поддержан грантом РФФИ №05-07-90204
155
Рис.1. Структура XML-данных университета. Для корневого элемента university может иметься ноль или более элементов student и course. Элемент student содержит информацию о студенте: адрес студента (в элементе address), содержащий подэлементы с названием города, улицы и номером дома (city, street, houseNo), имя студента (в элементе name), уникальный номер студенческого билета (в элементе SNO), возраст студента (в элементе age), курсы лекций, посещаемые студентом (ноль или более элементов taking). Элемент course содержит информацию о курсе лекций: название курса (в элементе title), уникальный номер курса (CNO). Ниже приводится пример XML-документа “university_data”, обладающего описанной структурой. Moscow Kommunisticheskaya 25 19283764 Kate 120 123
156
показанной на рис 1. С точки зрения приложения, работающего с XML-данными заранее определенной структуры, эта операция модификации данных является некорректной, так как после ее проведения XML-данные перестают соответствовать этой структуре. Таким образом, описанную проблему логично рассмотреть как требование приложения к системе управления XML-данными поддерживать XML-данные в соответствии с заранее определенной структурой. Рассмотрим следующую операцию модификации данных. Студенту с именем Kate добавляется номер курса лекции, посещаемый этим студентом.
23 Moscow Kommunisticheskaya 1 19283723 Alex 123 23
UPDATE insert 212 into document(“university_data”)/university/student[name=”Kate”] (2)
123 Database Systems 120 Artificial Intelligence
Данная операция модификации добавляет к данным студента номер курса лекций, посещаемого студентом, информация о котором не содержится в данных. То есть, нет данных о курсе лекций с номером 212, что приводит к противоречию с изначальным описанием данных, где сказано, что для каждого номера курса лекции, содержащегося в данных студента, должны существовать данные о курсе лекций с таким номером. Следующая операция модификации данных добавляет данные о курсе лекций с номером, который уже встречается в данных.
Приложению, работающему с этими XML-данными, время от времени необходимо проводить модификации данных. Рассмотрим несколько примеров выражений модификации и обратим внимание на то, какие проблемы, связанные с нарушением изначального описания, могут возникнуть при таких модификациях. Для наглядности операции модификации мы будем описывать на языке модификации XML-данных XUpdate, поддерживаемом в XML-СУБД Sedna[13]. Язык XUpdate является расширением языка запросов XML-данных XQuery[17] операциями модификации XML-данных. Основные конструкции языка XUpdate, в частности, выражения, адресующие узел XML-документа, базируются на конструкциях языка XQuery. Следующее выражение модификации XML-данных добавляет информацию об адресе студента с именем Kate: UPDATE (1) insert Moscow, Ostankinskaya st., 8 into document(“university_data”)/university/student[name=”Kate”]
Согласно описанной выше структуре XML-данных элемент address студента состоит из подэлементов city, street и houseNo, содержащих называние города, улицы и номер дома соответственно. Выражение модификации (1) всю информацию об адресе вставляет в элемент address. После проведения рассмотренной операции модификации данные университета не соответствуют структуре, 157
UPDATE (3) insert 123 Computer Networks into document(“university_data”)/university
После проведения описанной операции модификации данные содержат информацию о двух курсах лекций с одинаковыми номерами, что противоречит изначальному описанию данных, в которых сказано, что номера курсов лекций уникальны. Проблемы, возникшие при выполнении операций модификации (2) и (3) имеют непосредственный аналог в реляционных СУБД, в литературе часто называются ограничениями целостности по ссылкам. В разделе 5 мы рассмотрим эти проблемы формально в контексте XML-СУБД. Рассмотрим следующий пример операции модификации данных. (4)
UPDATE REPLACE //student[name="Kate"]/age AS $x WITH {$x+10}
Данная операция модификации увеличивает возраст студента с именем Kate на 10. Таким образом, после проведения этой операции возраст будет равен 33, что противоречит исходному описанию данных, ограничивающему возраст студентов 30 годами. 158
В этом примере мы столкнулись с проблемой, для которой также имеется аналог в реляционных СУБД. Согласно [16], аналогом ограничения на возраст студентов из нашего примера в реляционных СУБД является ограничение на атрибут, а аналогичная операция модификации, в результате которой значение становится больше 30, нарушает это ограничение. Несмотря на аналогии, в контексте XML-СУБД эта проблема требует пересмотра. В разделе 5 мы рассмотрим ее формально в контексте XML-СУБД. Итак, мы рассмотрели пример приложения, работающего с XML-данными, и несколько выражений модификации этих данных, выполняемых приложением. После выполнения этих операций модификации данные перестают удовлетворять своему исходному описанию. Естественно предположить, что решение таких проблем должна предоставлять система управления XMLданными, используемая приложением. Как правило, такие требования выдвигаются к СУБД вне зависимости от того, на какой модели данных основана эта СУБД. Таким образом, следующей нашей целью в этой работе является формальное определение видов ограничений целостности, которые должны поддерживаться современной XML-СУБД.
2. Структурные ограничения целостности В этом разделе мы рассмотрим первый вид ограничений целостности, который назовем структурными ограничениями целостности. Вернемся к первой операции модификации из примера. Эта операция добавляет элемент address в качестве потомка элемента student, что делает XML-данные не соответствующими структуре, изображенной на рис 1. Таким образом, эта структура является ограничением, накладываемым на данные. В контексте XML структура, которой должны обладать XML-данные, называется схемой XML-данных. В отличие от HTML, являющегося конкретным языком, синтаксис которого включает фиксированный предопределенный стандартом языка набор тегов разметки, XML представляет собой расширяемый язык, с использованием которого можно создавать различные языки, т.е. метаязык. При этом XML-данные являются самоописываемыми благодаря использованию тегов. С другой стороны, важнейшее свойство XML – расширяемость, обозначенное в названии языка, подразумевает наличие механизмов определения схемы XML-данных. То есть XMLданные могут поступать как самостоятельно, так и с заранее определенной схемой, которая может использоваться как для адекватной интерпретации самих данных, так и для проверки правильности структуры данных. Таким образом, в XML-СУБД определение схемы, которой должны удовлетворять XML-данные (говоря о XML-данных, будем иметь в виду XMLдокументы), является определением структурного ограничения целостности для этих данных. На этом этапе наших рассуждений возникают следующие вопросы: каким образом можно определить схему XML-данных? И что значит то утверждение, 159
что XML-данные не нарушают структурное ограничение целостности, определенное в СУБД для этих данных? Перейдем к обсуждению первого вопроса. В настоящее время существует около десятка языков описания схем XML-данных [8, 9], поддерживаемых различными организациями. Наиболее популярными из них являются языки DTD [1], XML Schema [3] (предоставлены консорциумом W3C), RELAX (разработан Макото Мурата, в настоящее время проводится стандартизация в JSA (Japanese Standard Association)) [19], XDR (Microsoft)[9], SOX(Schema for Object-Oriented XML) [9]. Схемы XML-данных (как, впрочем, и схемы любой модели данных) предназначены для описания структурных и семантических ограничений, которые должны выполняться на любом наборе данных, удовлетворяющем данной схеме. Характерными примерами структурного ограничения являются спецификации содержания элементов (например, элемент с именем А может содержать только элементы с именем В). Характерными примерами семантических ограничений являются спецификации ключей (уникальных атрибутов). Несмотря на то, что языки описания схем достаточно сильно различаются по выразительной мощности, многие принципы построения ограничений схожи и основаны на использовании регулярных выражений. В большей степени это касается структурных ограничений. Поэтому многие свойства структурных ограничений в рамках одного языка имеют свои аналоги в других языках. Исходя из этих рассуждений, структурные ограничения целостности в XMLСУБД разумно описывать при помощи одного из языков описания схем XMLданных. На сегодняшний день существует множество работ по сравнению языков описания XML-схем. В этих работах представляется глубокий анализ языков и предлагаются различные критерии для их сравнения [7, 8]. В частности, сравнительный анализ проводится путем сопоставления языков описания схем регулярным грамматикам [7]. В нашей работе, опираясь на результаты [7, 8, 9], мы предлагаем в качестве языка описания структурных ограничений целостности для XML-СУБД использовать XML Schema [3] по следующим причинам: 1) XML Schema является гораздо более мощным языком по сравнению с очень популярным на первых этапах развития XML языком XML DTD; 2) Язык обладает механизмами, облегчающими спецификацию схем: определение сложных типов, определение анонимных типов, определение групп, определение подтипов путем расширения и ограничения, группы подстановок, определение абстрактных типов; 3) XML Schema в настоящее время успешно заменяет DTD; 4) XML Schema является стандартом W3C [2]; 5) В XML Schema для описания схем используется синтаксис XML, что облегчает обработку ограничений целостности, позволяя пользоваться развитым инструментарием для обработки XML.
160
Если вернуться к нашему примеру, структурное ограничение целостности, то есть определение структуры данных из рис.1, выраженное на языке описания XML-схем, выглядит следующим образом: