Mercurial > hg > tema
changeset 1:548a93c24e55 release_0_1jk
Tema 0.1jk - Javakonkurs edition (imported from CVS).
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TODO Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,1 @@ +if, <, >, =, +, -, *, /
--- a/build.xml Tue May 16 18:04:09 2006 +0400 +++ b/build.xml Thu Dec 14 23:22:05 2006 +0300 @@ -5,6 +5,7 @@ <property name="build" value="build"/> <property name="dist" value="dist"/> <property name="res" value="res"/> + <property name="doc" value="doc"/> <property name="jar_file" value="tema.jar"/> <target name="init"> @@ -14,20 +15,30 @@ <target name="compile" depends="init"> <javac srcdir="${src}" destdir="${build}" - deprecation="on" optimize="on" debug="on"/> + deprecation="on" optimize="on" debug="on"> + <!-- <compilerarg value="-Xlint:unchecked"/> --> + </javac> </target> <target name="dist" depends="compile"> <jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf"> <fileset dir="${build}" includes="**/*.class"/> + <fileset dir="${res}" includes="**/*"/> </jar> - </target> + </target> + <target name="javadoc" depends="init"> + <javadoc destdir="${doc}/api" sourcepath="${src}" + packagenames="kryshen.tema.*"> + </javadoc> + </target> + <target name="clean"> <delete> <fileset dir="${build}" includes="**/*.class"/> </delete> <delete file="${dist}/${jar_file}"/> + <delete dir="${doc}/api"/> </target> </project>
--- a/dist/biotopes/biotope.template Tue May 16 18:04:09 2006 +0400 +++ b/dist/biotopes/biotope.template Thu Dec 14 23:22:05 2006 +0300 @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="ISO-8859-5"?> <!DOCTYPE чъьАпщьу_рьтп SYSTEM "brief.dtd"> -<!-- rangcode: <%xml_escape get\rangcode%> --> +<!-- rangcode: <%xml_escape db\rangcode%> --> <чъьАпщьу_рьтп show="0"> <ЮьАЦщзь display="0"> - <%optional:<зпЮБп_ЮпАъЮчАБЮпщущьО щчэуЮ="1" file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> + <%optional:<зпЮБп_ЮпАъЮчАБЮпщущьО щчэуЮ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\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%></прБчЮК_чъьАпщьО> + <щпврпщьу><%xml_escape db\rusname%></щпврпщьу> + <зшпАА><%xml_escape db\class0%></зшпАА> + <ъчтзшпАА1><%xml_escape db\class1%></ъчтзшпАА1> + <ъчтзшпАА2><%xml_escape db\class2%></ъчтзшпАА2> + <ъчтзшпАА3><%xml_escape db\class3%></ъчтзшпАА3> + <зЮпБзпО_ЕпЮпзБуЮьАБьзп rows="3"><%xml_cdata db\descript%></зЮпБзпО_ЕпЮпзБуЮьАБьзп> + <ъЮьэуЮ_чъьАпщьО rows="3"><%xml_cdata db\geobotdescr%></ъЮьэуЮ_чъьАпщьО> + <прБчЮК_чъьАпщьО><%xml_escape db\contributors%></прБчЮК_чъьАпщьО> </чъьАпщьу_рьтп>
--- a/dist/biotopes/classes.template Tue May 16 18:04:09 2006 +0400 +++ b/dist/biotopes/classes.template Thu Dec 14 23:22:05 2006 +0300 @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="ISO-8859-5"?> <зшпААьДьзпФьО><%query:class_sql [%\ <!-- rangcode: <%xml_escape get\rangcode%> --> - <зшпАА id="<%get\NUMBER%>"><%xml_escape get\rusname%></зшпАА>%]%> + <зшпАА id="<%get\NUMBER%>"><%xml_escape db\rusname%></зшпАА>%]%> </зшпААьДьзпФьО>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/biotopes/doc/article.txt Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,391 @@ +* Преобразование базы данных в 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-формат электронной библиотеки КарНЦ РАН.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/biotopes/doc/readme.html Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,86 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <title>DbReader</title> + <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" /> +</head> + +<body> +<h1>DbReader</h1> + +<h2>Установка программы</h2> +<ol> +<li>Распаковать архив.</li> + +<li>Установить источник данных:<br /> +в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes-data.mdb.</li> + +<li>Настроить программу:<br /> +В файле dbreader.properties указать имя, присвоенное источнику данных:<br /> + <code>resource: jdbc:odbc:<em>имя</em></code><br /> +и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):<br /> + <code>resource_base: C:\\biotopes</code><br /> +(символ '\' необходимо дублировать)</li> + +<li>Запуск программы:<br /> +<code>dbreader.bat</code> или<br /> +<code>java -jar dbreader.jar</code>.<br /> +Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с <a href="http://java.sun.com/j2se/1.5.0/download.jsp">http://java.sun.com/j2se/1.5.0/download.jsp</a>. Возможно, будет работать и со старыми версиями JRE - не проверял. + +Все значения файла конфигурации можно переопределять при запуске программы:<br /> +команда <code>java -Dru.karrc.dbreader.<em>ключ</em>=<em>значение</em> -jar dbreader.jar</code><br /> +(например: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li> +</ol> + +<h2>Работа программы</h2> + +<p>Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.</p> +<p>Формат инструкций: <code><%<em>список_функций</em>[:|\]<em>данные</em>%></code>, <em>список функций</em> - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.</p> + +<h3>Разделители между списком функций и данными</h3> + +<ul> + <li><code>:</code> - данные будут обрабатываться рекурсивно.</li> + <li><code>\</code> - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов <code><%</code> и <code>%></code> (<code><%\<%%></code> и <code><%\%%>></code>).</li> +</ul> + +<h3>Функции</h3> + +<ul> + <li><code><%get:<em>имя</em>%></code><br /> + Заменяется на значение встроенной переменной или колонки запроса.</li> + + <li><code><%optional:<em>текст</em>%></code><br /> + Заменяется на <em>текст</em>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.</li> + + <li><code><%escape:<em>текст</em>%></code><br /> + Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).</li> + + <li><code><%invoke:<em>имя</em>; <em>парам1</em> <em>парам2</em> ... <em>парамN</em>%></code><br /> + Выполняет запрос с параметрами <em>имя</em>.sql и заменяется на результаты обработки шаблона <em>имя</em>.template. Значения параметров подставляются в запрос вместо символа '?'.</li> + + <li><code><%image:<em>исх_файл</em> <em>кон_файл</em> <em>формат</em> [<em>макс_ширина</em>] [<em>макс_высота</em>]%></code><br /> + Загружает изображение из файла <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <em>кон_файл</em>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. +При успешном выполнении, инструкция <code><%image:...%></code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li> + + <li><code><%copy:<em>исх_файл</em> <em>кон_файл</em>%></code><br /> + Копирует файл <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") в <em>кон_файл</em>. При успешном выполнении, инструкция <code><%copy:...%></code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li> +</ul> + +<h3>Встроенные переменные</h3> + +<p><code>NUMBER</code> - порядковый номер строки результата выполнения запроса. +Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить <code>SUPER.</code> (например: <code>SUPER.NUMBER</code>).</p> + +<h3>Пример</h3> + +<p>Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:</p> +<p><code><%escape get:name%></code></p> + +<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru">Михаил Крышень</a></i></p> + +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/biotopes/doc/readme.txt Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,63 @@ +text/plain; charset=UTF-8 + +пёя│я┌п╟п╫п╬п╡п╨п╟ п©я─п╬пЁя─п╟п╪п╪я▀ +------------------- + +1. п═п╟я│п©п╟п╨п╬п╡п╟я┌я▄ п╟я─я┘п╦п╡. + +2. пёя│я┌п╟п╫п╬п╡п╦я┌я▄ п╦я│я┌п╬я┤п╫п╦п╨ п╢п╟п╫п╫я▀я┘: +п╡ Windows 2000: п÷п╟п╫п╣п╩я▄ я┐п©я─п╟п╡п╩п╣п╫п╦я▐/п░п╢п╪п╦п╫п╦я│я┌я─п╦я─п╬п╡п╟п╫п╦п╣/п≤я│я┌п╬я┤п╫п╦п╨п╦ п╢п╟п╫п╫я▀я┘ (ODBC), п╢п╬п╠п╟п╡п╦я┌я▄ biotopes.mdb. + +3. п²п╟я│я┌я─п╬п╦я┌я▄ п©я─п╬пЁя─п╟п╪п╪я┐: +п▓ я└п╟п╧п╩п╣ dbreader.properties я┐п╨п╟п╥п╟я┌я▄ п╦п╪я▐, п©я─п╦я│п╡п╬п╣п╫п╫п╬п╣ п╦я│я┌п╬я┤п╫п╦п╨я┐ п╢п╟п╫п╫я▀я┘: + "resource: jdbc:odbc:<п╦п╪я▐>" +п╦ п©я┐я┌я▄ п╨ п╨п╟я┌п╟п╩п╬пЁя┐, п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬я┌п╬я─п╬пЁп╬ п©я─п╬пЁя─п╟п╪п╪п╟ п╠я┐п╢п╣я┌ п╦я│п╨п╟я┌я▄ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ (я│п╬п╢п╣я─п╤п╟я┴п╦п╧ biotopephotos п╦ maps): + "resource_base: C:\\biotopes" +(я│п╦п╪п╡п╬п╩ '\' п╫п╣п╬п╠я┘п╬п╢п╦п╪п╬ п╢я┐п╠п╩п╦я─п╬п╡п╟я┌я▄) + +4. п≈п╟п©я┐я│п╨ п©я─п╬пЁя─п╟п╪п╪я▀: dbreader.bat п╦п╩п╦ "java -jar dbreader.jar" +п■п╩я▐ п╥п╟п©я┐я│п╨п╟ п╫п╣п╬п╠я┘п╬п╢п╦п╪п╟ Java Runtime Environment (JRE) 5.0, п╪п╬п╤п╫п╬ я│п╨п╟я┤п╟я┌я▄ я│ http://java.sun.com/j2se/1.5.0/download.jsp. п▓п╬п╥п╪п╬п╤п╫п╬, п╠я┐п╢п╣я┌ я─п╟п╠п╬я┌п╟я┌я▄ п╦ я│п╬ я│я┌п╟я─я▀п╪п╦ п╡п╣я─я│п╦я▐п╪п╦ JRE - п╫п╣ п©я─п╬п╡п╣я─я▐п╩. + +п▓я│п╣ п╥п╫п╟я┤п╣п╫п╦я▐ я└п╟п╧п╩п╟ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦ п╪п╬п╤п╫п╬ п©п╣я─п╣п╬п©я─п╣п╢п╣п╩я▐я┌я▄ п©я─п╦ п╥п╟п©я┐я│п╨п╣ п©я─п╬пЁя─п╟п╪п╪я▀: + п╨п╬п╪п╟п╫п╢п╟ "java -Dru.karrc.dbreader.<п╨п╩я▌я┤>=<п╥п╫п╟я┤п╣п╫п╦п╣> -jar dbreader.jar" +(п╫п╟п©я─п╦п╪п╣я─: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar") + + +п═п╟п╠п╬я┌п╟ п©я─п╬пЁя─п╟п╪п╪я▀ +---------------- + +п÷я─п╬пЁя─п╟п╪п╪п╟ п╡я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ biotope.sql (п╦п╩п╦ п╢я─я┐пЁп╬п╧, я┐п╨п╟п╥п╟п╫п╫я▀п╧ п╡ dbreader.properties), п©п╬я│п╩п╣ я┤п╣пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ я└п╟п╧п╩ biotope.template, п╥п╟п╪п╣п╫я▐я▐ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╣п╪ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐. + +п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧: "<%я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧[:|\]п╢п╟п╫п╫я▀п╣%>", я│п©п╦я│п╬п╨ я└я┐п╫п╨я├п╦п╧ - п╦п╪п╣п╫п╟ я└я┐п╫п╨я├п╦п╧ я─п╟п╥п╢п╣п╩п╣п╫п╫я▀п╣ п©я─п╬п╠п╣п╩п╬п╪, я│п©п╦я│п╬п╨ п╪п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п∙я│п╩п╦ я┐п╨п╟п╥п╟п╫п╬ п╫п╣я│п╨п╬п╩я▄п╨п╬ я└я┐п╫п╨я├п╦п╧, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐ п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧. + +п═п╟п╥п╢п╣п╩п╦я┌п╣п╩п╦ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦: +':' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ я─п╣п╨я┐я─я│п╦п╡п╫п╬. +'\' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п©п╣я─п╣п╢п╟п╫я▀ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦. п°п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ п╢п╩я▐ я█п╨я─п╟п╫п╦я─п╬п╡п╟п╫п╦я▐ п╨п╬п╪п╠п╦п╫п╟я├п╦п╧ я│п╦п╪п╡п╬п╩п╬п╡ "<%" п╦ "%>" ("<%\<%%>" п╦ "<%\%%>>"). + +п╓я┐п╫п╨я├п╦п╦: +<%get:<п╦п╪я▐>%> - п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ п╡я│я┌я─п╬п╣п╫п╫п╬п╧ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╦п╩п╦ п╨п╬п╩п╬п╫п╨п╦ п╥п╟п©я─п╬я│п╟. + +<%optional:<я┌п╣п╨я│я┌>%> +п≈п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ <я┌п╣п╨я│я┌>, п╣я│п╩п╦ п╡ п╫п╣п╪ п╫п╟п╧п╢п╣п╫я▀ п╦п╫я│я┌я─я┐п╨я├п╦п╦, п╥п╟п╪п╣п╫п╦п╡я┬п╦п╣я│я▐ п╫п╟ п╫п╣п©я┐я│я┌я▀п╣ я│я┌я─п╬п╨п╦, п╦п╫п╟я┤п╣ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. + +<%escape:<я┌п╣п╨я│я┌>%> +п≈п╟п╪п╣п╫я▐п╣я┌ п╡ я┌п╣п╨я│я┌п╣ "п╬п©п╟я│п╫я▀п╣" я│п╦п╪п╡п╬п╩я▀ (я┌п╟п╠п╩п╦я├п╟ п╥п╟п╪п╣п╫ п╥п╟п╢п╟п╣я┌я│я▐ п╡ я└п╟п╧п╩п╣ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦). + +<%invoke:<п╦п╪я▐> <п©п╟я─п╟п╪1> <п©п╟я─п╟п╪2> ... <п©п╟я─п╟п╪N>%> +п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦ <п╦п╪я▐>.sql п╦ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <п╦п╪я▐>.template. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟ '?'. + +<%image:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩> <я└п╬я─п╪п╟я┌> [<п╪п╟п╨я│_я┬п╦я─п╦п╫п╟>] [<п╪п╟п╨я│_п╡я▀я│п╬я┌п╟>]%> +п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦ п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡ <п╨п╬п╫_я└п╟п╧п╩>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀. +п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!image ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. + +<%copy:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩>%> +п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base"). +п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!copy ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. + +п▓я│я┌я─п╬п╣п╫п╫я▀п╣ п©п╣я─п╣п╪п╣п╫п╫я▀п╣: +NUMBER - п©п╬я─я▐п╢п╨п╬п╡я▀п╧ п╫п╬п╪п╣я─ я│я┌я─п╬п╨п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ п╥п╟п©я─п╬я│п╟. +п╖я┌п╬п╠я▀ п╬п╠я─п╟я┌п╦я┌я▄я│я▐ п╨ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╥п╟п©я─п╬я│п╟, п╦п╥ п╨п╬я┌п╬я─п╬пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣п╪я▀п╧ я┬п╟п╠п╩п╬п╫ п╠я▀п╩ п╡я▀п╥п╡п╟п╫ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ invoke, п©п╣я─п╣п╢ п╦п╪п╣п╫п╣п╪ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╫я┐п╤п╫п╬ п╢п╬п╠п╟п╡п╦я┌я▄ "SUPER." (п╫п╟п©я─п╦п╪п╣я─: "SUPER.NUMBER"). + +п÷я─п╦п╪п╣я─: +п║п╩п╣п╢я┐я▌я┴п╟я▐ п╦п╫я│я┌я─я┐п╨я├п╦я▐ п©п╬п╩я┐я┤п╦я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п╦п╥ я│я┌п╬п╩п╠я├п╟ name п╦ п╥п╟п╪п╣п╫п╦я┌ п╡ п╫п╣п╪ я│п©п╣я├п╦п╟п╩я▄п╫я▀п╣ я│п╦п╪п╡п╬п╩я▀: +<%escape get:name%>
--- a/dist/biotopes/main.template Tue May 16 18:04:09 2006 +0400 +++ b/dist/biotopes/main.template Thu Dec 14 23:22:05 2006 +0300 @@ -4,7 +4,7 @@ <%prepare:class_sql <%read\class.sql%>%> <%prepare:plant_sql <%read\plant.sql%>%> - <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> + <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%> <%write:classes.xml <%include\classes.template%>%> <%write:plants.xml <%include\plants.template%>%>
--- a/dist/biotopes/photo.template Tue May 16 18:04:09 2006 +0400 +++ b/dist/biotopes/photo.template Thu Dec 14 23:22:05 2006 +0300 @@ -1,3 +1,3 @@ - <ДчБчсЮпДьО 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%>"/> + <ДчБчсЮпДьО num="<%number\%>" <%optional:прБчЮ="<%xml_escape db\authphoto%>" %>text="" + file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" + big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
--- a/dist/biotopes/plants.template Tue May 16 18:04:09 2006 +0400 +++ b/dist/biotopes/plants.template Thu Dec 14 23:22:05 2006 +0300 @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="ISO-8859-5"?> <ЮпАБущьО><%query:plant_sql [%\ - <!-- rangcode: <%xml_escape get\rangcode%> --> - <ЮпАБущьу><%xml_escape get\rusname%></ЮпАБущьу>%]%> + <!-- rangcode: <%xml_escape db\rangcode%> --> + <ЮпАБущьу><%xml_escape db\rusname%></ЮпАБущьу>%]%> </ЮпАБущьО>
--- a/dist/readme.html Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "DTD/xhtml1-transitional.dtd"> - -<html> - -<head> - <title>DbReader</title> - <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" /> -</head> - -<body> -<h1>DbReader</h1> - -<h2>Установка программы</h2> -<ol> -<li>Распаковать архив.</li> - -<li>Установить источник данных:<br /> -в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes-data.mdb.</li> - -<li>Настроить программу:<br /> -В файле dbreader.properties указать имя, присвоенное источнику данных:<br /> - <code>resource: jdbc:odbc:<em>имя</em></code><br /> -и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):<br /> - <code>resource_base: C:\\biotopes</code><br /> -(символ '\' необходимо дублировать)</li> - -<li>Запуск программы:<br /> -<code>dbreader.bat</code> или<br /> -<code>java -jar dbreader.jar</code>.<br /> -Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с <a href="http://java.sun.com/j2se/1.5.0/download.jsp">http://java.sun.com/j2se/1.5.0/download.jsp</a>. Возможно, будет работать и со старыми версиями JRE - не проверял. - -Все значения файла конфигурации можно переопределять при запуске программы:<br /> -команда <code>java -Dru.karrc.dbreader.<em>ключ</em>=<em>значение</em> -jar dbreader.jar</code><br /> -(например: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li> -</ol> - -<h2>Работа программы</h2> - -<p>Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.</p> -<p>Формат инструкций: <code><%<em>список_функций</em>[:|\]<em>данные</em>%></code>, <em>список функций</em> - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.</p> - -<h3>Разделители между списком функций и данными</h3> - -<ul> - <li><code>:</code> - данные будут обрабатываться рекурсивно.</li> - <li><code>\</code> - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов <code><%</code> и <code>%></code> (<code><%\<%%></code> и <code><%\%%>></code>).</li> -</ul> - -<h3>Функции</h3> - -<ul> - <li><code><%get:<em>имя</em>%></code><br /> - Заменяется на значение встроенной переменной или колонки запроса.</li> - - <li><code><%optional:<em>текст</em>%></code><br /> - Заменяется на <em>текст</em>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.</li> - - <li><code><%escape:<em>текст</em>%></code><br /> - Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).</li> - - <li><code><%invoke:<em>имя</em>; <em>парам1</em> <em>парам2</em> ... <em>парамN</em>%></code><br /> - Выполняет запрос с параметрами <em>имя</em>.sql и заменяется на результаты обработки шаблона <em>имя</em>.template. Значения параметров подставляются в запрос вместо символа '?'.</li> - - <li><code><%image:<em>исх_файл</em> <em>кон_файл</em> <em>формат</em> [<em>макс_ширина</em>] [<em>макс_высота</em>]%></code><br /> - Загружает изображение из файла <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <em>кон_файл</em>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. -При успешном выполнении, инструкция <code><%image:...%></code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li> - - <li><code><%copy:<em>исх_файл</em> <em>кон_файл</em>%></code><br /> - Копирует файл <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") в <em>кон_файл</em>. При успешном выполнении, инструкция <code><%copy:...%></code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li> -</ul> - -<h3>Встроенные переменные</h3> - -<p><code>NUMBER</code> - порядковый номер строки результата выполнения запроса. -Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить <code>SUPER.</code> (например: <code>SUPER.NUMBER</code>).</p> - -<h3>Пример</h3> - -<p>Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:</p> -<p><code><%escape get:name%></code></p> - -<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru">Михаил Крышень</a></i></p> - -</body> -</html>
--- a/dist/readme.txt Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -text/plain; charset=UTF-8 - -пёя│я┌п╟п╫п╬п╡п╨п╟ п©я─п╬пЁя─п╟п╪п╪я▀ -------------------- - -1. п═п╟я│п©п╟п╨п╬п╡п╟я┌я▄ п╟я─я┘п╦п╡. - -2. пёя│я┌п╟п╫п╬п╡п╦я┌я▄ п╦я│я┌п╬я┤п╫п╦п╨ п╢п╟п╫п╫я▀я┘: -п╡ Windows 2000: п÷п╟п╫п╣п╩я▄ я┐п©я─п╟п╡п╩п╣п╫п╦я▐/п░п╢п╪п╦п╫п╦я│я┌я─п╦я─п╬п╡п╟п╫п╦п╣/п≤я│я┌п╬я┤п╫п╦п╨п╦ п╢п╟п╫п╫я▀я┘ (ODBC), п╢п╬п╠п╟п╡п╦я┌я▄ biotopes.mdb. - -3. п²п╟я│я┌я─п╬п╦я┌я▄ п©я─п╬пЁя─п╟п╪п╪я┐: -п▓ я└п╟п╧п╩п╣ dbreader.properties я┐п╨п╟п╥п╟я┌я▄ п╦п╪я▐, п©я─п╦я│п╡п╬п╣п╫п╫п╬п╣ п╦я│я┌п╬я┤п╫п╦п╨я┐ п╢п╟п╫п╫я▀я┘: - "resource: jdbc:odbc:<п╦п╪я▐>" -п╦ п©я┐я┌я▄ п╨ п╨п╟я┌п╟п╩п╬пЁя┐, п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬я┌п╬я─п╬пЁп╬ п©я─п╬пЁя─п╟п╪п╪п╟ п╠я┐п╢п╣я┌ п╦я│п╨п╟я┌я▄ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ (я│п╬п╢п╣я─п╤п╟я┴п╦п╧ biotopephotos п╦ maps): - "resource_base: C:\\biotopes" -(я│п╦п╪п╡п╬п╩ '\' п╫п╣п╬п╠я┘п╬п╢п╦п╪п╬ п╢я┐п╠п╩п╦я─п╬п╡п╟я┌я▄) - -4. п≈п╟п©я┐я│п╨ п©я─п╬пЁя─п╟п╪п╪я▀: dbreader.bat п╦п╩п╦ "java -jar dbreader.jar" -п■п╩я▐ п╥п╟п©я┐я│п╨п╟ п╫п╣п╬п╠я┘п╬п╢п╦п╪п╟ Java Runtime Environment (JRE) 5.0, п╪п╬п╤п╫п╬ я│п╨п╟я┤п╟я┌я▄ я│ http://java.sun.com/j2se/1.5.0/download.jsp. п▓п╬п╥п╪п╬п╤п╫п╬, п╠я┐п╢п╣я┌ я─п╟п╠п╬я┌п╟я┌я▄ п╦ я│п╬ я│я┌п╟я─я▀п╪п╦ п╡п╣я─я│п╦я▐п╪п╦ JRE - п╫п╣ п©я─п╬п╡п╣я─я▐п╩. - -п▓я│п╣ п╥п╫п╟я┤п╣п╫п╦я▐ я└п╟п╧п╩п╟ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦ п╪п╬п╤п╫п╬ п©п╣я─п╣п╬п©я─п╣п╢п╣п╩я▐я┌я▄ п©я─п╦ п╥п╟п©я┐я│п╨п╣ п©я─п╬пЁя─п╟п╪п╪я▀: - п╨п╬п╪п╟п╫п╢п╟ "java -Dru.karrc.dbreader.<п╨п╩я▌я┤>=<п╥п╫п╟я┤п╣п╫п╦п╣> -jar dbreader.jar" -(п╫п╟п©я─п╦п╪п╣я─: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar") - - -п═п╟п╠п╬я┌п╟ п©я─п╬пЁя─п╟п╪п╪я▀ ----------------- - -п÷я─п╬пЁя─п╟п╪п╪п╟ п╡я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ biotope.sql (п╦п╩п╦ п╢я─я┐пЁп╬п╧, я┐п╨п╟п╥п╟п╫п╫я▀п╧ п╡ dbreader.properties), п©п╬я│п╩п╣ я┤п╣пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ я└п╟п╧п╩ biotope.template, п╥п╟п╪п╣п╫я▐я▐ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╣п╪ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐. - -п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧: "<%я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧[:|\]п╢п╟п╫п╫я▀п╣%>", я│п©п╦я│п╬п╨ я└я┐п╫п╨я├п╦п╧ - п╦п╪п╣п╫п╟ я└я┐п╫п╨я├п╦п╧ я─п╟п╥п╢п╣п╩п╣п╫п╫я▀п╣ п©я─п╬п╠п╣п╩п╬п╪, я│п©п╦я│п╬п╨ п╪п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п∙я│п╩п╦ я┐п╨п╟п╥п╟п╫п╬ п╫п╣я│п╨п╬п╩я▄п╨п╬ я└я┐п╫п╨я├п╦п╧, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐ п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧. - -п═п╟п╥п╢п╣п╩п╦я┌п╣п╩п╦ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦: -':' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ я─п╣п╨я┐я─я│п╦п╡п╫п╬. -'\' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п©п╣я─п╣п╢п╟п╫я▀ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦. п°п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ п╢п╩я▐ я█п╨я─п╟п╫п╦я─п╬п╡п╟п╫п╦я▐ п╨п╬п╪п╠п╦п╫п╟я├п╦п╧ я│п╦п╪п╡п╬п╩п╬п╡ "<%" п╦ "%>" ("<%\<%%>" п╦ "<%\%%>>"). - -п╓я┐п╫п╨я├п╦п╦: -<%get:<п╦п╪я▐>%> - п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ п╡я│я┌я─п╬п╣п╫п╫п╬п╧ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╦п╩п╦ п╨п╬п╩п╬п╫п╨п╦ п╥п╟п©я─п╬я│п╟. - -<%optional:<я┌п╣п╨я│я┌>%> -п≈п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ <я┌п╣п╨я│я┌>, п╣я│п╩п╦ п╡ п╫п╣п╪ п╫п╟п╧п╢п╣п╫я▀ п╦п╫я│я┌я─я┐п╨я├п╦п╦, п╥п╟п╪п╣п╫п╦п╡я┬п╦п╣я│я▐ п╫п╟ п╫п╣п©я┐я│я┌я▀п╣ я│я┌я─п╬п╨п╦, п╦п╫п╟я┤п╣ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. - -<%escape:<я┌п╣п╨я│я┌>%> -п≈п╟п╪п╣п╫я▐п╣я┌ п╡ я┌п╣п╨я│я┌п╣ "п╬п©п╟я│п╫я▀п╣" я│п╦п╪п╡п╬п╩я▀ (я┌п╟п╠п╩п╦я├п╟ п╥п╟п╪п╣п╫ п╥п╟п╢п╟п╣я┌я│я▐ п╡ я└п╟п╧п╩п╣ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦). - -<%invoke:<п╦п╪я▐> <п©п╟я─п╟п╪1> <п©п╟я─п╟п╪2> ... <п©п╟я─п╟п╪N>%> -п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦ <п╦п╪я▐>.sql п╦ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <п╦п╪я▐>.template. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟ '?'. - -<%image:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩> <я└п╬я─п╪п╟я┌> [<п╪п╟п╨я│_я┬п╦я─п╦п╫п╟>] [<п╪п╟п╨я│_п╡я▀я│п╬я┌п╟>]%> -п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦ п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡ <п╨п╬п╫_я└п╟п╧п╩>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀. -п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!image ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. - -<%copy:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩>%> -п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base"). -п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!copy ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐. - -п▓я│я┌я─п╬п╣п╫п╫я▀п╣ п©п╣я─п╣п╪п╣п╫п╫я▀п╣: -NUMBER - п©п╬я─я▐п╢п╨п╬п╡я▀п╧ п╫п╬п╪п╣я─ я│я┌я─п╬п╨п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ п╥п╟п©я─п╬я│п╟. -п╖я┌п╬п╠я▀ п╬п╠я─п╟я┌п╦я┌я▄я│я▐ п╨ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╥п╟п©я─п╬я│п╟, п╦п╥ п╨п╬я┌п╬я─п╬пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣п╪я▀п╧ я┬п╟п╠п╩п╬п╫ п╠я▀п╩ п╡я▀п╥п╡п╟п╫ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ invoke, п©п╣я─п╣п╢ п╦п╪п╣п╫п╣п╪ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╫я┐п╤п╫п╬ п╢п╬п╠п╟п╡п╦я┌я▄ "SUPER." (п╫п╟п©я─п╦п╪п╣я─: "SUPER.NUMBER"). - -п÷я─п╦п╪п╣я─: -п║п╩п╣п╢я┐я▌я┴п╟я▐ п╦п╫я│я┌я─я┐п╨я├п╦я▐ п©п╬п╩я┐я┤п╦я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п╦п╥ я│я┌п╬п╩п╠я├п╟ name п╦ п╥п╟п╪п╣п╫п╦я┌ п╡ п╫п╣п╪ я│п©п╣я├п╦п╟п╩я▄п╫я▀п╣ я│п╦п╪п╡п╬п╩я▀: -<%escape get:name%>
--- a/dist/tema Tue May 16 18:04:09 2006 +0400 +++ b/dist/tema Thu Dec 14 23:22:05 2006 +0300 @@ -1,3 +1,3 @@ #!/bin/sh -java -jar tema.jar +java -jar tema.jar "$@"
--- a/dist/tema.bat Tue May 16 18:04:09 2006 +0400 +++ b/dist/tema.bat Thu Dec 14 23:22:05 2006 +0300 @@ -1,1 +1,1 @@ -java -jar tema.jar +java -jar tema.jar %1
--- a/dist/tema.properties Tue May 16 18:04:09 2006 +0400 +++ b/dist/tema.properties Thu Dec 14 23:22:05 2006 +0300 @@ -9,14 +9,14 @@ main_template : main.template # File encodings -# input_encoding : ISO-8859-5 -# output_encoding : ISO-8859-5 +# input_encoding : UTF-8 +# output_encoding : UTF-8 # Cache templates -cache_read : true +# cache_read : true # Output main_template parsing result to stderr -#output : stderr +# output : stderr # File to output error messages (redirect stderr) -#log : tema.log +# log : tema.log
--- a/doc/article.txt Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,391 +0,0 @@ -* Преобразование базы данных в 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-формат электронной библиотеки КарНЦ РАН.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/manual/index.html Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,358 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <title>п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +</head> + +<body> +<h1>п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA</h1> + +п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ п╥п╟п╢п╟п╫п╫я▀п╣ я┬п╟п╠п╩п╬п╫я▀ я┌п╣п╨я│я┌п╬п╡я▀я┘ я└п╟п╧п╩п╬п╡ п╦ +п╥п╟п╪п╣п╫я▐п╣я┌ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╦я┘ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐. + +<p><b>п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧</b></p> + +<blockquote> + <code><%<i>я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧</i>{:|\|`}<i>п╢п╟п╫п╫я▀п╣</i>%></code> +</blockquote> +<p> +пЁп╢п╣<br /> + +<code><i>я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧</i></code> - я│п©п╦я│п╬п╨ п╦п╪п╣п╫ я└я┐п╫п╨я├п╦п╧, я─п╟п╥п╢п╣п╩п╣п╫п╫я▀я┘ + п©я─п╬п╠п╣п╩п╟п╪п╦. п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪.<br /> +<code><i>п╢п╟п╫п╫я▀п╣</i></code> - п╢п╟п╫п╫я▀п╣, п©п╣я─п╣п╢п╟п╡п╟п╣п╪я▀п╣ я└я┐п╫п╨я├п╦п╦. +</p> + +<p><b>п╓п╬я─п╪п╟я┌ п╢п╟п╫п╫я▀я┘</b></p> + +<blockquote> + <code> + [<i>я│п©п╦я│п╬п╨_п╟я─пЁя┐п╪п╣п╫я┌п╬п╡</i>][<i>я┌п╣п╨я│я┌</i>] + </code> +</blockquote> +<p> +пЁп╢п╣<br /> + +<code><i>я│п©п╦я│п╬п╨_п╟я─пЁя┐п╪п╣п╫я┌п╬п╡</i></code> - я│п©п╦я│п╬п╨ п╟я─пЁя┐п╪п╣п╫я┌п╬п╡ я└я┐п╫п╨я├п╦п╦, я─п╟п╥п╢п╣п╩п╣п╫п╫я▀я┘ п©я─п╬п╠п╣п╩п╟п╪п╦. + п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪.<br /> +<code><i>я┌п╣п╨я│я┌</i></code> - я┌п╣п╨я│я┌, п©п╣я─п╣п╢п╟п╡п╟п╣п╪я▀п╧ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ я─п╟п╥п╠п╦п╣п╫п╦я▐ п╫п╟ п╟я─пЁя┐п╪п╣п╫я┌я▀. + п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п п╬п╩п╦я┤п╣я│я┌п╡п╬ п╟я─пЁя┐п╪п╣п╫я┌п╬п╡, п©п╬я│п╩п╣ п╨п╬я┌п╬я─п╬пЁп╬ я│п╩п╣п╢я┐п╣я┌ + я┌п╣п╨я│я┌, п╥п╟п╡п╦я│п╦я┌ п╬я┌ я└я┐п╫п╨я├п╦п╦. +</p><p> +п═п╟п╥п╢п╣п╩п╦я┌п╣п╩я▄ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦ п╬п©я─п╣п╢п╣п╩я▐п╣я┌, п╨п╟п╨ п╢п╬п╩п╤п╫я▀ +п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ п╢п╟п╫п╫я▀п╣ я└я┐п╫п╨я├п╦п╦: +</p><p> +<code>:</code> - я─п╣п╨я┐я─я│п╦п╡п╫п╟я▐ п╬п╠я─п╟п╠п╬я┌п╨п╟,<br /> +<code>\</code> п╦п╩п╦ <code>`</code> - п©п╣я─п╣п╢п╟я┌я▄ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦. +</p><p> +п∙я│п╩п╦ п╡ я│п©п╦я│п╨п╣ я└я┐п╫п╨я├п╦п╧ п╥п╟п╢п╟п╫п╬ п╢п╡п╣ п╦ п╠п╬п╩п╣п╣ я└я┐п╫п╨я├п╦п╦, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐, +п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧, я┌п╟п╨ я┤я┌п╬ п╨п╟п╤п╢п╟я▐ я└я┐п╫п╨я├п╦я▐ п©п╬п╩я┐я┤п╟п╣я┌ п╡ п╨п╟я┤п╣я│я┌п╡п╣ п╢п╟п╫п╫я▀я┘ +я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ я│п╩п╣п╢я┐я▌я┴п╣п╧ я└я┐п╫п╨я├п╦п╦. +</p><p> +п п╟п╤п╢п╟я▐ я└я┐п╫п╨я├п╦я▐ п╦п╪п╣п╣я┌ п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ - я├п╣п╩п╬п╣ я┤п╦я│п╩п╬. п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ +п╦п╫я│я┌я─я┐п╨я├п╦п╦ - п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ п©п╣я─п╡п╬п╧ п╡ я│п©п╦я│п╨п╣ я└я┐п╫п╨я├п╦п╦. п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, +п©п╬п╩я┐я┤п╟п╣п╪я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ я┌п╣п╨я│я┌п╟ - я│я┐п╪п╪п╟ п╨п╬п╢п╬п╡ п╡п╬п╥п╡я─п╟я┌п╟ п╬п╠я─п╟п╠п╬я┌п╟п╫п╫я▀я┘ +п╦п╫я│я┌я─я┐п╨я├п╦п╧ (п╨п╟п╨ п©я─п╟п╡п╦п╩п╬, я│п╪я▀я│п╩ я█я┌п╬пЁп╬ п╥п╫п╟я┤п╣п╫п╦я▐ - п╨п╬п╩п╦я┤п╣я│я┌п╡п╬ п╦п╫я│я┌я─я┐п╨я├п╦п╧, +п╥п╟п╪п╣п╫п╣п╫п╫я▀я┘ п╫п╟ п╫п╣п©я┐я│я┌п╬п╧ я┌п╣п╨я│я┌). +</p><p> +п я─п╬п╪п╣ я│п╨п╬п╠п╬п╨ '<', '>', п╪п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ я│п╨п╬п╠п╨п╦ '[', ']'. +</p> + + +<h2>п╓я┐п╫п╨я├п╦п╦</h2> + +<p><code><b>set</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п╒п╣п╨я│я┌:</td> +<td><i>п╥п╫п╟я┤п╣п╫п╦п╣</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td> +<td>пёя│я┌п╟п╫п╟п╡п╩п╦п╡п╟п╣я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ <i>п╦п╪я▐</i>.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1</td></tr> +</table> + +<p><code><b>define</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п╒п╣п╨я│я┌:</td> +<td><i>я┬п╟п╠п╩п╬п╫</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п·п©я─п╣п╢п╣п╩я▐п╣я┌ п╫п╬п╡я┐я▌ я└я┐п╫п╨я├п╦я▌ <i>п╦п╪я▐</i>, п©я─п╦ +п╡я▀п╥п╬п╡п╣ п╨п╬я┌п╬я─п╬п╧ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌я│я▐ <i>я┬п╟п╠п╩п╬п╫</i>. п÷я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ п╢п╬я│я┌я┐п©п╫я▀ +я└я┐п╫п╨я├п╦п╦ <code>nextarg</code> п╢п╩я▐ п©п╬п╩я┐я┤п╣п╫п╦я▐ п╬я┤п╣я─п╣п╢п╫п╬пЁп╬ п╟я─пЁя┐п╪п╣п╫я┌п╟ +п╡я▀п╥я▀п╡п╟п╣п╪п╬п╧ я└я┐п╫п╨я├п╦п╦ п╦ <code>data</code> п╢п╩я▐ п©п╬п╩я┐я┤п╣п╫п╦я▐ я┌п╣п╨я│я┌п╟.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1</td></tr> +</table> + +<p><code><b>load</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦п╪я▐</i> <i>п╦п╪я▐_п╨п╩п╟я│я│п╟</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td> + +<td>п·п©я─п╣п╢п╣п╩я▐п╣я┌ п╫п╬п╡я┐я▌ я└я┐п╫п╨я├п╦я▌ <i>п╦п╪я▐</i>. п═п╣п╟п╩п╦п╥п╟я├п╦я▐ я└я┐п╫п╨я├п╦п╦ п╬п©я─п╣п╢п╣п╩п╣п╫п╟ +Java-п╨п╩п╟я│я│п╬п╪ <i>п╦п╪я▐_п╨п╩п╟я│я│п╟</i>, п╫п╟я│п╩п╣п╢я┐я▌я┴п╦п╪ п╨п╩п╟я│я│ +<code>kryshen.tema.Function</code>.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1</td></tr> +</table> + +<p><code><b>prepare</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п╒п╣п╨я│я┌:</td> +<td><i>п╥п╟п©я─п╬я│</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td> +<td>п÷п╬п╢пЁп╬я┌п╟п╡п╩п╦п╡п╟п╣я┌ SQL-п╥п╟п©я─п╬я│ <i>п╥п╟п©я─п╬я│</i> п╢п╩я▐ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐, п╥п╟п©п╦я│я▀п╡п╟п╣я┌ +п©п╬п╢пЁп╬я┌п╬п╡п╩п╣п╫п╫я▀п╧ п╥п╟п©я─п╬я│ п╡ п©п╣я─п╣п╪п╣п╫п╫я┐я▌ <i>п╦п╪я▐</i>.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td><i>п╦п╪я▐</i></td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1</td></tr> +</table> + +<p><code><b>query</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦п╪я▐_п╥п╟п©я─п╬я│п╟</i> <i>я┬п╟п╠п╩п╬п╫</i> <i>п©п╟я─п╟п╪1</i> ... <i>п©п╟я─п╟п╪N</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td> +<td>п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦, п©п╬п╢пЁп╬я┌п╬п╡п╩п╣п╫п╫я▀п╧ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ +prepare. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟ +'?'. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╬п╩п╣п╧ п╬я┌п╡п╣я┌п╟ п╢п╬я│я┌я┐п©п╫я▀ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ <code>db</code>, +п╨п╟п╨ п©п╣я─п╣п╪п╣п╫п╫я▀п╣ я┬п╟п╠п╩п╬п╫п╟ <i>я┬п╟п╠п╩п╬п╫</i>. п÷я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ я┌п╟п╨п╤п╣ +п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п©п╣я─п╣п╪п╣п╫п╫п╟я▐ <code>number</code>, я│п╬п╢п╣я─п╤п╟я┴п╟я▐ п╫п╬п╪п╣я─ я┌п╣п╨я┐я┴п╣п╧ +я│я┌я─п╬п╨п╦ п╬я┌п╡п╣я┌п╟.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td>я─п╣п╥я┐п╩я▄я┌п╟я┌ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <i>я┬п╟п╠п╩п╬п╫</i> п╢п╩я▐ п╨п╟п╤п╢п╬п╧ я│я┌я─п╬п╨п╦ +п╬я┌п╡п╣я┌п╟.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>п п╬п╩п╦я┤п╣я│я┌п╡п╬ п©п╬п╩я┐я┤п╣п╫п╫я▀я┘ я│я┌я─п╬п╨ п╬я┌п╡п╣я┌п╟.</td></tr> +</table> + +<p><code><b>optional</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td> +<td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i>, п╣я│п╩п╦ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ п╢п╟п╫п╫я▀я┘ +п╠я▀п╩ п©п╬п╩я┐я┤п╣п╫ п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ п╬я┌п╩п╦я┤п╫я▀п╧ п╬я┌ 0, п╦п╫п╟я┤п╣ - п©я┐я│я┌п╟я▐ +я│я┌я─п╬п╨п╟.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1, п╣я│п╩п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌ - п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟, 0 - п╦п╫п╟я┤п╣.</td></tr> +</table> + +<p><code><b>image</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td> +<td><i>п╦я│я┘_я└п╟п╧п╩</i> <i>п╨п╬п╫_я└п╟п╧п╩</i> <i>я└п╬я─п╪п╟я┌</i> [<i>п╪п╟п╨я│_я┬п╦я─п╦п╫п╟</i> +[<i>п╪п╟п╨я│_п╡я▀я│п╬я┌п╟</i>]]</td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td> +<td>п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <i>п╦я│я┘_я└п╟п╧п╩</i> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ +п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦ +п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡ +<i>п╨п╬п╫_я└п╟п╧п╩</i>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣ +п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td> +<td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td> +<td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 - п╦п╫п╟я┤п╣.</td></tr> +</table> + + +<p><code><b>copy</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>п╦я│я┘_я└п╟п╧п╩</i> <i>п╨п╬п╫_я└п╟п╧п╩</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <i>п╦я│я┘_я└п╟п╧п╩</i> п╡ я└п╟п╧п╩ +<i>п╨п╬п╫_я└п╟п╧п╩</i> (п©я┐я┌я▄ <i>п╦я│я┘_я└п╟п╧п╩</i> п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ +п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base").</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, +п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 - +п╦п╫п╟я┤п╣.</td></tr> +</table> + +<p><code><b>write</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr> + +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п≈п╟п©п╦я│я▀п╡п╟п╣я┌ <i>п╢п╟п╫п╫я▀п╣</i> п╡ я└п╟п╧п╩ +<i>п╦я│я┘_я└п╟п╧п╩</i>.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, +п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 - +п╦п╫п╟я┤п╣.</td></tr> +</table> + +<p><code><b>read</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr> +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╖п╦я┌п╟п╣я┌ я└п╟п╧п╩ <i>п╦п╪я▐_я└п╟п╧п╩п╟</i>.</td></tr> +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п©я─п╬я┤п╦я┌п╟п╫п╫я▀п╣ п╢п╟п╫п╫я▀п╣ п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, + п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr> +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 - +п╦п╫п╟я┤п╣.</td></tr> +</table> + +<p><code><b>include</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr> +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╡п╨п╩я▌я┤п╟п╣я┌ я┬п╟п╠п╩п╬п╫ п╦п╥ я└п╟п╧п╩п╟ +<i>п╦п╪я▐_я└п╟п╧п╩п╟</i>.</td></tr> +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>я─п╣п╥я┐п╩я▄я┌п╟я┌ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟.</td></tr> +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ +я┬п╟п╠п╩п╬п╫п╟.</td></tr> +</table> + +<p><code><b>!</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> + +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╫п╣я┌.</td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╫п╣я┌.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr> +</table> + +<p><code><b>replace</b></code></p> + +<table> +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>я│я┌я─1</i> <i>я│я┌я─2</i></td></tr> + +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╢п╟п╫п╫я▀п╣, я│ п╥п╟п╪п╣п╫п╣п╫п╫я▀п╪п╦ п╡я┘п╬п╤п╢п╣п╫п╦я▐п╪п╦ п©п╬п╢я│я┌я─п╬п╨п╦ +<i>я│я┌я─1</i> п╫п╟ <i>я│я┌я─2</i>.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr> +</table> + +<p><code><b>xml_escape</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>я┌п╣п╨я│я┌ <i>п╢п╟п╫п╫я▀п╣</i>, п╡ п╨п╬я┌п╬я─п╬п╪ я│п╦п╪п╡п╬п╩я▀ +'&', '<', '>', '`', '\' п╥п╟п╪п╣п╫п╣п╫я▀ п╫п╟ я│п╬п╬я┌п╡п╣я┌я│я┌п╡я┐я▌я┴п╦п╣ я│я┐я┴п╫п╬я│я┌п╦ +XML.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr> +</table> + +<p><code><b>xml_cdata</b></code></p> + +<table> +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr> + +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╢п╟п╫п╫я▀п╣ п╡ п╡п╦п╢п╣ п╠п╩п╬п╨п╟ XML CDATA.</td></tr> + +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘. </td></tr> +</table> + +<p> +п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA я─п╟я│я┬п╦я─я▐п╣п╪: п╡п╬п╥п╪п╬п╤п╫п╬ п╢п╬п╠п╟п╡п╩п╣п╫п╦п╣ п╡ я│п╦я│я┌п╣п╪я┐ п╫п╬п╡я▀я┘ +я└я┐п╫п╨я├п╦п╧, я─п╣п╟п╩п╦п╥п╬п╡п╟п╫п╫я▀я┘ п╡ п╡п╦п╢п╣ п╨п╩п╟я│я│п╬п╡ п╫п╟ я▐п╥я▀п╨п╣ Java. +</p> + +<h2>п≈п╟п©я┐я│п╨</h2> + +<p>java -jar tema.jar [<i>п╬п©я├п╦п╦</i>] +</p><p> +п·п©я├п╦п╦: +</p> +<table> +<tr><td>-d[emo]</td><td>п■п╣п╪п╬п╫я│я┌я─п╟я├п╦п╬п╫п╫я▀п╧ я─п╣п╤п╦п╪</td></tr> +<tr><td>-v[ersion]</td><td>п▓я▀п╡п╬п╢ п╡п╣я─я│п╦п╦</td></tr> +<tr><td>-h[help] -u[sage]</td><td>п▓я▀п╡п╬п╢ я│п©я─п╟п╡п╨п╦</td></tr> +</table> + +<p> +п÷я─п╦ п╥п╟п©я┐я│п╨п╣ я┤п╦я┌п╟п╣я┌я│я▐ я└п╟п╧п╩ "tema.properties" п╦п╥ я┌п╣п╨я┐я┴п╣пЁп╬ п╨п╟я┌п╟п╩п╬пЁп╟.<br /> +п÷я─п╦п╪п╣я─ я└п╟п╧п╩п╟ "tema.properties": +</p> + +<pre> +# п²п╟я│я┌я─п╬п╧п╨п╟ п╦я│я┌п╬я┤п╫п╦п╨п╟ п╢п╟п╫п╫я▀я┘ +# resource : jdbc:odbc:database +# driver : sun.jdbc.odbc.JdbcOdbcDriver + +# п▒п╟п╥п╬п╡я▀п╧ п╨п╟я┌п╟п╩п╬пЁ я─п╣я│я┐я─я│п╬п╡ +# resource_base : . + +# п╗п╟п╠п╩п╬п╫, я│ п╨п╬я┌п╬я─п╬пЁп╬ п╫п╟я┤п╦п╫п╟п╣я┌я│я▐ п╬п╠я─п╟п╠п╬я┌п╨п╟ +main_template : main.template + +# п п╬п╢п╦я─п╬п╡п╨п╦ я└п╟п╧п╩п╬п╡ +# input_encoding : UTF-8 +# output_encoding : UTF-8 + +# п я█я┬п╦я─п╬п╡п╟п╫п╦п╣ я┬п╟п╠п╩п╬п╫п╬п╡ +# cache_read : true + +# п▓я▀п╡п╬п╢ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ я─п╟п╥п╠п╬я─п╟ я┬п╟п╠п╩п╬п╫п╟ main.template п╡ stderr +# output : stderr + +# п▓я▀п╡п╬п╢ я│п╬п╬п╠я┴п╣п╫п╦п╧ п╬п╠ п╬я┬п╦п╠п╨п╟я┘ п╡ я└п╟п╧п╩ +# log : dbreader.log +</pre> + +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/kryshen/tema/demo/demo.template Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,25 @@ +[%!\ TEMA demo template %] + +п▓я▀п╡п╬п╢ я┌п╣п╨я│я┌п╟: +test text + +п▓я▀п╡п╬п╢ я│п©п╣я├п╦п╟п╩я▄п╫я▀я┘ я│п╦п╪п╡п╬п╩п╬п╡: +[%\<%test%>%] + +п·п╠я┼я▐п╡п╩п╣п╫п╦п╣ я└я┐п╫п╨я├п╦п╦: +<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%> + +п▓я▀п╥п╬п╡ п╫п╬п╡п╬п╧ я└я┐п╫п╨я├п╦п╦: +<%test:1 2 3%> + +п≈п╟пЁя─я┐п╥п╨п╟ я└я┐п╫п╨я├п╦п╦ п╦п╥ п╨п╩п╟я│я│п╟: +<%load\hello kryshen.tema.demo.Hello%> + +п▓я▀п©п╬п╩п╣п╫п╣п╫п╦п╣ п╥п╟пЁя─я┐п╤п╣п╫п╫п╬п╧ я└я┐п╫п╨я├п╦п╦: +<%hello\TEMA%> + +пёя│п╩п╬п╡п╫п╬п╣ п╡я▀п©п╬п╩п╫п╣п╫п╦п╣: +<%optional:<%true:%>True%> <%optional:<%false:%>False%> + +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ xml_escape: +<%xml_escape\x < a & b%>
--- a/sample/class.xml Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-5"?> -<зшпААьДьзпФьО> - <зшпАА id="1">╟щБЮчъчсущщКу эуАБччяьБпщьО</зшпАА> - <зшпАА id="2">╪чЮО ь эчЮАзьу ъчяуЮужЛО</зшпАА> - <зшпАА id="3">╬вуЮп ь ъЮьяЮужщКу эуАБччяьБпщьО</зшпАА> - <зшпАА id="4">юузь, ЮЦГЛь ь ъЮьяЮужщКу эуАБччяьБпщьО</зшпАА> - <зшпАА id="5">╠чшчБп ь впячшчГущщКу вуэшь</зшпАА> - <зшпАА id="6">аЦЕчтчшЛщКу эуАБччяьБпщьО</зшпАА> -</зшпААьДьзпФьО>
--- a/sample/plants.xml Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-5"?> -<ЮпАБущьО> - <ЮпАБущьу>Betula sp.</ЮпАБущьу> - <ЮпАБущьу>Calamagrostis arundinacea</ЮпАБущьу> - <ЮпАБущьу>Geranium sylvaticum</ЮпАБущьу> -</ЮпАБущьО>
--- a/src/kryshen/tema/Function.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/Function.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: Function.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Function.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ */ package kryshen.tema; @@ -10,13 +24,19 @@ import java.util.*; import java.sql.ResultSet; +/** + * Abstact class for TEMA functions. + * + * @author Mikhail A. Kryshen + */ public abstract class Function { - public final String name; - protected Function(String name) { - this.name = name; - } - + /** + * Invoke the function. + * + * @param fdp FunctionDataParser to access function arguments. + * @param out Writer for the function output. + */ public abstract int invoke(FunctionDataParser fdp, Writer out) throws IOException, TemplateException; }
--- a/src/kryshen/tema/FunctionDataParser.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/FunctionDataParser.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: FunctionDataParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: FunctionDataParser.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ */ package kryshen.tema; @@ -23,13 +37,13 @@ private TemplateParser tp; private FunctionData fd; - private Reader in; + private TemplateReader in; private boolean available = true; private boolean first = true; FunctionDataParser(TemplateParser tp, FunctionData fd, - Reader in) { + TemplateReader in) { this.tp = tp; this.fd = fd; this.in = in; @@ -40,7 +54,7 @@ if (!available) throw new TemplateException - ("Unexpected end of instruction data."); + ("Unexpected end of instruction data.", in); TemplateParser.Result r; @@ -53,11 +67,11 @@ argument ? ARG_SEPARATORS : null, (argument || !first) ? ARG_SEPARATORS : null); } else if (fd == FunctionData.SUBFUNCTION && argument) { - /* Subfunction can pass a list of arguments */ + // Subfunction can pass a list of arguments StringWriter sw = new StringWriter(); tp.parseFunction(in, sw); sw.close(); - in = new StringReader(sw.toString()); + in = new TemplateReader(new StringReader(sw.toString()), in); fd = FunctionData.NONRECURSIVE; r = parseData(out, true); } else if (fd == FunctionData.SUBFUNCTION) { @@ -74,7 +88,7 @@ } public int parseData(Writer out) throws IOException, TemplateException { - return parseData(out, false).substitutions; + return parseData(out, false).retCode; } public String getData() throws IOException, TemplateException { @@ -92,7 +106,7 @@ r = parseData(out, true); } - return r.substitutions; + return r.retCode; } public String getNextArg() throws IOException, TemplateException { @@ -119,4 +133,8 @@ public TemplateParser getTemplateParser() { return tp; } + + public TemplateReader getTemplateReader() { + return in; + } }
--- a/src/kryshen/tema/Functions.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/Functions.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: Functions.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Functions.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $ */ package kryshen.tema; @@ -9,328 +23,48 @@ import java.io.*; import java.util.*; -import java.sql.SQLException; -import java.sql.PreparedStatement; - import kryshen.tema.functions.*; +/** + * Standard TEMA functions. + * + * @author Mikhail A. Kryshen + */ public class Functions { - public static final Function GET = - new Function("get") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String name = fdp.getData(); - return fdp.getTemplateParser().parseVariable(name, out); - } - }; - - public static final Function SET = - new Function("set") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getData(); - - fdp.getTemplateParser().setValue(arg0, arg1); - - out.write(arg0); - return 1; - } - }; - - /* prepare:qury_name sql_statement */ - public static final Function PREPARE = - new Function("prepare") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String data = fdp.getData(); - - PreparedStatement statement; - - try { - statement = Tema.connection.prepareStatement(data); - } catch (SQLException e) { - throw new TemplateException(e.getMessage(), e); - } - - fdp.getTemplateParser().setValue(arg0, statement); - - out.write(arg0); - return 1; - } - }; - - public static final Function OPTIONAL = - new Function("optional") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - StringWriter sw = new StringWriter(); - int s = fdp.parseData(sw); - sw.close(); - String data = sw.toString(); - - if (s > 0) { - out.write(data); - return 1; - } else { - return 0; - } - } - }; - - public static final Function IMAGE = - new Function("image") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - String arg2 = fdp.getNextArg(); - int arg3 = fdp.hasMoreData() ? - Integer.parseInt(fdp.getNextArg()) : -1; - int arg4 = fdp.hasMoreData() ? - Integer.parseInt(fdp.getNextArg()) : -1; - - File source = new File - (Tema.getProperty("resource_base"), arg0); - - try { - ImageConverter.convert - (source, /* source file */ - new File(arg1), /* dest file */ - arg2, /* format */ - arg3, /* max width */ - arg4); /* max height */ - } catch (Exception e) { - System.err.println(e); - return 0; - } - - out.write(arg1); - return 1; - } - }; - - public static final Function COPY = - new Function("copy") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - - File source = new File - (Tema.getProperty("resource_base"), arg0); - File dest = new File(arg1); - - try { - copyFile(source, dest); - } catch (IOException e) { - System.err.println(e); - return 0; - } - out.write(arg1); - return 1; - } - }; - - /* query:sql_query template arg1 arg2 ... argN */ - public static final Function QUERY = - new Function("query") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - List<String> args = fdp.getArgs(); - - TemplateParser tp = fdp.getTemplateParser(); - - try { - return Tema.query - (arg1, (PreparedStatement)tp.getValue(arg0), - args, tp, out); - } catch (SQLException e) { - throw new TemplateException(e.getMessage(), e); - } - } - }; - - public static final Function WRITE = - new Function("write") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - - System.err.println("Writing " + arg0 + "..."); - - Writer fw; + // TODO: arithmetics, conditions - try { - fw = Tema.createFileWriter(arg0); - } catch (IOException e) { - System.err.println(e); - return 0; - } - - try { - fdp.parseData(fw); - } finally { - fw.close(); - } - - out.write(arg0); - - System.err.println("Saved " + arg0 + "."); - return 1; - } - }; - - public static final Function READ = - new Function("read") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { + /** + * Register all standard functions. + * + * @param p TemplateParser to register functions in. + */ + static void registerAllFunctions(TemplateParser p) { + p.registerFunction("!", Standard.NULL_OUTPUT); + p.registerFunction("set", Standard.SET); + p.registerFunction("load", Standard.LOAD); + p.registerFunction("query", Standard.QUERY); + p.registerFunction("prepare", Standard.PREPARE); + p.registerFunction("replace", Standard.REPLACE); + p.registerFunction("xml_escape", Standard.XML_ESCAPE); + p.registerFunction("xml_cdata", Standard.XML_CDATA); - String filename = fdp.getData(); - String file; - - try { - file = Tema.readFile(new File(filename)); - } catch (IOException e) { - System.err.println(e); - return 0; - } - - out.write(file); - return 1; - } - }; - - public static final Function INCLUDE = - new Function("include") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String filename = fdp.getData(); - - Reader fin = new BufferedReader - (Tema.createCachedFileReader(new File(filename))); - - int r = fdp.getTemplateParser().parse(fin, out); - - fin.close(); - return r; - } - }; - - public static final Function NULL_OUTPUT = - new Function("!") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - /* Write nothing. */ - return fdp.parseData(new Writer() { - public void close() {} - public void flush() {} - public void write(char[] cbuf, int off, int len) {} - }); - } - }; - - public static final Function REPLACE = - new Function("replace") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); + p.registerFunction("define", Define.DEFINE); - ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; - } - }; - - public static final Function XML_ESCAPE = - new Function("xml_escape") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - final String[] chars = {"&", "<", ">", "`", "\""}; - final String[] escape = {"&", "<", ">", "'", """}; - - ReplaceWriter rw = new ReplaceWriter(out, chars, escape); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; - } - }; - - public static final Function XML_CDATA = - new Function("xml_cdata") { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - ReplaceWriter rw = new ReplaceWriter - (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>"); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; - } - }; - - public static final Function DEFINE = new Define(); + p.registerFunction("write", IO.WRITE); + p.registerFunction("read", IO.READ); + p.registerFunction("include", IO.INCLUDE); + p.registerFunction("copy", IO.COPY); - private static void copyFile(File src, File dest) throws IOException { - System.err.print("Copying " + src + "... "); - - if (src.lastModified() < dest.lastModified()) { - System.err.println(dest + " is up to date."); - return; - } + p.registerFunction("false", Logics.FALSE); + p.registerFunction("true", Logics.TRUE); + p.registerFunction("optional", Logics.OPTIONAL); - File parent = dest.getParentFile(); - if (parent != null) parent.mkdirs(); + p.registerFunction("image", ImageConverter.IMAGE); - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dest); - - byte[] buffer = new byte[1024]; - int len; - while ((len = in.read(buffer)) > 0) { - out.write(buffer, 0, len); - } - in.close(); - out.close(); - - System.err.println("saved " + dest + "."); - } - - static void registerAllFunctions(TemplateParser p) { - p.registerFunction(GET); - p.registerFunction(SET); - p.registerFunction(OPTIONAL); - p.registerFunction(IMAGE); - p.registerFunction(COPY); - p.registerFunction(QUERY); - p.registerFunction(PREPARE); - p.registerFunction(WRITE); - p.registerFunction(READ); - p.registerFunction(INCLUDE); - p.registerFunction(NULL_OUTPUT); - p.registerFunction(REPLACE); - p.registerFunction(XML_ESCAPE); - p.registerFunction(XML_CDATA); - p.registerFunction(DEFINE); + /* + Other functuons: + db - defined in Tema.query(). + nextarg, data - defined in Define.invoke(). + */ } }
--- a/src/kryshen/tema/ImageConverter.java Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen - * - * $Id: ImageConverter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ - */ - -package kryshen.tema; - -import java.util.*; -import java.io.*; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.AffineTransform; -import javax.imageio.*; -import javax.imageio.stream.*; - -/** - * Class defines static method to convert images to specified format. - * - * @author Mikhail A. Kryshen - */ -class ImageConverter { - - static void convert(File source, File dest, String format, - int maxWidth, int maxHeight) - throws IOException, InterruptedException { - - System.err.print("Converting image " + source + "... "); - - if (source.lastModified() < dest.lastModified()) { - System.err.println(dest + " is up to date."); - return; - } - - BufferedImage image = ImageIO.read(source); - - //int type = image.getType(); - //final int type = BufferedImage.TYPE_INT_RGB; - //ColorModel cm = image.getColorModel(); - - int w = image.getWidth(null); - int h = image.getHeight(null); - - //boolean scale = false; - - float scale = 1f; - - if (maxWidth > 0 && w > maxWidth) - scale = (float)maxWidth / w; - - if (maxHeight > 0 && h * scale > maxHeight) - scale = (float)maxHeight / h; - - if (scale != 1f) { - w *= scale; h *= scale; - -// ColorModel cm = image.getColorModel(); -// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); -// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); -// BufferedImage scaled = new BufferedImage -// (cm, raster, alphaPremultiplied, null); - -// BufferedImage scaled = new BufferedImage(w, h, image.getType()); - - - Image scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH); - - ColorModel cm = image.getColorModel(); - boolean alphaPremultiplied = image.isAlphaPremultiplied(); - WritableRaster raster = cm.createCompatibleWritableRaster(w, h); - image = new BufferedImage(cm, raster, alphaPremultiplied, null); - - Graphics g = image.getGraphics(); - g.drawImage(scaled, 0, 0, null); - g.dispose(); - -// image = scale(image, scaled, scale); -// Graphics2D g = scaled.createGraphics(); -// g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, -// RenderingHints.VALUE_INTERPOLATION_BILINEAR); -// System.err.print(" " + g.drawImage(image, 0, 0, w, h, null) + " "); -// g.dispose(); -// image = scaled; - } - - File parent = dest.getParentFile(); - if (parent != null) parent.mkdirs(); - - ImageIO.write(image, format, dest); - System.err.println("saved " + dest + "."); - } - -// public static ColorModel getColorModel(Image image) -// throws InterruptedException { - -// PixelGrabber grabby = new PixelGrabber(image, 0, 0, 1, 1, false); -// if (!grabby.grabPixels()) -// throw new RuntimeException("pixel grab fails"); -// return grabby.getColorModel(); -// } - -// private static BufferedImage scale(BufferedImage image, -// BufferedImage dest, -// float scale) { - -// AffineTransform tx = new AffineTransform(); -// tx.scale(scale, scale); - -// AffineTransformOp op = new AffineTransformOp -// (tx, AffineTransformOp.TYPE_BILINEAR); - -// return op.filter(image, dest); -// } - - // TEST - - public static void main(String[] args) - throws IOException, InterruptedException { - - convert(new File(args[0]), new File(args[1]), "png", 300, 300); - } - - -// public static BufferedImage toBufferedImage(Image image, ColorModel cm) { -// if (image instanceof BufferedImage) -// return (BufferedImage)image; - -// int w = image.getWidth(null); -// int h = image.getHeight(null); - -// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); -// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); -// BufferedImage result = new BufferedImage(cm, raster, alphaPremultiplied, null); -// Graphics2D g = result.createGraphics(); - -// g.drawImage(image, 0, 0, null); -// g.dispose(); - -// return result; -// } -} - - -// This is how I'd recommend it in JDK1.4 using javax.imageio.ImageIO to -// do the reading/writing and Java2D to do the scaling. - -// // read in the original image -// BufferedImage in = ImageIO.read(new File("in.jpg")); - -// // create a new image of the smaller size -// BufferedImage out = new BufferedImage(newWidth, newHeight); - -// // get the graphics associated with the new image -// Graphics g = out.getGraphics(); - -// // draw the original image into the new image, scaling -// // on the fly -// g.drawImage(in, newWidth, newHeight, null); - -// // dispose the graphics object -// g.dispose(); - -// // write out the new image -// ImagIO.write("out.jpg", "jpeg", new File("out.jpg")); - -// ------------------------------------------ - -// For nicer scaling, you could add a rendering hint to the graphics -// object before painting. - -// ie. - -// Graphics2D g2d = (Graphics2D)g; -// g2d.setRenderingHint(RenderingHints.KEY_INTEPOLATION, -// RenderingHints.VALUE_INTERPOLATION_BILINEAR); - -// or use VALUE_INTERPOLATION_BICUBIC for the best. - -// But as you can guess, nicer == slower. - -// Shannon Hickey -// shann...@swingteam.com -// Swing Team http://TheSwingConnection.com http://TheJavaTutorial.com -// Java Software, a division of Sun Microsystems, Inc.
--- a/src/kryshen/tema/ReplaceWriter.java Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2006 Mikhail A. Kryshen - * - * $Id: ReplaceWriter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ - */ - -package kryshen.tema; - -import java.io.Writer; -import java.io.FilterWriter; -import java.io.IOException; - -import java.util.LinkedList; -import java.util.Iterator; - -/** - * FilterWriter which replaces characters with escape strings. - * - * @author Mikhail A. Kryshen - */ -class ReplaceWriter extends FilterWriter { - private String[] patterns; - private String[] replaces; - - private String prefix; - private String postfix; - - private int maxPatternLength = 0; - - /** Had this Writer processed any data? */ - private boolean processedData = false; - - private StringBuffer buffer = new StringBuffer(); - - public ReplaceWriter(Writer w, String pattern, String replace) { - this(w, new String[]{pattern}, new String[]{replace}); - } - - public ReplaceWriter(Writer w, String pattern, String replace, - String prefix, String postfix) { - - this(w, new String[]{pattern}, new String[]{replace}, - prefix, postfix); - } - - public ReplaceWriter(Writer w, String[] patterns, String[] replaces) { - this(w, patterns, replaces, null, null); - } - - public ReplaceWriter(Writer w, String[] patterns, String[] replaces, - String prefix, String postfix) { - super(w); - - this.patterns = patterns; - this.replaces = replaces; - - this.prefix = prefix; - this.postfix = postfix; - - for (int i = 0; i < patterns.length; i++) { - int length = patterns[i].length(); - if (length > maxPatternLength) - maxPatternLength = length; - } - } - - private boolean processBuffer(int minLength) throws IOException { - if (buffer.length() == 0) return false; - - if (!processedData) { - if (prefix != null) - super.write(prefix, 0, prefix.length()); - processedData = true; - } - - int k; - for (k = 0; minLength + k < buffer.length(); k++) { - for (int i = 0; i < patterns.length; i++) { - String pattern = patterns[i]; - int length = pattern.length(); - - if (length + k > buffer.length()) - continue; - - boolean match = true; - - for (int j = 0; j < length; j++) { - if (pattern.charAt(j) != buffer.charAt(j + k)) { - match = false; - break; - } - } - - if (match) { - super.write(buffer.substring(0, k), 0, k); - buffer.delete(0, k + length); - super.write(replaces[i], 0, replaces[i].length()); - return true; - } - } - } - - super.write(buffer.substring(0, k), 0, k); - buffer.delete(0, k); - - return false; - } - - public void write(int c) throws IOException { - buffer.append((char)c); - processBuffer(maxPatternLength); - } - - public void write(char[] cbuf, int off, int len) throws IOException { - for (int i = off; i < off + len; i++) { - buffer.append(cbuf[i]); - } - processBuffer(maxPatternLength); - } - - public void write(String str, int off, int len) throws IOException { - buffer.append(str.substring(off, off + len)); - processBuffer(maxPatternLength); - } - - public void finish() throws IOException { - while (processBuffer(0)); - -// super.write(buffer.toString(), 0, buffer.length()); -// buffer.delete(0, buffer.length()); - - if (processedData && postfix != null) - super.write(postfix, 0, postfix.length()); - } - - public void close() throws IOException { - finish(); - super.close(); - } -}
--- a/src/kryshen/tema/Tema.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/Tema.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: Tema.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Tema.java,v 1.17 2006/12/14 19:44:31 mikhail Exp $ */ package kryshen.tema; @@ -23,31 +37,135 @@ import java.io.*; +import kryshen.tema.demo.DemoFrame; + /** * Tema main class. * * @author Mikhail A. Kryshen */ public class Tema { + public static final String TITLE = "TEMA"; + public static final String VERSION = "0.1"; + public static final String AUTHOR = "Mikhail A. Kryshen"; + private static final String CONFIG_FILE = "tema.properties"; private static final String ENV_PREFIX = "kryshen.tema."; private static Properties config = new Properties(); - static Connection connection = null; + private static Connection connection = null; private static String inputEncoding; private static String outputEncoding; - static Map<File, String> fileCache = null; + private static Map<File, String> fileCache = null; public static void main(String[] args) - throws IOException, TemplateException, SQLException, + throws IOException, SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + boolean demo = false; + boolean version = false; + boolean help = false; + + // Parse arguments. + for (int i = 0; i < args.length; i++) { + if ("-demo".equals(args[i]) || + "-d".equals(args[i])) { + demo = true; + } else if ("-version".equals(args[i]) || + "-v".equals(args[i])) { + version = true; + } else if ("-help".equals(args[i]) || + "-h".equals(args[i]) || + "-usage".equals(args[i]) || + "-u".equals(args[i])) { + help = true; + } else { + System.err.println("Invalid option: " + args[i]); + return; + } + } + + if (version || help) { + System.err.println(TITLE + " " + VERSION + " by " + AUTHOR); + + if (help) { + PrintStream err = System.err; + + err.println(); + err.println("Usage: tema [OPTIONS]"); + err.println(); + err.println("Options:"); + err.println(" -d[emo] Demo mode"); + err.println(" -v[ersion] Print version"); + err.println(" -h[help] -u[sage] Print this help message"); + } + return; + } + + if (demo) { + // Run in demo mode. + DemoFrame df = new DemoFrame(); + df.pack(); + df.setVisible(true); + return; + } + + process(); + } + + /** + * Standard execution. + */ + private static void process() + throws IOException, SQLException, + ClassNotFoundException, InstantiationException, + IllegalAccessException { + InputStream configIn = new FileInputStream(CONFIG_FILE); config.load(configIn); configIn.close(); + + configure(); + + String main = getProperty("main_template"); + String output = getProperty("output"); + + Writer out; + + if ("stderr".equals(output)) + out = new OutputStreamWriter(System.err); + else + out = new OutputStreamWriter(System.out); + + TemplateReader in = createTemplateReader(new File(main)); + TemplateParser p = new TemplateParser(); + TemplateException te = null; + + try { + p.parse(in, out); + } catch (TemplateException e) { + te = e; + } finally { + in.close(); + out.flush(); + } + + if (te != null) { + System.err.println(te.getMessage()); + if (te.getCause() != null) { + System.err.println("Caused by " + te.getCause()); + } + } else { + System.err.println("Done"); + } + } + + private static void configure() + throws IOException, SQLException, IllegalAccessException, + ClassNotFoundException, InstantiationException { String logFile = getProperty("log"); if (logFile != null && logFile.length() > 0) @@ -71,51 +189,14 @@ // Open connection. connection = DriverManager.getConnection(resourceProperty); } - -// String maxFilesString = getProperty("max_output_files"); -// int maxFiles = -1; -// if (maxFilesString != null) -// maxFiles = Integer.parseInt(maxFilesString); - - String main = getProperty("main_template"); - String output = getProperty("output"); - - Writer out; - - if ("stderr".equals(output)) - out = new OutputStreamWriter(System.err); - else - out = new OutputStreamWriter(System.out); - - InputStream is = new FileInputStream(main); - Reader in = new BufferedReader(new InputStreamReader(is, inputEncoding)); - - TemplateParser p = new TemplateParser(); - try { - p.parse(in, out); - } finally { - in.close(); - out.flush(); - } - - System.err.println("Done"); } -// private static void readEscapes() { -// for (int i = 1;; i++) { -// String pattern = getProperty("escape_char_" + i); - -// if (pattern == null) break; - -// escapes.put(pattern.charAt(0), -// getProperty("escape_string_" + i)); -// } -// } + /** * Get configuration property. */ - static String getProperty(String name) { + public static String getProperty(String name) { String value = System.getProperty(ENV_PREFIX + name); if (value != null) return value; return config.getProperty(name); @@ -124,16 +205,17 @@ /** * Get configuration property. */ - static String getProperty(String name, String fallback) { + public static String getProperty(String name, String fallback) { String value = getProperty(name); if (value != null) return value; return fallback; } /** - * Process subquery and template. + * Process database query. * - * @param template template to fill with data. + * @param templateReader reader for the template + * to fill with data. * @param ps query statement to execute. * @param args list of query parameters. * @param superParser invoking object. @@ -141,14 +223,13 @@ * * @return number of processed rows in query result. */ - static int query(String template, PreparedStatement ps, - List<String> args, - TemplateParser superParser, - Writer out) + public static int query(TemplateReader templateReader, + PreparedStatement ps, + List<String> args, + TemplateParser superParser, + Writer out) throws IOException, SQLException, TemplateException { - StringReader templateReader = new StringReader(template); - int i = 1; for (String arg : args) { @@ -165,21 +246,34 @@ names[j] = rm.getColumnName(j + 1); } - TemplateParser p = new TemplateParser(superParser); - + final TemplateParser p = new TemplateParser(superParser); + final HashMap<String, Object> fields = new HashMap<String, Object>(); + + p.registerFunction("db", new Function() { + public int invoke(FunctionDataParser fdp, + final Writer out) + throws IOException, TemplateException { + + String name = fdp.getData(); + Object value = fields.get(name); + + return p.parseValue(value, out); + } + }); + for (i = 1; r.next(); i++) { - p.clearValues(); for (int j = 0; j < columnCount; j++) { Object value = r.getObject(j + 1); if (r.wasNull()) value = null; - - p.setValue(names[j], value); + + fields.put(names[j], value); } - p.setValue("NUMBER", i); + p.setValue("number", i); p.parse(templateReader, out); templateReader.reset(); + fields.clear(); } r.close(); @@ -187,32 +281,56 @@ return i - 1; } - static Writer createFileWriter(String filename) throws IOException { + public static BufferedWriter createFileWriter(String filename) + throws IOException { + OutputStream os = new FileOutputStream(filename); - return new OutputStreamWriter(os, Tema.outputEncoding); + return new BufferedWriter + (new OutputStreamWriter(os, Tema.outputEncoding)); + } + + public static BufferedReader createFileReader(File file) + throws IOException { + + InputStream is = new FileInputStream(file); + return new BufferedReader + (new InputStreamReader(is, Tema.inputEncoding)); } - static Reader createFileReader(File file) throws IOException { - InputStream is = new FileInputStream(file); - return new InputStreamReader(is, Tema.inputEncoding); + public static TemplateReader createTemplateReader(File file) + throws IOException { + + return new TemplateReader + (new LineNumberReader(createCachedFileReader(file)), file.getPath()); } - static Reader createCachedFileReader(File file) throws IOException { + /** + * Creates StringReader for a cached file if caching is enabled or + * a BufferedReader. + * + * @param file File to read. + * @return Reader for a file. + */ + public static Reader createCachedFileReader(File file) + throws IOException { + if (fileCache != null) return new StringReader(readFile(file)); else return createFileReader(file); } /** * Read text file. + * + * @return file contents. */ - static String readFile(File file) throws IOException { + public static String readFile(File file) throws IOException { String data; - + if (fileCache != null) { data = fileCache.get(file); if (data != null) return data; } - + Reader r = new BufferedReader(createFileReader(file)); // FIXME: possible overflow (long -> int). @@ -234,4 +352,13 @@ return data; } + + /** + * Get database connection. + * + * @return database connection if any was configured. + */ + public static Connection getDbConnection() { + return connection; + } }
--- a/src/kryshen/tema/TemplateException.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/TemplateException.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: TemplateException.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: TemplateException.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ */ package kryshen.tema; @@ -12,13 +26,36 @@ * @author Mikhail A. Kryshen */ public class TemplateException extends Exception { - // TODO: store the number of template line with error. + //private String source; + //private int line; + +// public TemplateException(String message) { +// super(message); +// } - public TemplateException(String message) { - super(message); +// public TemplateException(String message, Throwable cause) { +// super(message, cause); +// } + + public TemplateException(String message, Throwable cause, + TemplateReader tr) { + this(message, cause, tr.getSource(), tr.getLineNumber() + 1); } - public TemplateException(String message, Throwable cause) { - super(message, cause); + public TemplateException(String message, TemplateReader tr) { + this(message, tr.getSource(), tr.getLineNumber() + 1); + } + + public TemplateException(String message, Throwable cause, + String source, int line) { + super(source + ":" + line + ": " + message, cause); + //this.source = source; + //this.line = line; + } + + public TemplateException(String message, String source, int line) { + super(source + ":" + line + ": " + message); + //this.source = source; + //this.line = line; } }
--- a/src/kryshen/tema/TemplateParser.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/TemplateParser.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: TemplateParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: TemplateParser.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $ */ package kryshen.tema; @@ -10,12 +24,14 @@ import java.util.*; /** - * Parser for DbReader templates. + * Parser for TEMA templates. * * @author Mikhail A. Kryshen */ public class TemplateParser { - static final String SUPER = "SUPER."; + // TODO: report non-critical errors and warnings. + + static final String SUPER_PREFIX = "super."; /* Brackets. */ static final char[] BR_LEFT = {'<', '['}; @@ -28,6 +44,9 @@ static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'}; + /** + * Methods of parsing function arguments and data. + */ static enum FunctionData { SUBFUNCTION, RECURSIVE, NONRECURSIVE; }; @@ -38,24 +57,22 @@ static class Result { Terminator terminator; - int substitutions; + int retCode; /** No text had been parsed. */ boolean empty; - Result(Terminator terminator, int substitutions, boolean empty) { + Result(Terminator terminator, int retCode, boolean empty) { this.terminator = terminator; - this.substitutions = substitutions; + this.retCode = retCode; this.empty = empty; } Result() { - this(null, 0, true); + this(null, -1, true); } }; - private Map<String, Function> functions = new HashMap<String, Function>(); - private Map<String, Object> variables = new HashMap<String, Object>(); private TemplateParser superParser; @@ -71,26 +88,26 @@ Functions.registerAllFunctions(this); } - public void registerFunction(Function f) { - functions.put(f.name, f); + public void registerFunction(String name, Function f) { + variables.put(name, f); } - public int parse(Reader in, Writer out) + public int parse(TemplateReader in, Writer out) throws IOException, TemplateException { - return parse(in, out, true, null, null).substitutions; + return parse(in, out, true, null, null).retCode; } /** * Parse template. * - * @param in Reader to read template data. + * @param in TemplateReader to read template data. * @param out Writer to write processed data. * @param recursive enables recursive processing. * @param separators characters which terminate parsing block. * @param leading characters to ignore at the beginning of the block. */ - Result parse(Reader in, Writer out, boolean recursive, + Result parse(TemplateReader in, Writer out, boolean recursive, char[] separators, char[] leading) throws IOException, TemplateException { @@ -117,10 +134,13 @@ if (recursive && leftBracket && c == BR_IN) { + if (result.retCode < 0) + result.retCode = 0; + lc = -1; int tb = termBracket; termBracket = BR_RIGHT[index]; - result.substitutions += parseFunction(in, out); + result.retCode += parseFunction(in, out); termBracket = tb; } else if (lc == BR_IN && c == termBracket) { @@ -151,22 +171,6 @@ return result; } - int parseVariable(String name, Writer out) - throws IOException, TemplateException { - - Object ovalue = getValue(name); - if (ovalue == null) - return 0; - - String svalue = ovalue.toString(); - - if (svalue == null || svalue.length() == 0) - return 0; - - out.write(svalue); - return 1; - } - boolean isSeparator(int c, char[] separators) { for (char p : separators) { if (c == p) return true; @@ -175,7 +179,7 @@ return false; } - int parseFunction(Reader in, Writer out) + int parseFunction(TemplateReader in, Writer out) throws IOException, TemplateException { StringBuffer sb = new StringBuffer(); @@ -196,16 +200,28 @@ FunctionData.NONRECURSIVE, in, out); } else if (c < 0) { - System.err.println("Error: unexpected end of file."); - return 0; + throw new TemplateException("Unexpected end of file.", in); } else { sb.append((char)c); } } } + int parseValue(Object value, Writer out) throws IOException { + if (value == null) + return 0; + + String svalue = value.toString(); + + if (svalue == null || svalue.length() == 0) + return 0; + + out.write(svalue); + return 1; + } + private int invokeFunction(String name, FunctionData fd, - Reader in, Writer out) + TemplateReader in, Writer out) throws IOException, TemplateException { FunctionDataParser fdp = new FunctionDataParser(this, fd, in); @@ -214,14 +230,15 @@ return fdp.parseData(out); } - Function f = getFunction(name); + Object value = getValue(name); + int r; - if (f == null) { - throw new TemplateException("Unknown function: " + name); + if (value instanceof Function) { + r = ((Function) value).invoke(fdp, out); + } else { + r = parseValue(value, out); } - int r = f.invoke(fdp, out); - if (fdp.hasMoreData()) { /* Skip remaining function data. */ fdp.parseData(new Writer() { @@ -234,27 +251,14 @@ return r; } - Function getFunction(String name) throws TemplateException { - Function function = functions.get(name); - if (function != null) return function; - - if (superParser != null) { - if (name.startsWith(SUPER)) - return superParser.getFunction(name.substring(SUPER.length())); - else - return superParser.getFunction(name); - } - - return null; - } - - Object getValue(String name) throws TemplateException { + public Object getValue(String name) throws TemplateException { Object value = variables.get(name); if (value != null) return value; if (superParser != null) { - if (name.startsWith(SUPER)) - return superParser.getValue(name.substring(SUPER.length())); + if (name.startsWith(SUPER_PREFIX)) + return superParser.getValue + (name.substring(SUPER_PREFIX.length())); else return superParser.getValue(name); } @@ -262,21 +266,26 @@ return null; } - void setValue(String name, Object value) { + public void setValue(String name, Object value) { variables.put(name, value); } - void clearValues() { + public void clearValues() { variables.clear(); + Functions.registerAllFunctions(this); } // TEST - public static void main(String[] args) + public static void main(String[] args) throws IOException, TemplateException { TemplateParser p = new TemplateParser(); - FileReader in = new FileReader("parser.in"); + TemplateReader in = + new TemplateReader + (new LineNumberReader + (new FileReader("parser.in")), "parser.in"); + FileWriter out = new FileWriter("parser.out"); p.parse(in, out);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/TemplateReader.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: TemplateReader.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ + */ + +package kryshen.tema; + +import java.io.Reader; +import java.io.LineNumberReader; +import java.io.FilterReader; +import java.io.IOException; + +/** + * Reader for TEMA templates. Stores data source name (commonly + * filename) and tracks line numbers for error reporting. + * + * @author Mikhail A. Kryshen + */ +public class TemplateReader extends FilterReader { + private String source = null; + + private LineNumberReader lnReader = null; + private TemplateReader parentReader = null; + + public TemplateReader(LineNumberReader in, String source) { + super(in); + this.lnReader = in; + this.source = source; + } + + public TemplateReader(Reader in, TemplateReader parent) { + super(in); + this.source = source; + } + + public String getSource() { + if (source != null) + return source; + + return parentReader.getSource(); + } + + public int getLineNumber() { + if (lnReader != null) + return lnReader.getLineNumber(); + + return parentReader.getLineNumber(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/demo/DemoFrame.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: DemoFrame.java,v 1.3 2006/12/14 15:59:48 mikhail Exp $ + */ + +package kryshen.tema.demo; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.URL; + +import kryshen.tema.*; + +/** + * TEMA demonstation console. + */ +public class DemoFrame extends Frame { + private TextArea input; + private TextArea output; + private TextArea error; + + public DemoFrame() { + super("TEMA demo console"); + + GridBagLayout gbl = new GridBagLayout(); + + GridBagConstraints c = new GridBagConstraints(); + + setLayout(gbl); + + input = new TextArea(25, 40); + input.setEditable(true); + + output = new TextArea(25, 40); + output.setEditable(false); + + error = new TextArea(5, 80); + error.setEditable(false); + + Label l; + + c.insets = new Insets(3, 3, 3, 3); + c.fill = GridBagConstraints.BOTH; + c.gridwidth = GridBagConstraints.RELATIVE; + + l = new Label("Enter your code and click \"Process\"."); + + gbl.setConstraints(l, c); + add(l); + + Panel buttons = new Panel(); + buttons.setLayout(new FlowLayout(FlowLayout.LEFT)); + + Button process = new Button("Process"); + Button clear = new Button("Clear"); + Button close = new Button("Close"); + + buttons.add(process); + buttons.add(clear); + buttons.add(close); + + c.gridwidth = GridBagConstraints.REMAINDER; + + gbl.setConstraints(buttons, c); + add(buttons); + + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.CENTER; + c.gridwidth = GridBagConstraints.RELATIVE; + + l = new Label("Input:"); + + gbl.setConstraints(l, c); + add(l); + + c.gridwidth = GridBagConstraints.REMAINDER; + + l = new Label("Output:"); + + gbl.setConstraints(l, c); + add(l); + + c.gridwidth = GridBagConstraints.RELATIVE; + + gbl.setConstraints(input, c); + add(input); + + c.gridwidth = GridBagConstraints.REMAINDER; + + gbl.setConstraints(output, c); + add(output); + + l = new Label("Errors:"); + + gbl.setConstraints(l, c); + add(l); + + gbl.setConstraints(error, c); + add(error); + + process.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + process(); + } + }); + + clear.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + error.setText(""); + output.setText(""); + input.setText(""); + + } + }); + + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dispose(); + } + }); + + URL source = getClass().getResource("demo.template"); + StringBuffer buffer = new StringBuffer(); + + try { + Reader in = new BufferedReader + (new InputStreamReader(source.openStream(), "UTF-8")); + + for (int ch = in.read(); ch >= 0; ch = in.read()) { + buffer.append((char)ch); + } + + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + input.setText(buffer.toString()); + } + + private void process() { + String s = input.getText(); + + TemplateReader tr = new TemplateReader + (new LineNumberReader(new StringReader(s)), "input"); + TemplateParser tp = new TemplateParser(); + StringWriter sw = new StringWriter(); + + error.setText(""); + + try { + tp.parse(tr, sw); + } catch (Exception e) { + error.setText(e.toString()); + } + + output.setText(sw.toString()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/demo/Hello.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Hello.java,v 1.2 2006/12/14 14:39:24 mikhail Exp $ + */ + +package kryshen.tema.demo; + +import java.io.Writer; +import java.io.IOException; +import kryshen.tema.*; + +/** + * Example function implementation. + * + * @author Mikhail A. Kryshen + */ +public class Hello extends Function { + public Hello() {} + + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + out.write("Hello, "); + fdp.parseData(out); + + return 1; + } +}
--- a/src/kryshen/tema/functions/Define.java Tue May 16 18:04:09 2006 +0400 +++ b/src/kryshen/tema/functions/Define.java Thu Dec 14 23:22:05 2006 +0300 @@ -1,7 +1,21 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * $Id: Define.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Define.java,v 1.7 2006/12/14 14:35:00 mikhail Exp $ */ package kryshen.tema.functions; @@ -11,9 +25,15 @@ import kryshen.tema.*; +/** + * Define function implementation. + * + * @author Mikhail A. Kryshen + */ public class Define extends Function { + public static final Function DEFINE = new Define(); + public Define() { - super("define"); } public int invoke(FunctionDataParser fdp, Writer out) @@ -22,37 +42,42 @@ final String arg0 = fdp.getNextArg(); final String data = fdp.getData(); - Function newFunction = new Function(arg0) { + Function newFunction = new Function() { public int invoke(final FunctionDataParser fdp, final Writer out) throws IOException, TemplateException { - + TemplateParser functionParser = new TemplateParser(fdp.getTemplateParser()); - functionParser.registerFunction(new Function("nextarg") { - public int invoke(FunctionDataParser unusedFdp, - final Writer out) - throws IOException, TemplateException { - - return fdp.parseNextArg(out); - } - }); + functionParser.registerFunction + ("nextarg", new Function() { + public int invoke(FunctionDataParser unusedFdp, + final Writer out) + throws IOException, TemplateException { + + return fdp.parseNextArg(out); + } + }); + + functionParser.registerFunction + ("data",new Function() { + public int invoke(FunctionDataParser unusedFdp, + final Writer out) + throws IOException, TemplateException { + + return fdp.parseData(out); + } + }); + + TemplateReader dataReader = new TemplateReader + (new StringReader(data), fdp.getTemplateReader()); - functionParser.registerFunction(new Function("data") { - public int invoke(FunctionDataParser unusedFdp, - final Writer out) - throws IOException, TemplateException { - - return fdp.parseData(out); - } - }); - - return functionParser.parse(new StringReader(data), out); + return functionParser.parse(dataReader, out); } }; - - fdp.getTemplateParser().registerFunction(newFunction); - + + fdp.getTemplateParser().registerFunction(arg0, newFunction); + out.write(arg0); return 1; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/IO.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: IO.java,v 1.4 2006/12/14 15:59:49 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.*; +import java.util.*; + +import kryshen.tema.*; + +/** + * I/O functions. + */ +public class IO { + public static final Function COPY = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + + File source = new File + (Tema.getProperty("resource_base"), arg0); + File dest = new File(arg1); + + try { + copyFile(source, dest); + } catch (IOException e) { + System.err.println(e); + return 0; + } + out.write(arg1); + return 1; + } + }; + + public static final Function WRITE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + + System.err.println("Writing " + arg0 + "..."); + + Writer fw; + + try { + fw = Tema.createFileWriter(arg0); + } catch (IOException e) { + System.err.println(e); + //throw new TemplateException(e.getMessage(), e, in); + return 0; + } + + try { + fdp.parseData(fw); + } finally { + fw.close(); + } + + out.write(arg0); + + System.err.println("Saved " + arg0 + "."); + return 1; + } + }; + + public static final Function READ = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String filename = fdp.getData(); + String file; + + try { + file = Tema.readFile(new File(filename)); + } catch (IOException e) { + System.err.println(e); + //throw new TemplateException(e.getMessage(), e, in); + return 0; + } + + out.write(file); + return 1; + } + }; + + public static final Function INCLUDE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String filename = fdp.getData(); + + TemplateReader fin; + + try { + fin = Tema.createTemplateReader(new File(filename)); + } catch (IOException e) { + throw new TemplateException(e.getMessage(), e, + fdp.getTemplateReader()); + } + + int r = fdp.getTemplateParser().parse(fin, out); + + fin.close(); + return r; + } + }; + + /** + * Update file (copy if newer). + * + * @param src source file. + * @param dest destination file. + * + * @trows IOException on copying error. + */ + private static void copyFile(File src, File dest) throws IOException { + System.err.print("Copying " + src + "... "); + + if (src.lastModified() < dest.lastModified()) { + System.err.println(dest + " is up to date."); + return; + } + + File parent = dest.getParentFile(); + if (parent != null) parent.mkdirs(); + + InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dest); + + byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + in.close(); + out.close(); + + System.err.println("saved " + dest + "."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/ImageConverter.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: ImageConverter.java,v 1.4 2006/12/14 19:44:32 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.util.*; +import java.io.*; +import java.awt.*; +import java.awt.image.*; +import java.awt.geom.AffineTransform; +import javax.imageio.*; +import javax.imageio.stream.*; + +import kryshen.tema.*; + +/** + * Convert images to specified format. + * + * @author Mikhail A. Kryshen + */ +public class ImageConverter extends Function { + + public static final Function IMAGE = new ImageConverter(); + + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + String arg2 = fdp.getNextArg(); + int arg3 = fdp.hasMoreData() ? + Integer.parseInt(fdp.getNextArg()) : -1; + int arg4 = fdp.hasMoreData() ? + Integer.parseInt(fdp.getNextArg()) : -1; + + File source = new File + (Tema.getProperty("resource_base"), arg0); + + try { + convert + (source, /* source file */ + new File(arg1), /* dest file */ + arg2, /* format */ + arg3, /* max width */ + arg4); /* max height */ + } catch (Exception e) { + System.err.println(e); + return 0; + } + + out.write(arg1); + return 1; + } + + public static void convert(File source, File dest, String format, + int maxWidth, int maxHeight) + throws IOException, InterruptedException { + + System.err.print("Converting image " + source + "... "); + + if (source.lastModified() < dest.lastModified()) { + System.err.println(dest + " is up to date."); + return; + } + + BufferedImage image = ImageIO.read(source); + + //int type = image.getType(); + //final int type = BufferedImage.TYPE_INT_RGB; + //ColorModel cm = image.getColorModel(); + + int w = image.getWidth(null); + int h = image.getHeight(null); + + //boolean scale = false; + + float scale = 1f; + + if (maxWidth > 0 && w > maxWidth) + scale = (float)maxWidth / w; + + if (maxHeight > 0 && h * scale > maxHeight) + scale = (float)maxHeight / h; + + if (scale != 1f) { + w *= scale; h *= scale; + +// ColorModel cm = image.getColorModel(); +// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); +// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); +// BufferedImage scaled = new BufferedImage +// (cm, raster, alphaPremultiplied, null); + +// BufferedImage scaled = new BufferedImage(w, h, image.getType()); + + + Image scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH); + + ColorModel cm = image.getColorModel(); + boolean alphaPremultiplied = image.isAlphaPremultiplied(); + WritableRaster raster = cm.createCompatibleWritableRaster(w, h); + image = new BufferedImage(cm, raster, alphaPremultiplied, null); + + Graphics g = image.getGraphics(); + g.drawImage(scaled, 0, 0, null); + g.dispose(); + +// image = scale(image, scaled, scale); +// Graphics2D g = scaled.createGraphics(); +// g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, +// RenderingHints.VALUE_INTERPOLATION_BILINEAR); +// System.err.print(" " + g.drawImage(image, 0, 0, w, h, null) + " "); +// g.dispose(); +// image = scaled; + } + + File parent = dest.getParentFile(); + if (parent != null) parent.mkdirs(); + + ImageIO.write(image, format, dest); + System.err.println("saved " + dest + "."); + } + +// public static ColorModel getColorModel(Image image) +// throws InterruptedException { + +// PixelGrabber grabby = new PixelGrabber(image, 0, 0, 1, 1, false); +// if (!grabby.grabPixels()) +// throw new RuntimeException("pixel grab fails"); +// return grabby.getColorModel(); +// } + +// private static BufferedImage scale(BufferedImage image, +// BufferedImage dest, +// float scale) { + +// AffineTransform tx = new AffineTransform(); +// tx.scale(scale, scale); + +// AffineTransformOp op = new AffineTransformOp +// (tx, AffineTransformOp.TYPE_BILINEAR); + +// return op.filter(image, dest); +// } + + // TEST + public static void main(String[] args) + throws IOException, InterruptedException { + + convert(new File(args[0]), new File(args[1]), "png", 300, 300); + } + + +// public static BufferedImage toBufferedImage(Image image, ColorModel cm) { +// if (image instanceof BufferedImage) +// return (BufferedImage)image; + +// int w = image.getWidth(null); +// int h = image.getHeight(null); + +// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); +// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); +// BufferedImage result = new BufferedImage(cm, raster, alphaPremultiplied, null); +// Graphics2D g = result.createGraphics(); + +// g.drawImage(image, 0, 0, null); +// g.dispose(); + +// return result; +// } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/Logics.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Logics.java,v 1.6 2006/12/14 14:39:26 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.*; +import java.util.*; + +import kryshen.tema.*; + +/** + * Logical and conditional functions. + * + * @author Mikhail A. Kryshen + */ +public class Logics { + public static final Function FALSE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + fdp.parseData(out); + return 0; + } + }; + + public static final Function TRUE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + fdp.parseData(out); + return 1; + } + }; + + /** + * Outputs it's data it has non-zero value. + */ + public static final Function OPTIONAL = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + StringWriter sw = new StringWriter(); + int s = fdp.parseData(sw); + sw.close(); + String data = sw.toString(); + + if (s != 0) { + out.write(data); + return 1; + } else { + return 0; + } + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/ReplaceWriter.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: ReplaceWriter.java,v 1.2 2006/12/14 14:39:26 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.Writer; +import java.io.FilterWriter; +import java.io.IOException; + +import java.util.LinkedList; +import java.util.Iterator; + +/** + * FilterWriter which replaces characters with escape strings. + * + * @author Mikhail A. Kryshen + */ +class ReplaceWriter extends FilterWriter { + private String[] patterns; + private String[] replaces; + + private String prefix; + private String postfix; + + private int maxPatternLength = 0; + + /** Have this Writer processed any data? */ + private boolean processedData = false; + + private StringBuffer buffer = new StringBuffer(); + + public ReplaceWriter(Writer w, String pattern, String replace) { + this(w, new String[]{pattern}, new String[]{replace}); + } + + public ReplaceWriter(Writer w, String pattern, String replace, + String prefix, String postfix) { + + this(w, new String[]{pattern}, new String[]{replace}, + prefix, postfix); + } + + public ReplaceWriter(Writer w, String[] patterns, String[] replaces) { + this(w, patterns, replaces, null, null); + } + + public ReplaceWriter(Writer w, String[] patterns, String[] replaces, + String prefix, String postfix) { + super(w); + + this.patterns = patterns; + this.replaces = replaces; + + this.prefix = prefix; + this.postfix = postfix; + + for (int i = 0; i < patterns.length; i++) { + int length = patterns[i].length(); + if (length > maxPatternLength) + maxPatternLength = length; + } + } + + private boolean processBuffer(int minLength) throws IOException { + if (buffer.length() == 0) return false; + + if (!processedData) { + if (prefix != null) + super.write(prefix, 0, prefix.length()); + processedData = true; + } + + int k; + for (k = 0; minLength + k < buffer.length(); k++) { + for (int i = 0; i < patterns.length; i++) { + String pattern = patterns[i]; + int length = pattern.length(); + + if (length + k > buffer.length()) + continue; + + boolean match = true; + + for (int j = 0; j < length; j++) { + if (pattern.charAt(j) != buffer.charAt(j + k)) { + match = false; + break; + } + } + + if (match) { + super.write(buffer.substring(0, k), 0, k); + buffer.delete(0, k + length); + super.write(replaces[i], 0, replaces[i].length()); + return true; + } + } + } + + super.write(buffer.substring(0, k), 0, k); + buffer.delete(0, k); + + return false; + } + + public void write(int c) throws IOException { + buffer.append((char)c); + processBuffer(maxPatternLength); + } + + public void write(char[] cbuf, int off, int len) throws IOException { + for (int i = off; i < off + len; i++) { + buffer.append(cbuf[i]); + } + processBuffer(maxPatternLength); + } + + public void write(String str, int off, int len) throws IOException { + buffer.append(str.substring(off, off + len)); + processBuffer(maxPatternLength); + } + + public void finish() throws IOException { + while (processBuffer(0)); + +// super.write(buffer.toString(), 0, buffer.length()); +// buffer.delete(0, buffer.length()); + + if (processedData && postfix != null) + super.write(postfix, 0, postfix.length()); + } + + public void close() throws IOException { + finish(); + super.close(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/Standard.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: Standard.java,v 1.5 2006/12/14 14:39:26 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.*; +import java.util.*; +import java.net.*; + +import java.sql.SQLException; +import java.sql.PreparedStatement; + +import kryshen.tema.*; + +/** + * Standard TEMA functions. + */ +public class Standard { + public static final Function SET = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getData(); + + fdp.getTemplateParser().setValue(arg0, arg1); + + out.write(arg0); + return 1; + } + }; + + /* prepare:qury_name sql_statement */ + public static final Function PREPARE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String data = fdp.getData(); + + PreparedStatement statement; + + try { + statement = Tema.getDbConnection() + .prepareStatement(data); + } catch (SQLException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } + + fdp.getTemplateParser().setValue(arg0, statement); + + out.write(arg0); + return 1; + } + }; + + /* query:sql_query template arg1 arg2 ... argN */ + public static final Function QUERY = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + List<String> args = fdp.getArgs(); + + TemplateParser tp = fdp.getTemplateParser(); + + TemplateReader tr = + new TemplateReader(new StringReader(arg1), + fdp.getTemplateReader()); + + try { + return Tema.query + (tr, (PreparedStatement)tp.getValue(arg0), + args, tp, out); + } catch (SQLException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } + } + }; + + public static final Function REPLACE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + + ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + public static final Function LOAD = + + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + final String name = fdp.getNextArg(); + final String className = fdp.getNextArg(); + + List<URL> urls = new ArrayList<URL>(1); + + while (fdp.hasMoreData()) { + urls.add(new URL(fdp.getNextArg())); + } + + ClassLoader loader = this.getClass().getClassLoader(); + + if (urls.size() > 0) { + loader = new URLClassLoader + (urls.toArray(new URL[0]), loader); + } + + Class<Function> functionClass; + Function function; + + try { + functionClass = loadFunctionClass(loader, className); + } catch (ClassNotFoundException e) { + throw new TemplateException + ("Class not found", e, fdp.getTemplateReader()); + } catch (ClassCastException e) { + throw new TemplateException + ("Not a function class", e, fdp.getTemplateReader()); + } + + try { + function = functionClass.newInstance(); + } catch (InstantiationException e) { + throw new TemplateException + ("Could not load class", e, fdp.getTemplateReader()); + } catch (IllegalAccessException e) { + throw new TemplateException + ("Could not load class", e, fdp.getTemplateReader()); + } + + fdp.getTemplateParser().registerFunction(name, function); + + + out.write(name); + return 1; + } + }; + + public static final Function NULL_OUTPUT = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + /* Write nothing. */ + return fdp.parseData(new Writer() { + public void close() {} + public void flush() {} + public void write(char[] cbuf, int off, int len) {} + }); + } + }; + + public static final Function XML_ESCAPE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + final String[] chars = {"&", "<", ">", "`", "\""}; + final String[] escape = {"&", "<", ">", "'", """}; + + ReplaceWriter rw = new ReplaceWriter(out, chars, escape); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + public static final Function XML_CDATA = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + ReplaceWriter rw = new ReplaceWriter + (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>"); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + + @SuppressWarnings("unchecked") + private static Class<Function> loadFunctionClass + (ClassLoader loader, String className) + throws ClassNotFoundException { + + return (Class<Function>)loader.loadClass(className); + } + + /** + * Update file (copy if newer). + * + * @param src source file. + * @param dest destination file. + * + * @trows IOException on copying error. + */ + private static void copyFile(File src, File dest) throws IOException { + System.err.print("Copying " + src + "... "); + + if (src.lastModified() < dest.lastModified()) { + System.err.println(dest + " is up to date."); + return; + } + + File parent = dest.getParentFile(); + if (parent != null) parent.mkdirs(); + + InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dest); + + byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + in.close(); + out.close(); + + System.err.println("saved " + dest + "."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/Hello.java Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,21 @@ +import java.io.Writer; +import java.io.IOException; +import kryshen.tema.*; + +/** + * Test function class. + * + * @author Mikhail A. Kryshen + */ +public class Hello extends Function { + public Hello() {} + + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + out.write("Hello, "); + fdp.parseData(out); + + return 1; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/demo Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,4 @@ +#!/bin/sh + +#java -jar ../dist/tema.jar +java -classpath .:../dist/tema.jar kryshen.tema.Tema
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/demo.bat Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,1 @@ +java -classpath .:..\dist\tema.jar kryshen.tema.Tema
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/include.template Thu Dec 14 23:22:05 2006 +0300 @@ -0,0 +1,1 @@ +<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%> \ No newline at end of file
--- a/test/inctest.template Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<%test:1 2 3%>
--- a/test/macrotest Tue May 16 18:04:09 2006 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -#!/bin/sh - -java -jar ../dist/tema.jar
--- a/test/main.template Tue May 16 18:04:09 2006 +0400 +++ b/test/main.template Thu Dec 14 23:22:05 2006 +0300 @@ -1,3 +1,28 @@ -<%define`test [%nextarg:%]+[%nextarg:%]=[%data:]%> -<%include`inctest.template%> -<%test:<%test:ab cd x%> [%\<%test\1 2 3%>%] y%> +[%!\ UTF-8 text %] + +п▓я▀п╡п╬п╢ я┌п╣п╨я│я┌п╟: +test text + +п▓я▀п╡п╬п╢ я│п©п╣я├п╦п╟п╩я▄п╫я▀я┘ я│п╦п╪п╡п╬п╩п╬п╡: +[%\<%test%>%] + +п▓п╨п╩я▌я┤п╣п╫п╦п╣ я└п╟п╧п╩п╟ я│ п╬п╠я┼я▐п╡п╩п╣п╫п╦п╣п╪ я└я┐п╫п╨я├п╦п╦: +<%include:include.template%> + +п▓я▀п╥п╬п╡ п╫п╬п╡п╬п╧ я└я┐п╫п╨я├п╦п╦: +<%test:1 2 3%> + +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ read: +<%read\include.template%> + +п≈п╟пЁя─я┐п╥п╨п╟ я└я┐п╫п╨я├п╦п╦ п╦п╥ п╨п╩п╟я│я│п╟: +<%load\hello Hello%> + +п▓я▀п©п╬п╩п╣п╫п╣п╫п╦п╣ п╥п╟пЁя─я┐п╤п╣п╫п╫п╬п╧ я└я┐п╫п╨я├п╦п╦: +<%hello\TEMA%> + +пёя│п╩п╬п╡п╫п╬п╣ п╡я▀п©п╬п╩п╫п╣п╫п╦п╣: +<%optional:<%true:%>True%> <%optional:<%false:%>False%> + +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ xml_escape: +<%xml_escape\x < a & b%>
--- a/test/tema.properties Tue May 16 18:04:09 2006 +0400 +++ b/test/tema.properties Thu Dec 14 23:22:05 2006 +0300 @@ -1,16 +1,16 @@ # Data source configuration -# resource : jdbc:odbc:biotopes-data +# resource : jdbc:odbc:database # driver : sun.jdbc.odbc.JdbcOdbcDriver # Base directory for images and files -# resource_base : C:\\biotopes\\db +# resource_base : . # Template to start processing with main_template : main.template # File encodings -# input_encoding : ISO-8859-5 -# output_encoding : ISO-8859-5 +input_encoding : UTF-8 +output_encoding : UTF-8 # Cache templates # cache_read : true