Mercurial > hg > tema
view misc/biotopes/doc/article.txt @ 22:1bd3a6740cfb
Fix return value calculation.
author | Mikhail Kryshen <mikhail@kryshen.net> |
---|---|
date | Wed, 22 Apr 2009 03:04:30 +0400 |
parents | 6c41a0b43e58 |
children |
line wrap: on
line source
* Преобразование базы данных в XML-формат электронной библиотеки. Для решения задачи преобразования базы данных "Местообитания Восточной Фенноскандии" из формата Microsoft Access в XML-формат электронной библиотеки КарНЦ РАН была разработана программная система DbReader. Программа DbReader является универсальным средством для представления информации из баз данных в текстовых форматах. Программа обрабатывает заданные шаблоны текстовых файлов и заменяет найденные в них инструкции на результаты их выполнения. Различные инструкции позволяют формировать SQL-запросы, выполнять их и обрабатывать полученные данные. * Формат инструкций: <%<список_функций>{:|\}<данные>%> где <список_функций> - список имен функций, разделенных пробелами. Может быть пустым. <данные> - данные, передаваемые функции. * Формат данных: [<список_аргументов>][<текст>] где <список_аргументов> - список аргументов функции, разделенных пробелами. Может быть пустым. <текст> - текст, передаваемый функции без разбиения на аргументы. Может быть пустым. Количество аргументов, после которого следует текст, зависит от функции. Разделитель между списком функций и данными определяет, как должны обрабатываться данные функции: : - рекурсивная обработка, \ - передать без обработки. Если в списке функций задано две и более функции, они выполняются, начиная с последней, так что каждая функция получает в качестве данных результат выполнения следующей функции. Каждая функция имеет код возврата - целое число. Код возврата инструкции - код возврата первой в списке функции. Код возврата, получаемый при обработке текста - сумма кодов возврата обработанных инструкций. Вместо скобок '<', '>' можно использовать скобки '[', ']'. * Реализованные функции: Функция: set Аргументы: <имя> Текст: <значение> Действие: устанавливает значение переменной <имя> Результат: <имя> Код возврата: 1 Функция: get Аргументы: <имя> Результат: значение переменной <имя>. Код возврата: 1, если значение переменной было установлено, 0 - иначе. Функция: prepare Аргументы: <имя> Текст: <запрос> Действие: Подготавливает SQL-запрос <запрос> для выполнения, записывает подготовленный запрос в переменную <имя>. Результат: <имя> Код возврата: 1 Функция: query Аргументы: <имя_запроса> <шаблон> <парам1> ... <парамN> Действие: Выполняет запрос с параметрами, подготовленный с помощью функции prepare. Значения параметров подставляются в запрос вместо символа '?'. Значения полей ответа будут записаны, как переменные шаблона <шаблон>. При обработки шаблона <шаблон> также определяется переменная NUMBER, содержащая номер текущей строки ответа. Переменные, определенные в вызывающем шаблоне, доступны из шаблона <шаблон> по имени SUPER.<имя_переменной>. Результат: результат обработки шаблона <шаблон> для каждой строки ответа. Код возврата: количество полученных строк ответа. Функция: optional Текст: <данные> Результат: <данные>, если при обработке данных был получен код возврата отличный от 0, иначе - пустая строка. Код возврата: 1, если результат - пустая строка, 0 - иначе. Функция: image Аргументы: <исх_файл> <кон_файл> <формат> [<макс_ширина> [<макс_высота>]] Действие: Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. Результат: <кон_файл> при успешном выполнении, пустая строка - иначе. Код возврата: 1 при успешном выполнении, 0 - иначе. Функция: copy Аргументы: <исх_файл> <кон_файл> Действие: Копирует файл <исх_файл> в файл <кон_файл> (путь <исх_файл> определяется относительно конфигурационного параметра "resource_base"). Результат: <кон_файл> при успешном выполнении, пустая строка - иначе. Код возврата: 1 при успешном выполнении, 0 - иначе. Функция: write Аргументы: <имя_файла> Текст: <данные> Действие: Записывает <данные> в файл <исх_файл>. Результат: <кон_файл> при успешном выполнении, пустая строка - иначе. Код возврата: 1 при успешном выполнении, 0 - иначе. Функция: read Текст: <имя_файла> Действие: Читает файл <имя_файла>. Результат: прочитанные данные при успешном выполнении, пустая строка - иначе. Код возврата: 1 при успешном выполнении, 0 - иначе. Функция: include Текст: <имя_файла> Действие: включает шаблон из файла <имя_файла>. Результат: результат обработки шаблона. Код возврата: код возврата, полученный при обработке шаблона. Функция: ! Текст: <данные> Действие: нет. Результат: нет. Код возврата: код возврата, полученный при обработке текста данных. Функция: replace Аргументы: <стр1> <стр2> Текст: <данные> Результат: данные, с замененными вхождениями подстроки <стр1> на <стр2>. Код возврата: код возврата, полученный при обработке текста данных. Функция: xml_escape Текст: <данные> Результат: текст <данные>, в котором символы '&', '<', '>', '`', '\' заменены на соответствующие сущности XML. Код возврата: код возврата, полученный при обработке текста данных. Функция: xml_cdata Текст: <данные> Результат: данные в виде блока XML CDATA. Код возврата: код возврата, полученный при обработке текста данных. Система DbReader расширяема: возможно добавление в систему новых функций, реализованных в виде классов на языке Java. * Применение системы DbReader для преобразования базы данных "Местообитания Восточной Фенноскандии" из формата Microsoft Access в XML-формат электронной библиотеки КарНЦ РАН Для преобразования используются две таблицы базы данных "Местообитания Восточной Фенноскандии" (перечислены только используемые поля): biotopelist (code, rangcode, rusname, engname, descript, geobotdescr, contributors, descrdate) code - счетчик, ключевое поле; rangcode - поле в формате ABBCCDDEE, где А, BB, CC, DD, ЕЕ - коды класса, подклассов и растения; rusname, engname, descript, geobotdescr - текстовые поля; descrdate - дата. photos (biotope, photo, authphoto) biotope - число, указывает на code в biotopelist; photo - имя файла фотографии; authphoto - текст. Требуется сгенерировать xml-файл для каждой записи в biotopelist, файл со списком классов, файл со списком растений, полноразмерные и уменьшенные версии каждой фотографии. Для генерации xml-файлов с описаниями биотопов использовался следующий шаблон DbReader (файл biotope.template): ---------------------------------------------------------------------- <?xml version="1.0" encoding="ISO-8859-5"?> <!DOCTYPE описание_вида SYSTEM "brief.dtd"> <!-- rangcode: <%xml_escape get\rangcode%> --> <описание_вида show="0"> <рисунки display="0"> <%optional:<карта_распространения номер="1" file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> <%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> </рисунки> <название><%xml_escape get\rusname%></название> <класс><%xml_escape get\class0%></класс> <подкласс1><%xml_escape get\class1%></подкласс1> <подкласс2><%xml_escape get\class2%></подкласс2> <подкласс3><%xml_escape get\class3%></подкласс3> <краткая_характеристика rows="3"><%xml_cdata get\descript%></краткая_характеристика> <пример_описания rows="3"><%xml_cdata get\geobotdescr%></пример_описания> <авторы_описания><%xml_escape get\contributors%></авторы_описания> </описание_вида> ---------------------------------------------------------------------- Соответствующий SQL-запрос, при выполнении которого устанавливаются значения переменных шаблона rangcode, rusname, class0, class1, class2, class3, descript, geobotdescr и contributors (файл biotope.sql): ---------------------------------------------------------------------- SELECT t1.*, (SELECT t2.rusname FROM biotopelist AS t2 WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND Right(t2.rangcode, 8) = '00000000' AND Right(t1.rangcode, 8) <> '00000000') AS class0, (SELECT t2.rusname FROM biotopelist AS t2 WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND Right(t2.rangcode, 6) = '000000' AND Right(t1.rangcode, 6) <> '000000') AS class1, (SELECT t2.rusname FROM biotopelist AS t2 WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND Right(t2.rangcode, 4) = '0000' AND Right(t1.rangcode, 4) <> '0000') AS class2, (SELECT t2.rusname FROM biotopelist AS t2 WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND Right(t2.rangcode, 2) = '00' AND Right(t1.rangcode, 2) <> '00') AS class3 FROM biotopelist AS t1 WHERE rusname ---------------------------------------------------------------------- Шаблон biotope.template содержит инструкцию <%include\photo.template%>, включающую шаблон описания фотографии (файл photo.template): ---------------------------------------------------------------------- <фотография num="<%xml_escape get\NUMBER%>" <%optional:автор="<%xml_escape get\authphoto%>" %>text="" file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/> ---------------------------------------------------------------------- Соответствующий SQL-запрос для получения описания фотографий (photo.sql): ---------------------------------------------------------------------- SELECT * from photos WHERE biotope = ? ---------------------------------------------------------------------- Шаблон, генерирующий список классов (файл classes.template): ---------------------------------------------------------------------- <?xml version="1.0" encoding="ISO-8859-5"?> <классификация><%query:class_sql [%\ <!-- rangcode: <%xml_escape get\rangcode%> --> <класс id="<%get\NUMBER%>"><%xml_escape get\rusname%></класс>%]%> </классификация> ---------------------------------------------------------------------- Соответствующий SQL-запрос (class.sql): ---------------------------------------------------------------------- SELECT t1.* FROM biotopelist AS t1 WHERE rusname AND Right(t1.rangcode, 8) = '00000000' AND EXISTS (SELECT NULL FROM biotopelist AS t2 WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND Right(t2.rangcode, 8) <> '00000000') ---------------------------------------------------------------------- Шаблон, генерирующий список растений (файл plants.template): ---------------------------------------------------------------------- <?xml version="1.0" encoding="ISO-8859-5"?> <растения><%query:plant_sql [%\ <!-- rangcode: <%xml_escape get\rangcode%> --> <растение><%xml_escape get\rusname%></растение>%]%> </растения> ---------------------------------------------------------------------- Соответствующий SQL-запрос (plant.sql): ---------------------------------------------------------------------- SELECT t1.* FROM biotopelist AS t1 WHERE rusname AND Right(t1.rangcode, 2) <> '00' ---------------------------------------------------------------------- Система DbReader начинает работу с обработки шаблона index.template, который содержит вызовы перечисленных выше SQL-запросов и включения шаблонов: ---------------------------------------------------------------------- <%!: <%prepare:biotope_sql <%read\biotope.sql%>%> <%prepare:photo_sql <%read\photo.sql%>%> <%prepare:class_sql <%read\class.sql%>%> <%prepare:plant_sql <%read\plant.sql%>%> <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> <%write:classes.xml <%include\classes.template%>%> <%write:plants.xml <%include\plants.template%>%> %> ---------------------------------------------------------------------- Пример сгенерированного XML-файла: ---------------------------------------------------------------------- <?xml version="1.0" encoding="ISO-8859-5"?> <!DOCTYPE описание_вида SYSTEM "brief.dtd"> <!-- rangcode: E04020302 --> <описание_вида show="0"> <рисунки display="0"> <фотография num="1" автор="Крышень А.М." text="" file="images/3_1.jpg" big="images/big/3_1.jpg"/> <фотография num="2" автор="Крышень А.М." text="" file="images/3_2.jpg" big="images/big/3_2.jpg"/> </рисунки> <название>Betula sp. - Avenella flexuosa - Polytrichum commune</название> <класс>E. Суходольные местообитания</класс> <подкласс1>Автоморфные влажные</подкласс1> <подкласс2></подкласс2> <подкласс3></подкласс3> <краткая_характеристика rows="3"><![CDATA[Развиваются на луговиковых вырубках лесов черничного типа. Через 5 - 7 лет после рубки порослевая береза выходит из яруса травянистых растений, ее влияние сказывается, в первую очередь, на влажности почвы.]]></краткая_характеристика> <пример_описания rows="3"></пример_описания> <авторы_описания></авторы_описания> </описание_вида> ---------------------------------------------------------------------- * Структура программы DbReader Программа DbReader написана на языке программирования Java и состоит из следующих основных классов: ru.karrc.dbreader.DbReader: cодержит точку входа программы. Загружает конфигурацию, устанавливает соединение с источником данных с помощью библиотеки JDBC, запускает обработку основного шаблона. ru.karrc.dbreader.TemplateParser: осуществляет разбор шаблона, обработку инструкций и вызов функций. ru.karrc.dbreader.Function: абстрактный класс. Реализации всех функций DbReader наследуют этот класс. ru.karrc.dbreader.FunctionDataParser: обработчик данных функции. Посволяет получить список аргументов и текст, передаваемый функции. При необходимости вызывает рекурсивную обработку данных с помощью TemplateParser. ru.karrc.dbreader.Functions: содержит реализации функций в виде анонимных классов, наследующих Function. ru.karrc.dbreader.TemplateParser: исключение, выбрасываемое в случае возникновения ошибки при обработке шаблона. Кроме того, реализовано несколько впомогательных классов, которые используются в реализациях функций системы. * Метрики реализованной программной системы. Количество файлов исходного кода: 8, Количество Java-классов (включая анонимные): 27, Общее количество строк исходного текста: 1311, Количество строк кода (исключая пустые строки и комментарии): 812, Количество строк комментариев: 180. * Заключение Автором была разработана программная система DbReader, которая является расширяемым и универсальным средством для представления информации из баз данных в текстовых форматах. С помощью системы DbReader база данных "Местообитания Восточной Фенноскандии" была переведена в XML-формат электронной библиотеки КарНЦ РАН.