changeset 1:548a93c24e55 release_0_1jk

Tema 0.1jk - Javakonkurs edition (imported from CVS).
author Mikhail Kryshen <mikhail@kryshen.net>
date Thu, 14 Dec 2006 23:22:05 +0300
parents 1d2fe61a3a62
children 6c41a0b43e58
files TODO build.xml dist/biotopes/biotope.template dist/biotopes/classes.template dist/biotopes/doc/article.txt dist/biotopes/doc/readme.html dist/biotopes/doc/readme.txt dist/biotopes/main.template dist/biotopes/photo.template dist/biotopes/plants.template dist/readme.html dist/readme.txt dist/tema dist/tema.bat dist/tema.properties doc/article.txt doc/manual/index.html res/kryshen/tema/demo/demo.template sample/class.xml sample/plants.xml src/kryshen/tema/Function.java src/kryshen/tema/FunctionDataParser.java src/kryshen/tema/Functions.java src/kryshen/tema/ImageConverter.java src/kryshen/tema/ReplaceWriter.java src/kryshen/tema/Tema.java src/kryshen/tema/TemplateException.java src/kryshen/tema/TemplateParser.java src/kryshen/tema/TemplateReader.java src/kryshen/tema/demo/DemoFrame.java src/kryshen/tema/demo/Hello.java src/kryshen/tema/functions/Define.java src/kryshen/tema/functions/IO.java src/kryshen/tema/functions/ImageConverter.java src/kryshen/tema/functions/Logics.java src/kryshen/tema/functions/ReplaceWriter.java src/kryshen/tema/functions/Standard.java test/Hello.class test/Hello.java test/demo test/demo.bat test/include.template test/inctest.template test/macrotest test/main.template test/tema.properties
diffstat 46 files changed, 2611 insertions(+), 1411 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/TODO	Thu Dec 14 23:22:05 2006 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +if, <, >, =, +, -, *, /
     2.1 --- a/build.xml	Tue May 16 18:04:09 2006 +0400
     2.2 +++ b/build.xml	Thu Dec 14 23:22:05 2006 +0300
     2.3 @@ -5,6 +5,7 @@
     2.4      <property name="build"    value="build"/>
     2.5      <property name="dist"     value="dist"/>
     2.6      <property name="res"      value="res"/>
     2.7 +    <property name="doc"      value="doc"/>
     2.8      <property name="jar_file" value="tema.jar"/>
     2.9  
    2.10      <target name="init">
    2.11 @@ -14,20 +15,30 @@
    2.12  
    2.13      <target name="compile" depends="init">
    2.14          <javac srcdir="${src}" destdir="${build}"
    2.15 -               deprecation="on" optimize="on" debug="on"/>
    2.16 +               deprecation="on" optimize="on" debug="on">
    2.17 +          <!-- <compilerarg value="-Xlint:unchecked"/> -->
    2.18 +        </javac>
    2.19      </target>
    2.20  
    2.21      <target name="dist" depends="compile">
    2.22  	<jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf">
    2.23  	    <fileset dir="${build}" includes="**/*.class"/>
    2.24 +	    <fileset dir="${res}" includes="**/*"/>
    2.25  	</jar>
    2.26 -    </target>    
    2.27 +    </target>
    2.28  
    2.29 +    <target name="javadoc" depends="init">
    2.30 +        <javadoc destdir="${doc}/api" sourcepath="${src}"
    2.31 +                 packagenames="kryshen.tema.*">
    2.32 +        </javadoc>
    2.33 +    </target>
    2.34 + 
    2.35      <target name="clean">
    2.36  	<delete>
    2.37  	    <fileset dir="${build}" includes="**/*.class"/>
    2.38  	</delete>
    2.39  	<delete file="${dist}/${jar_file}"/>
    2.40 +	<delete dir="${doc}/api"/>
    2.41      </target>
    2.42      
    2.43  </project>
     3.1 --- a/dist/biotopes/biotope.template	Tue May 16 18:04:09 2006 +0400
     3.2 +++ b/dist/biotopes/biotope.template	Thu Dec 14 23:22:05 2006 +0300
     3.3 @@ -1,17 +1,17 @@
     3.4  <?xml version="1.0" encoding="ISO-8859-5"?>
     3.5  <!DOCTYPE чъьАпщьу_рьтп SYSTEM "brief.dtd">
     3.6 -<!-- rangcode: <%xml_escape get\rangcode%> -->
     3.7 +<!-- rangcode: <%xml_escape db\rangcode%> -->
     3.8  <чъьАпщьу_рьтп show="0">
     3.9    <ЮьАЦщзь display="0">
    3.10 -    <%optional:<зпЮБп_ЮпАъЮчАБЮпщущьО щчэуЮ="1" file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%>
    3.11 +    <%optional:<зпЮБп_ЮпАъЮчАБЮпщущьО щчэуЮ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\code%>.png png%>"/>%>
    3.12  <%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
    3.13    </ЮьАЦщзь>
    3.14 -  <щпврпщьу><%xml_escape get\rusname%></щпврпщьу>
    3.15 -  <зшпАА><%xml_escape get\class0%></зшпАА>
    3.16 -  <ъчтзшпАА1><%xml_escape get\class1%></ъчтзшпАА1>
    3.17 -  <ъчтзшпАА2><%xml_escape get\class2%></ъчтзшпАА2>
    3.18 -  <ъчтзшпАА3><%xml_escape get\class3%></ъчтзшпАА3>
    3.19 -  <зЮпБзпО_ЕпЮпзБуЮьАБьзп rows="3"><%xml_cdata get\descript%></зЮпБзпО_ЕпЮпзБуЮьАБьзп>
    3.20 -  <ъЮьэуЮ_чъьАпщьО rows="3"><%xml_cdata get\geobotdescr%></ъЮьэуЮ_чъьАпщьО>
    3.21 -  <прБчЮК_чъьАпщьО><%xml_escape get\contributors%></прБчЮК_чъьАпщьО>
    3.22 +  <щпврпщьу><%xml_escape db\rusname%></щпврпщьу>
    3.23 +  <зшпАА><%xml_escape db\class0%></зшпАА>
    3.24 +  <ъчтзшпАА1><%xml_escape db\class1%></ъчтзшпАА1>
    3.25 +  <ъчтзшпАА2><%xml_escape db\class2%></ъчтзшпАА2>
    3.26 +  <ъчтзшпАА3><%xml_escape db\class3%></ъчтзшпАА3>
    3.27 +  <зЮпБзпО_ЕпЮпзБуЮьАБьзп rows="3"><%xml_cdata db\descript%></зЮпБзпО_ЕпЮпзБуЮьАБьзп>
    3.28 +  <ъЮьэуЮ_чъьАпщьО rows="3"><%xml_cdata db\geobotdescr%></ъЮьэуЮ_чъьАпщьО>
    3.29 +  <прБчЮК_чъьАпщьО><%xml_escape db\contributors%></прБчЮК_чъьАпщьО>
    3.30  </чъьАпщьу_рьтп>
     4.1 --- a/dist/biotopes/classes.template	Tue May 16 18:04:09 2006 +0400
     4.2 +++ b/dist/biotopes/classes.template	Thu Dec 14 23:22:05 2006 +0300
     4.3 @@ -1,5 +1,5 @@
     4.4  <?xml version="1.0" encoding="ISO-8859-5"?>
     4.5  <зшпААьДьзпФьО><%query:class_sql [%\
     4.6    <!-- rangcode: <%xml_escape get\rangcode%> -->
     4.7 -  <зшпАА id="<%get\NUMBER%>"><%xml_escape get\rusname%></зшпАА>%]%>
     4.8 +  <зшпАА id="<%get\NUMBER%>"><%xml_escape db\rusname%></зшпАА>%]%>
     4.9  </зшпААьДьзпФьО>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/dist/biotopes/doc/article.txt	Thu Dec 14 23:22:05 2006 +0300
     5.3 @@ -0,0 +1,391 @@
     5.4 +* Преобразование базы данных в XML-формат электронной библиотеки.
     5.5 +
     5.6 +Для решения задачи преобразования базы данных "Местообитания Восточной
     5.7 +Фенноскандии" из формата Microsoft Access в XML-формат электронной
     5.8 +библиотеки КарНЦ РАН была разработана программная система DbReader.
     5.9 +
    5.10 +Программа DbReader является универсальным средством для представления
    5.11 +информации из баз данных в текстовых форматах. Программа обрабатывает
    5.12 +заданные шаблоны текстовых файлов и заменяет найденные в них
    5.13 +инструкции на результаты их выполнения. Различные инструкции позволяют
    5.14 +формировать SQL-запросы, выполнять их и обрабатывать полученные
    5.15 +данные.
    5.16 +
    5.17 +
    5.18 +* Формат инструкций:
    5.19 +
    5.20 +    <%<список_функций>{:|\}<данные>%>
    5.21 +  где 
    5.22 +
    5.23 +<список_функций> - список имен функций, разделенных пробелами.
    5.24 +    Может быть пустым.
    5.25 +<данные> - данные, передаваемые функции.
    5.26 +
    5.27 +
    5.28 +* Формат данных:
    5.29 +
    5.30 +    [<список_аргументов>][<текст>]
    5.31 +  где
    5.32 +
    5.33 +<список_аргументов> - список аргументов функции, разделенных пробелами.
    5.34 +    Может быть пустым.
    5.35 +<текст> - текст, передаваемый функции без разбиения на аргументы.
    5.36 +    Может быть пустым. Количество аргументов, после которого следует
    5.37 +    текст, зависит от функции.
    5.38 +
    5.39 +Разделитель между списком функций и данными определяет, как должны
    5.40 +обрабатываться данные функции:
    5.41 +: - рекурсивная обработка,
    5.42 +\ - передать без обработки.
    5.43 +
    5.44 +Если в списке функций задано две и более функции, они выполняются,
    5.45 +начиная с последней, так что каждая функция получает в качестве данных
    5.46 +результат выполнения следующей функции.
    5.47 +
    5.48 +Каждая функция имеет код возврата - целое число. Код возврата
    5.49 +инструкции - код возврата первой в списке функции. Код возврата,
    5.50 +получаемый при обработке текста - сумма кодов возврата обработанных
    5.51 +инструкций.
    5.52 +
    5.53 +Вместо скобок '<', '>' можно использовать скобки '[', ']'.
    5.54 +
    5.55 +
    5.56 +* Реализованные функции:
    5.57 +
    5.58 +Функция:      set
    5.59 +Аргументы:    <имя>
    5.60 +Текст:        <значение>
    5.61 +Действие:     устанавливает значение переменной <имя>
    5.62 +Результат:    <имя>
    5.63 +Код возврата: 1
    5.64 +
    5.65 +Функция:      get
    5.66 +Аргументы:    <имя>
    5.67 +Результат:    значение переменной <имя>. 
    5.68 +Код возврата: 1, если значение переменной было установлено, 0 - иначе.
    5.69 +
    5.70 +Функция:      prepare
    5.71 +Аргументы:    <имя>
    5.72 +Текст:        <запрос>
    5.73 +Действие:     Подготавливает SQL-запрос <запрос> для выполнения,
    5.74 +              записывает подготовленный запрос в переменную <имя>.
    5.75 +Результат:    <имя>
    5.76 +Код возврата: 1
    5.77 +
    5.78 +Функция:      query
    5.79 +Аргументы:    <имя_запроса> <шаблон> <парам1> ... <парамN>
    5.80 +Действие:     Выполняет запрос с параметрами, подготовленный с помощью
    5.81 +              функции prepare. Значения параметров подставляются в
    5.82 +              запрос вместо символа '?'. Значения полей ответа будут
    5.83 +              записаны, как переменные шаблона <шаблон>. При обработки
    5.84 +              шаблона <шаблон> также определяется переменная NUMBER,
    5.85 +              содержащая номер текущей строки ответа. Переменные,
    5.86 +              определенные в вызывающем шаблоне, доступны из шаблона
    5.87 +              <шаблон> по имени SUPER.<имя_переменной>.
    5.88 +
    5.89 +Результат:    результат обработки шаблона <шаблон> для каждой строки
    5.90 +              ответа.
    5.91 +Код возврата: количество полученных строк ответа.
    5.92 +
    5.93 +Функция:      optional
    5.94 +Текст:        <данные>
    5.95 +Результат:    <данные>, если при обработке данных был получен
    5.96 +              код возврата отличный от 0, иначе - пустая строка.
    5.97 +Код возврата: 1, если результат - пустая строка, 0 - иначе.
    5.98 +
    5.99 +Функция:      image
   5.100 +Аргументы:    <исх_файл> <кон_файл> <формат> [<макс_ширина> [<макс_высота>]]
   5.101 +Действие:     Загружает изображение из файла <исх_файл> (путь определяется
   5.102 +              относительно конфигурационного параметра "resource_base") и
   5.103 +              преобразует его в указанный формат, сохраняя результат в
   5.104 +              <кон_файл>. Если заданы максимальная высота и ширина, большие
   5.105 +              изображения будут уменьшены. 
   5.106 +Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
   5.107 +Код возврата: 1 при успешном выполнении, 0 - иначе.
   5.108 +
   5.109 +Функция:      copy
   5.110 +Аргументы:    <исх_файл> <кон_файл>
   5.111 +Действие:     Копирует файл <исх_файл> в файл <кон_файл>
   5.112 +	      (путь <исх_файл> определяется относительно
   5.113 +              конфигурационного параметра "resource_base").
   5.114 +Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
   5.115 +Код возврата: 1 при успешном выполнении, 0 - иначе.
   5.116 +
   5.117 +Функция:      write
   5.118 +Аргументы:    <имя_файла>
   5.119 +Текст:        <данные>
   5.120 +Действие:     Записывает <данные> в файл <исх_файл>.
   5.121 +Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
   5.122 +Код возврата: 1 при успешном выполнении, 0 - иначе.
   5.123 +
   5.124 +Функция:      read
   5.125 +Текст:        <имя_файла>
   5.126 +Действие:     Читает файл <имя_файла>.
   5.127 +Результат:    прочитанные данные при успешном выполнении, пустая
   5.128 +              строка - иначе.
   5.129 +Код возврата: 1 при успешном выполнении, 0 - иначе.
   5.130 +
   5.131 +Функция:      include
   5.132 +Текст:        <имя_файла>
   5.133 +Действие:     включает шаблон из файла <имя_файла>.
   5.134 +Результат:    результат обработки шаблона.
   5.135 +Код возврата: код возврата, полученный при обработке шаблона.
   5.136 +
   5.137 +Функция:      !
   5.138 +Текст:        <данные>
   5.139 +Действие:     нет.
   5.140 +Результат:    нет.
   5.141 +Код возврата: код возврата, полученный при обработке текста данных.
   5.142 +
   5.143 +Функция:      replace
   5.144 +Аргументы:    <стр1> <стр2>
   5.145 +Текст:        <данные>
   5.146 +Результат:    данные, с замененными вхождениями подстроки <стр1>
   5.147 +	      на <стр2>.
   5.148 +Код возврата: код возврата, полученный при обработке текста данных.
   5.149 +
   5.150 +Функция:      xml_escape
   5.151 +Текст:        <данные>
   5.152 +Результат:    текст <данные>, в котором  символы
   5.153 +              '&', '<', '>', '`', '\' заменены на соответствующие
   5.154 +	      сущности XML.
   5.155 +Код возврата: код возврата, полученный при обработке текста данных.
   5.156 +
   5.157 +Функция:      xml_cdata
   5.158 +Текст:        <данные>
   5.159 +Результат:    данные в виде блока XML CDATA.
   5.160 +Код возврата: код возврата, полученный при обработке текста данных.
   5.161 +
   5.162 +Система DbReader расширяема: возможно добавление в систему новых
   5.163 +функций, реализованных в виде классов на языке Java.
   5.164 +
   5.165 +
   5.166 +* Применение системы DbReader для преобразования базы данных
   5.167 +  "Местообитания Восточной Фенноскандии" из формата Microsoft Access в
   5.168 +  XML-формат электронной библиотеки КарНЦ РАН
   5.169 +
   5.170 +Для преобразования используются две таблицы базы данных "Местообитания
   5.171 +Восточной Фенноскандии" (перечислены только используемые поля):
   5.172 +
   5.173 +biotopelist (code, rangcode, rusname, engname, descript, geobotdescr,
   5.174 +             contributors, descrdate)
   5.175 +
   5.176 +  code - счетчик, ключевое поле;
   5.177 +  rangcode - поле в формате ABBCCDDEE, где А, BB, CC, DD, ЕЕ - коды
   5.178 +             класса, подклассов и растения;
   5.179 +  rusname, engname, descript, geobotdescr - текстовые поля;
   5.180 +  descrdate - дата.
   5.181 +
   5.182 +photos (biotope, photo, authphoto)
   5.183 +
   5.184 +  biotope - число, указывает на code в biotopelist;
   5.185 +  photo - имя файла фотографии;
   5.186 +  authphoto - текст.
   5.187 +
   5.188 +Требуется сгенерировать xml-файл для каждой записи в biotopelist, файл
   5.189 +со списком классов, файл со списком растений, полноразмерные и
   5.190 +уменьшенные версии каждой фотографии.
   5.191 +
   5.192 +Для генерации xml-файлов с описаниями биотопов использовался следующий
   5.193 +шаблон DbReader (файл biotope.template):
   5.194 +
   5.195 +----------------------------------------------------------------------
   5.196 +<?xml version="1.0" encoding="ISO-8859-5"?>
   5.197 +<!DOCTYPE описание_вида SYSTEM "brief.dtd">
   5.198 +<!-- rangcode: <%xml_escape get\rangcode%> -->
   5.199 +<описание_вида show="0">
   5.200 +  <рисунки display="0">
   5.201 +    <%optional:<карта_распространения номер="1"
   5.202 +    file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%>
   5.203 +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
   5.204 +  </рисунки>
   5.205 +  <название><%xml_escape get\rusname%></название>
   5.206 +  <класс><%xml_escape get\class0%></класс>
   5.207 +  <подкласс1><%xml_escape get\class1%></подкласс1>
   5.208 +  <подкласс2><%xml_escape get\class2%></подкласс2>
   5.209 +  <подкласс3><%xml_escape get\class3%></подкласс3>
   5.210 +  <краткая_характеристика rows="3"><%xml_cdata get\descript%></краткая_характеристика>
   5.211 +  <пример_описания rows="3"><%xml_cdata get\geobotdescr%></пример_описания>
   5.212 +  <авторы_описания><%xml_escape get\contributors%></авторы_описания>
   5.213 +</описание_вида>
   5.214 +----------------------------------------------------------------------
   5.215 +
   5.216 +Соответствующий SQL-запрос, при выполнении которого устанавливаются
   5.217 +значения переменных шаблона rangcode, rusname, class0, class1, class2,
   5.218 +class3, descript, geobotdescr и contributors (файл biotope.sql):
   5.219 +
   5.220 +----------------------------------------------------------------------
   5.221 +SELECT t1.*,
   5.222 +
   5.223 +(SELECT t2.rusname FROM biotopelist AS t2
   5.224 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
   5.225 +AND Right(t2.rangcode, 8)  = '00000000'
   5.226 +AND Right(t1.rangcode, 8) <> '00000000') AS class0,
   5.227 +
   5.228 +(SELECT t2.rusname FROM biotopelist AS t2
   5.229 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
   5.230 +AND Right(t2.rangcode, 6)  = '000000'
   5.231 +AND Right(t1.rangcode, 6) <> '000000') AS class1,
   5.232 +
   5.233 +(SELECT t2.rusname FROM biotopelist AS t2
   5.234 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
   5.235 +AND Right(t2.rangcode, 4)  = '0000'
   5.236 +AND Right(t1.rangcode, 4) <> '0000') AS class2,
   5.237 +
   5.238 +(SELECT t2.rusname FROM biotopelist AS t2
   5.239 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
   5.240 +AND Right(t2.rangcode, 2)  = '00'
   5.241 +AND Right(t1.rangcode, 2) <> '00') AS class3
   5.242 +
   5.243 +FROM biotopelist AS t1
   5.244 +WHERE rusname
   5.245 +----------------------------------------------------------------------
   5.246 +
   5.247 +Шаблон biotope.template содержит инструкцию <%include\photo.template%>,
   5.248 +включающую шаблон описания фотографии (файл photo.template):
   5.249 +
   5.250 +----------------------------------------------------------------------
   5.251 +    <фотография num="<%xml_escape get\NUMBER%>"
   5.252 +       <%optional:автор="<%xml_escape get\authphoto%>" %>text="" 
   5.253 +       file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 
   5.254 +        big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
   5.255 +----------------------------------------------------------------------
   5.256 +
   5.257 +Соответствующий SQL-запрос для получения описания фотографий
   5.258 +(photo.sql):
   5.259 +
   5.260 +----------------------------------------------------------------------
   5.261 +SELECT * from photos WHERE biotope = ?
   5.262 +----------------------------------------------------------------------
   5.263 +
   5.264 +Шаблон, генерирующий список классов (файл classes.template):
   5.265 +
   5.266 +----------------------------------------------------------------------
   5.267 +<?xml version="1.0" encoding="ISO-8859-5"?>
   5.268 +<классификация><%query:class_sql [%\
   5.269 +  <!-- rangcode: <%xml_escape get\rangcode%> -->
   5.270 +  <класс id="<%get\NUMBER%>"><%xml_escape get\rusname%></класс>%]%>
   5.271 +</классификация>
   5.272 +----------------------------------------------------------------------
   5.273 +
   5.274 +Соответствующий SQL-запрос (class.sql):
   5.275 +
   5.276 +----------------------------------------------------------------------
   5.277 +SELECT t1.*
   5.278 +FROM biotopelist AS t1
   5.279 +WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
   5.280 +  AND EXISTS
   5.281 +    (SELECT NULL FROM biotopelist AS t2
   5.282 +     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
   5.283 +     AND Right(t2.rangcode, 8) <> '00000000')
   5.284 +----------------------------------------------------------------------
   5.285 +
   5.286 +Шаблон, генерирующий список растений (файл plants.template):
   5.287 +
   5.288 +----------------------------------------------------------------------
   5.289 +<?xml version="1.0" encoding="ISO-8859-5"?>
   5.290 +<растения><%query:plant_sql [%\
   5.291 +  <!-- rangcode: <%xml_escape get\rangcode%> -->
   5.292 +  <растение><%xml_escape get\rusname%></растение>%]%>
   5.293 +</растения>
   5.294 +----------------------------------------------------------------------
   5.295 +
   5.296 +Соответствующий SQL-запрос (plant.sql):
   5.297 +
   5.298 +----------------------------------------------------------------------
   5.299 +SELECT t1.*
   5.300 +FROM biotopelist AS t1
   5.301 +WHERE rusname AND Right(t1.rangcode, 2) <> '00'
   5.302 +----------------------------------------------------------------------
   5.303 +
   5.304 +Система DbReader начинает работу с обработки шаблона index.template,
   5.305 +который содержит вызовы перечисленных выше SQL-запросов и включения
   5.306 +шаблонов:
   5.307 +
   5.308 +----------------------------------------------------------------------
   5.309 +<%!:
   5.310 +  <%prepare:biotope_sql <%read\biotope.sql%>%>
   5.311 +  <%prepare:photo_sql <%read\photo.sql%>%>
   5.312 +  <%prepare:class_sql <%read\class.sql%>%>
   5.313 +  <%prepare:plant_sql <%read\plant.sql%>%>
   5.314 +
   5.315 +  <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%>
   5.316 +
   5.317 +  <%write:classes.xml <%include\classes.template%>%>
   5.318 +  <%write:plants.xml <%include\plants.template%>%>
   5.319 +%>
   5.320 +----------------------------------------------------------------------
   5.321 +
   5.322 +Пример сгенерированного XML-файла:
   5.323 +
   5.324 +----------------------------------------------------------------------
   5.325 +<?xml version="1.0" encoding="ISO-8859-5"?>
   5.326 +<!DOCTYPE описание_вида SYSTEM "brief.dtd">
   5.327 +<!-- rangcode: E04020302 -->
   5.328 +<описание_вида show="0">
   5.329 +  <рисунки display="0">    
   5.330 +    <фотография num="1" автор="Крышень А.М." text="" 
   5.331 +                file="images/3_1.jpg" 
   5.332 +                big="images/big/3_1.jpg"/>
   5.333 +    <фотография num="2" автор="Крышень А.М." text="" 
   5.334 +                file="images/3_2.jpg" 
   5.335 +                big="images/big/3_2.jpg"/>
   5.336 +  </рисунки>
   5.337 +  <название>Betula sp. - Avenella flexuosa - Polytrichum commune</название>
   5.338 +  <класс>E. Суходольные местообитания</класс>
   5.339 +  <подкласс1>Автоморфные влажные</подкласс1>
   5.340 +  <подкласс2></подкласс2>
   5.341 +  <подкласс3></подкласс3>
   5.342 +  <краткая_характеристика rows="3"><![CDATA[Развиваются  на луговиковых вырубках лесов черничного типа.  Через 5 - 7 лет  после рубки порослевая береза выходит из  яруса травянистых растений, ее влияние сказывается, в первую очередь, на влажности почвы.]]></краткая_характеристика>
   5.343 +  <пример_описания rows="3"></пример_описания>
   5.344 +  <авторы_описания></авторы_описания>
   5.345 +</описание_вида>
   5.346 +----------------------------------------------------------------------
   5.347 +
   5.348 +
   5.349 +* Структура программы DbReader
   5.350 +
   5.351 +Программа DbReader написана на языке программирования Java и состоит
   5.352 +из следующих основных классов:
   5.353 +
   5.354 +ru.karrc.dbreader.DbReader: cодержит точку входа программы. Загружает
   5.355 +конфигурацию, устанавливает соединение с источником данных с помощью
   5.356 +библиотеки JDBC, запускает обработку основного шаблона.
   5.357 +
   5.358 +ru.karrc.dbreader.TemplateParser: осуществляет разбор шаблона,
   5.359 +обработку инструкций и вызов функций.
   5.360 +
   5.361 +ru.karrc.dbreader.Function: абстрактный класс. Реализации всех функций
   5.362 +DbReader наследуют этот класс.
   5.363 +
   5.364 +ru.karrc.dbreader.FunctionDataParser: обработчик данных
   5.365 +функции. Посволяет получить список аргументов и текст, передаваемый
   5.366 +функции. При необходимости вызывает рекурсивную обработку данных с
   5.367 +помощью TemplateParser.
   5.368 +
   5.369 +ru.karrc.dbreader.Functions: содержит реализации функций в виде
   5.370 +анонимных классов, наследующих Function.
   5.371 +
   5.372 +ru.karrc.dbreader.TemplateParser: исключение, выбрасываемое в случае
   5.373 +возникновения ошибки при обработке шаблона.
   5.374 +
   5.375 +Кроме того, реализовано несколько впомогательных классов, которые
   5.376 +используются в реализациях функций системы.
   5.377 +
   5.378 +
   5.379 +* Метрики реализованной программной системы.
   5.380 +
   5.381 +Количество файлов исходного кода: 8,
   5.382 +Количество Java-классов (включая анонимные): 27,
   5.383 +Общее количество строк исходного текста: 1311,
   5.384 +Количество строк кода (исключая пустые строки и комментарии): 812,
   5.385 +Количество строк комментариев: 180.
   5.386 +
   5.387 +
   5.388 +* Заключение
   5.389 +
   5.390 +Автором была разработана программная система DbReader, которая
   5.391 +является расширяемым и универсальным средством для представления
   5.392 +информации из баз данных в текстовых форматах. С помощью системы
   5.393 +DbReader база данных "Местообитания Восточной Фенноскандии" была
   5.394 +переведена в XML-формат электронной библиотеки КарНЦ РАН.
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/dist/biotopes/doc/readme.html	Thu Dec 14 23:22:05 2006 +0300
     6.3 @@ -0,0 +1,86 @@
     6.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
     6.5 +          "DTD/xhtml1-transitional.dtd">
     6.6 +
     6.7 +<html>
     6.8 +
     6.9 +<head>
    6.10 +  <title>DbReader</title>
    6.11 +  <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" />
    6.12 +</head>
    6.13 +
    6.14 +<body>
    6.15 +<h1>DbReader</h1>
    6.16 +
    6.17 +<h2>Установка программы</h2>
    6.18 +<ol>
    6.19 +<li>Распаковать архив.</li>
    6.20 +
    6.21 +<li>Установить источник данных:<br />
    6.22 +в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes-data.mdb.</li>
    6.23 +
    6.24 +<li>Настроить программу:<br />
    6.25 +В файле dbreader.properties указать имя, присвоенное источнику данных:<br />
    6.26 +    <code>resource: jdbc:odbc:<em>имя</em></code><br />
    6.27 +и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):<br />
    6.28 +    <code>resource_base: C:\\biotopes</code><br />
    6.29 +(символ '\' необходимо дублировать)</li>
    6.30 +
    6.31 +<li>Запуск программы:<br />
    6.32 +<code>dbreader.bat</code> или<br />
    6.33 +<code>java -jar dbreader.jar</code>.<br />
    6.34 +Для запуска необходима 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 - не проверял.
    6.35 +
    6.36 +Все значения файла конфигурации можно переопределять при запуске программы:<br />
    6.37 +команда <code>java -Dru.karrc.dbreader.<em>ключ</em>=<em>значение</em> -jar dbreader.jar</code><br />
    6.38 +(например: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li>
    6.39 +</ol>
    6.40 +
    6.41 +<h2>Работа программы</h2>
    6.42 +
    6.43 +<p>Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.</p>
    6.44 +<p>Формат инструкций: <code>&lt;%<em>список_функций</em>[:|\]<em>данные</em>%&gt;</code>, <em>список функций</em> - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.</p>
    6.45 +
    6.46 +<h3>Разделители между списком функций и данными</h3>
    6.47 +
    6.48 +<ul>
    6.49 +  <li><code>:</code> - данные будут обрабатываться рекурсивно.</li>
    6.50 +  <li><code>\</code> - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов <code>&lt;%</code> и <code>%&gt;</code> (<code>&lt;%\&lt;%%&gt;</code> и <code>&lt;%\%%&gt;&gt;</code>).</li>
    6.51 +</ul>
    6.52 +
    6.53 +<h3>Функции</h3>
    6.54 +
    6.55 +<ul>
    6.56 +  <li><code>&lt;%get:<em>имя</em>%&gt;</code><br />
    6.57 +  Заменяется на значение встроенной переменной или колонки запроса.</li>
    6.58 +
    6.59 +  <li><code>&lt;%optional:<em>текст</em>%&gt;</code><br />
    6.60 +  Заменяется на <em>текст</em>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.</li>
    6.61 +
    6.62 +  <li><code>&lt;%escape:<em>текст</em>%&gt;</code><br />
    6.63 +  Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).</li>
    6.64 +
    6.65 +  <li><code>&lt;%invoke:<em>имя</em>; <em>парам1</em> <em>парам2</em> ... <em>парамN</em>%&gt;</code><br />
    6.66 +  Выполняет запрос с параметрами <em>имя</em>.sql и заменяется на результаты обработки шаблона <em>имя</em>.template. Значения параметров подставляются в запрос вместо символа '?'.</li>
    6.67 +
    6.68 +  <li><code>&lt;%image:<em>исх_файл</em> <em>кон_файл</em> <em>формат</em> [<em>макс_ширина</em>] [<em>макс_высота</em>]%&gt;</code><br />
    6.69 +  Загружает изображение из файла <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <em>кон_файл</em>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены.
    6.70 +При успешном выполнении, инструкция <code>&lt;%image:...%&gt;</code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li>
    6.71 +
    6.72 +  <li><code>&lt;%copy:<em>исх_файл</em> <em>кон_файл</em>%&gt;</code><br />
    6.73 +  Копирует файл <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") в <em>кон_файл</em>. При успешном выполнении, инструкция <code>&lt;%copy:...%&gt;</code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li>
    6.74 +</ul>
    6.75 +
    6.76 +<h3>Встроенные переменные</h3>
    6.77 +
    6.78 +<p><code>NUMBER</code> - порядковый номер строки результата выполнения запроса.
    6.79 +Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить <code>SUPER.</code> (например: <code>SUPER.NUMBER</code>).</p>
    6.80 +
    6.81 +<h3>Пример</h3>
    6.82 +
    6.83 +<p>Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:</p>
    6.84 +<p><code>&lt;%escape get:name%&gt;</code></p>
    6.85 +
    6.86 +<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru">Михаил Крышень</a></i></p>
    6.87 +
    6.88 +</body>
    6.89 +</html>
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/dist/biotopes/doc/readme.txt	Thu Dec 14 23:22:05 2006 +0300
     7.3 @@ -0,0 +1,63 @@
     7.4 +text/plain; charset=UTF-8
     7.5 +
     7.6 +пёя│я┌п╟п╫п╬п╡п╨п╟ п©я─п╬пЁя─п╟п╪п╪я▀
     7.7 +-------------------
     7.8 +
     7.9 +1. п═п╟я│п©п╟п╨п╬п╡п╟я┌я▄ п╟я─я┘п╦п╡.
    7.10 +
    7.11 +2. пёя│я┌п╟п╫п╬п╡п╦я┌я▄ п╦я│я┌п╬я┤п╫п╦п╨ п╢п╟п╫п╫я▀я┘:
    7.12 +п╡ Windows 2000: п÷п╟п╫п╣п╩я▄ я┐п©я─п╟п╡п╩п╣п╫п╦я▐/п░п╢п╪п╦п╫п╦я│я┌я─п╦я─п╬п╡п╟п╫п╦п╣/п≤я│я┌п╬я┤п╫п╦п╨п╦ п╢п╟п╫п╫я▀я┘ (ODBC), п╢п╬п╠п╟п╡п╦я┌я▄ biotopes.mdb.
    7.13 +
    7.14 +3. п²п╟я│я┌я─п╬п╦я┌я▄ п©я─п╬пЁя─п╟п╪п╪я┐:
    7.15 +п▓ я└п╟п╧п╩п╣ dbreader.properties я┐п╨п╟п╥п╟я┌я▄ п╦п╪я▐, п©я─п╦я│п╡п╬п╣п╫п╫п╬п╣ п╦я│я┌п╬я┤п╫п╦п╨я┐ п╢п╟п╫п╫я▀я┘:
    7.16 +    "resource: jdbc:odbc:<п╦п╪я▐>"
    7.17 +п╦ п©я┐я┌я▄ п╨ п╨п╟я┌п╟п╩п╬пЁя┐, п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬я┌п╬я─п╬пЁп╬ п©я─п╬пЁя─п╟п╪п╪п╟ п╠я┐п╢п╣я┌ п╦я│п╨п╟я┌я▄ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ (я│п╬п╢п╣я─п╤п╟я┴п╦п╧ biotopephotos п╦ maps):
    7.18 +    "resource_base: C:\\biotopes"
    7.19 +(я│п╦п╪п╡п╬п╩ '\' п╫п╣п╬п╠я┘п╬п╢п╦п╪п╬ п╢я┐п╠п╩п╦я─п╬п╡п╟я┌я▄)
    7.20 +
    7.21 +4. п≈п╟п©я┐я│п╨ п©я─п╬пЁя─п╟п╪п╪я▀: dbreader.bat п╦п╩п╦ "java -jar dbreader.jar"
    7.22 +п■п╩я▐ п╥п╟п©я┐я│п╨п╟ п╫п╣п╬п╠я┘п╬п╢п╦п╪п╟ Java Runtime Environment (JRE) 5.0, п╪п╬п╤п╫п╬ я│п╨п╟я┤п╟я┌я▄ я│ http://java.sun.com/j2se/1.5.0/download.jsp. п▓п╬п╥п╪п╬п╤п╫п╬, п╠я┐п╢п╣я┌ я─п╟п╠п╬я┌п╟я┌я▄ п╦ я│п╬ я│я┌п╟я─я▀п╪п╦ п╡п╣я─я│п╦я▐п╪п╦ JRE - п╫п╣ п©я─п╬п╡п╣я─я▐п╩.
    7.23 +
    7.24 +п▓я│п╣ п╥п╫п╟я┤п╣п╫п╦я▐ я└п╟п╧п╩п╟ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦ п╪п╬п╤п╫п╬ п©п╣я─п╣п╬п©я─п╣п╢п╣п╩я▐я┌я▄ п©я─п╦ п╥п╟п©я┐я│п╨п╣ п©я─п╬пЁя─п╟п╪п╪я▀:
    7.25 +    п╨п╬п╪п╟п╫п╢п╟ "java -Dru.karrc.dbreader.<п╨п╩я▌я┤>=<п╥п╫п╟я┤п╣п╫п╦п╣> -jar dbreader.jar"
    7.26 +(п╫п╟п©я─п╦п╪п╣я─: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar")
    7.27 +
    7.28 +
    7.29 +п═п╟п╠п╬я┌п╟ п©я─п╬пЁя─п╟п╪п╪я▀
    7.30 +----------------
    7.31 +
    7.32 +п÷я─п╬пЁя─п╟п╪п╪п╟ п╡я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ biotope.sql (п╦п╩п╦ п╢я─я┐пЁп╬п╧, я┐п╨п╟п╥п╟п╫п╫я▀п╧ п╡ dbreader.properties), п©п╬я│п╩п╣ я┤п╣пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ я└п╟п╧п╩ biotope.template, п╥п╟п╪п╣п╫я▐я▐ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╣п╪ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐.
    7.33 +
    7.34 +п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧: "<%я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧[:|\]п╢п╟п╫п╫я▀п╣%>", я│п©п╦я│п╬п╨ я└я┐п╫п╨я├п╦п╧ - п╦п╪п╣п╫п╟ я└я┐п╫п╨я├п╦п╧ я─п╟п╥п╢п╣п╩п╣п╫п╫я▀п╣ п©я─п╬п╠п╣п╩п╬п╪, я│п©п╦я│п╬п╨ п╪п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п∙я│п╩п╦ я┐п╨п╟п╥п╟п╫п╬ п╫п╣я│п╨п╬п╩я▄п╨п╬ я└я┐п╫п╨я├п╦п╧, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐ п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧.
    7.35 +
    7.36 +п═п╟п╥п╢п╣п╩п╦я┌п╣п╩п╦ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦:
    7.37 +':' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ я─п╣п╨я┐я─я│п╦п╡п╫п╬.
    7.38 +'\' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п©п╣я─п╣п╢п╟п╫я▀ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦. п°п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ п╢п╩я▐ я█п╨я─п╟п╫п╦я─п╬п╡п╟п╫п╦я▐ п╨п╬п╪п╠п╦п╫п╟я├п╦п╧ я│п╦п╪п╡п╬п╩п╬п╡ "<%" п╦ "%>" ("<%\<%%>" п╦ "<%\%%>>").
    7.39 +
    7.40 +п╓я┐п╫п╨я├п╦п╦:
    7.41 +<%get:<п╦п╪я▐>%> - п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ п╡я│я┌я─п╬п╣п╫п╫п╬п╧ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╦п╩п╦ п╨п╬п╩п╬п╫п╨п╦ п╥п╟п©я─п╬я│п╟.
    7.42 +
    7.43 +<%optional:<я┌п╣п╨я│я┌>%>
    7.44 +п≈п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ <я┌п╣п╨я│я┌>, п╣я│п╩п╦ п╡ п╫п╣п╪ п╫п╟п╧п╢п╣п╫я▀ п╦п╫я│я┌я─я┐п╨я├п╦п╦, п╥п╟п╪п╣п╫п╦п╡я┬п╦п╣я│я▐ п╫п╟ п╫п╣п©я┐я│я┌я▀п╣ я│я┌я─п╬п╨п╦, п╦п╫п╟я┤п╣ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
    7.45 +
    7.46 +<%escape:<я┌п╣п╨я│я┌>%>
    7.47 +п≈п╟п╪п╣п╫я▐п╣я┌ п╡ я┌п╣п╨я│я┌п╣ "п╬п©п╟я│п╫я▀п╣" я│п╦п╪п╡п╬п╩я▀ (я┌п╟п╠п╩п╦я├п╟ п╥п╟п╪п╣п╫ п╥п╟п╢п╟п╣я┌я│я▐ п╡ я└п╟п╧п╩п╣ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦).
    7.48 +
    7.49 +<%invoke:<п╦п╪я▐> <п©п╟я─п╟п╪1> <п©п╟я─п╟п╪2> ... <п©п╟я─п╟п╪N>%>
    7.50 +п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦ <п╦п╪я▐>.sql п╦ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <п╦п╪я▐>.template. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟ '?'.
    7.51 +
    7.52 +<%image:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩> <я└п╬я─п╪п╟я┌> [<п╪п╟п╨я│_я┬п╦я─п╦п╫п╟>] [<п╪п╟п╨я│_п╡я▀я│п╬я┌п╟>]%>
    7.53 +п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦ п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡ <п╨п╬п╫_я└п╟п╧п╩>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀.
    7.54 +п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!image ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
    7.55 +
    7.56 +<%copy:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩>%>
    7.57 +п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base").
    7.58 +п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!copy ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
    7.59 +
    7.60 +п▓я│я┌я─п╬п╣п╫п╫я▀п╣ п©п╣я─п╣п╪п╣п╫п╫я▀п╣:
    7.61 +NUMBER - п©п╬я─я▐п╢п╨п╬п╡я▀п╧ п╫п╬п╪п╣я─ я│я┌я─п╬п╨п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ п╥п╟п©я─п╬я│п╟.
    7.62 +п╖я┌п╬п╠я▀ п╬п╠я─п╟я┌п╦я┌я▄я│я▐ п╨ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╥п╟п©я─п╬я│п╟, п╦п╥ п╨п╬я┌п╬я─п╬пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣п╪я▀п╧ я┬п╟п╠п╩п╬п╫ п╠я▀п╩ п╡я▀п╥п╡п╟п╫ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ invoke, п©п╣я─п╣п╢ п╦п╪п╣п╫п╣п╪ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╫я┐п╤п╫п╬ п╢п╬п╠п╟п╡п╦я┌я▄ "SUPER." (п╫п╟п©я─п╦п╪п╣я─: "SUPER.NUMBER").
    7.63 +
    7.64 +п÷я─п╦п╪п╣я─:
    7.65 +п║п╩п╣п╢я┐я▌я┴п╟я▐ п╦п╫я│я┌я─я┐п╨я├п╦я▐ п©п╬п╩я┐я┤п╦я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п╦п╥ я│я┌п╬п╩п╠я├п╟ name п╦ п╥п╟п╪п╣п╫п╦я┌ п╡ п╫п╣п╪ я│п©п╣я├п╦п╟п╩я▄п╫я▀п╣ я│п╦п╪п╡п╬п╩я▀:
    7.66 +<%escape get:name%>
     8.1 --- a/dist/biotopes/main.template	Tue May 16 18:04:09 2006 +0400
     8.2 +++ b/dist/biotopes/main.template	Thu Dec 14 23:22:05 2006 +0300
     8.3 @@ -4,7 +4,7 @@
     8.4    <%prepare:class_sql <%read\class.sql%>%>
     8.5    <%prepare:plant_sql <%read\plant.sql%>%>
     8.6  
     8.7 -  <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%>
     8.8 +  <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%>
     8.9  
    8.10    <%write:classes.xml <%include\classes.template%>%>
    8.11    <%write:plants.xml <%include\plants.template%>%>
     9.1 --- a/dist/biotopes/photo.template	Tue May 16 18:04:09 2006 +0400
     9.2 +++ b/dist/biotopes/photo.template	Thu Dec 14 23:22:05 2006 +0300
     9.3 @@ -1,3 +1,3 @@
     9.4 -    <ДчБчсЮпДьО num="<%xml_escape get\NUMBER%>" <%optional:прБчЮ="<%xml_escape get\authphoto%>" %>text="" 
     9.5 -                file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 
     9.6 -                big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
     9.7 +    <ДчБчсЮпДьО num="<%number\%>" <%optional:прБчЮ="<%xml_escape db\authphoto%>" %>text="" 
     9.8 +                file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" 
     9.9 +                big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
    10.1 --- a/dist/biotopes/plants.template	Tue May 16 18:04:09 2006 +0400
    10.2 +++ b/dist/biotopes/plants.template	Thu Dec 14 23:22:05 2006 +0300
    10.3 @@ -1,5 +1,5 @@
    10.4  <?xml version="1.0" encoding="ISO-8859-5"?>
    10.5  <ЮпАБущьО><%query:plant_sql [%\
    10.6 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
    10.7 -  <ЮпАБущьу><%xml_escape get\rusname%></ЮпАБущьу>%]%>
    10.8 +  <!-- rangcode: <%xml_escape db\rangcode%> -->
    10.9 +  <ЮпАБущьу><%xml_escape db\rusname%></ЮпАБущьу>%]%>
   10.10  </ЮпАБущьО>
    11.1 --- a/dist/readme.html	Tue May 16 18:04:09 2006 +0400
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,86 +0,0 @@
    11.4 -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    11.5 -          "DTD/xhtml1-transitional.dtd">
    11.6 -
    11.7 -<html>
    11.8 -
    11.9 -<head>
   11.10 -  <title>DbReader</title>
   11.11 -  <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" />
   11.12 -</head>
   11.13 -
   11.14 -<body>
   11.15 -<h1>DbReader</h1>
   11.16 -
   11.17 -<h2>Установка программы</h2>
   11.18 -<ol>
   11.19 -<li>Распаковать архив.</li>
   11.20 -
   11.21 -<li>Установить источник данных:<br />
   11.22 -в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes-data.mdb.</li>
   11.23 -
   11.24 -<li>Настроить программу:<br />
   11.25 -В файле dbreader.properties указать имя, присвоенное источнику данных:<br />
   11.26 -    <code>resource: jdbc:odbc:<em>имя</em></code><br />
   11.27 -и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):<br />
   11.28 -    <code>resource_base: C:\\biotopes</code><br />
   11.29 -(символ '\' необходимо дублировать)</li>
   11.30 -
   11.31 -<li>Запуск программы:<br />
   11.32 -<code>dbreader.bat</code> или<br />
   11.33 -<code>java -jar dbreader.jar</code>.<br />
   11.34 -Для запуска необходима 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 - не проверял.
   11.35 -
   11.36 -Все значения файла конфигурации можно переопределять при запуске программы:<br />
   11.37 -команда <code>java -Dru.karrc.dbreader.<em>ключ</em>=<em>значение</em> -jar dbreader.jar</code><br />
   11.38 -(например: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li>
   11.39 -</ol>
   11.40 -
   11.41 -<h2>Работа программы</h2>
   11.42 -
   11.43 -<p>Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.</p>
   11.44 -<p>Формат инструкций: <code>&lt;%<em>список_функций</em>[:|\]<em>данные</em>%&gt;</code>, <em>список функций</em> - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.</p>
   11.45 -
   11.46 -<h3>Разделители между списком функций и данными</h3>
   11.47 -
   11.48 -<ul>
   11.49 -  <li><code>:</code> - данные будут обрабатываться рекурсивно.</li>
   11.50 -  <li><code>\</code> - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов <code>&lt;%</code> и <code>%&gt;</code> (<code>&lt;%\&lt;%%&gt;</code> и <code>&lt;%\%%&gt;&gt;</code>).</li>
   11.51 -</ul>
   11.52 -
   11.53 -<h3>Функции</h3>
   11.54 -
   11.55 -<ul>
   11.56 -  <li><code>&lt;%get:<em>имя</em>%&gt;</code><br />
   11.57 -  Заменяется на значение встроенной переменной или колонки запроса.</li>
   11.58 -
   11.59 -  <li><code>&lt;%optional:<em>текст</em>%&gt;</code><br />
   11.60 -  Заменяется на <em>текст</em>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.</li>
   11.61 -
   11.62 -  <li><code>&lt;%escape:<em>текст</em>%&gt;</code><br />
   11.63 -  Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).</li>
   11.64 -
   11.65 -  <li><code>&lt;%invoke:<em>имя</em>; <em>парам1</em> <em>парам2</em> ... <em>парамN</em>%&gt;</code><br />
   11.66 -  Выполняет запрос с параметрами <em>имя</em>.sql и заменяется на результаты обработки шаблона <em>имя</em>.template. Значения параметров подставляются в запрос вместо символа '?'.</li>
   11.67 -
   11.68 -  <li><code>&lt;%image:<em>исх_файл</em> <em>кон_файл</em> <em>формат</em> [<em>макс_ширина</em>] [<em>макс_высота</em>]%&gt;</code><br />
   11.69 -  Загружает изображение из файла <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <em>кон_файл</em>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены.
   11.70 -При успешном выполнении, инструкция <code>&lt;%image:...%&gt;</code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li>
   11.71 -
   11.72 -  <li><code>&lt;%copy:<em>исх_файл</em> <em>кон_файл</em>%&gt;</code><br />
   11.73 -  Копирует файл <em>исх_файл</em> (путь определяется относительно конфигурационного параметра "resource_base") в <em>кон_файл</em>. При успешном выполнении, инструкция <code>&lt;%copy:...%&gt;</code> будет заменена на значение <em>кон_файл</em>, иначе - на пустую строку.</li>
   11.74 -</ul>
   11.75 -
   11.76 -<h3>Встроенные переменные</h3>
   11.77 -
   11.78 -<p><code>NUMBER</code> - порядковый номер строки результата выполнения запроса.
   11.79 -Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить <code>SUPER.</code> (например: <code>SUPER.NUMBER</code>).</p>
   11.80 -
   11.81 -<h3>Пример</h3>
   11.82 -
   11.83 -<p>Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:</p>
   11.84 -<p><code>&lt;%escape get:name%&gt;</code></p>
   11.85 -
   11.86 -<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru">Михаил Крышень</a></i></p>
   11.87 -
   11.88 -</body>
   11.89 -</html>
    12.1 --- a/dist/readme.txt	Tue May 16 18:04:09 2006 +0400
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,63 +0,0 @@
    12.4 -text/plain; charset=UTF-8
    12.5 -
    12.6 -пёя│я┌п╟п╫п╬п╡п╨п╟ п©я─п╬пЁя─п╟п╪п╪я▀
    12.7 --------------------
    12.8 -
    12.9 -1. п═п╟я│п©п╟п╨п╬п╡п╟я┌я▄ п╟я─я┘п╦п╡.
   12.10 -
   12.11 -2. пёя│я┌п╟п╫п╬п╡п╦я┌я▄ п╦я│я┌п╬я┤п╫п╦п╨ п╢п╟п╫п╫я▀я┘:
   12.12 -п╡ Windows 2000: п÷п╟п╫п╣п╩я▄ я┐п©я─п╟п╡п╩п╣п╫п╦я▐/п░п╢п╪п╦п╫п╦я│я┌я─п╦я─п╬п╡п╟п╫п╦п╣/п≤я│я┌п╬я┤п╫п╦п╨п╦ п╢п╟п╫п╫я▀я┘ (ODBC), п╢п╬п╠п╟п╡п╦я┌я▄ biotopes.mdb.
   12.13 -
   12.14 -3. п²п╟я│я┌я─п╬п╦я┌я▄ п©я─п╬пЁя─п╟п╪п╪я┐:
   12.15 -п▓ я└п╟п╧п╩п╣ dbreader.properties я┐п╨п╟п╥п╟я┌я▄ п╦п╪я▐, п©я─п╦я│п╡п╬п╣п╫п╫п╬п╣ п╦я│я┌п╬я┤п╫п╦п╨я┐ п╢п╟п╫п╫я▀я┘:
   12.16 -    "resource: jdbc:odbc:<п╦п╪я▐>"
   12.17 -п╦ п©я┐я┌я▄ п╨ п╨п╟я┌п╟п╩п╬пЁя┐, п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬я┌п╬я─п╬пЁп╬ п©я─п╬пЁя─п╟п╪п╪п╟ п╠я┐п╢п╣я┌ п╦я│п╨п╟я┌я▄ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ (я│п╬п╢п╣я─п╤п╟я┴п╦п╧ biotopephotos п╦ maps):
   12.18 -    "resource_base: C:\\biotopes"
   12.19 -(я│п╦п╪п╡п╬п╩ '\' п╫п╣п╬п╠я┘п╬п╢п╦п╪п╬ п╢я┐п╠п╩п╦я─п╬п╡п╟я┌я▄)
   12.20 -
   12.21 -4. п≈п╟п©я┐я│п╨ п©я─п╬пЁя─п╟п╪п╪я▀: dbreader.bat п╦п╩п╦ "java -jar dbreader.jar"
   12.22 -п■п╩я▐ п╥п╟п©я┐я│п╨п╟ п╫п╣п╬п╠я┘п╬п╢п╦п╪п╟ Java Runtime Environment (JRE) 5.0, п╪п╬п╤п╫п╬ я│п╨п╟я┤п╟я┌я▄ я│ http://java.sun.com/j2se/1.5.0/download.jsp. п▓п╬п╥п╪п╬п╤п╫п╬, п╠я┐п╢п╣я┌ я─п╟п╠п╬я┌п╟я┌я▄ п╦ я│п╬ я│я┌п╟я─я▀п╪п╦ п╡п╣я─я│п╦я▐п╪п╦ JRE - п╫п╣ п©я─п╬п╡п╣я─я▐п╩.
   12.23 -
   12.24 -п▓я│п╣ п╥п╫п╟я┤п╣п╫п╦я▐ я└п╟п╧п╩п╟ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦ п╪п╬п╤п╫п╬ п©п╣я─п╣п╬п©я─п╣п╢п╣п╩я▐я┌я▄ п©я─п╦ п╥п╟п©я┐я│п╨п╣ п©я─п╬пЁя─п╟п╪п╪я▀:
   12.25 -    п╨п╬п╪п╟п╫п╢п╟ "java -Dru.karrc.dbreader.<п╨п╩я▌я┤>=<п╥п╫п╟я┤п╣п╫п╦п╣> -jar dbreader.jar"
   12.26 -(п╫п╟п©я─п╦п╪п╣я─: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar")
   12.27 -
   12.28 -
   12.29 -п═п╟п╠п╬я┌п╟ п©я─п╬пЁя─п╟п╪п╪я▀
   12.30 -----------------
   12.31 -
   12.32 -п÷я─п╬пЁя─п╟п╪п╪п╟ п╡я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ biotope.sql (п╦п╩п╦ п╢я─я┐пЁп╬п╧, я┐п╨п╟п╥п╟п╫п╫я▀п╧ п╡ dbreader.properties), п©п╬я│п╩п╣ я┤п╣пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ я└п╟п╧п╩ biotope.template, п╥п╟п╪п╣п╫я▐я▐ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╣п╪ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐.
   12.33 -
   12.34 -п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧: "<%я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧[:|\]п╢п╟п╫п╫я▀п╣%>", я│п©п╦я│п╬п╨ я└я┐п╫п╨я├п╦п╧ - п╦п╪п╣п╫п╟ я└я┐п╫п╨я├п╦п╧ я─п╟п╥п╢п╣п╩п╣п╫п╫я▀п╣ п©я─п╬п╠п╣п╩п╬п╪, я│п©п╦я│п╬п╨ п╪п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п∙я│п╩п╦ я┐п╨п╟п╥п╟п╫п╬ п╫п╣я│п╨п╬п╩я▄п╨п╬ я└я┐п╫п╨я├п╦п╧, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐ п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧.
   12.35 -
   12.36 -п═п╟п╥п╢п╣п╩п╦я┌п╣п╩п╦ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦:
   12.37 -':' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ я─п╣п╨я┐я─я│п╦п╡п╫п╬.
   12.38 -'\' - п╢п╟п╫п╫я▀п╣ п╠я┐п╢я┐я┌ п©п╣я─п╣п╢п╟п╫я▀ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦. п°п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ п╢п╩я▐ я█п╨я─п╟п╫п╦я─п╬п╡п╟п╫п╦я▐ п╨п╬п╪п╠п╦п╫п╟я├п╦п╧ я│п╦п╪п╡п╬п╩п╬п╡ "<%" п╦ "%>" ("<%\<%%>" п╦ "<%\%%>>").
   12.39 -
   12.40 -п╓я┐п╫п╨я├п╦п╦:
   12.41 -<%get:<п╦п╪я▐>%> - п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ п╡я│я┌я─п╬п╣п╫п╫п╬п╧ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╦п╩п╦ п╨п╬п╩п╬п╫п╨п╦ п╥п╟п©я─п╬я│п╟.
   12.42 -
   12.43 -<%optional:<я┌п╣п╨я│я┌>%>
   12.44 -п≈п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ <я┌п╣п╨я│я┌>, п╣я│п╩п╦ п╡ п╫п╣п╪ п╫п╟п╧п╢п╣п╫я▀ п╦п╫я│я┌я─я┐п╨я├п╦п╦, п╥п╟п╪п╣п╫п╦п╡я┬п╦п╣я│я▐ п╫п╟ п╫п╣п©я┐я│я┌я▀п╣ я│я┌я─п╬п╨п╦, п╦п╫п╟я┤п╣ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
   12.45 -
   12.46 -<%escape:<я┌п╣п╨я│я┌>%>
   12.47 -п≈п╟п╪п╣п╫я▐п╣я┌ п╡ я┌п╣п╨я│я┌п╣ "п╬п©п╟я│п╫я▀п╣" я│п╦п╪п╡п╬п╩я▀ (я┌п╟п╠п╩п╦я├п╟ п╥п╟п╪п╣п╫ п╥п╟п╢п╟п╣я┌я│я▐ п╡ я└п╟п╧п╩п╣ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╦).
   12.48 -
   12.49 -<%invoke:<п╦п╪я▐> <п©п╟я─п╟п╪1> <п©п╟я─п╟п╪2> ... <п©п╟я─п╟п╪N>%>
   12.50 -п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦ <п╦п╪я▐>.sql п╦ п╥п╟п╪п╣п╫я▐п╣я┌я│я▐ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <п╦п╪я▐>.template. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟ '?'.
   12.51 -
   12.52 -<%image:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩> <я└п╬я─п╪п╟я┌> [<п╪п╟п╨я│_я┬п╦я─п╦п╫п╟>] [<п╪п╟п╨я│_п╡я▀я│п╬я┌п╟>]%>
   12.53 -п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦ п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡ <п╨п╬п╫_я└п╟п╧п╩>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀.
   12.54 -п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!image ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
   12.55 -
   12.56 -<%copy:<п╦я│я┘_я└п╟п╧п╩> <п╨п╬п╫_я└п╟п╧п╩>%>
   12.57 -п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <п╦я│я┘_я└п╟п╧п╩> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base").
   12.58 -п÷я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п╦п╫я│я┌я─я┐п╨я├п╦я▐ "<%!copy ...%>" п╠я┐п╢п╣я┌ п╥п╟п╪п╣п╫п╣п╫п╟ п╫п╟ п╥п╫п╟я┤п╣п╫п╦п╣ <п╨п╬п╫_я└п╟п╧п╩>, п╦п╫п╟я┤п╣ - п╫п╟ п©я┐я│я┌я┐я▌ я│я┌я─п╬п╨я┐.
   12.59 -
   12.60 -п▓я│я┌я─п╬п╣п╫п╫я▀п╣ п©п╣я─п╣п╪п╣п╫п╫я▀п╣:
   12.61 -NUMBER - п©п╬я─я▐п╢п╨п╬п╡я▀п╧ п╫п╬п╪п╣я─ я│я┌я─п╬п╨п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ п╥п╟п©я─п╬я│п╟.
   12.62 -п╖я┌п╬п╠я▀ п╬п╠я─п╟я┌п╦я┌я▄я│я▐ п╨ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╥п╟п©я─п╬я│п╟, п╦п╥ п╨п╬я┌п╬я─п╬пЁп╬ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣п╪я▀п╧ я┬п╟п╠п╩п╬п╫ п╠я▀п╩ п╡я▀п╥п╡п╟п╫ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ invoke, п©п╣я─п╣п╢ п╦п╪п╣п╫п╣п╪ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ п╫я┐п╤п╫п╬ п╢п╬п╠п╟п╡п╦я┌я▄ "SUPER." (п╫п╟п©я─п╦п╪п╣я─: "SUPER.NUMBER").
   12.63 -
   12.64 -п÷я─п╦п╪п╣я─:
   12.65 -п║п╩п╣п╢я┐я▌я┴п╟я▐ п╦п╫я│я┌я─я┐п╨я├п╦я▐ п©п╬п╩я┐я┤п╦я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п╦п╥ я│я┌п╬п╩п╠я├п╟ name п╦ п╥п╟п╪п╣п╫п╦я┌ п╡ п╫п╣п╪ я│п©п╣я├п╦п╟п╩я▄п╫я▀п╣ я│п╦п╪п╡п╬п╩я▀:
   12.66 -<%escape get:name%>
    13.1 --- a/dist/tema	Tue May 16 18:04:09 2006 +0400
    13.2 +++ b/dist/tema	Thu Dec 14 23:22:05 2006 +0300
    13.3 @@ -1,3 +1,3 @@
    13.4  #!/bin/sh
    13.5  
    13.6 -java -jar tema.jar
    13.7 +java -jar tema.jar "$@"
    14.1 --- a/dist/tema.bat	Tue May 16 18:04:09 2006 +0400
    14.2 +++ b/dist/tema.bat	Thu Dec 14 23:22:05 2006 +0300
    14.3 @@ -1,1 +1,1 @@
    14.4 -java -jar tema.jar
    14.5 +java -jar tema.jar %1
    15.1 --- a/dist/tema.properties	Tue May 16 18:04:09 2006 +0400
    15.2 +++ b/dist/tema.properties	Thu Dec 14 23:22:05 2006 +0300
    15.3 @@ -9,14 +9,14 @@
    15.4  main_template     : main.template
    15.5  
    15.6  # File encodings
    15.7 -# input_encoding    : ISO-8859-5
    15.8 -# output_encoding   : ISO-8859-5
    15.9 +# input_encoding    : UTF-8
   15.10 +# output_encoding   : UTF-8
   15.11  
   15.12  # Cache templates
   15.13 -cache_read        : true
   15.14 +# cache_read        : true
   15.15  
   15.16  # Output main_template parsing result to stderr
   15.17 -#output            : stderr
   15.18 +# output            : stderr
   15.19  
   15.20  # File to output error messages (redirect stderr)
   15.21 -#log               : tema.log
   15.22 +# log               : tema.log
    16.1 --- a/doc/article.txt	Tue May 16 18:04:09 2006 +0400
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,391 +0,0 @@
    16.4 -* Преобразование базы данных в XML-формат электронной библиотеки.
    16.5 -
    16.6 -Для решения задачи преобразования базы данных "Местообитания Восточной
    16.7 -Фенноскандии" из формата Microsoft Access в XML-формат электронной
    16.8 -библиотеки КарНЦ РАН была разработана программная система DbReader.
    16.9 -
   16.10 -Программа DbReader является универсальным средством для представления
   16.11 -информации из баз данных в текстовых форматах. Программа обрабатывает
   16.12 -заданные шаблоны текстовых файлов и заменяет найденные в них
   16.13 -инструкции на результаты их выполнения. Различные инструкции позволяют
   16.14 -формировать SQL-запросы, выполнять их и обрабатывать полученные
   16.15 -данные.
   16.16 -
   16.17 -
   16.18 -* Формат инструкций:
   16.19 -
   16.20 -    <%<список_функций>{:|\}<данные>%>
   16.21 -  где 
   16.22 -
   16.23 -<список_функций> - список имен функций, разделенных пробелами.
   16.24 -    Может быть пустым.
   16.25 -<данные> - данные, передаваемые функции.
   16.26 -
   16.27 -
   16.28 -* Формат данных:
   16.29 -
   16.30 -    [<список_аргументов>][<текст>]
   16.31 -  где
   16.32 -
   16.33 -<список_аргументов> - список аргументов функции, разделенных пробелами.
   16.34 -    Может быть пустым.
   16.35 -<текст> - текст, передаваемый функции без разбиения на аргументы.
   16.36 -    Может быть пустым. Количество аргументов, после которого следует
   16.37 -    текст, зависит от функции.
   16.38 -
   16.39 -Разделитель между списком функций и данными определяет, как должны
   16.40 -обрабатываться данные функции:
   16.41 -: - рекурсивная обработка,
   16.42 -\ - передать без обработки.
   16.43 -
   16.44 -Если в списке функций задано две и более функции, они выполняются,
   16.45 -начиная с последней, так что каждая функция получает в качестве данных
   16.46 -результат выполнения следующей функции.
   16.47 -
   16.48 -Каждая функция имеет код возврата - целое число. Код возврата
   16.49 -инструкции - код возврата первой в списке функции. Код возврата,
   16.50 -получаемый при обработке текста - сумма кодов возврата обработанных
   16.51 -инструкций.
   16.52 -
   16.53 -Вместо скобок '<', '>' можно использовать скобки '[', ']'.
   16.54 -
   16.55 -
   16.56 -* Реализованные функции:
   16.57 -
   16.58 -Функция:      set
   16.59 -Аргументы:    <имя>
   16.60 -Текст:        <значение>
   16.61 -Действие:     устанавливает значение переменной <имя>
   16.62 -Результат:    <имя>
   16.63 -Код возврата: 1
   16.64 -
   16.65 -Функция:      get
   16.66 -Аргументы:    <имя>
   16.67 -Результат:    значение переменной <имя>. 
   16.68 -Код возврата: 1, если значение переменной было установлено, 0 - иначе.
   16.69 -
   16.70 -Функция:      prepare
   16.71 -Аргументы:    <имя>
   16.72 -Текст:        <запрос>
   16.73 -Действие:     Подготавливает SQL-запрос <запрос> для выполнения,
   16.74 -              записывает подготовленный запрос в переменную <имя>.
   16.75 -Результат:    <имя>
   16.76 -Код возврата: 1
   16.77 -
   16.78 -Функция:      query
   16.79 -Аргументы:    <имя_запроса> <шаблон> <парам1> ... <парамN>
   16.80 -Действие:     Выполняет запрос с параметрами, подготовленный с помощью
   16.81 -              функции prepare. Значения параметров подставляются в
   16.82 -              запрос вместо символа '?'. Значения полей ответа будут
   16.83 -              записаны, как переменные шаблона <шаблон>. При обработки
   16.84 -              шаблона <шаблон> также определяется переменная NUMBER,
   16.85 -              содержащая номер текущей строки ответа. Переменные,
   16.86 -              определенные в вызывающем шаблоне, доступны из шаблона
   16.87 -              <шаблон> по имени SUPER.<имя_переменной>.
   16.88 -
   16.89 -Результат:    результат обработки шаблона <шаблон> для каждой строки
   16.90 -              ответа.
   16.91 -Код возврата: количество полученных строк ответа.
   16.92 -
   16.93 -Функция:      optional
   16.94 -Текст:        <данные>
   16.95 -Результат:    <данные>, если при обработке данных был получен
   16.96 -              код возврата отличный от 0, иначе - пустая строка.
   16.97 -Код возврата: 1, если результат - пустая строка, 0 - иначе.
   16.98 -
   16.99 -Функция:      image
  16.100 -Аргументы:    <исх_файл> <кон_файл> <формат> [<макс_ширина> [<макс_высота>]]
  16.101 -Действие:     Загружает изображение из файла <исх_файл> (путь определяется
  16.102 -              относительно конфигурационного параметра "resource_base") и
  16.103 -              преобразует его в указанный формат, сохраняя результат в
  16.104 -              <кон_файл>. Если заданы максимальная высота и ширина, большие
  16.105 -              изображения будут уменьшены. 
  16.106 -Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
  16.107 -Код возврата: 1 при успешном выполнении, 0 - иначе.
  16.108 -
  16.109 -Функция:      copy
  16.110 -Аргументы:    <исх_файл> <кон_файл>
  16.111 -Действие:     Копирует файл <исх_файл> в файл <кон_файл>
  16.112 -	      (путь <исх_файл> определяется относительно
  16.113 -              конфигурационного параметра "resource_base").
  16.114 -Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
  16.115 -Код возврата: 1 при успешном выполнении, 0 - иначе.
  16.116 -
  16.117 -Функция:      write
  16.118 -Аргументы:    <имя_файла>
  16.119 -Текст:        <данные>
  16.120 -Действие:     Записывает <данные> в файл <исх_файл>.
  16.121 -Результат:    <кон_файл> при успешном выполнении, пустая строка - иначе.
  16.122 -Код возврата: 1 при успешном выполнении, 0 - иначе.
  16.123 -
  16.124 -Функция:      read
  16.125 -Текст:        <имя_файла>
  16.126 -Действие:     Читает файл <имя_файла>.
  16.127 -Результат:    прочитанные данные при успешном выполнении, пустая
  16.128 -              строка - иначе.
  16.129 -Код возврата: 1 при успешном выполнении, 0 - иначе.
  16.130 -
  16.131 -Функция:      include
  16.132 -Текст:        <имя_файла>
  16.133 -Действие:     включает шаблон из файла <имя_файла>.
  16.134 -Результат:    результат обработки шаблона.
  16.135 -Код возврата: код возврата, полученный при обработке шаблона.
  16.136 -
  16.137 -Функция:      !
  16.138 -Текст:        <данные>
  16.139 -Действие:     нет.
  16.140 -Результат:    нет.
  16.141 -Код возврата: код возврата, полученный при обработке текста данных.
  16.142 -
  16.143 -Функция:      replace
  16.144 -Аргументы:    <стр1> <стр2>
  16.145 -Текст:        <данные>
  16.146 -Результат:    данные, с замененными вхождениями подстроки <стр1>
  16.147 -	      на <стр2>.
  16.148 -Код возврата: код возврата, полученный при обработке текста данных.
  16.149 -
  16.150 -Функция:      xml_escape
  16.151 -Текст:        <данные>
  16.152 -Результат:    текст <данные>, в котором  символы
  16.153 -              '&', '<', '>', '`', '\' заменены на соответствующие
  16.154 -	      сущности XML.
  16.155 -Код возврата: код возврата, полученный при обработке текста данных.
  16.156 -
  16.157 -Функция:      xml_cdata
  16.158 -Текст:        <данные>
  16.159 -Результат:    данные в виде блока XML CDATA.
  16.160 -Код возврата: код возврата, полученный при обработке текста данных.
  16.161 -
  16.162 -Система DbReader расширяема: возможно добавление в систему новых
  16.163 -функций, реализованных в виде классов на языке Java.
  16.164 -
  16.165 -
  16.166 -* Применение системы DbReader для преобразования базы данных
  16.167 -  "Местообитания Восточной Фенноскандии" из формата Microsoft Access в
  16.168 -  XML-формат электронной библиотеки КарНЦ РАН
  16.169 -
  16.170 -Для преобразования используются две таблицы базы данных "Местообитания
  16.171 -Восточной Фенноскандии" (перечислены только используемые поля):
  16.172 -
  16.173 -biotopelist (code, rangcode, rusname, engname, descript, geobotdescr,
  16.174 -             contributors, descrdate)
  16.175 -
  16.176 -  code - счетчик, ключевое поле;
  16.177 -  rangcode - поле в формате ABBCCDDEE, где А, BB, CC, DD, ЕЕ - коды
  16.178 -             класса, подклассов и растения;
  16.179 -  rusname, engname, descript, geobotdescr - текстовые поля;
  16.180 -  descrdate - дата.
  16.181 -
  16.182 -photos (biotope, photo, authphoto)
  16.183 -
  16.184 -  biotope - число, указывает на code в biotopelist;
  16.185 -  photo - имя файла фотографии;
  16.186 -  authphoto - текст.
  16.187 -
  16.188 -Требуется сгенерировать xml-файл для каждой записи в biotopelist, файл
  16.189 -со списком классов, файл со списком растений, полноразмерные и
  16.190 -уменьшенные версии каждой фотографии.
  16.191 -
  16.192 -Для генерации xml-файлов с описаниями биотопов использовался следующий
  16.193 -шаблон DbReader (файл biotope.template):
  16.194 -
  16.195 -----------------------------------------------------------------------
  16.196 -<?xml version="1.0" encoding="ISO-8859-5"?>
  16.197 -<!DOCTYPE описание_вида SYSTEM "brief.dtd">
  16.198 -<!-- rangcode: <%xml_escape get\rangcode%> -->
  16.199 -<описание_вида show="0">
  16.200 -  <рисунки display="0">
  16.201 -    <%optional:<карта_распространения номер="1"
  16.202 -    file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%>
  16.203 -<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
  16.204 -  </рисунки>
  16.205 -  <название><%xml_escape get\rusname%></название>
  16.206 -  <класс><%xml_escape get\class0%></класс>
  16.207 -  <подкласс1><%xml_escape get\class1%></подкласс1>
  16.208 -  <подкласс2><%xml_escape get\class2%></подкласс2>
  16.209 -  <подкласс3><%xml_escape get\class3%></подкласс3>
  16.210 -  <краткая_характеристика rows="3"><%xml_cdata get\descript%></краткая_характеристика>
  16.211 -  <пример_описания rows="3"><%xml_cdata get\geobotdescr%></пример_описания>
  16.212 -  <авторы_описания><%xml_escape get\contributors%></авторы_описания>
  16.213 -</описание_вида>
  16.214 -----------------------------------------------------------------------
  16.215 -
  16.216 -Соответствующий SQL-запрос, при выполнении которого устанавливаются
  16.217 -значения переменных шаблона rangcode, rusname, class0, class1, class2,
  16.218 -class3, descript, geobotdescr и contributors (файл biotope.sql):
  16.219 -
  16.220 -----------------------------------------------------------------------
  16.221 -SELECT t1.*,
  16.222 -
  16.223 -(SELECT t2.rusname FROM biotopelist AS t2
  16.224 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  16.225 -AND Right(t2.rangcode, 8)  = '00000000'
  16.226 -AND Right(t1.rangcode, 8) <> '00000000') AS class0,
  16.227 -
  16.228 -(SELECT t2.rusname FROM biotopelist AS t2
  16.229 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
  16.230 -AND Right(t2.rangcode, 6)  = '000000'
  16.231 -AND Right(t1.rangcode, 6) <> '000000') AS class1,
  16.232 -
  16.233 -(SELECT t2.rusname FROM biotopelist AS t2
  16.234 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
  16.235 -AND Right(t2.rangcode, 4)  = '0000'
  16.236 -AND Right(t1.rangcode, 4) <> '0000') AS class2,
  16.237 -
  16.238 -(SELECT t2.rusname FROM biotopelist AS t2
  16.239 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
  16.240 -AND Right(t2.rangcode, 2)  = '00'
  16.241 -AND Right(t1.rangcode, 2) <> '00') AS class3
  16.242 -
  16.243 -FROM biotopelist AS t1
  16.244 -WHERE rusname
  16.245 -----------------------------------------------------------------------
  16.246 -
  16.247 -Шаблон biotope.template содержит инструкцию <%include\photo.template%>,
  16.248 -включающую шаблон описания фотографии (файл photo.template):
  16.249 -
  16.250 -----------------------------------------------------------------------
  16.251 -    <фотография num="<%xml_escape get\NUMBER%>"
  16.252 -       <%optional:автор="<%xml_escape get\authphoto%>" %>text="" 
  16.253 -       file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 
  16.254 -        big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
  16.255 -----------------------------------------------------------------------
  16.256 -
  16.257 -Соответствующий SQL-запрос для получения описания фотографий
  16.258 -(photo.sql):
  16.259 -
  16.260 -----------------------------------------------------------------------
  16.261 -SELECT * from photos WHERE biotope = ?
  16.262 -----------------------------------------------------------------------
  16.263 -
  16.264 -Шаблон, генерирующий список классов (файл classes.template):
  16.265 -
  16.266 -----------------------------------------------------------------------
  16.267 -<?xml version="1.0" encoding="ISO-8859-5"?>
  16.268 -<классификация><%query:class_sql [%\
  16.269 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
  16.270 -  <класс id="<%get\NUMBER%>"><%xml_escape get\rusname%></класс>%]%>
  16.271 -</классификация>
  16.272 -----------------------------------------------------------------------
  16.273 -
  16.274 -Соответствующий SQL-запрос (class.sql):
  16.275 -
  16.276 -----------------------------------------------------------------------
  16.277 -SELECT t1.*
  16.278 -FROM biotopelist AS t1
  16.279 -WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
  16.280 -  AND EXISTS
  16.281 -    (SELECT NULL FROM biotopelist AS t2
  16.282 -     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  16.283 -     AND Right(t2.rangcode, 8) <> '00000000')
  16.284 -----------------------------------------------------------------------
  16.285 -
  16.286 -Шаблон, генерирующий список растений (файл plants.template):
  16.287 -
  16.288 -----------------------------------------------------------------------
  16.289 -<?xml version="1.0" encoding="ISO-8859-5"?>
  16.290 -<растения><%query:plant_sql [%\
  16.291 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
  16.292 -  <растение><%xml_escape get\rusname%></растение>%]%>
  16.293 -</растения>
  16.294 -----------------------------------------------------------------------
  16.295 -
  16.296 -Соответствующий SQL-запрос (plant.sql):
  16.297 -
  16.298 -----------------------------------------------------------------------
  16.299 -SELECT t1.*
  16.300 -FROM biotopelist AS t1
  16.301 -WHERE rusname AND Right(t1.rangcode, 2) <> '00'
  16.302 -----------------------------------------------------------------------
  16.303 -
  16.304 -Система DbReader начинает работу с обработки шаблона index.template,
  16.305 -который содержит вызовы перечисленных выше SQL-запросов и включения
  16.306 -шаблонов:
  16.307 -
  16.308 -----------------------------------------------------------------------
  16.309 -<%!:
  16.310 -  <%prepare:biotope_sql <%read\biotope.sql%>%>
  16.311 -  <%prepare:photo_sql <%read\photo.sql%>%>
  16.312 -  <%prepare:class_sql <%read\class.sql%>%>
  16.313 -  <%prepare:plant_sql <%read\plant.sql%>%>
  16.314 -
  16.315 -  <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%>
  16.316 -
  16.317 -  <%write:classes.xml <%include\classes.template%>%>
  16.318 -  <%write:plants.xml <%include\plants.template%>%>
  16.319 -%>
  16.320 -----------------------------------------------------------------------
  16.321 -
  16.322 -Пример сгенерированного XML-файла:
  16.323 -
  16.324 -----------------------------------------------------------------------
  16.325 -<?xml version="1.0" encoding="ISO-8859-5"?>
  16.326 -<!DOCTYPE описание_вида SYSTEM "brief.dtd">
  16.327 -<!-- rangcode: E04020302 -->
  16.328 -<описание_вида show="0">
  16.329 -  <рисунки display="0">    
  16.330 -    <фотография num="1" автор="Крышень А.М." text="" 
  16.331 -                file="images/3_1.jpg" 
  16.332 -                big="images/big/3_1.jpg"/>
  16.333 -    <фотография num="2" автор="Крышень А.М." text="" 
  16.334 -                file="images/3_2.jpg" 
  16.335 -                big="images/big/3_2.jpg"/>
  16.336 -  </рисунки>
  16.337 -  <название>Betula sp. - Avenella flexuosa - Polytrichum commune</название>
  16.338 -  <класс>E. Суходольные местообитания</класс>
  16.339 -  <подкласс1>Автоморфные влажные</подкласс1>
  16.340 -  <подкласс2></подкласс2>
  16.341 -  <подкласс3></подкласс3>
  16.342 -  <краткая_характеристика rows="3"><![CDATA[Развиваются  на луговиковых вырубках лесов черничного типа.  Через 5 - 7 лет  после рубки порослевая береза выходит из  яруса травянистых растений, ее влияние сказывается, в первую очередь, на влажности почвы.]]></краткая_характеристика>
  16.343 -  <пример_описания rows="3"></пример_описания>
  16.344 -  <авторы_описания></авторы_описания>
  16.345 -</описание_вида>
  16.346 -----------------------------------------------------------------------
  16.347 -
  16.348 -
  16.349 -* Структура программы DbReader
  16.350 -
  16.351 -Программа DbReader написана на языке программирования Java и состоит
  16.352 -из следующих основных классов:
  16.353 -
  16.354 -ru.karrc.dbreader.DbReader: cодержит точку входа программы. Загружает
  16.355 -конфигурацию, устанавливает соединение с источником данных с помощью
  16.356 -библиотеки JDBC, запускает обработку основного шаблона.
  16.357 -
  16.358 -ru.karrc.dbreader.TemplateParser: осуществляет разбор шаблона,
  16.359 -обработку инструкций и вызов функций.
  16.360 -
  16.361 -ru.karrc.dbreader.Function: абстрактный класс. Реализации всех функций
  16.362 -DbReader наследуют этот класс.
  16.363 -
  16.364 -ru.karrc.dbreader.FunctionDataParser: обработчик данных
  16.365 -функции. Посволяет получить список аргументов и текст, передаваемый
  16.366 -функции. При необходимости вызывает рекурсивную обработку данных с
  16.367 -помощью TemplateParser.
  16.368 -
  16.369 -ru.karrc.dbreader.Functions: содержит реализации функций в виде
  16.370 -анонимных классов, наследующих Function.
  16.371 -
  16.372 -ru.karrc.dbreader.TemplateParser: исключение, выбрасываемое в случае
  16.373 -возникновения ошибки при обработке шаблона.
  16.374 -
  16.375 -Кроме того, реализовано несколько впомогательных классов, которые
  16.376 -используются в реализациях функций системы.
  16.377 -
  16.378 -
  16.379 -* Метрики реализованной программной системы.
  16.380 -
  16.381 -Количество файлов исходного кода: 8,
  16.382 -Количество Java-классов (включая анонимные): 27,
  16.383 -Общее количество строк исходного текста: 1311,
  16.384 -Количество строк кода (исключая пустые строки и комментарии): 812,
  16.385 -Количество строк комментариев: 180.
  16.386 -
  16.387 -
  16.388 -* Заключение
  16.389 -
  16.390 -Автором была разработана программная система DbReader, которая
  16.391 -является расширяемым и универсальным средством для представления
  16.392 -информации из баз данных в текстовых форматах. С помощью системы
  16.393 -DbReader база данных "Местообитания Восточной Фенноскандии" была
  16.394 -переведена в XML-формат электронной библиотеки КарНЦ РАН.
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/doc/manual/index.html	Thu Dec 14 23:22:05 2006 +0300
    17.3 @@ -0,0 +1,358 @@
    17.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    17.5 +          "DTD/xhtml1-transitional.dtd">
    17.6 +
    17.7 +<html>
    17.8 +
    17.9 +<head>
   17.10 +  <title>п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA</title>
   17.11 +  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   17.12 +</head>
   17.13 +
   17.14 +<body>
   17.15 +<h1>п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA</h1>
   17.16 +
   17.17 +п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌ п╥п╟п╢п╟п╫п╫я▀п╣ я┬п╟п╠п╩п╬п╫я▀ я┌п╣п╨я│я┌п╬п╡я▀я┘ я└п╟п╧п╩п╬п╡ п╦
   17.18 +п╥п╟п╪п╣п╫я▐п╣я┌ п╫п╟п╧п╢п╣п╫п╫я▀п╣ п╡ п╫п╦я┘ п╦п╫я│я┌я─я┐п╨я├п╦п╦ п╫п╟ я─п╣п╥я┐п╩я▄я┌п╟я┌я▀ п╦я┘ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐.
   17.19 +
   17.20 +<p><b>п╓п╬я─п╪п╟я┌ п╦п╫я│я┌я─я┐п╨я├п╦п╧</b></p>
   17.21 +
   17.22 +<blockquote>
   17.23 +  <code>&lt;%<i>я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧</i>{:|\|`}<i>п╢п╟п╫п╫я▀п╣</i>%&gt;</code>  
   17.24 +</blockquote>
   17.25 +<p>
   17.26 +пЁп╢п╣<br />
   17.27 +
   17.28 +<code><i>я│п©п╦я│п╬п╨_я└я┐п╫п╨я├п╦п╧</i></code> - я│п©п╦я│п╬п╨ п╦п╪п╣п╫ я└я┐п╫п╨я├п╦п╧, я─п╟п╥п╢п╣п╩п╣п╫п╫я▀я┘
   17.29 +    п©я─п╬п╠п╣п╩п╟п╪п╦. п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪.<br />
   17.30 +<code><i>п╢п╟п╫п╫я▀п╣</i></code> - п╢п╟п╫п╫я▀п╣, п©п╣я─п╣п╢п╟п╡п╟п╣п╪я▀п╣ я└я┐п╫п╨я├п╦п╦.
   17.31 +</p>
   17.32 +
   17.33 +<p><b>п╓п╬я─п╪п╟я┌ п╢п╟п╫п╫я▀я┘</b></p>
   17.34 +
   17.35 +<blockquote>
   17.36 +  <code>
   17.37 +    [<i>я│п©п╦я│п╬п╨_п╟я─пЁя┐п╪п╣п╫я┌п╬п╡</i>][<i>я┌п╣п╨я│я┌</i>]
   17.38 +  </code>
   17.39 +</blockquote>
   17.40 +<p>
   17.41 +пЁп╢п╣<br />
   17.42 +
   17.43 +<code><i>я│п©п╦я│п╬п╨_п╟я─пЁя┐п╪п╣п╫я┌п╬п╡</i></code> - я│п©п╦я│п╬п╨ п╟я─пЁя┐п╪п╣п╫я┌п╬п╡ я└я┐п╫п╨я├п╦п╦, я─п╟п╥п╢п╣п╩п╣п╫п╫я▀я┘ п©я─п╬п╠п╣п╩п╟п╪п╦.
   17.44 +    п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪.<br />
   17.45 +<code><i>я┌п╣п╨я│я┌</i></code> - я┌п╣п╨я│я┌, п©п╣я─п╣п╢п╟п╡п╟п╣п╪я▀п╧ я└я┐п╫п╨я├п╦п╦ п╠п╣п╥ я─п╟п╥п╠п╦п╣п╫п╦я▐ п╫п╟ п╟я─пЁя┐п╪п╣п╫я┌я▀.
   17.46 +    п°п╬п╤п╣я┌ п╠я▀я┌я▄ п©я┐я│я┌я▀п╪. п п╬п╩п╦я┤п╣я│я┌п╡п╬ п╟я─пЁя┐п╪п╣п╫я┌п╬п╡, п©п╬я│п╩п╣ п╨п╬я┌п╬я─п╬пЁп╬ я│п╩п╣п╢я┐п╣я┌
   17.47 +    я┌п╣п╨я│я┌, п╥п╟п╡п╦я│п╦я┌ п╬я┌ я└я┐п╫п╨я├п╦п╦.
   17.48 +</p><p>
   17.49 +п═п╟п╥п╢п╣п╩п╦я┌п╣п╩я▄ п╪п╣п╤п╢я┐ я│п©п╦я│п╨п╬п╪ я└я┐п╫п╨я├п╦п╧ п╦ п╢п╟п╫п╫я▀п╪п╦ п╬п©я─п╣п╢п╣п╩я▐п╣я┌, п╨п╟п╨ п╢п╬п╩п╤п╫я▀
   17.50 +п╬п╠я─п╟п╠п╟я┌я▀п╡п╟я┌я▄я│я▐ п╢п╟п╫п╫я▀п╣ я└я┐п╫п╨я├п╦п╦:
   17.51 +</p><p>
   17.52 +<code>:</code> - я─п╣п╨я┐я─я│п╦п╡п╫п╟я▐ п╬п╠я─п╟п╠п╬я┌п╨п╟,<br />
   17.53 +<code>\</code> п╦п╩п╦ <code>`</code> - п©п╣я─п╣п╢п╟я┌я▄ п╠п╣п╥ п╬п╠я─п╟п╠п╬я┌п╨п╦.
   17.54 +</p><p>
   17.55 +п∙я│п╩п╦ п╡ я│п©п╦я│п╨п╣ я└я┐п╫п╨я├п╦п╧ п╥п╟п╢п╟п╫п╬ п╢п╡п╣ п╦ п╠п╬п╩п╣п╣ я└я┐п╫п╨я├п╦п╦, п╬п╫п╦ п╡я▀п©п╬п╩п╫я▐я▌я┌я│я▐,
   17.56 +п╫п╟я┤п╦п╫п╟я▐ я│ п©п╬я│п╩п╣п╢п╫п╣п╧, я┌п╟п╨ я┤я┌п╬ п╨п╟п╤п╢п╟я▐ я└я┐п╫п╨я├п╦я▐ п©п╬п╩я┐я┤п╟п╣я┌ п╡ п╨п╟я┤п╣я│я┌п╡п╣ п╢п╟п╫п╫я▀я┘
   17.57 +я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐ я│п╩п╣п╢я┐я▌я┴п╣п╧ я└я┐п╫п╨я├п╦п╦.
   17.58 +</p><p>
   17.59 +п п╟п╤п╢п╟я▐ я└я┐п╫п╨я├п╦я▐ п╦п╪п╣п╣я┌ п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ - я├п╣п╩п╬п╣ я┤п╦я│п╩п╬. п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟
   17.60 +п╦п╫я│я┌я─я┐п╨я├п╦п╦ - п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ п©п╣я─п╡п╬п╧ п╡ я│п©п╦я│п╨п╣ я└я┐п╫п╨я├п╦п╦. п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟,
   17.61 +п©п╬п╩я┐я┤п╟п╣п╪я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ я┌п╣п╨я│я┌п╟ - я│я┐п╪п╪п╟ п╨п╬п╢п╬п╡ п╡п╬п╥п╡я─п╟я┌п╟ п╬п╠я─п╟п╠п╬я┌п╟п╫п╫я▀я┘
   17.62 +п╦п╫я│я┌я─я┐п╨я├п╦п╧ (п╨п╟п╨ п©я─п╟п╡п╦п╩п╬, я│п╪я▀я│п╩ я█я┌п╬пЁп╬ п╥п╫п╟я┤п╣п╫п╦я▐ - п╨п╬п╩п╦я┤п╣я│я┌п╡п╬ п╦п╫я│я┌я─я┐п╨я├п╦п╧,
   17.63 +п╥п╟п╪п╣п╫п╣п╫п╫я▀я┘ п╫п╟ п╫п╣п©я┐я│я┌п╬п╧ я┌п╣п╨я│я┌).
   17.64 +</p><p>
   17.65 +п я─п╬п╪п╣ я│п╨п╬п╠п╬п╨ '&lt;', '&gt;', п╪п╬п╤п╫п╬ п╦я│п©п╬п╩я▄п╥п╬п╡п╟я┌я▄ я│п╨п╬п╠п╨п╦ '[', ']'.
   17.66 +</p>
   17.67 +
   17.68 +
   17.69 +<h2>п╓я┐п╫п╨я├п╦п╦</h2>
   17.70 +
   17.71 +<p><code><b>set</b></code></p>
   17.72 +
   17.73 +<table>
   17.74 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
   17.75 +<td><i>п╦п╪я▐</i></td></tr>
   17.76 +
   17.77 +<tr><td>п╒п╣п╨я│я┌:</td>
   17.78 +<td><i>п╥п╫п╟я┤п╣п╫п╦п╣</i></td></tr>
   17.79 +
   17.80 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td>
   17.81 +<td>пёя│я┌п╟п╫п╟п╡п╩п╦п╡п╟п╣я┌ п╥п╫п╟я┤п╣п╫п╦п╣ п©п╣я─п╣п╪п╣п╫п╫п╬п╧ <i>п╦п╪я▐</i>.</td></tr>
   17.82 +
   17.83 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
   17.84 +<td><i>п╦п╪я▐</i></td></tr>
   17.85 +
   17.86 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
   17.87 +<td>1</td></tr>
   17.88 +</table>
   17.89 +
   17.90 +<p><code><b>define</b></code></p>
   17.91 +
   17.92 +<table>
   17.93 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
   17.94 +<td><i>п╦п╪я▐</i></td></tr>
   17.95 +
   17.96 +<tr><td>п╒п╣п╨я│я┌:</td>
   17.97 +<td><i>я┬п╟п╠п╩п╬п╫</i></td></tr>
   17.98 +
   17.99 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п·п©я─п╣п╢п╣п╩я▐п╣я┌ п╫п╬п╡я┐я▌ я└я┐п╫п╨я├п╦я▌ <i>п╦п╪я▐</i>, п©я─п╦
  17.100 +п╡я▀п╥п╬п╡п╣ п╨п╬я┌п╬я─п╬п╧ п╬п╠я─п╟п╠п╟я┌я▀п╡п╟п╣я┌я│я▐ <i>я┬п╟п╠п╩п╬п╫</i>. п÷я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ п╢п╬я│я┌я┐п©п╫я▀
  17.101 +я└я┐п╫п╨я├п╦п╦ <code>nextarg</code> п╢п╩я▐ п©п╬п╩я┐я┤п╣п╫п╦я▐ п╬я┤п╣я─п╣п╢п╫п╬пЁп╬ п╟я─пЁя┐п╪п╣п╫я┌п╟
  17.102 +п╡я▀п╥я▀п╡п╟п╣п╪п╬п╧ я└я┐п╫п╨я├п╦п╦ п╦ <code>data</code> п╢п╩я▐ п©п╬п╩я┐я┤п╣п╫п╦я▐ я┌п╣п╨я│я┌п╟.</td></tr>
  17.103 +
  17.104 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
  17.105 +<td><i>п╦п╪я▐</i></td></tr>
  17.106 +
  17.107 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.108 +<td>1</td></tr>
  17.109 +</table>
  17.110 +
  17.111 +<p><code><b>load</b></code></p>
  17.112 +
  17.113 +<table>
  17.114 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
  17.115 +<td><i>п╦п╪я▐</i> <i>п╦п╪я▐_п╨п╩п╟я│я│п╟</i></td></tr>
  17.116 +
  17.117 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td>
  17.118 +
  17.119 +<td>п·п©я─п╣п╢п╣п╩я▐п╣я┌ п╫п╬п╡я┐я▌ я└я┐п╫п╨я├п╦я▌ <i>п╦п╪я▐</i>. п═п╣п╟п╩п╦п╥п╟я├п╦я▐ я└я┐п╫п╨я├п╦п╦ п╬п©я─п╣п╢п╣п╩п╣п╫п╟
  17.120 +Java-п╨п╩п╟я│я│п╬п╪ <i>п╦п╪я▐_п╨п╩п╟я│я│п╟</i>, п╫п╟я│п╩п╣п╢я┐я▌я┴п╦п╪ п╨п╩п╟я│я│
  17.121 +<code>kryshen.tema.Function</code>.</td></tr>
  17.122 +
  17.123 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
  17.124 +<td><i>п╦п╪я▐</i></td></tr>
  17.125 +
  17.126 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.127 +<td>1</td></tr>
  17.128 +</table>
  17.129 +
  17.130 +<p><code><b>prepare</b></code></p>
  17.131 +
  17.132 +<table>
  17.133 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
  17.134 +<td><i>п╦п╪я▐</i></td></tr>
  17.135 +
  17.136 +<tr><td>п╒п╣п╨я│я┌:</td>
  17.137 +<td><i>п╥п╟п©я─п╬я│</i></td></tr>
  17.138 +
  17.139 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td>
  17.140 +<td>п÷п╬п╢пЁп╬я┌п╟п╡п╩п╦п╡п╟п╣я┌ SQL-п╥п╟п©я─п╬я│ <i>п╥п╟п©я─п╬я│</i> п╢п╩я▐ п╡я▀п©п╬п╩п╫п╣п╫п╦я▐, п╥п╟п©п╦я│я▀п╡п╟п╣я┌
  17.141 +п©п╬п╢пЁп╬я┌п╬п╡п╩п╣п╫п╫я▀п╧ п╥п╟п©я─п╬я│ п╡ п©п╣я─п╣п╪п╣п╫п╫я┐я▌ <i>п╦п╪я▐</i>.</td></tr>
  17.142 +
  17.143 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
  17.144 +<td><i>п╦п╪я▐</i></td></tr>
  17.145 +
  17.146 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.147 +<td>1</td></tr>
  17.148 +</table>
  17.149 +
  17.150 +<p><code><b>query</b></code></p>
  17.151 +
  17.152 +<table>
  17.153 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
  17.154 +<td><i>п╦п╪я▐_п╥п╟п©я─п╬я│п╟</i> <i>я┬п╟п╠п╩п╬п╫</i> <i>п©п╟я─п╟п╪1</i> ... <i>п©п╟я─п╟п╪N</i></td></tr>
  17.155 +
  17.156 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td>
  17.157 +<td>п▓я▀п©п╬п╩п╫я▐п╣я┌ п╥п╟п©я─п╬я│ я│ п©п╟я─п╟п╪п╣я┌я─п╟п╪п╦, п©п╬п╢пЁп╬я┌п╬п╡п╩п╣п╫п╫я▀п╧ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦
  17.158 +prepare. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╟я─п╟п╪п╣я┌я─п╬п╡ п©п╬п╢я│я┌п╟п╡п╩я▐я▌я┌я│я▐ п╡ п╥п╟п©я─п╬я│ п╡п╪п╣я│я┌п╬ я│п╦п╪п╡п╬п╩п╟
  17.159 +'?'. п≈п╫п╟я┤п╣п╫п╦я▐ п©п╬п╩п╣п╧ п╬я┌п╡п╣я┌п╟ п╢п╬я│я┌я┐п©п╫я▀ я│ п©п╬п╪п╬я┴я▄я▌ я└я┐п╫п╨я├п╦п╦ <code>db</code>,
  17.160 +п╨п╟п╨ п©п╣я─п╣п╪п╣п╫п╫я▀п╣ я┬п╟п╠п╩п╬п╫п╟ <i>я┬п╟п╠п╩п╬п╫</i>. п÷я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ я┌п╟п╨п╤п╣
  17.161 +п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п©п╣я─п╣п╪п╣п╫п╫п╟я▐ <code>number</code>, я│п╬п╢п╣я─п╤п╟я┴п╟я▐ п╫п╬п╪п╣я─ я┌п╣п╨я┐я┴п╣п╧
  17.162 +я│я┌я─п╬п╨п╦ п╬я┌п╡п╣я┌п╟.</td></tr>
  17.163 +
  17.164 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
  17.165 +<td>я─п╣п╥я┐п╩я▄я┌п╟я┌ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟ <i>я┬п╟п╠п╩п╬п╫</i> п╢п╩я▐ п╨п╟п╤п╢п╬п╧ я│я┌я─п╬п╨п╦
  17.166 +п╬я┌п╡п╣я┌п╟.</td></tr>
  17.167 +
  17.168 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.169 +<td>п п╬п╩п╦я┤п╣я│я┌п╡п╬ п©п╬п╩я┐я┤п╣п╫п╫я▀я┘ я│я┌я─п╬п╨ п╬я┌п╡п╣я┌п╟.</td></tr>
  17.170 +</table>
  17.171 +
  17.172 +<p><code><b>optional</b></code></p>
  17.173 +
  17.174 +<table>
  17.175 +<tr><td>п╒п╣п╨я│я┌:</td>
  17.176 +<td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.177 +
  17.178 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i>, п╣я│п╩п╦ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣ п╢п╟п╫п╫я▀я┘
  17.179 +п╠я▀п╩ п©п╬п╩я┐я┤п╣п╫ п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟ п╬я┌п╩п╦я┤п╫я▀п╧ п╬я┌ 0, п╦п╫п╟я┤п╣ - п©я┐я│я┌п╟я▐
  17.180 +я│я┌я─п╬п╨п╟.</td></tr>
  17.181 +
  17.182 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.183 +<td>1, п╣я│п╩п╦ я─п╣п╥я┐п╩я▄я┌п╟я┌ - п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟, 0 - п╦п╫п╟я┤п╣.</td></tr>
  17.184 +</table>
  17.185 +
  17.186 +<p><code><b>image</b></code></p>
  17.187 +
  17.188 +<table>
  17.189 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td>
  17.190 +<td><i>п╦я│я┘_я└п╟п╧п╩</i> <i>п╨п╬п╫_я└п╟п╧п╩</i> <i>я└п╬я─п╪п╟я┌</i> [<i>п╪п╟п╨я│_я┬п╦я─п╦п╫п╟</i>
  17.191 +[<i>п╪п╟п╨я│_п╡я▀я│п╬я┌п╟</i>]]</td></tr>
  17.192 +
  17.193 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td>
  17.194 +<td>п≈п╟пЁя─я┐п╤п╟п╣я┌ п╦п╥п╬п╠я─п╟п╤п╣п╫п╦п╣ п╦п╥ я└п╟п╧п╩п╟ <i>п╦я│я┘_я└п╟п╧п╩</i> (п©я┐я┌я▄ п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐
  17.195 +п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬ п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base") п╦
  17.196 +п©я─п╣п╬п╠я─п╟п╥я┐п╣я┌ п╣пЁп╬ п╡ я┐п╨п╟п╥п╟п╫п╫я▀п╧ я└п╬я─п╪п╟я┌, я│п╬я┘я─п╟п╫я▐я▐ я─п╣п╥я┐п╩я▄я┌п╟я┌ п╡
  17.197 +<i>п╨п╬п╫_я└п╟п╧п╩</i>. п∙я│п╩п╦ п╥п╟п╢п╟п╫я▀ п╪п╟п╨я│п╦п╪п╟п╩я▄п╫п╟я▐ п╡я▀я│п╬я┌п╟ п╦ я┬п╦я─п╦п╫п╟, п╠п╬п╩я▄я┬п╦п╣
  17.198 +п╦п╥п╬п╠я─п╟п╤п╣п╫п╦я▐ п╠я┐п╢я┐я┌ я┐п╪п╣п╫я▄я┬п╣п╫я▀.</td></tr>
  17.199 +
  17.200 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td>
  17.201 +<td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr>
  17.202 +
  17.203 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td>
  17.204 +<td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 - п╦п╫п╟я┤п╣.</td></tr>
  17.205 +</table>
  17.206 +
  17.207 +
  17.208 +<p><code><b>copy</b></code></p>
  17.209 +
  17.210 +<table>
  17.211 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>п╦я│я┘_я└п╟п╧п╩</i> <i>п╨п╬п╫_я└п╟п╧п╩</i></td></tr>
  17.212 +
  17.213 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п п╬п©п╦я─я┐п╣я┌ я└п╟п╧п╩ <i>п╦я│я┘_я└п╟п╧п╩</i> п╡ я└п╟п╧п╩
  17.214 +<i>п╨п╬п╫_я└п╟п╧п╩</i> (п©я┐я┌я▄ <i>п╦я│я┘_я└п╟п╧п╩</i> п╬п©я─п╣п╢п╣п╩я▐п╣я┌я│я▐ п╬я┌п╫п╬я│п╦я┌п╣п╩я▄п╫п╬
  17.215 +п╨п╬п╫я└п╦пЁя┐я─п╟я├п╦п╬п╫п╫п╬пЁп╬ п©п╟я─п╟п╪п╣я┌я─п╟ "resource_base").</td></tr>
  17.216 +
  17.217 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦,
  17.218 +п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr>
  17.219 +
  17.220 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 -
  17.221 +п╦п╫п╟я┤п╣.</td></tr>
  17.222 +</table>
  17.223 +
  17.224 +<p><code><b>write</b></code></p>
  17.225 +
  17.226 +<table>
  17.227 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr>
  17.228 +
  17.229 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.230 +
  17.231 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п≈п╟п©п╦я│я▀п╡п╟п╣я┌ <i>п╢п╟п╫п╫я▀п╣</i> п╡ я└п╟п╧п╩
  17.232 +<i>п╦я│я┘_я└п╟п╧п╩</i>.</td></tr>
  17.233 +
  17.234 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td><i>п╨п╬п╫_я└п╟п╧п╩</i> п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦,
  17.235 +п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr>
  17.236 +
  17.237 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 -
  17.238 +п╦п╫п╟я┤п╣.</td></tr>
  17.239 +</table>
  17.240 +
  17.241 +<p><code><b>read</b></code></p>
  17.242 +
  17.243 +<table>
  17.244 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr>
  17.245 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╖п╦я┌п╟п╣я┌ я└п╟п╧п╩ <i>п╦п╪я▐_я└п╟п╧п╩п╟</i>.</td></tr>
  17.246 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п©я─п╬я┤п╦я┌п╟п╫п╫я▀п╣ п╢п╟п╫п╫я▀п╣ п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦,
  17.247 +  п©я┐я│я┌п╟я▐ я│я┌я─п╬п╨п╟ - п╦п╫п╟я┤п╣.</td></tr>
  17.248 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>1 п©я─п╦ я┐я│п©п╣я┬п╫п╬п╪ п╡я▀п©п╬п╩п╫п╣п╫п╦п╦, 0 -
  17.249 +п╦п╫п╟я┤п╣.</td></tr>
  17.250 +</table>
  17.251 +
  17.252 +<p><code><b>include</b></code></p>
  17.253 +
  17.254 +<table>
  17.255 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╦п╪я▐_я└п╟п╧п╩п╟</i></td></tr>
  17.256 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╡п╨п╩я▌я┤п╟п╣я┌ я┬п╟п╠п╩п╬п╫ п╦п╥ я└п╟п╧п╩п╟
  17.257 +<i>п╦п╪я▐_я└п╟п╧п╩п╟</i>.</td></tr>
  17.258 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>я─п╣п╥я┐п╩я▄я┌п╟я┌ п╬п╠я─п╟п╠п╬я┌п╨п╦ я┬п╟п╠п╩п╬п╫п╟.</td></tr>
  17.259 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣
  17.260 +я┬п╟п╠п╩п╬п╫п╟.</td></tr>
  17.261 +</table>
  17.262 +
  17.263 +<p><code><b>!</b></code></p>
  17.264 +
  17.265 +<table>
  17.266 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.267 +
  17.268 +<tr><td>п■п╣п╧я│я┌п╡п╦п╣:</td><td>п╫п╣я┌.</td></tr>
  17.269 +
  17.270 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╫п╣я┌.</td></tr>
  17.271 +
  17.272 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td>п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣
  17.273 +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr>
  17.274 +</table>
  17.275 +
  17.276 +<p><code><b>replace</b></code></p>
  17.277 +
  17.278 +<table>
  17.279 +<tr><td>п░я─пЁя┐п╪п╣п╫я┌я▀:</td><td><i>я│я┌я─1</i> <i>я│я┌я─2</i></td></tr>
  17.280 +
  17.281 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.282 +
  17.283 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╢п╟п╫п╫я▀п╣, я│ п╥п╟п╪п╣п╫п╣п╫п╫я▀п╪п╦ п╡я┘п╬п╤п╢п╣п╫п╦я▐п╪п╦ п©п╬п╢я│я┌я─п╬п╨п╦
  17.284 +<i>я│я┌я─1</i> п╫п╟ <i>я│я┌я─2</i>.</td></tr>
  17.285 +
  17.286 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣
  17.287 +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr>
  17.288 +</table>
  17.289 +
  17.290 +<p><code><b>xml_escape</b></code></p>
  17.291 +
  17.292 +<table>
  17.293 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.294 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>я┌п╣п╨я│я┌ <i>п╢п╟п╫п╫я▀п╣</i>, п╡ п╨п╬я┌п╬я─п╬п╪ я│п╦п╪п╡п╬п╩я▀
  17.295 +'&amp;', '&lt;', '&gt;', '`', '\' п╥п╟п╪п╣п╫п╣п╫я▀ п╫п╟ я│п╬п╬я┌п╡п╣я┌я│я┌п╡я┐я▌я┴п╦п╣ я│я┐я┴п╫п╬я│я┌п╦
  17.296 +XML.</td></tr>
  17.297 +
  17.298 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣
  17.299 +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.</td></tr>
  17.300 +</table>
  17.301 +
  17.302 +<p><code><b>xml_cdata</b></code></p>
  17.303 +
  17.304 +<table>
  17.305 +<tr><td>п╒п╣п╨я│я┌:</td><td><i>п╢п╟п╫п╫я▀п╣</i></td></tr>
  17.306 +
  17.307 +<tr><td>п═п╣п╥я┐п╩я▄я┌п╟я┌:</td><td>п╢п╟п╫п╫я▀п╣ п╡ п╡п╦п╢п╣ п╠п╩п╬п╨п╟ XML CDATA.</td></tr>
  17.308 +
  17.309 +<tr><td>п п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟:</td><td> п╨п╬п╢ п╡п╬п╥п╡я─п╟я┌п╟, п©п╬п╩я┐я┤п╣п╫п╫я▀п╧ п©я─п╦ п╬п╠я─п╟п╠п╬я┌п╨п╣
  17.310 +я┌п╣п╨я│я┌п╟ п╢п╟п╫п╫я▀я┘.  </td></tr>
  17.311 +</table>
  17.312 +
  17.313 +<p>
  17.314 +п°п╟п╨я─п╬п©я─п╬я├п╣я│я│п╬я─ TEMA я─п╟я│я┬п╦я─я▐п╣п╪: п╡п╬п╥п╪п╬п╤п╫п╬ п╢п╬п╠п╟п╡п╩п╣п╫п╦п╣ п╡ я│п╦я│я┌п╣п╪я┐ п╫п╬п╡я▀я┘
  17.315 +я└я┐п╫п╨я├п╦п╧, я─п╣п╟п╩п╦п╥п╬п╡п╟п╫п╫я▀я┘ п╡ п╡п╦п╢п╣ п╨п╩п╟я│я│п╬п╡ п╫п╟ я▐п╥я▀п╨п╣ Java.
  17.316 +</p>
  17.317 +
  17.318 +<h2>п≈п╟п©я┐я│п╨</h2>
  17.319 +
  17.320 +<p>java -jar tema.jar [<i>п╬п©я├п╦п╦</i>]
  17.321 +</p><p>
  17.322 +п·п©я├п╦п╦:
  17.323 +</p>
  17.324 +<table>
  17.325 +<tr><td>-d[emo]</td><td>п■п╣п╪п╬п╫я│я┌я─п╟я├п╦п╬п╫п╫я▀п╧ я─п╣п╤п╦п╪</td></tr>
  17.326 +<tr><td>-v[ersion]</td><td>п▓я▀п╡п╬п╢ п╡п╣я─я│п╦п╦</td></tr>
  17.327 +<tr><td>-h[help] -u[sage]</td><td>п▓я▀п╡п╬п╢ я│п©я─п╟п╡п╨п╦</td></tr>
  17.328 +</table>
  17.329 +
  17.330 +<p>
  17.331 +п÷я─п╦ п╥п╟п©я┐я│п╨п╣ я┤п╦я┌п╟п╣я┌я│я▐ я└п╟п╧п╩ "tema.properties" п╦п╥ я┌п╣п╨я┐я┴п╣пЁп╬ п╨п╟я┌п╟п╩п╬пЁп╟.<br />
  17.332 +п÷я─п╦п╪п╣я─ я└п╟п╧п╩п╟ "tema.properties":
  17.333 +</p>
  17.334 +
  17.335 +<pre>
  17.336 +# п²п╟я│я┌я─п╬п╧п╨п╟ п╦я│я┌п╬я┤п╫п╦п╨п╟ п╢п╟п╫п╫я▀я┘
  17.337 +# resource          : jdbc:odbc:database
  17.338 +# driver            : sun.jdbc.odbc.JdbcOdbcDriver
  17.339 +
  17.340 +# п▒п╟п╥п╬п╡я▀п╧ п╨п╟я┌п╟п╩п╬пЁ я─п╣я│я┐я─я│п╬п╡
  17.341 +# resource_base     : .
  17.342 +
  17.343 +# п╗п╟п╠п╩п╬п╫, я│ п╨п╬я┌п╬я─п╬пЁп╬ п╫п╟я┤п╦п╫п╟п╣я┌я│я▐ п╬п╠я─п╟п╠п╬я┌п╨п╟
  17.344 +main_template     : main.template
  17.345 +
  17.346 +# п п╬п╢п╦я─п╬п╡п╨п╦ я└п╟п╧п╩п╬п╡
  17.347 +# input_encoding    : UTF-8
  17.348 +# output_encoding   : UTF-8
  17.349 +
  17.350 +# п я█я┬п╦я─п╬п╡п╟п╫п╦п╣ я┬п╟п╠п╩п╬п╫п╬п╡
  17.351 +# cache_read        : true
  17.352 +
  17.353 +# п▓я▀п╡п╬п╢ я─п╣п╥я┐п╩я▄я┌п╟я┌п╟ я─п╟п╥п╠п╬я─п╟ я┬п╟п╠п╩п╬п╫п╟ main.template п╡ stderr
  17.354 +# output            : stderr
  17.355 +
  17.356 +# п▓я▀п╡п╬п╢ я│п╬п╬п╠я┴п╣п╫п╦п╧ п╬п╠ п╬я┬п╦п╠п╨п╟я┘ п╡ я└п╟п╧п╩
  17.357 +# log               : dbreader.log
  17.358 +</pre>
  17.359 +
  17.360 +</body>
  17.361 +</html>
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/res/kryshen/tema/demo/demo.template	Thu Dec 14 23:22:05 2006 +0300
    18.3 @@ -0,0 +1,25 @@
    18.4 +[%!\ TEMA demo template %]
    18.5 +
    18.6 +п▓я▀п╡п╬п╢ я┌п╣п╨я│я┌п╟:
    18.7 +test text
    18.8 +
    18.9 +п▓я▀п╡п╬п╢ я│п©п╣я├п╦п╟п╩я▄п╫я▀я┘ я│п╦п╪п╡п╬п╩п╬п╡:
   18.10 +[%\<%test%>%]
   18.11 +
   18.12 +п·п╠я┼я▐п╡п╩п╣п╫п╦п╣ я└я┐п╫п╨я├п╦п╦:
   18.13 +<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%>   
   18.14 +
   18.15 +п▓я▀п╥п╬п╡ п╫п╬п╡п╬п╧ я└я┐п╫п╨я├п╦п╦:
   18.16 +<%test:1 2 3%>
   18.17 +
   18.18 +п≈п╟пЁя─я┐п╥п╨п╟ я└я┐п╫п╨я├п╦п╦ п╦п╥ п╨п╩п╟я│я│п╟:
   18.19 +<%load\hello kryshen.tema.demo.Hello%>
   18.20 +
   18.21 +п▓я▀п©п╬п╩п╣п╫п╣п╫п╦п╣ п╥п╟пЁя─я┐п╤п╣п╫п╫п╬п╧ я└я┐п╫п╨я├п╦п╦:
   18.22 +<%hello\TEMA%>
   18.23 +
   18.24 +пёя│п╩п╬п╡п╫п╬п╣ п╡я▀п©п╬п╩п╫п╣п╫п╦п╣:
   18.25 +<%optional:<%true:%>True%> <%optional:<%false:%>False%>
   18.26 +
   18.27 +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ xml_escape:
   18.28 +<%xml_escape\x < a & b%>
    19.1 --- a/sample/class.xml	Tue May 16 18:04:09 2006 +0400
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,9 +0,0 @@
    19.4 -<?xml version="1.0" encoding="ISO-8859-5"?>
    19.5 -<зшпААьДьзпФьО>
    19.6 -  <зшпАА id="1">╟щБЮчъчсущщКу эуАБччяьБпщьО</зшпАА>
    19.7 -  <зшпАА id="2">╪чЮО ь эчЮАзьу ъчяуЮужЛО</зшпАА>
    19.8 -  <зшпАА id="3">╬вуЮп ь ъЮьяЮужщКу эуАБччяьБпщьО</зшпАА>
    19.9 -  <зшпАА id="4">юузь, ЮЦГЛь ь ъЮьяЮужщКу эуАБччяьБпщьО</зшпАА>
   19.10 -  <зшпАА id="5">╠чшчБп ь впячшчГущщКу вуэшь</зшпАА>
   19.11 -  <зшпАА id="6">аЦЕчтчшЛщКу эуАБччяьБпщьО</зшпАА>
   19.12 -</зшпААьДьзпФьО>
    20.1 --- a/sample/plants.xml	Tue May 16 18:04:09 2006 +0400
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,6 +0,0 @@
    20.4 -<?xml version="1.0" encoding="ISO-8859-5"?>
    20.5 -<ЮпАБущьО>
    20.6 -  <ЮпАБущьу>Betula sp.</ЮпАБущьу>
    20.7 -  <ЮпАБущьу>Calamagrostis arundinacea</ЮпАБущьу>
    20.8 -  <ЮпАБущьу>Geranium sylvaticum</ЮпАБущьу>
    20.9 -</ЮпАБущьО>
    21.1 --- a/src/kryshen/tema/Function.java	Tue May 16 18:04:09 2006 +0400
    21.2 +++ b/src/kryshen/tema/Function.java	Thu Dec 14 23:22:05 2006 +0300
    21.3 @@ -1,7 +1,21 @@
    21.4  /*
    21.5 - * Copyright (C) 2005, 2006 Mikhail A. Kryshen
    21.6 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    21.7   *
    21.8 - * $Id: Function.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    21.9 + *  This program is free software; you can redistribute it and/or modify
   21.10 + *  it under the terms of the GNU General Public License as published by
   21.11 + *  the Free Software Foundation; either version 2 of the License, or
   21.12 + *  (at your option) any later version.
   21.13 + *
   21.14 + *  This program is distributed in the hope that it will be useful,
   21.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.17 + *  GNU General Public License for more details.
   21.18 + *
   21.19 + *  You should have received a copy of the GNU General Public License
   21.20 + *  along with this program; if not, write to the Free Software
   21.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21.22 + *
   21.23 + *  $Id: Function.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   21.24   */
   21.25  
   21.26  package kryshen.tema;
   21.27 @@ -10,13 +24,19 @@
   21.28  import java.util.*;
   21.29  import java.sql.ResultSet;
   21.30  
   21.31 +/**
   21.32 + * Abstact class for TEMA functions.
   21.33 + *
   21.34 + * @author Mikhail A. Kryshen
   21.35 + */
   21.36  public abstract class Function {
   21.37 -    public final String name;
   21.38  
   21.39 -    protected Function(String name) {
   21.40 -	this.name = name;
   21.41 -    }
   21.42 -
   21.43 +    /**
   21.44 +     * Invoke the function.
   21.45 +     *
   21.46 +     * @param fdp FunctionDataParser to access function arguments.
   21.47 +     * @param out Writer for the function output.
   21.48 +     */
   21.49      public abstract int invoke(FunctionDataParser fdp, Writer out)
   21.50          throws IOException, TemplateException;
   21.51  }
    22.1 --- a/src/kryshen/tema/FunctionDataParser.java	Tue May 16 18:04:09 2006 +0400
    22.2 +++ b/src/kryshen/tema/FunctionDataParser.java	Thu Dec 14 23:22:05 2006 +0300
    22.3 @@ -1,7 +1,21 @@
    22.4  /*
    22.5 - * Copyright (C) 2006 Mikhail A. Kryshen
    22.6 + *  Copyright (C) 2006 Mikhail A. Kryshen
    22.7   *
    22.8 - * $Id: FunctionDataParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    22.9 + *  This program is free software; you can redistribute it and/or modify
   22.10 + *  it under the terms of the GNU General Public License as published by
   22.11 + *  the Free Software Foundation; either version 2 of the License, or
   22.12 + *  (at your option) any later version.
   22.13 + *
   22.14 + *  This program is distributed in the hope that it will be useful,
   22.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.17 + *  GNU General Public License for more details.
   22.18 + *
   22.19 + *  You should have received a copy of the GNU General Public License
   22.20 + *  along with this program; if not, write to the Free Software
   22.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22.22 + *
   22.23 + *  $Id: FunctionDataParser.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   22.24   */
   22.25  
   22.26  package kryshen.tema;
   22.27 @@ -23,13 +37,13 @@
   22.28  
   22.29      private TemplateParser tp;
   22.30      private FunctionData fd;
   22.31 -    private Reader in;
   22.32 +    private TemplateReader in;
   22.33  
   22.34      private boolean available = true;
   22.35      private boolean first = true;
   22.36  
   22.37      FunctionDataParser(TemplateParser tp, FunctionData fd,
   22.38 -                       Reader in) {
   22.39 +                       TemplateReader in) {
   22.40          this.tp = tp;
   22.41          this.fd = fd;
   22.42          this.in = in;
   22.43 @@ -40,7 +54,7 @@
   22.44          
   22.45          if (!available)
   22.46              throw new TemplateException
   22.47 -		("Unexpected end of instruction data.");
   22.48 +		("Unexpected end of instruction data.", in);
   22.49  
   22.50          TemplateParser.Result r;
   22.51  
   22.52 @@ -53,11 +67,11 @@
   22.53                           argument ? ARG_SEPARATORS : null,
   22.54                           (argument || !first) ? ARG_SEPARATORS : null);
   22.55          } else if (fd == FunctionData.SUBFUNCTION && argument) {
   22.56 -            /* Subfunction can pass a list of arguments */
   22.57 +            // Subfunction can pass a list of arguments
   22.58              StringWriter sw = new StringWriter();
   22.59              tp.parseFunction(in, sw);
   22.60              sw.close();
   22.61 -            in = new StringReader(sw.toString());
   22.62 +            in = new TemplateReader(new StringReader(sw.toString()), in);
   22.63              fd = FunctionData.NONRECURSIVE;
   22.64              r = parseData(out, true);
   22.65          } else if (fd == FunctionData.SUBFUNCTION) {
   22.66 @@ -74,7 +88,7 @@
   22.67      }
   22.68  
   22.69      public int parseData(Writer out) throws IOException, TemplateException {
   22.70 -        return parseData(out, false).substitutions; 
   22.71 +        return parseData(out, false).retCode; 
   22.72      }
   22.73  
   22.74      public String getData() throws IOException, TemplateException {        
   22.75 @@ -92,7 +106,7 @@
   22.76              r = parseData(out, true);
   22.77          }
   22.78  
   22.79 -        return r.substitutions;
   22.80 +        return r.retCode;
   22.81      }
   22.82  
   22.83      public String getNextArg() throws IOException, TemplateException {        
   22.84 @@ -119,4 +133,8 @@
   22.85      public TemplateParser getTemplateParser() {
   22.86          return tp;
   22.87      }
   22.88 +    
   22.89 +    public TemplateReader getTemplateReader() {
   22.90 +        return in;
   22.91 +    }
   22.92  }
    23.1 --- a/src/kryshen/tema/Functions.java	Tue May 16 18:04:09 2006 +0400
    23.2 +++ b/src/kryshen/tema/Functions.java	Thu Dec 14 23:22:05 2006 +0300
    23.3 @@ -1,7 +1,21 @@
    23.4  /*
    23.5 - * Copyright (C) 2005, 2006 Mikhail A. Kryshen
    23.6 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    23.7   *
    23.8 - * $Id: Functions.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    23.9 + *  This program is free software; you can redistribute it and/or modify
   23.10 + *  it under the terms of the GNU General Public License as published by
   23.11 + *  the Free Software Foundation; either version 2 of the License, or
   23.12 + *  (at your option) any later version.
   23.13 + *
   23.14 + *  This program is distributed in the hope that it will be useful,
   23.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.17 + *  GNU General Public License for more details.
   23.18 + *
   23.19 + *  You should have received a copy of the GNU General Public License
   23.20 + *  along with this program; if not, write to the Free Software
   23.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23.22 + *
   23.23 + *  $Id: Functions.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $
   23.24   */
   23.25  
   23.26  package kryshen.tema;
   23.27 @@ -9,328 +23,48 @@
   23.28  import java.io.*;
   23.29  import java.util.*;
   23.30  
   23.31 -import java.sql.SQLException;
   23.32 -import java.sql.PreparedStatement;
   23.33 -
   23.34  import kryshen.tema.functions.*;
   23.35  
   23.36 +/**
   23.37 + * Standard TEMA functions.
   23.38 + *
   23.39 + * @author Mikhail A. Kryshen
   23.40 + */
   23.41  public class Functions {
   23.42 -    public static final Function GET =
   23.43 -        new Function("get") {
   23.44 -            public int invoke(FunctionDataParser fdp, Writer out)
   23.45 -                throws IOException, TemplateException {
   23.46 +    // TODO: arithmetics, conditions
   23.47  
   23.48 -		String name = fdp.getData();
   23.49 -                return fdp.getTemplateParser().parseVariable(name, out);
   23.50 -            }
   23.51 -        };
   23.52 +    /**
   23.53 +     * Register all standard functions.
   23.54 +     *
   23.55 +     * @param p TemplateParser to register functions in.
   23.56 +     */
   23.57 +    static void registerAllFunctions(TemplateParser p) {
   23.58 +        p.registerFunction("!",          Standard.NULL_OUTPUT);
   23.59 +        p.registerFunction("set",        Standard.SET);
   23.60 +        p.registerFunction("load",       Standard.LOAD);
   23.61 +        p.registerFunction("query",      Standard.QUERY);
   23.62 +        p.registerFunction("prepare",    Standard.PREPARE);
   23.63 +        p.registerFunction("replace",    Standard.REPLACE);
   23.64 +        p.registerFunction("xml_escape", Standard.XML_ESCAPE);
   23.65 +        p.registerFunction("xml_cdata",  Standard.XML_CDATA);
   23.66  
   23.67 -    public static final Function SET =
   23.68 -        new Function("set") {
   23.69 -            public int invoke(FunctionDataParser fdp, Writer out)
   23.70 -                throws IOException, TemplateException {
   23.71 +        p.registerFunction("define",     Define.DEFINE);
   23.72  
   23.73 -                String arg0 = fdp.getNextArg();
   23.74 -                String arg1 = fdp.getData();
   23.75 -                
   23.76 -                fdp.getTemplateParser().setValue(arg0, arg1);
   23.77 -                
   23.78 -		out.write(arg0);
   23.79 -                return 1;
   23.80 -            }
   23.81 -        };
   23.82 +        p.registerFunction("write",      IO.WRITE);
   23.83 +        p.registerFunction("read",       IO.READ);
   23.84 +        p.registerFunction("include",    IO.INCLUDE);
   23.85 +        p.registerFunction("copy",       IO.COPY);
   23.86  
   23.87 -    /* prepare:qury_name sql_statement */
   23.88 -    public static final Function PREPARE =
   23.89 -        new Function("prepare") {
   23.90 -            public int invoke(FunctionDataParser fdp, Writer out)
   23.91 -                throws IOException, TemplateException {
   23.92 +	p.registerFunction("false",      Logics.FALSE);
   23.93 +	p.registerFunction("true",       Logics.TRUE);
   23.94 +        p.registerFunction("optional",   Logics.OPTIONAL);
   23.95  
   23.96 -                String arg0 = fdp.getNextArg();
   23.97 -                String data = fdp.getData();
   23.98 +        p.registerFunction("image",      ImageConverter.IMAGE);
   23.99  
  23.100 -		PreparedStatement statement;
  23.101 -
  23.102 -		try {
  23.103 -		    statement = Tema.connection.prepareStatement(data);
  23.104 -		} catch (SQLException e) {
  23.105 -		    throw new TemplateException(e.getMessage(), e);
  23.106 -		}
  23.107 -                
  23.108 -                fdp.getTemplateParser().setValue(arg0, statement);   
  23.109 -             
  23.110 -		out.write(arg0);
  23.111 -                return 1;
  23.112 -            }
  23.113 -        };
  23.114 -
  23.115 -    public static final Function OPTIONAL =
  23.116 -        new Function("optional") {
  23.117 -            public int invoke(FunctionDataParser fdp, Writer out)
  23.118 -                throws IOException, TemplateException {
  23.119 -
  23.120 -                StringWriter sw = new StringWriter();
  23.121 -                int s = fdp.parseData(sw);
  23.122 -                sw.close();
  23.123 -                String data = sw.toString();
  23.124 -
  23.125 -                if (s > 0) {
  23.126 -                    out.write(data);
  23.127 -                    return 1;
  23.128 -                } else {
  23.129 -                    return 0;
  23.130 -                }
  23.131 -            }
  23.132 -        };
  23.133 -
  23.134 -    public static final Function IMAGE =
  23.135 -        new Function("image") {
  23.136 -            public int invoke(FunctionDataParser fdp, Writer out)
  23.137 -                throws IOException, TemplateException {
  23.138 -
  23.139 -                String arg0 = fdp.getNextArg();
  23.140 -                String arg1 = fdp.getNextArg();
  23.141 -                String arg2 = fdp.getNextArg();
  23.142 -                int arg3 = fdp.hasMoreData() ? 
  23.143 -		    Integer.parseInt(fdp.getNextArg()) : -1;
  23.144 -                int arg4 = fdp.hasMoreData() ? 
  23.145 -		    Integer.parseInt(fdp.getNextArg()) : -1;
  23.146 -
  23.147 -                File source = new File
  23.148 -                    (Tema.getProperty("resource_base"), arg0);
  23.149 -
  23.150 -                try {
  23.151 -                    ImageConverter.convert
  23.152 -                        (source,                  /* source file */
  23.153 -                         new File(arg1),          /* dest file */
  23.154 -                         arg2,                    /* format */
  23.155 -                         arg3,                    /* max width */
  23.156 -                         arg4);                   /* max height */
  23.157 -                } catch (Exception e) {
  23.158 -                    System.err.println(e);
  23.159 -                    return 0;
  23.160 -                }
  23.161 -
  23.162 -                out.write(arg1);
  23.163 -                return 1;
  23.164 -            }
  23.165 -        };
  23.166 -
  23.167 -    public static final Function COPY =
  23.168 -        new Function("copy") {
  23.169 -           public int invoke(FunctionDataParser fdp, Writer out)
  23.170 -                throws IOException, TemplateException {
  23.171 -
  23.172 -                String arg0 = fdp.getNextArg();
  23.173 -                String arg1 = fdp.getNextArg();
  23.174 -
  23.175 -                File source = new File
  23.176 -                    (Tema.getProperty("resource_base"), arg0);
  23.177 -                File dest = new File(arg1);
  23.178 -                
  23.179 -                try {
  23.180 -                    copyFile(source, dest);
  23.181 -                } catch (IOException e) {
  23.182 -                    System.err.println(e);
  23.183 -                    return 0;
  23.184 -                }
  23.185 -                out.write(arg1);
  23.186 -                return 1;
  23.187 -            }
  23.188 -        };
  23.189 -
  23.190 -    /* query:sql_query template arg1 arg2 ... argN */
  23.191 -    public static final Function QUERY =
  23.192 -        new Function("query") {
  23.193 -           public int invoke(FunctionDataParser fdp, Writer out)
  23.194 -                throws IOException, TemplateException {
  23.195 -                
  23.196 -                String arg0 = fdp.getNextArg();
  23.197 -                String arg1 = fdp.getNextArg();
  23.198 -		List<String> args = fdp.getArgs();				
  23.199 -
  23.200 -		TemplateParser tp = fdp.getTemplateParser();
  23.201 -
  23.202 -		try {
  23.203 -		    return Tema.query
  23.204 -			(arg1, (PreparedStatement)tp.getValue(arg0),
  23.205 -			 args, tp, out);
  23.206 -		} catch (SQLException e) {
  23.207 -		    throw new TemplateException(e.getMessage(), e);
  23.208 -		}
  23.209 -            }
  23.210 -        };
  23.211 -
  23.212 -    public static final Function WRITE =
  23.213 -        new Function("write") {
  23.214 -           public int invoke(FunctionDataParser fdp, Writer out)
  23.215 -                throws IOException, TemplateException {
  23.216 -
  23.217 -                String arg0 = fdp.getNextArg();
  23.218 -
  23.219 -		System.err.println("Writing " + arg0 + "...");
  23.220 -
  23.221 -                Writer fw;
  23.222 -
  23.223 -                try {
  23.224 -		    fw = Tema.createFileWriter(arg0);
  23.225 -                } catch (IOException e) {
  23.226 -                    System.err.println(e);
  23.227 -                    return 0;
  23.228 -                }
  23.229 -                
  23.230 -                try {
  23.231 -		    fdp.parseData(fw);
  23.232 -                } finally {
  23.233 -                    fw.close();
  23.234 -                }
  23.235 -
  23.236 -                out.write(arg0);
  23.237 -		
  23.238 -		System.err.println("Saved " + arg0 + ".");
  23.239 -                return 1;
  23.240 -            }
  23.241 -        };
  23.242 -
  23.243 -    public static final Function READ =
  23.244 -        new Function("read") {
  23.245 -           public int invoke(FunctionDataParser fdp, Writer out)
  23.246 -                throws IOException, TemplateException {
  23.247 -
  23.248 -	       String filename = fdp.getData();
  23.249 -	       String file;
  23.250 -	       
  23.251 -                try {
  23.252 -                    file = Tema.readFile(new File(filename));
  23.253 -                } catch (IOException e) {
  23.254 -                    System.err.println(e);
  23.255 -                    return 0;
  23.256 -                }
  23.257 -		
  23.258 -                out.write(file);
  23.259 -                return 1;
  23.260 -            }
  23.261 -        };
  23.262 -
  23.263 -    public static final Function INCLUDE =
  23.264 -        new Function("include") {
  23.265 -           public int invoke(FunctionDataParser fdp, Writer out)
  23.266 -                throws IOException, TemplateException {
  23.267 -                
  23.268 -                String filename = fdp.getData();
  23.269 -                
  23.270 -                Reader fin = new BufferedReader
  23.271 -		    (Tema.createCachedFileReader(new File(filename)));
  23.272 -                
  23.273 -                int r = fdp.getTemplateParser().parse(fin, out);
  23.274 -
  23.275 -                fin.close();
  23.276 -                return r;
  23.277 -            }
  23.278 -        };
  23.279 -
  23.280 -    public static final Function NULL_OUTPUT =
  23.281 -        new Function("!") {
  23.282 -	    public int invoke(FunctionDataParser fdp, Writer out)
  23.283 -		throws IOException, TemplateException {		
  23.284 -
  23.285 -		/* Write nothing. */
  23.286 -		return fdp.parseData(new Writer() {
  23.287 -                    public void close() {}
  23.288 -                    public void flush() {}
  23.289 -                    public void write(char[] cbuf, int off, int len) {}
  23.290 -                });
  23.291 -            }
  23.292 -        };
  23.293 -
  23.294 -    public static final Function REPLACE =
  23.295 -        new Function("replace") {
  23.296 -	    public int invoke(FunctionDataParser fdp, Writer out)
  23.297 -		throws IOException, TemplateException {		
  23.298 -
  23.299 -                String arg0 = fdp.getNextArg();
  23.300 -                String arg1 = fdp.getNextArg();
  23.301 -
  23.302 -                ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1);
  23.303 -
  23.304 -                int ret = fdp.parseData(rw);
  23.305 -                rw.finish();
  23.306 -                return ret;
  23.307 -            }
  23.308 -        };
  23.309 -
  23.310 -    public static final Function XML_ESCAPE =
  23.311 -        new Function("xml_escape") {
  23.312 -	    public int invoke(FunctionDataParser fdp, Writer out)
  23.313 -		throws IOException, TemplateException {		
  23.314 -
  23.315 -                final String[] chars = {"&", "<", ">", "`", "\""};
  23.316 -                final String[] escape = {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"};
  23.317 -
  23.318 -                ReplaceWriter rw = new ReplaceWriter(out, chars, escape);
  23.319 -
  23.320 -                int ret = fdp.parseData(rw);
  23.321 -                rw.finish();
  23.322 -                return ret;
  23.323 -            }
  23.324 -        };
  23.325 -
  23.326 -    public static final Function XML_CDATA =
  23.327 -        new Function("xml_cdata") {
  23.328 -	    public int invoke(FunctionDataParser fdp, Writer out)
  23.329 -		throws IOException, TemplateException {		
  23.330 -
  23.331 -                ReplaceWriter rw = new ReplaceWriter
  23.332 -                    (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>");
  23.333 -
  23.334 -                int ret = fdp.parseData(rw);
  23.335 -                rw.finish();
  23.336 -                return ret;
  23.337 -            }
  23.338 -        };
  23.339 -    
  23.340 -    public static final Function DEFINE = new Define();
  23.341 -
  23.342 -    private static void copyFile(File src, File dest) throws IOException {
  23.343 -	System.err.print("Copying " + src + "... ");
  23.344 -	
  23.345 -	if (src.lastModified() < dest.lastModified()) {
  23.346 -	    System.err.println(dest + " is up to date.");
  23.347 -	    return;
  23.348 -	}
  23.349 -
  23.350 -	File parent = dest.getParentFile();
  23.351 -	if (parent != null) parent.mkdirs();
  23.352 -
  23.353 -        InputStream in = new FileInputStream(src);
  23.354 -        OutputStream out = new FileOutputStream(dest);
  23.355 -        
  23.356 -        byte[] buffer = new byte[1024];
  23.357 -        int len;
  23.358 -        while ((len = in.read(buffer)) > 0) {
  23.359 -            out.write(buffer, 0, len);
  23.360 -        }
  23.361 -        in.close();
  23.362 -        out.close();
  23.363 -
  23.364 -	System.err.println("saved " + dest + ".");
  23.365 -    }
  23.366 -
  23.367 -    static void registerAllFunctions(TemplateParser p) {
  23.368 -        p.registerFunction(GET);
  23.369 -        p.registerFunction(SET);
  23.370 -        p.registerFunction(OPTIONAL);
  23.371 -        p.registerFunction(IMAGE);
  23.372 -        p.registerFunction(COPY);
  23.373 -        p.registerFunction(QUERY);
  23.374 -        p.registerFunction(PREPARE);
  23.375 -        p.registerFunction(WRITE);
  23.376 -        p.registerFunction(READ);
  23.377 -        p.registerFunction(INCLUDE);
  23.378 -        p.registerFunction(NULL_OUTPUT);
  23.379 -        p.registerFunction(REPLACE);
  23.380 -        p.registerFunction(XML_ESCAPE);
  23.381 -        p.registerFunction(XML_CDATA);
  23.382 -        p.registerFunction(DEFINE);
  23.383 +	/* 
  23.384 +	   Other functuons:
  23.385 +	   db - defined in Tema.query().
  23.386 +	   nextarg, data - defined in Define.invoke().
  23.387 +	*/
  23.388      }
  23.389  }
    24.1 --- a/src/kryshen/tema/ImageConverter.java	Tue May 16 18:04:09 2006 +0400
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,184 +0,0 @@
    24.4 -/*
    24.5 - * Copyright (C) 2005, 2006 Mikhail A. Kryshen
    24.6 - *
    24.7 - * $Id: ImageConverter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    24.8 - */
    24.9 -
   24.10 -package kryshen.tema;
   24.11 -
   24.12 -import java.util.*;
   24.13 -import java.io.*;
   24.14 -import java.awt.*;
   24.15 -import java.awt.image.*;
   24.16 -import java.awt.geom.AffineTransform;
   24.17 -import javax.imageio.*;
   24.18 -import javax.imageio.stream.*;
   24.19 -
   24.20 -/**
   24.21 - * Class defines static method to convert images to specified format.
   24.22 - *
   24.23 - * @author Mikhail A. Kryshen
   24.24 - */
   24.25 -class ImageConverter {    
   24.26 -
   24.27 -    static void convert(File source, File dest, String format,
   24.28 -		 int maxWidth, int maxHeight) 
   24.29 -	throws IOException, InterruptedException {
   24.30 -	
   24.31 -	System.err.print("Converting image " + source + "... ");
   24.32 -
   24.33 -	if (source.lastModified() < dest.lastModified()) {
   24.34 -	    System.err.println(dest + " is up to date.");
   24.35 -	    return;
   24.36 -	}
   24.37 -
   24.38 -	BufferedImage image = ImageIO.read(source);
   24.39 -
   24.40 -	//int type = image.getType();
   24.41 -	//final int type = BufferedImage.TYPE_INT_RGB;
   24.42 -	//ColorModel cm = image.getColorModel();
   24.43 -
   24.44 -        int w = image.getWidth(null);
   24.45 -        int h = image.getHeight(null);
   24.46 -
   24.47 -	//boolean scale = false;
   24.48 -
   24.49 -	float scale = 1f;
   24.50 -
   24.51 -	if (maxWidth > 0 && w > maxWidth)
   24.52 -	    scale = (float)maxWidth / w;
   24.53 -	
   24.54 -	if (maxHeight > 0 && h * scale > maxHeight)
   24.55 -	    scale = (float)maxHeight / h;
   24.56 -
   24.57 -	if (scale != 1f) {
   24.58 -	    w *= scale; h *= scale;
   24.59 -
   24.60 -// 	    ColorModel cm = image.getColorModel();	    
   24.61 -// 	    boolean alphaPremultiplied = cm.isAlphaPremultiplied();
   24.62 -// 	    WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
   24.63 -// 	    BufferedImage scaled = new BufferedImage
   24.64 -// 		(cm, raster, alphaPremultiplied, null);
   24.65 -
   24.66 -// 	    BufferedImage scaled = new BufferedImage(w, h, image.getType());
   24.67 -	    
   24.68 -
   24.69 - 	    Image scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH);
   24.70 -
   24.71 - 	    ColorModel cm = image.getColorModel();	    
   24.72 - 	    boolean alphaPremultiplied = image.isAlphaPremultiplied();
   24.73 - 	    WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
   24.74 - 	    image = new BufferedImage(cm, raster, alphaPremultiplied, null);
   24.75 -
   24.76 -	    Graphics g = image.getGraphics();
   24.77 -	    g.drawImage(scaled, 0, 0, null);
   24.78 -	    g.dispose();
   24.79 -
   24.80 -//	    image = scale(image, scaled, scale);
   24.81 -//	    Graphics2D g = scaled.createGraphics();
   24.82 -//	    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
   24.83 -// 			       RenderingHints.VALUE_INTERPOLATION_BILINEAR);
   24.84 -// 	    System.err.print(" " + g.drawImage(image, 0, 0, w, h, null) + " ");
   24.85 -// 	    g.dispose();
   24.86 -// 	    image = scaled;
   24.87 -	}
   24.88 -       
   24.89 -	File parent = dest.getParentFile();
   24.90 -	if (parent != null) parent.mkdirs();
   24.91 -
   24.92 - 	ImageIO.write(image, format, dest);
   24.93 -	System.err.println("saved " + dest + ".");	
   24.94 -    }
   24.95 -
   24.96 -//     public static ColorModel getColorModel(Image image) 
   24.97 -// 	throws InterruptedException {
   24.98 -
   24.99 -// 	PixelGrabber grabby = new PixelGrabber(image, 0, 0, 1, 1, false);
  24.100 -// 	if (!grabby.grabPixels())
  24.101 -// 	    throw new RuntimeException("pixel grab fails");
  24.102 -// 	return grabby.getColorModel();
  24.103 -//     }
  24.104 -
  24.105 -//     private static BufferedImage scale(BufferedImage image, 
  24.106 -// 				       BufferedImage dest, 
  24.107 -// 				       float scale) {
  24.108 -
  24.109 -// 	AffineTransform tx = new AffineTransform();
  24.110 -// 	tx.scale(scale, scale);
  24.111 -
  24.112 -//  	AffineTransformOp op = new AffineTransformOp
  24.113 -//  	    (tx, AffineTransformOp.TYPE_BILINEAR);
  24.114 -
  24.115 -// 	return op.filter(image, dest);
  24.116 -//     }
  24.117 -
  24.118 -    // TEST
  24.119 -    
  24.120 -    public static void main(String[] args) 
  24.121 -	throws IOException, InterruptedException {
  24.122 -
  24.123 -	convert(new File(args[0]), new File(args[1]), "png", 300, 300);
  24.124 -    }
  24.125 -
  24.126 -
  24.127 -//     public static BufferedImage toBufferedImage(Image image, ColorModel cm) {
  24.128 -// 	if (image instanceof BufferedImage)
  24.129 -// 	    return (BufferedImage)image;
  24.130 -
  24.131 -// 	int w = image.getWidth(null);
  24.132 -// 	int h = image.getHeight(null);
  24.133 -
  24.134 -// 	boolean alphaPremultiplied = cm.isAlphaPremultiplied();
  24.135 -// 	WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
  24.136 -// 	BufferedImage result = new BufferedImage(cm, raster, alphaPremultiplied, null);
  24.137 -// 	Graphics2D g = result.createGraphics();
  24.138 -
  24.139 -// 	g.drawImage(image, 0, 0, null);
  24.140 -// 	g.dispose();
  24.141 -
  24.142 -// 	return result;
  24.143 -//     }
  24.144 -}
  24.145 -
  24.146 -
  24.147 -// This is how I'd recommend it in JDK1.4 using javax.imageio.ImageIO to
  24.148 -// do the reading/writing and Java2D to do the scaling.
  24.149 -
  24.150 -// // read in the original image
  24.151 -// BufferedImage in = ImageIO.read(new File("in.jpg"));
  24.152 -
  24.153 -// // create a new image of the smaller size
  24.154 -// BufferedImage out = new BufferedImage(newWidth, newHeight);
  24.155 -
  24.156 -// // get the graphics associated with the new image
  24.157 -// Graphics g = out.getGraphics();
  24.158 -
  24.159 -// // draw the original image into the new image, scaling
  24.160 -// // on the fly
  24.161 -// g.drawImage(in, newWidth, newHeight, null);
  24.162 -
  24.163 -// // dispose the graphics object
  24.164 -// g.dispose();
  24.165 -
  24.166 -// // write out the new image
  24.167 -// ImagIO.write("out.jpg", "jpeg", new File("out.jpg"));
  24.168 -
  24.169 -// ------------------------------------------
  24.170 -
  24.171 -// For nicer scaling, you could add a rendering hint to the graphics
  24.172 -// object before painting.
  24.173 -
  24.174 -// ie.
  24.175 -
  24.176 -// Graphics2D g2d = (Graphics2D)g;
  24.177 -// g2d.setRenderingHint(RenderingHints.KEY_INTEPOLATION,
  24.178 -//                      RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  24.179 -
  24.180 -// or use VALUE_INTERPOLATION_BICUBIC for the best.
  24.181 -
  24.182 -// But as you can guess, nicer == slower.
  24.183 -
  24.184 -// Shannon Hickey
  24.185 -// shann...@swingteam.com
  24.186 -// Swing Team  http://TheSwingConnection.com  http://TheJavaTutorial.com
  24.187 -// Java Software,  a division of Sun Microsystems, Inc. 
    25.1 --- a/src/kryshen/tema/ReplaceWriter.java	Tue May 16 18:04:09 2006 +0400
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,140 +0,0 @@
    25.4 -/*
    25.5 - * Copyright (C) 2006 Mikhail A. Kryshen
    25.6 - *
    25.7 - * $Id: ReplaceWriter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    25.8 - */
    25.9 -
   25.10 -package kryshen.tema;
   25.11 -
   25.12 -import java.io.Writer;
   25.13 -import java.io.FilterWriter;
   25.14 -import java.io.IOException;
   25.15 -
   25.16 -import java.util.LinkedList;
   25.17 -import java.util.Iterator;
   25.18 -
   25.19 -/**
   25.20 - * FilterWriter which replaces characters with escape strings.
   25.21 - *
   25.22 - * @author Mikhail A. Kryshen
   25.23 - */
   25.24 -class ReplaceWriter extends FilterWriter {
   25.25 -    private String[] patterns;
   25.26 -    private String[] replaces;
   25.27 -
   25.28 -    private String prefix;
   25.29 -    private String postfix;
   25.30 -
   25.31 -    private int maxPatternLength = 0;
   25.32 -
   25.33 -    /** Had this Writer processed any data? */
   25.34 -    private boolean processedData = false;
   25.35 -
   25.36 -    private StringBuffer buffer = new StringBuffer();
   25.37 -
   25.38 -    public ReplaceWriter(Writer w, String pattern, String replace) {
   25.39 -        this(w, new String[]{pattern}, new String[]{replace});
   25.40 -    }
   25.41 -
   25.42 -    public ReplaceWriter(Writer w, String pattern, String replace,
   25.43 -                         String prefix, String postfix) {
   25.44 -
   25.45 -        this(w, new String[]{pattern}, new String[]{replace}, 
   25.46 -             prefix, postfix);
   25.47 -    }
   25.48 -
   25.49 -    public ReplaceWriter(Writer w, String[] patterns, String[] replaces) {
   25.50 -        this(w, patterns, replaces, null, null);
   25.51 -    }
   25.52 -
   25.53 -    public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 
   25.54 -                         String prefix, String postfix) {
   25.55 -	super(w);
   25.56 -        
   25.57 -	this.patterns = patterns;
   25.58 -	this.replaces = replaces;
   25.59 -        
   25.60 -        this.prefix = prefix;
   25.61 -        this.postfix = postfix;
   25.62 -        
   25.63 -	for (int i = 0; i < patterns.length; i++) {
   25.64 -	    int length = patterns[i].length();
   25.65 -	    if (length > maxPatternLength)
   25.66 -		maxPatternLength = length;
   25.67 -	}
   25.68 -    }
   25.69 -
   25.70 -    private boolean processBuffer(int minLength) throws IOException {
   25.71 -        if (buffer.length() == 0) return false;
   25.72 -
   25.73 -        if (!processedData) {
   25.74 -            if (prefix != null)
   25.75 -                super.write(prefix, 0, prefix.length());
   25.76 -            processedData = true;
   25.77 -        }
   25.78 -
   25.79 -        int k;
   25.80 -	for (k = 0; minLength + k < buffer.length(); k++) {
   25.81 -	    for (int i = 0; i < patterns.length; i++) {
   25.82 -		String pattern = patterns[i];
   25.83 -		int length = pattern.length();
   25.84 -
   25.85 -                if (length + k > buffer.length())
   25.86 -                    continue;
   25.87 -
   25.88 -		boolean match = true;
   25.89 -
   25.90 -		for (int j = 0; j < length; j++) {
   25.91 -		    if (pattern.charAt(j) != buffer.charAt(j + k)) {
   25.92 -			match = false;
   25.93 -                        break;
   25.94 -		    }
   25.95 -		}
   25.96 -
   25.97 -		if (match) {
   25.98 -                    super.write(buffer.substring(0, k), 0, k);
   25.99 -                    buffer.delete(0, k + length);
  25.100 -                    super.write(replaces[i], 0, replaces[i].length());
  25.101 -		    return true;
  25.102 -		}
  25.103 -	    }
  25.104 -	}
  25.105 -
  25.106 -        super.write(buffer.substring(0, k), 0, k);
  25.107 -        buffer.delete(0, k);
  25.108 -
  25.109 -        return false;
  25.110 -    }
  25.111 -
  25.112 -    public void write(int c) throws IOException {
  25.113 -	buffer.append((char)c);
  25.114 -	processBuffer(maxPatternLength);
  25.115 -    }
  25.116 -
  25.117 -    public void write(char[] cbuf, int off, int len) throws IOException {
  25.118 -	for (int i = off; i < off + len; i++) {
  25.119 -	    buffer.append(cbuf[i]);
  25.120 -	}
  25.121 -	processBuffer(maxPatternLength);
  25.122 -    }
  25.123 -
  25.124 -    public void write(String str, int off, int len) throws IOException {
  25.125 -        buffer.append(str.substring(off, off + len));
  25.126 -	processBuffer(maxPatternLength);
  25.127 -    }
  25.128 -
  25.129 -    public void finish() throws IOException {
  25.130 -        while (processBuffer(0));
  25.131 -
  25.132 -//         super.write(buffer.toString(), 0, buffer.length());
  25.133 -//         buffer.delete(0, buffer.length());
  25.134 -
  25.135 -        if (processedData && postfix != null)
  25.136 -            super.write(postfix, 0, postfix.length());
  25.137 -    }
  25.138 -
  25.139 -    public void close() throws IOException {
  25.140 -        finish();
  25.141 -        super.close();
  25.142 -    }
  25.143 -}
    26.1 --- a/src/kryshen/tema/Tema.java	Tue May 16 18:04:09 2006 +0400
    26.2 +++ b/src/kryshen/tema/Tema.java	Thu Dec 14 23:22:05 2006 +0300
    26.3 @@ -1,7 +1,21 @@
    26.4  /*
    26.5 - * Copyright (C) 2005, 2006 Mikhail A. Kryshen
    26.6 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    26.7   *
    26.8 - * $Id: Tema.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    26.9 + *  This program is free software; you can redistribute it and/or modify
   26.10 + *  it under the terms of the GNU General Public License as published by
   26.11 + *  the Free Software Foundation; either version 2 of the License, or
   26.12 + *  (at your option) any later version.
   26.13 + *
   26.14 + *  This program is distributed in the hope that it will be useful,
   26.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.17 + *  GNU General Public License for more details.
   26.18 + *
   26.19 + *  You should have received a copy of the GNU General Public License
   26.20 + *  along with this program; if not, write to the Free Software
   26.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   26.22 + *
   26.23 + *  $Id: Tema.java,v 1.17 2006/12/14 19:44:31 mikhail Exp $
   26.24   */
   26.25  
   26.26  package kryshen.tema;
   26.27 @@ -23,31 +37,135 @@
   26.28  
   26.29  import java.io.*;
   26.30  
   26.31 +import kryshen.tema.demo.DemoFrame;
   26.32 +
   26.33  /**
   26.34   * Tema main class.
   26.35   *
   26.36   * @author Mikhail A. Kryshen
   26.37   */
   26.38  public class Tema {
   26.39 +    public static final String TITLE = "TEMA";
   26.40 +    public static final String VERSION = "0.1";
   26.41 +    public static final String AUTHOR = "Mikhail A. Kryshen";
   26.42 +
   26.43      private static final String CONFIG_FILE = "tema.properties";
   26.44      private static final String ENV_PREFIX = "kryshen.tema.";
   26.45  
   26.46      private static Properties config = new Properties();
   26.47 -    static Connection connection = null;
   26.48 +    private static Connection connection = null;
   26.49  
   26.50      private static String inputEncoding;
   26.51      private static String outputEncoding;
   26.52  
   26.53 -    static Map<File, String> fileCache = null;
   26.54 +    private static Map<File, String> fileCache = null;
   26.55  
   26.56      public static void main(String[] args) 
   26.57 -	throws IOException, TemplateException, SQLException,
   26.58 +	throws IOException, SQLException,
   26.59  	       ClassNotFoundException, InstantiationException, 
   26.60  	       IllegalAccessException {
   26.61  	
   26.62 +        boolean demo = false;
   26.63 +        boolean version = false;
   26.64 +        boolean help = false;
   26.65 +
   26.66 +        // Parse arguments.
   26.67 +        for (int i = 0; i < args.length; i++) {
   26.68 +            if ("-demo".equals(args[i]) || 
   26.69 +                "-d".equals(args[i])) {
   26.70 +                demo = true;
   26.71 +            } else if ("-version".equals(args[i]) ||
   26.72 +                       "-v".equals(args[i])) {
   26.73 +                version = true;
   26.74 +            } else if ("-help".equals(args[i]) ||
   26.75 +                       "-h".equals(args[i]) ||
   26.76 +                       "-usage".equals(args[i]) ||
   26.77 +                       "-u".equals(args[i])) {
   26.78 +                help = true;
   26.79 +            } else {
   26.80 +                System.err.println("Invalid option: " + args[i]);
   26.81 +                return;
   26.82 +            }
   26.83 +        }
   26.84 +
   26.85 +        if (version || help) {
   26.86 +            System.err.println(TITLE + " " + VERSION + " by " + AUTHOR);        
   26.87 +
   26.88 +            if (help) {
   26.89 +                PrintStream err = System.err;
   26.90 +                
   26.91 +                err.println();
   26.92 +                err.println("Usage: tema [OPTIONS]");
   26.93 +                err.println();
   26.94 +                err.println("Options:");
   26.95 +                err.println("  -d[emo]             Demo mode");
   26.96 +                err.println("  -v[ersion]          Print version");
   26.97 +                err.println("  -h[help] -u[sage]   Print this help message");
   26.98 +            }
   26.99 +            return;
  26.100 +        }
  26.101 +
  26.102 +        if (demo) {
  26.103 +            // Run in demo mode.
  26.104 +            DemoFrame df = new DemoFrame();
  26.105 +            df.pack();
  26.106 +            df.setVisible(true);
  26.107 +            return;
  26.108 +        }
  26.109 +
  26.110 +        process();
  26.111 +    }
  26.112 +
  26.113 +    /**
  26.114 +     * Standard execution.
  26.115 +     */
  26.116 +    private static void process()
  26.117 +        throws IOException, SQLException,
  26.118 +               ClassNotFoundException, InstantiationException, 
  26.119 +               IllegalAccessException {
  26.120 +
  26.121          InputStream configIn = new FileInputStream(CONFIG_FILE);
  26.122          config.load(configIn);
  26.123          configIn.close();
  26.124 +        
  26.125 +        configure();
  26.126 +	
  26.127 +	String main = getProperty("main_template");
  26.128 +	String output = getProperty("output");
  26.129 +	
  26.130 +	Writer out;
  26.131 +
  26.132 +	if ("stderr".equals(output))
  26.133 +	    out = new OutputStreamWriter(System.err);
  26.134 +	else
  26.135 +	    out = new OutputStreamWriter(System.out);
  26.136 +
  26.137 +        TemplateReader in = createTemplateReader(new File(main));
  26.138 +        TemplateParser p = new TemplateParser();
  26.139 +        TemplateException te = null;
  26.140 +
  26.141 +	try {
  26.142 +	    p.parse(in, out);
  26.143 +        } catch (TemplateException e) {
  26.144 +            te = e;
  26.145 +	} finally {
  26.146 +	    in.close();
  26.147 +	    out.flush();
  26.148 +	}  
  26.149 +
  26.150 +        if (te != null) {
  26.151 +            System.err.println(te.getMessage());
  26.152 +            if (te.getCause() != null) {
  26.153 +                System.err.println("Caused by " + te.getCause());
  26.154 +            }
  26.155 +        } else {
  26.156 +            System.err.println("Done");
  26.157 +        }
  26.158 +    }
  26.159 +
  26.160 +    private static void configure() 
  26.161 +        throws IOException, SQLException, IllegalAccessException,
  26.162 +               ClassNotFoundException, InstantiationException {
  26.163  
  26.164          String logFile = getProperty("log");
  26.165          if (logFile != null && logFile.length() > 0)
  26.166 @@ -71,51 +189,14 @@
  26.167  	    // Open connection.
  26.168  	    connection = DriverManager.getConnection(resourceProperty);
  26.169  	}
  26.170 -	
  26.171 -// 	String maxFilesString = getProperty("max_output_files");
  26.172 -// 	int maxFiles = -1;
  26.173 -// 	if (maxFilesString != null)
  26.174 -// 	    maxFiles = Integer.parseInt(maxFilesString);
  26.175 -
  26.176 -	String main = getProperty("main_template");
  26.177 -	String output = getProperty("output");
  26.178 -	
  26.179 -	Writer out;
  26.180 -
  26.181 -	if ("stderr".equals(output))
  26.182 -	    out = new OutputStreamWriter(System.err);
  26.183 -	else
  26.184 -	    out = new OutputStreamWriter(System.out);
  26.185 -
  26.186 -	InputStream is = new FileInputStream(main);
  26.187 -        Reader in = new BufferedReader(new InputStreamReader(is, inputEncoding));
  26.188 -
  26.189 -        TemplateParser p = new TemplateParser();
  26.190 -	try {
  26.191 -	    p.parse(in, out);
  26.192 -	} finally {
  26.193 -	    in.close();
  26.194 -	    out.flush();
  26.195 -	}  
  26.196 -
  26.197 -	System.err.println("Done");
  26.198      }
  26.199  
  26.200 -//     private static void readEscapes() {
  26.201 -// 	for (int i = 1;; i++) {
  26.202 -// 	    String pattern = getProperty("escape_char_" + i);
  26.203 -
  26.204 -// 	    if (pattern == null) break;
  26.205 -
  26.206 -// 	    escapes.put(pattern.charAt(0),
  26.207 -// 			getProperty("escape_string_" + i));
  26.208 -// 	}
  26.209 -//     }
  26.210 +    
  26.211  
  26.212      /**
  26.213       * Get configuration property.
  26.214       */
  26.215 -    static String getProperty(String name) {
  26.216 +    public static String getProperty(String name) {
  26.217          String value = System.getProperty(ENV_PREFIX + name);
  26.218          if (value != null) return value;
  26.219          return config.getProperty(name);
  26.220 @@ -124,16 +205,17 @@
  26.221      /**
  26.222       * Get configuration property.
  26.223       */
  26.224 -    static String getProperty(String name, String fallback) {
  26.225 +    public static String getProperty(String name, String fallback) {
  26.226  	String value = getProperty(name);
  26.227  	if (value != null) return value;
  26.228  	return fallback;
  26.229      }
  26.230  
  26.231      /**
  26.232 -     * Process subquery and template.
  26.233 +     * Process database query.
  26.234       *
  26.235 -     * @param template template to fill with data.
  26.236 +     * @param templateReader reader for the template 
  26.237 +     *                       to fill with data.
  26.238       * @param ps query statement to execute.
  26.239       * @param args list of query parameters.
  26.240       * @param superParser invoking object.
  26.241 @@ -141,14 +223,13 @@
  26.242       *
  26.243       * @return number of processed rows in query result.
  26.244       */
  26.245 -    static int query(String template, PreparedStatement ps,
  26.246 -		     List<String> args,
  26.247 -		     TemplateParser superParser, 
  26.248 -                     Writer out)
  26.249 +    public static int query(TemplateReader templateReader,
  26.250 +                            PreparedStatement ps,
  26.251 +                            List<String> args,
  26.252 +                            TemplateParser superParser, 
  26.253 +                            Writer out)
  26.254  	throws IOException, SQLException, TemplateException {
  26.255  
  26.256 -	StringReader templateReader = new StringReader(template);
  26.257 -
  26.258  	int i = 1;
  26.259  
  26.260  	for (String arg : args) {
  26.261 @@ -165,21 +246,34 @@
  26.262  	    names[j] = rm.getColumnName(j + 1);
  26.263  	}
  26.264  
  26.265 -	TemplateParser p = new TemplateParser(superParser);
  26.266 -	
  26.267 +	final TemplateParser p = new TemplateParser(superParser);
  26.268 +	final HashMap<String, Object> fields = new HashMap<String, Object>();
  26.269 +
  26.270 +        p.registerFunction("db", new Function() {
  26.271 +                public int invoke(FunctionDataParser fdp, 
  26.272 +                                  final Writer out)
  26.273 +                    throws IOException, TemplateException {
  26.274 +                    
  26.275 +                    String name = fdp.getData();
  26.276 +                    Object value = fields.get(name);
  26.277 +		    
  26.278 +                    return p.parseValue(value, out);
  26.279 +                }
  26.280 +            });
  26.281 +
  26.282  	for (i = 1; r.next(); i++) {
  26.283 -	    p.clearValues();
  26.284  
  26.285  	    for (int j = 0; j < columnCount; j++) {
  26.286  		Object value = r.getObject(j + 1);
  26.287  		if (r.wasNull()) value = null;
  26.288 -
  26.289 -		p.setValue(names[j], value);
  26.290 +                
  26.291 +		fields.put(names[j], value);
  26.292  	    }
  26.293  
  26.294 -	    p.setValue("NUMBER", i);
  26.295 +	    p.setValue("number", i);
  26.296              p.parse(templateReader, out);
  26.297  	    templateReader.reset();
  26.298 +            fields.clear();
  26.299  	}
  26.300  
  26.301  	r.close();
  26.302 @@ -187,32 +281,56 @@
  26.303  	return i - 1;
  26.304      }
  26.305  
  26.306 -    static Writer createFileWriter(String filename) throws IOException {
  26.307 +    public static BufferedWriter createFileWriter(String filename) 
  26.308 +        throws IOException {
  26.309 +
  26.310  	OutputStream os = new FileOutputStream(filename);
  26.311 -	return new OutputStreamWriter(os, Tema.outputEncoding);
  26.312 +	return new BufferedWriter
  26.313 +            (new OutputStreamWriter(os, Tema.outputEncoding));
  26.314      }
  26.315  
  26.316 -    static Reader createFileReader(File file) throws IOException {
  26.317 +    public static BufferedReader createFileReader(File file)
  26.318 +        throws IOException {
  26.319 +
  26.320  	InputStream is = new FileInputStream(file);
  26.321 -	return new InputStreamReader(is, Tema.inputEncoding);
  26.322 +	return new BufferedReader
  26.323 +            (new InputStreamReader(is, Tema.inputEncoding));
  26.324      }
  26.325  
  26.326 -    static Reader createCachedFileReader(File file) throws IOException {
  26.327 +    public static TemplateReader createTemplateReader(File file)
  26.328 +        throws IOException {
  26.329 +
  26.330 +        return new TemplateReader
  26.331 +            (new LineNumberReader(createCachedFileReader(file)), file.getPath());
  26.332 +    }
  26.333 +
  26.334 +    /**
  26.335 +     * Creates StringReader for a cached file if caching is enabled or
  26.336 +     * a BufferedReader.
  26.337 +     *
  26.338 +     * @param file File to read.
  26.339 +     * @return Reader for a file.
  26.340 +     */
  26.341 +    public static Reader createCachedFileReader(File file) 
  26.342 +        throws IOException {
  26.343 +        
  26.344  	if (fileCache != null) return new StringReader(readFile(file));
  26.345  	else return createFileReader(file);
  26.346      }
  26.347  
  26.348      /**
  26.349       * Read text file.
  26.350 +     *
  26.351 +     * @return file contents.
  26.352       */
  26.353 -    static String readFile(File file) throws IOException {
  26.354 +    public static String readFile(File file) throws IOException {
  26.355  	String data;
  26.356 -
  26.357 +        
  26.358  	if (fileCache != null) {
  26.359  	    data = fileCache.get(file);	    
  26.360  	    if (data != null) return data;
  26.361  	}
  26.362 -
  26.363 +        
  26.364          Reader r = new BufferedReader(createFileReader(file));
  26.365  
  26.366          // FIXME: possible overflow (long -> int).
  26.367 @@ -234,4 +352,13 @@
  26.368  
  26.369  	return data;
  26.370      }
  26.371 +
  26.372 +    /**
  26.373 +     * Get database connection.
  26.374 +     *
  26.375 +     * @return database connection if any was configured.
  26.376 +     */
  26.377 +    public static Connection getDbConnection() {
  26.378 +        return connection;
  26.379 +    }
  26.380  }
    27.1 --- a/src/kryshen/tema/TemplateException.java	Tue May 16 18:04:09 2006 +0400
    27.2 +++ b/src/kryshen/tema/TemplateException.java	Thu Dec 14 23:22:05 2006 +0300
    27.3 @@ -1,7 +1,21 @@
    27.4  /*
    27.5 - * Copyright (C) 2006 Mikhail A. Kryshen
    27.6 + *  Copyright (C) 2006 Mikhail A. Kryshen
    27.7   *
    27.8 - * $Id: TemplateException.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    27.9 + *  This program is free software; you can redistribute it and/or modify
   27.10 + *  it under the terms of the GNU General Public License as published by
   27.11 + *  the Free Software Foundation; either version 2 of the License, or
   27.12 + *  (at your option) any later version.
   27.13 + *
   27.14 + *  This program is distributed in the hope that it will be useful,
   27.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.17 + *  GNU General Public License for more details.
   27.18 + *
   27.19 + *  You should have received a copy of the GNU General Public License
   27.20 + *  along with this program; if not, write to the Free Software
   27.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.22 + *
   27.23 + *  $Id: TemplateException.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   27.24   */
   27.25  
   27.26  package kryshen.tema;
   27.27 @@ -12,13 +26,36 @@
   27.28   * @author Mikhail A. Kryshen
   27.29   */
   27.30  public class TemplateException extends Exception {
   27.31 -    // TODO: store the number of template line with error.
   27.32 +    //private String source;
   27.33 +    //private int line;
   27.34  
   27.35 -    public TemplateException(String message) {
   27.36 -	super(message);
   27.37 +//     public TemplateException(String message) {
   27.38 +// 	super(message);
   27.39 +//     }
   27.40 +
   27.41 +//     public TemplateException(String message, Throwable cause) {
   27.42 +// 	super(message, cause);
   27.43 +//     }
   27.44 +
   27.45 +    public TemplateException(String message, Throwable cause,
   27.46 +                             TemplateReader tr) {
   27.47 +        this(message, cause, tr.getSource(), tr.getLineNumber() + 1);
   27.48      }
   27.49  
   27.50 -    public TemplateException(String message, Throwable cause) {
   27.51 -	super(message, cause);
   27.52 +    public TemplateException(String message, TemplateReader tr) {
   27.53 +        this(message, tr.getSource(), tr.getLineNumber() + 1);
   27.54 +    }
   27.55 +
   27.56 +    public TemplateException(String message, Throwable cause,
   27.57 +                             String source, int line) {
   27.58 +        super(source + ":" + line + ": " + message, cause);
   27.59 +        //this.source = source;
   27.60 +        //this.line = line;
   27.61 +    }
   27.62 +    
   27.63 +    public TemplateException(String message, String source, int line) {
   27.64 +        super(source + ":" + line + ": " + message);
   27.65 +        //this.source = source;
   27.66 +        //this.line = line;
   27.67      }
   27.68  }
    28.1 --- a/src/kryshen/tema/TemplateParser.java	Tue May 16 18:04:09 2006 +0400
    28.2 +++ b/src/kryshen/tema/TemplateParser.java	Thu Dec 14 23:22:05 2006 +0300
    28.3 @@ -1,7 +1,21 @@
    28.4  /*
    28.5 - * Copyright (C) 2005, 2006 Mikhail A. Kryshen
    28.6 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    28.7   *
    28.8 - * $Id: TemplateParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    28.9 + *  This program is free software; you can redistribute it and/or modify
   28.10 + *  it under the terms of the GNU General Public License as published by
   28.11 + *  the Free Software Foundation; either version 2 of the License, or
   28.12 + *  (at your option) any later version.
   28.13 + *
   28.14 + *  This program is distributed in the hope that it will be useful,
   28.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.17 + *  GNU General Public License for more details.
   28.18 + *
   28.19 + *  You should have received a copy of the GNU General Public License
   28.20 + *  along with this program; if not, write to the Free Software
   28.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.22 + *
   28.23 + *  $Id: TemplateParser.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $
   28.24   */
   28.25  
   28.26  package kryshen.tema;
   28.27 @@ -10,12 +24,14 @@
   28.28  import java.util.*;
   28.29  
   28.30  /**
   28.31 - * Parser for DbReader templates.
   28.32 + * Parser for TEMA templates.
   28.33   *
   28.34   * @author Mikhail A. Kryshen
   28.35   */
   28.36  public class TemplateParser {
   28.37 -    static final String SUPER = "SUPER.";
   28.38 +    // TODO: report non-critical errors and warnings.
   28.39 +
   28.40 +    static final String SUPER_PREFIX = "super.";
   28.41  
   28.42      /* Brackets. */
   28.43      static final char[] BR_LEFT = {'<', '['};
   28.44 @@ -28,6 +44,9 @@
   28.45      static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; 
   28.46      static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'};
   28.47  
   28.48 +    /**
   28.49 +     * Methods of parsing function arguments and data.
   28.50 +     */
   28.51      static enum FunctionData {
   28.52  	SUBFUNCTION, RECURSIVE, NONRECURSIVE;
   28.53      };
   28.54 @@ -38,24 +57,22 @@
   28.55  
   28.56      static class Result {
   28.57  	Terminator terminator;
   28.58 -	int substitutions;
   28.59 +	int retCode;
   28.60  
   28.61          /** No text had been parsed. */
   28.62          boolean empty; 
   28.63  
   28.64 -	Result(Terminator terminator, int substitutions, boolean empty) {
   28.65 +	Result(Terminator terminator, int retCode, boolean empty) {
   28.66              this.terminator = terminator;
   28.67 -            this.substitutions = substitutions;
   28.68 +            this.retCode = retCode;
   28.69              this.empty = empty;
   28.70          }
   28.71  
   28.72          Result() {
   28.73 -            this(null, 0, true);
   28.74 +            this(null, -1, true);
   28.75          }       
   28.76      };    
   28.77  
   28.78 -    private Map<String, Function> functions = new HashMap<String, Function>();
   28.79 -
   28.80      private Map<String, Object> variables = new HashMap<String, Object>();
   28.81      private TemplateParser superParser;
   28.82  
   28.83 @@ -71,26 +88,26 @@
   28.84          Functions.registerAllFunctions(this);
   28.85      }
   28.86  
   28.87 -    public void registerFunction(Function f) {
   28.88 -        functions.put(f.name, f);
   28.89 +    public void registerFunction(String name, Function f) {
   28.90 +        variables.put(name, f);
   28.91      }
   28.92  
   28.93 -    public int parse(Reader in, Writer out) 
   28.94 +    public int parse(TemplateReader in, Writer out) 
   28.95  	throws IOException, TemplateException {
   28.96  	
   28.97 -	return parse(in, out, true, null, null).substitutions;
   28.98 +	return parse(in, out, true, null, null).retCode;
   28.99      }
  28.100  
  28.101      /**
  28.102       *  Parse template.
  28.103       *
  28.104 -     * @param in Reader to read template data.
  28.105 +     * @param in TemplateReader to read template data.
  28.106       * @param out Writer to write processed data.
  28.107       * @param recursive enables recursive processing.
  28.108       * @param separators characters which terminate parsing block.
  28.109       * @param leading characters to ignore at the beginning of the block.
  28.110       */
  28.111 -    Result parse(Reader in, Writer out, boolean recursive, 
  28.112 +    Result parse(TemplateReader in, Writer out, boolean recursive, 
  28.113                   char[] separators, char[] leading)
  28.114  	throws IOException, TemplateException {
  28.115  
  28.116 @@ -117,10 +134,13 @@
  28.117  
  28.118  	    if (recursive && leftBracket && c == BR_IN) {
  28.119  		
  28.120 +                if (result.retCode < 0)
  28.121 +                    result.retCode = 0;
  28.122 +
  28.123  		lc = -1;
  28.124                  int tb = termBracket;
  28.125                  termBracket = BR_RIGHT[index];
  28.126 -		result.substitutions += parseFunction(in, out);
  28.127 +		result.retCode += parseFunction(in, out);
  28.128                  termBracket = tb;
  28.129  		
  28.130  	    } else if (lc == BR_IN && c == termBracket) {
  28.131 @@ -151,22 +171,6 @@
  28.132  	return result;
  28.133      }
  28.134  
  28.135 -    int parseVariable(String name, Writer out) 
  28.136 -	throws IOException, TemplateException {
  28.137 -
  28.138 -        Object ovalue = getValue(name);
  28.139 -        if (ovalue == null)
  28.140 -            return 0;
  28.141 -
  28.142 -	String svalue = ovalue.toString();
  28.143 -
  28.144 -	if (svalue == null || svalue.length() == 0)
  28.145 -	    return 0;
  28.146 -       
  28.147 -	out.write(svalue);
  28.148 -	return 1;
  28.149 -    }
  28.150 -
  28.151      boolean isSeparator(int c, char[] separators) {
  28.152          for (char p : separators) {
  28.153              if (c == p) return true;
  28.154 @@ -175,7 +179,7 @@
  28.155          return false;
  28.156      }
  28.157  
  28.158 -    int parseFunction(Reader in, Writer out)
  28.159 +    int parseFunction(TemplateReader in, Writer out)
  28.160  	throws IOException, TemplateException {
  28.161          
  28.162  	StringBuffer sb = new StringBuffer();
  28.163 @@ -196,16 +200,28 @@
  28.164  				      FunctionData.NONRECURSIVE, 
  28.165  				      in, out);
  28.166              } else if (c < 0) {
  28.167 -		System.err.println("Error: unexpected end of file.");
  28.168 -		return 0;
  28.169 +		throw new TemplateException("Unexpected end of file.", in);
  28.170              } else {
  28.171  		sb.append((char)c);
  28.172  	    }
  28.173  	}
  28.174      }
  28.175  
  28.176 +    int parseValue(Object value, Writer out) throws IOException {
  28.177 +        if (value == null)
  28.178 +            return 0;
  28.179 +
  28.180 +        String svalue = value.toString();
  28.181 +        
  28.182 +        if (svalue == null || svalue.length() == 0)
  28.183 +            return 0;
  28.184 +
  28.185 +        out.write(svalue);
  28.186 +        return 1;
  28.187 +    }
  28.188 +
  28.189      private int invokeFunction(String name, FunctionData fd,
  28.190 -			       Reader in, Writer out)
  28.191 +			       TemplateReader in, Writer out)
  28.192  	throws IOException, TemplateException {
  28.193  
  28.194          FunctionDataParser fdp = new FunctionDataParser(this, fd, in);
  28.195 @@ -214,14 +230,15 @@
  28.196              return fdp.parseData(out);
  28.197  	}
  28.198          
  28.199 -        Function f = getFunction(name);
  28.200 +        Object value = getValue(name);
  28.201 +        int r;
  28.202  
  28.203 -        if (f == null) {
  28.204 -	    throw new TemplateException("Unknown function: " + name);
  28.205 +        if (value instanceof Function) {            
  28.206 +            r = ((Function) value).invoke(fdp, out);           
  28.207 +        } else { 
  28.208 +            r = parseValue(value, out);
  28.209          }
  28.210  
  28.211 -        int r = f.invoke(fdp, out);
  28.212 -
  28.213  	if (fdp.hasMoreData()) {
  28.214  	    /* Skip remaining function data. */
  28.215  	    fdp.parseData(new Writer() {
  28.216 @@ -234,27 +251,14 @@
  28.217  	return r;
  28.218      }
  28.219  
  28.220 -    Function getFunction(String name) throws TemplateException {
  28.221 -	Function function = functions.get(name);
  28.222 -	if (function != null) return function;   
  28.223 -
  28.224 -	if (superParser != null) {
  28.225 -	    if (name.startsWith(SUPER))
  28.226 -		return superParser.getFunction(name.substring(SUPER.length()));
  28.227 -	    else
  28.228 -		return superParser.getFunction(name);
  28.229 -	}
  28.230 -
  28.231 -	return null;
  28.232 -    }
  28.233 -
  28.234 -    Object getValue(String name) throws TemplateException {
  28.235 +    public Object getValue(String name) throws TemplateException {
  28.236  	Object value = variables.get(name);
  28.237  	if (value != null) return value;   
  28.238  
  28.239  	if (superParser != null) {
  28.240 -	    if (name.startsWith(SUPER))
  28.241 -		return superParser.getValue(name.substring(SUPER.length()));
  28.242 +	    if (name.startsWith(SUPER_PREFIX))
  28.243 +		return superParser.getValue
  28.244 +                    (name.substring(SUPER_PREFIX.length()));
  28.245  	    else
  28.246  		return superParser.getValue(name);
  28.247  	}
  28.248 @@ -262,21 +266,26 @@
  28.249  	return null;
  28.250      }
  28.251  
  28.252 -    void setValue(String name, Object value) {
  28.253 +    public void setValue(String name, Object value) {
  28.254  	variables.put(name, value);
  28.255      }
  28.256  
  28.257 -    void clearValues() {
  28.258 +    public void clearValues() {
  28.259  	variables.clear();
  28.260 +        Functions.registerAllFunctions(this);
  28.261      }
  28.262  
  28.263      // TEST
  28.264 -    public static void main(String[] args) 
  28.265 +    public static void main(String[] args)
  28.266  	throws IOException, TemplateException {
  28.267  	
  28.268  	TemplateParser p = new TemplateParser();
  28.269  	
  28.270 -	FileReader in = new FileReader("parser.in");
  28.271 +	TemplateReader in = 
  28.272 +            new TemplateReader
  28.273 +            (new LineNumberReader
  28.274 +             (new FileReader("parser.in")), "parser.in");
  28.275 +
  28.276  	FileWriter out = new FileWriter("parser.out");
  28.277  
  28.278  	p.parse(in, out);
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/src/kryshen/tema/TemplateReader.java	Thu Dec 14 23:22:05 2006 +0300
    29.3 @@ -0,0 +1,64 @@
    29.4 +/*
    29.5 + *  Copyright (C) 2006 Mikhail A. Kryshen
    29.6 + *
    29.7 + *  This program is free software; you can redistribute it and/or modify
    29.8 + *  it under the terms of the GNU General Public License as published by
    29.9 + *  the Free Software Foundation; either version 2 of the License, or
   29.10 + *  (at your option) any later version.
   29.11 + *
   29.12 + *  This program is distributed in the hope that it will be useful,
   29.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.15 + *  GNU General Public License for more details.
   29.16 + *
   29.17 + *  You should have received a copy of the GNU General Public License
   29.18 + *  along with this program; if not, write to the Free Software
   29.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   29.20 + *
   29.21 + *  $Id: TemplateReader.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   29.22 + */
   29.23 +
   29.24 +package kryshen.tema;
   29.25 +
   29.26 +import java.io.Reader;
   29.27 +import java.io.LineNumberReader;
   29.28 +import java.io.FilterReader;
   29.29 +import java.io.IOException;
   29.30 +
   29.31 +/**
   29.32 + * Reader for TEMA templates. Stores data source name (commonly
   29.33 + * filename) and tracks line numbers for error reporting.
   29.34 + *
   29.35 + * @author Mikhail A. Kryshen
   29.36 + */
   29.37 +public class TemplateReader extends FilterReader {
   29.38 +    private String source = null;
   29.39 +
   29.40 +    private LineNumberReader lnReader = null;
   29.41 +    private TemplateReader parentReader = null;
   29.42 +
   29.43 +    public TemplateReader(LineNumberReader in, String source) {
   29.44 +        super(in);
   29.45 +        this.lnReader = in;
   29.46 +        this.source = source;
   29.47 +    }
   29.48 +
   29.49 +    public TemplateReader(Reader in, TemplateReader parent) {
   29.50 +        super(in);
   29.51 +        this.source = source;
   29.52 +    }
   29.53 +
   29.54 +    public String getSource() {
   29.55 +        if (source != null)
   29.56 +            return source;
   29.57 +        
   29.58 +        return parentReader.getSource();
   29.59 +    }
   29.60 +    
   29.61 +    public int getLineNumber() {
   29.62 +        if (lnReader != null)
   29.63 +            return lnReader.getLineNumber();
   29.64 +        
   29.65 +        return parentReader.getLineNumber();
   29.66 +    }
   29.67 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/src/kryshen/tema/demo/DemoFrame.java	Thu Dec 14 23:22:05 2006 +0300
    30.3 @@ -0,0 +1,181 @@
    30.4 +/*
    30.5 + *  Copyright (C) 2006 Mikhail A. Kryshen
    30.6 + *
    30.7 + *  This program is free software; you can redistribute it and/or modify
    30.8 + *  it under the terms of the GNU General Public License as published by
    30.9 + *  the Free Software Foundation; either version 2 of the License, or
   30.10 + *  (at your option) any later version.
   30.11 + *
   30.12 + *  This program is distributed in the hope that it will be useful,
   30.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.15 + *  GNU General Public License for more details.
   30.16 + *
   30.17 + *  You should have received a copy of the GNU General Public License
   30.18 + *  along with this program; if not, write to the Free Software
   30.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   30.20 + *
   30.21 + *  $Id: DemoFrame.java,v 1.3 2006/12/14 15:59:48 mikhail Exp $
   30.22 + */
   30.23 +
   30.24 +package kryshen.tema.demo;
   30.25 +
   30.26 +import java.awt.*;
   30.27 +import java.awt.event.*;
   30.28 +import java.io.*;
   30.29 +import java.net.URL;
   30.30 +
   30.31 +import kryshen.tema.*;
   30.32 +
   30.33 +/**
   30.34 + * TEMA demonstation console.
   30.35 + */
   30.36 +public class DemoFrame extends Frame {
   30.37 +    private TextArea input;
   30.38 +    private TextArea output;
   30.39 +    private TextArea error;
   30.40 +    
   30.41 +    public DemoFrame() {
   30.42 +        super("TEMA demo console");
   30.43 +
   30.44 +        GridBagLayout gbl = new GridBagLayout();
   30.45 +
   30.46 +        GridBagConstraints c = new GridBagConstraints();
   30.47 +
   30.48 +        setLayout(gbl);
   30.49 +
   30.50 +        input = new TextArea(25, 40);
   30.51 +        input.setEditable(true);
   30.52 +
   30.53 +        output = new TextArea(25, 40);
   30.54 +        output.setEditable(false);
   30.55 +
   30.56 +        error = new TextArea(5, 80);
   30.57 +        error.setEditable(false);
   30.58 +
   30.59 +        Label l;
   30.60 +
   30.61 +        c.insets = new Insets(3, 3, 3, 3);
   30.62 +        c.fill = GridBagConstraints.BOTH;
   30.63 +        c.gridwidth = GridBagConstraints.RELATIVE;
   30.64 +
   30.65 +        l = new Label("Enter your code and click \"Process\".");
   30.66 +
   30.67 +        gbl.setConstraints(l, c);
   30.68 +        add(l);
   30.69 +
   30.70 +        Panel buttons = new Panel();
   30.71 +        buttons.setLayout(new FlowLayout(FlowLayout.LEFT));
   30.72 +        
   30.73 +        Button process = new Button("Process");
   30.74 +        Button clear = new Button("Clear");
   30.75 +        Button close = new Button("Close");
   30.76 +
   30.77 +        buttons.add(process);
   30.78 +        buttons.add(clear);
   30.79 +        buttons.add(close);
   30.80 +
   30.81 +        c.gridwidth = GridBagConstraints.REMAINDER; 
   30.82 +
   30.83 +        gbl.setConstraints(buttons, c);
   30.84 +        add(buttons);
   30.85 +
   30.86 +        c.fill = GridBagConstraints.BOTH;
   30.87 +        c.anchor = GridBagConstraints.CENTER;
   30.88 +        c.gridwidth = GridBagConstraints.RELATIVE;
   30.89 +
   30.90 +        l = new Label("Input:");
   30.91 +
   30.92 +        gbl.setConstraints(l, c);
   30.93 +        add(l);
   30.94 +
   30.95 +        c.gridwidth = GridBagConstraints.REMAINDER; 
   30.96 +
   30.97 +        l = new Label("Output:");
   30.98 +
   30.99 +        gbl.setConstraints(l, c);
  30.100 +        add(l);
  30.101 +
  30.102 +        c.gridwidth = GridBagConstraints.RELATIVE; 
  30.103 +
  30.104 +        gbl.setConstraints(input, c);
  30.105 +        add(input);
  30.106 +       
  30.107 +        c.gridwidth = GridBagConstraints.REMAINDER; 
  30.108 +
  30.109 +        gbl.setConstraints(output, c);
  30.110 +        add(output);
  30.111 +
  30.112 +        l = new Label("Errors:");
  30.113 +
  30.114 +        gbl.setConstraints(l, c);
  30.115 +        add(l);
  30.116 +
  30.117 +        gbl.setConstraints(error, c);
  30.118 +        add(error);      
  30.119 +
  30.120 +        process.addActionListener(new ActionListener() {
  30.121 +                public void actionPerformed(ActionEvent e) {
  30.122 +                    process();
  30.123 +                }
  30.124 +            });
  30.125 +
  30.126 +        clear.addActionListener(new ActionListener() {
  30.127 +                public void actionPerformed(ActionEvent e) {
  30.128 +                    error.setText("");
  30.129 +                    output.setText("");
  30.130 +                    input.setText("");
  30.131 +                    
  30.132 +                }
  30.133 +            });
  30.134 +
  30.135 +        close.addActionListener(new ActionListener() {
  30.136 +                public void actionPerformed(ActionEvent e) {
  30.137 +                    dispose();
  30.138 +                }
  30.139 +            });
  30.140 +
  30.141 +        addWindowListener(new WindowAdapter() {
  30.142 +                public void windowClosing(WindowEvent e) {
  30.143 +                    dispose();
  30.144 +                }
  30.145 +            });
  30.146 +        
  30.147 +        URL source = getClass().getResource("demo.template");
  30.148 +        StringBuffer buffer = new StringBuffer();
  30.149 +
  30.150 +        try {
  30.151 +            Reader in = new BufferedReader
  30.152 +                (new InputStreamReader(source.openStream(), "UTF-8"));           
  30.153 +            
  30.154 +            for (int ch = in.read(); ch >= 0; ch = in.read()) {
  30.155 +                buffer.append((char)ch);
  30.156 +            }
  30.157 +
  30.158 +            in.close();
  30.159 +        } catch (IOException e) {
  30.160 +            e.printStackTrace();
  30.161 +        }
  30.162 +        
  30.163 +        input.setText(buffer.toString());
  30.164 +    }
  30.165 +
  30.166 +    private void process() {
  30.167 +        String s = input.getText();
  30.168 +        
  30.169 +        TemplateReader tr = new TemplateReader
  30.170 +            (new LineNumberReader(new StringReader(s)), "input");
  30.171 +        TemplateParser tp = new TemplateParser();
  30.172 +        StringWriter sw = new StringWriter();
  30.173 +
  30.174 +        error.setText("");
  30.175 +
  30.176 +        try {
  30.177 +            tp.parse(tr, sw);
  30.178 +        } catch (Exception e) {
  30.179 +            error.setText(e.toString());
  30.180 +        }
  30.181 +
  30.182 +        output.setText(sw.toString());
  30.183 +    }
  30.184 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/kryshen/tema/demo/Hello.java	Thu Dec 14 23:22:05 2006 +0300
    31.3 @@ -0,0 +1,43 @@
    31.4 +/*
    31.5 + *  Copyright (C) 2006 Mikhail A. Kryshen
    31.6 + *
    31.7 + *  This program is free software; you can redistribute it and/or modify
    31.8 + *  it under the terms of the GNU General Public License as published by
    31.9 + *  the Free Software Foundation; either version 2 of the License, or
   31.10 + *  (at your option) any later version.
   31.11 + *
   31.12 + *  This program is distributed in the hope that it will be useful,
   31.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.15 + *  GNU General Public License for more details.
   31.16 + *
   31.17 + *  You should have received a copy of the GNU General Public License
   31.18 + *  along with this program; if not, write to the Free Software
   31.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   31.20 + *
   31.21 + *  $Id: Hello.java,v 1.2 2006/12/14 14:39:24 mikhail Exp $
   31.22 + */
   31.23 +
   31.24 +package kryshen.tema.demo;
   31.25 +
   31.26 +import java.io.Writer;
   31.27 +import java.io.IOException;
   31.28 +import kryshen.tema.*;
   31.29 +
   31.30 +/**
   31.31 + * Example function implementation.
   31.32 + * 
   31.33 + * @author Mikhail A. Kryshen
   31.34 + */
   31.35 +public class Hello extends Function {
   31.36 +    public Hello() {}
   31.37 +
   31.38 +    public int invoke(FunctionDataParser fdp, Writer out)
   31.39 +        throws IOException, TemplateException {
   31.40 +        
   31.41 +        out.write("Hello, ");
   31.42 +        fdp.parseData(out);
   31.43 +
   31.44 +        return 1;
   31.45 +    }
   31.46 +}
    32.1 --- a/src/kryshen/tema/functions/Define.java	Tue May 16 18:04:09 2006 +0400
    32.2 +++ b/src/kryshen/tema/functions/Define.java	Thu Dec 14 23:22:05 2006 +0300
    32.3 @@ -1,7 +1,21 @@
    32.4  /*
    32.5 - * Copyright (C) 2006 Mikhail A. Kryshen
    32.6 + *  Copyright (C) 2006 Mikhail A. Kryshen
    32.7   *
    32.8 - * $Id: Define.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
    32.9 + *  This program is free software; you can redistribute it and/or modify
   32.10 + *  it under the terms of the GNU General Public License as published by
   32.11 + *  the Free Software Foundation; either version 2 of the License, or
   32.12 + *  (at your option) any later version.
   32.13 + *
   32.14 + *  This program is distributed in the hope that it will be useful,
   32.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.17 + *  GNU General Public License for more details.
   32.18 + *
   32.19 + *  You should have received a copy of the GNU General Public License
   32.20 + *  along with this program; if not, write to the Free Software
   32.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   32.22 + *
   32.23 + *  $Id: Define.java,v 1.7 2006/12/14 14:35:00 mikhail Exp $
   32.24   */
   32.25  
   32.26  package kryshen.tema.functions;
   32.27 @@ -11,9 +25,15 @@
   32.28  
   32.29  import kryshen.tema.*;
   32.30  
   32.31 +/**
   32.32 + * Define function implementation.
   32.33 + *
   32.34 + * @author Mikhail A. Kryshen
   32.35 + */
   32.36  public class Define extends Function {
   32.37 +    public static final Function DEFINE = new Define();
   32.38 +
   32.39      public Define() {
   32.40 -        super("define");
   32.41      }
   32.42  
   32.43      public int invoke(FunctionDataParser fdp, Writer out)
   32.44 @@ -22,37 +42,42 @@
   32.45          final String arg0 = fdp.getNextArg();
   32.46          final String data = fdp.getData();
   32.47  
   32.48 -        Function newFunction = new Function(arg0) {
   32.49 +        Function newFunction = new Function() {
   32.50                  public int invoke(final FunctionDataParser fdp, final Writer out)
   32.51                      throws IOException, TemplateException {
   32.52 -
   32.53 +		    
   32.54                      TemplateParser functionParser = 
   32.55                          new TemplateParser(fdp.getTemplateParser());
   32.56                      
   32.57 -                    functionParser.registerFunction(new Function("nextarg") {
   32.58 -                            public int invoke(FunctionDataParser unusedFdp, 
   32.59 -                                              final Writer out)
   32.60 -                                throws IOException, TemplateException {
   32.61 +                    functionParser.registerFunction
   32.62 +			("nextarg", new Function() {
   32.63 +				public int invoke(FunctionDataParser unusedFdp, 
   32.64 +						  final Writer out)
   32.65 +				    throws IOException, TemplateException {
   32.66 +				    
   32.67 +				    return fdp.parseNextArg(out);
   32.68 +				}
   32.69 +			    });
   32.70 +		    
   32.71 +                    functionParser.registerFunction
   32.72 +			("data",new Function() {
   32.73 +				public int invoke(FunctionDataParser unusedFdp, 
   32.74 +						  final Writer out)
   32.75 +				    throws IOException, TemplateException {
   32.76 +				    
   32.77 +				    return fdp.parseData(out);
   32.78 +				}
   32.79 +			    });
   32.80 +		    
   32.81 +                    TemplateReader dataReader = new TemplateReader
   32.82 +                        (new StringReader(data), fdp.getTemplateReader());
   32.83  
   32.84 -                                return fdp.parseNextArg(out);
   32.85 -                            }
   32.86 -                        });
   32.87 -
   32.88 -                    functionParser.registerFunction(new Function("data") {
   32.89 -                            public int invoke(FunctionDataParser unusedFdp, 
   32.90 -                                              final Writer out)
   32.91 -                                throws IOException, TemplateException {
   32.92 -
   32.93 -                                return fdp.parseData(out);
   32.94 -                            }
   32.95 -                        });
   32.96 -
   32.97 -                    return functionParser.parse(new StringReader(data), out);                                       
   32.98 +                    return functionParser.parse(dataReader, out);
   32.99                  }
  32.100              };
  32.101 -
  32.102 -        fdp.getTemplateParser().registerFunction(newFunction);
  32.103 -
  32.104 +	
  32.105 +        fdp.getTemplateParser().registerFunction(arg0, newFunction);
  32.106 +	
  32.107          out.write(arg0);
  32.108          return 1;
  32.109      }
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/src/kryshen/tema/functions/IO.java	Thu Dec 14 23:22:05 2006 +0300
    33.3 @@ -0,0 +1,163 @@
    33.4 +/*
    33.5 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    33.6 + *
    33.7 + *  This program is free software; you can redistribute it and/or modify
    33.8 + *  it under the terms of the GNU General Public License as published by
    33.9 + *  the Free Software Foundation; either version 2 of the License, or
   33.10 + *  (at your option) any later version.
   33.11 + *
   33.12 + *  This program is distributed in the hope that it will be useful,
   33.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 + *  GNU General Public License for more details.
   33.16 + *
   33.17 + *  You should have received a copy of the GNU General Public License
   33.18 + *  along with this program; if not, write to the Free Software
   33.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   33.20 + *
   33.21 + *  $Id: IO.java,v 1.4 2006/12/14 15:59:49 mikhail Exp $
   33.22 + */
   33.23 +
   33.24 +package kryshen.tema.functions;
   33.25 +
   33.26 +import java.io.*;
   33.27 +import java.util.*;
   33.28 +
   33.29 +import kryshen.tema.*;
   33.30 +
   33.31 +/**
   33.32 + * I/O functions.
   33.33 + */
   33.34 +public class IO {
   33.35 +    public static final Function COPY =
   33.36 +        new Function() {
   33.37 +           public int invoke(FunctionDataParser fdp, Writer out)
   33.38 +                throws IOException, TemplateException {
   33.39 +
   33.40 +                String arg0 = fdp.getNextArg();
   33.41 +                String arg1 = fdp.getNextArg();
   33.42 +
   33.43 +                File source = new File
   33.44 +                    (Tema.getProperty("resource_base"), arg0);
   33.45 +                File dest = new File(arg1);
   33.46 +                
   33.47 +                try {
   33.48 +                    copyFile(source, dest);
   33.49 +                } catch (IOException e) {
   33.50 +                    System.err.println(e);
   33.51 +                    return 0;
   33.52 +                }
   33.53 +                out.write(arg1);
   33.54 +                return 1;
   33.55 +            }
   33.56 +        };
   33.57 +
   33.58 +    public static final Function WRITE =
   33.59 +        new Function() {
   33.60 +           public int invoke(FunctionDataParser fdp, Writer out)
   33.61 +                throws IOException, TemplateException {
   33.62 +
   33.63 +                String arg0 = fdp.getNextArg();
   33.64 +
   33.65 +		System.err.println("Writing " + arg0 + "...");
   33.66 +
   33.67 +                Writer fw;
   33.68 +
   33.69 +                try {
   33.70 +		    fw = Tema.createFileWriter(arg0);
   33.71 +                } catch (IOException e) {
   33.72 +                    System.err.println(e);
   33.73 +                    //throw new TemplateException(e.getMessage(), e, in);
   33.74 +                    return 0;
   33.75 +                }
   33.76 +
   33.77 +                try {
   33.78 +		    fdp.parseData(fw);
   33.79 +                } finally {
   33.80 +                    fw.close();
   33.81 +                }
   33.82 +
   33.83 +                out.write(arg0);
   33.84 +
   33.85 +		System.err.println("Saved " + arg0 + ".");
   33.86 +                return 1;
   33.87 +            }
   33.88 +        };
   33.89 +
   33.90 +    public static final Function READ =
   33.91 +        new Function() {
   33.92 +           public int invoke(FunctionDataParser fdp, Writer out)
   33.93 +                throws IOException, TemplateException {
   33.94 +
   33.95 +	       String filename = fdp.getData();
   33.96 +	       String file;
   33.97 +	       
   33.98 +                try {
   33.99 +                    file = Tema.readFile(new File(filename));
  33.100 +                } catch (IOException e) {
  33.101 +                    System.err.println(e);
  33.102 +                    //throw new TemplateException(e.getMessage(), e, in);
  33.103 +                    return 0;
  33.104 +                }
  33.105 +		
  33.106 +                out.write(file);
  33.107 +                return 1;
  33.108 +            }
  33.109 +        };
  33.110 +
  33.111 +    public static final Function INCLUDE =
  33.112 +        new Function() {
  33.113 +           public int invoke(FunctionDataParser fdp, Writer out)
  33.114 +                throws IOException, TemplateException {
  33.115 +                
  33.116 +                String filename = fdp.getData();
  33.117 +                
  33.118 +                TemplateReader fin;
  33.119 +
  33.120 +                try {
  33.121 +                    fin = Tema.createTemplateReader(new File(filename));
  33.122 +                } catch (IOException e) {
  33.123 +                    throw new TemplateException(e.getMessage(), e,
  33.124 +                                                fdp.getTemplateReader());
  33.125 +                }
  33.126 +
  33.127 +                int r = fdp.getTemplateParser().parse(fin, out);
  33.128 +
  33.129 +                fin.close();
  33.130 +                return r;
  33.131 +            }
  33.132 +        };
  33.133 +
  33.134 +    /**
  33.135 +     * Update file (copy if newer).
  33.136 +     *
  33.137 +     * @param src source file.
  33.138 +     * @param dest destination file.
  33.139 +     *
  33.140 +     * @trows IOException on copying error.
  33.141 +     */
  33.142 +    private static void copyFile(File src, File dest) throws IOException {
  33.143 +	System.err.print("Copying " + src + "... ");
  33.144 +	
  33.145 +	if (src.lastModified() < dest.lastModified()) {
  33.146 +	    System.err.println(dest + " is up to date.");
  33.147 +	    return;
  33.148 +	}
  33.149 +
  33.150 +	File parent = dest.getParentFile();
  33.151 +	if (parent != null) parent.mkdirs();
  33.152 +
  33.153 +        InputStream in = new FileInputStream(src);
  33.154 +        OutputStream out = new FileOutputStream(dest);
  33.155 +        
  33.156 +        byte[] buffer = new byte[1024];
  33.157 +        int len;
  33.158 +        while ((len = in.read(buffer)) > 0) {
  33.159 +            out.write(buffer, 0, len);
  33.160 +        }
  33.161 +        in.close();
  33.162 +        out.close();
  33.163 +
  33.164 +	System.err.println("saved " + dest + ".");
  33.165 +    }
  33.166 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/src/kryshen/tema/functions/ImageConverter.java	Thu Dec 14 23:22:05 2006 +0300
    34.3 @@ -0,0 +1,188 @@
    34.4 +/*
    34.5 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    34.6 + *
    34.7 + *  This program is free software; you can redistribute it and/or modify
    34.8 + *  it under the terms of the GNU General Public License as published by
    34.9 + *  the Free Software Foundation; either version 2 of the License, or
   34.10 + *  (at your option) any later version.
   34.11 + *
   34.12 + *  This program is distributed in the hope that it will be useful,
   34.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.15 + *  GNU General Public License for more details.
   34.16 + *
   34.17 + *  You should have received a copy of the GNU General Public License
   34.18 + *  along with this program; if not, write to the Free Software
   34.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   34.20 + *
   34.21 + *  $Id: ImageConverter.java,v 1.4 2006/12/14 19:44:32 mikhail Exp $
   34.22 + */
   34.23 +
   34.24 +package kryshen.tema.functions;
   34.25 +
   34.26 +import java.util.*;
   34.27 +import java.io.*;
   34.28 +import java.awt.*;
   34.29 +import java.awt.image.*;
   34.30 +import java.awt.geom.AffineTransform;
   34.31 +import javax.imageio.*;
   34.32 +import javax.imageio.stream.*;
   34.33 +
   34.34 +import kryshen.tema.*;
   34.35 +
   34.36 +/**
   34.37 + * Convert images to specified format.
   34.38 + *
   34.39 + * @author Mikhail A. Kryshen
   34.40 + */
   34.41 +public class ImageConverter extends Function {    
   34.42 +
   34.43 +    public static final Function IMAGE = new ImageConverter();
   34.44 +
   34.45 +    public int invoke(FunctionDataParser fdp, Writer out)
   34.46 +        throws IOException, TemplateException {
   34.47 +        
   34.48 +        String arg0 = fdp.getNextArg();
   34.49 +        String arg1 = fdp.getNextArg();
   34.50 +        String arg2 = fdp.getNextArg();
   34.51 +        int arg3 = fdp.hasMoreData() ? 
   34.52 +            Integer.parseInt(fdp.getNextArg()) : -1;
   34.53 +        int arg4 = fdp.hasMoreData() ? 
   34.54 +            Integer.parseInt(fdp.getNextArg()) : -1;
   34.55 +        
   34.56 +        File source = new File
   34.57 +            (Tema.getProperty("resource_base"), arg0);
   34.58 +        
   34.59 +        try {
   34.60 +            convert
   34.61 +                (source,                  /* source file */
   34.62 +                 new File(arg1),          /* dest file */
   34.63 +                 arg2,                    /* format */
   34.64 +                 arg3,                    /* max width */
   34.65 +                 arg4);                   /* max height */
   34.66 +        } catch (Exception e) {
   34.67 +            System.err.println(e);
   34.68 +            return 0;
   34.69 +        }
   34.70 +        
   34.71 +        out.write(arg1);
   34.72 +        return 1;
   34.73 +    }    
   34.74 +    
   34.75 +    public static void convert(File source, File dest, String format,
   34.76 +                               int maxWidth, int maxHeight) 
   34.77 +	throws IOException, InterruptedException {
   34.78 +	
   34.79 +	System.err.print("Converting image " + source + "... ");
   34.80 +        
   34.81 +	if (source.lastModified() < dest.lastModified()) {
   34.82 +	    System.err.println(dest + " is up to date.");
   34.83 +	    return;
   34.84 +	}
   34.85 +
   34.86 +	BufferedImage image = ImageIO.read(source);
   34.87 +
   34.88 +	//int type = image.getType();
   34.89 +	//final int type = BufferedImage.TYPE_INT_RGB;
   34.90 +	//ColorModel cm = image.getColorModel();
   34.91 +
   34.92 +        int w = image.getWidth(null);
   34.93 +        int h = image.getHeight(null);
   34.94 +
   34.95 +	//boolean scale = false;
   34.96 +
   34.97 +	float scale = 1f;
   34.98 +
   34.99 +	if (maxWidth > 0 && w > maxWidth)
  34.100 +	    scale = (float)maxWidth / w;
  34.101 +	
  34.102 +	if (maxHeight > 0 && h * scale > maxHeight)
  34.103 +	    scale = (float)maxHeight / h;
  34.104 +
  34.105 +	if (scale != 1f) {
  34.106 +	    w *= scale; h *= scale;
  34.107 +
  34.108 +// 	    ColorModel cm = image.getColorModel();	    
  34.109 +// 	    boolean alphaPremultiplied = cm.isAlphaPremultiplied();
  34.110 +// 	    WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
  34.111 +// 	    BufferedImage scaled = new BufferedImage
  34.112 +// 		(cm, raster, alphaPremultiplied, null);
  34.113 +
  34.114 +// 	    BufferedImage scaled = new BufferedImage(w, h, image.getType());
  34.115 +	    
  34.116 +
  34.117 + 	    Image scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH);
  34.118 +
  34.119 + 	    ColorModel cm = image.getColorModel();	    
  34.120 + 	    boolean alphaPremultiplied = image.isAlphaPremultiplied();
  34.121 + 	    WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
  34.122 + 	    image = new BufferedImage(cm, raster, alphaPremultiplied, null);
  34.123 +
  34.124 +	    Graphics g = image.getGraphics();
  34.125 +	    g.drawImage(scaled, 0, 0, null);
  34.126 +	    g.dispose();
  34.127 +
  34.128 +//	    image = scale(image, scaled, scale);
  34.129 +//	    Graphics2D g = scaled.createGraphics();
  34.130 +//	    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
  34.131 +// 			       RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  34.132 +// 	    System.err.print(" " + g.drawImage(image, 0, 0, w, h, null) + " ");
  34.133 +// 	    g.dispose();
  34.134 +// 	    image = scaled;
  34.135 +	}
  34.136 +       
  34.137 +	File parent = dest.getParentFile();
  34.138 +	if (parent != null) parent.mkdirs();
  34.139 +
  34.140 + 	ImageIO.write(image, format, dest);
  34.141 +	System.err.println("saved " + dest + ".");	
  34.142 +    }
  34.143 +
  34.144 +//     public static ColorModel getColorModel(Image image) 
  34.145 +// 	throws InterruptedException {
  34.146 +
  34.147 +// 	PixelGrabber grabby = new PixelGrabber(image, 0, 0, 1, 1, false);
  34.148 +// 	if (!grabby.grabPixels())
  34.149 +// 	    throw new RuntimeException("pixel grab fails");
  34.150 +// 	return grabby.getColorModel();
  34.151 +//     }
  34.152 +
  34.153 +//     private static BufferedImage scale(BufferedImage image, 
  34.154 +// 				       BufferedImage dest, 
  34.155 +// 				       float scale) {
  34.156 +
  34.157 +// 	AffineTransform tx = new AffineTransform();
  34.158 +// 	tx.scale(scale, scale);
  34.159 +
  34.160 +//  	AffineTransformOp op = new AffineTransformOp
  34.161 +//  	    (tx, AffineTransformOp.TYPE_BILINEAR);
  34.162 +
  34.163 +// 	return op.filter(image, dest);
  34.164 +//     }
  34.165 +
  34.166 +    // TEST    
  34.167 +    public static void main(String[] args) 
  34.168 +	throws IOException, InterruptedException {
  34.169 +
  34.170 +	convert(new File(args[0]), new File(args[1]), "png", 300, 300);
  34.171 +    }
  34.172 +
  34.173 +
  34.174 +//     public static BufferedImage toBufferedImage(Image image, ColorModel cm) {
  34.175 +// 	if (image instanceof BufferedImage)
  34.176 +// 	    return (BufferedImage)image;
  34.177 +
  34.178 +// 	int w = image.getWidth(null);
  34.179 +// 	int h = image.getHeight(null);
  34.180 +
  34.181 +// 	boolean alphaPremultiplied = cm.isAlphaPremultiplied();
  34.182 +// 	WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
  34.183 +// 	BufferedImage result = new BufferedImage(cm, raster, alphaPremultiplied, null);
  34.184 +// 	Graphics2D g = result.createGraphics();
  34.185 +
  34.186 +// 	g.drawImage(image, 0, 0, null);
  34.187 +// 	g.dispose();
  34.188 +
  34.189 +// 	return result;
  34.190 +//     }
  34.191 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/kryshen/tema/functions/Logics.java	Thu Dec 14 23:22:05 2006 +0300
    35.3 @@ -0,0 +1,75 @@
    35.4 +/*
    35.5 + *  Copyright (C) 2006 Mikhail A. Kryshen
    35.6 + *
    35.7 + *  This program is free software; you can redistribute it and/or modify
    35.8 + *  it under the terms of the GNU General Public License as published by
    35.9 + *  the Free Software Foundation; either version 2 of the License, or
   35.10 + *  (at your option) any later version.
   35.11 + *
   35.12 + *  This program is distributed in the hope that it will be useful,
   35.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.15 + *  GNU General Public License for more details.
   35.16 + *
   35.17 + *  You should have received a copy of the GNU General Public License
   35.18 + *  along with this program; if not, write to the Free Software
   35.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   35.20 + *
   35.21 + *  $Id: Logics.java,v 1.6 2006/12/14 14:39:26 mikhail Exp $
   35.22 + */
   35.23 +
   35.24 +package kryshen.tema.functions;
   35.25 +
   35.26 +import java.io.*;
   35.27 +import java.util.*;
   35.28 +
   35.29 +import kryshen.tema.*;
   35.30 +
   35.31 +/**
   35.32 + * Logical and conditional functions.
   35.33 + *
   35.34 + * @author Mikhail A. Kryshen
   35.35 + */
   35.36 +public class Logics {
   35.37 +    public static final Function FALSE =
   35.38 +        new Function() {
   35.39 +            public int invoke(FunctionDataParser fdp, Writer out)
   35.40 +                throws IOException, TemplateException {
   35.41 +		
   35.42 +		fdp.parseData(out);
   35.43 +                return 0;
   35.44 +            }
   35.45 +        };
   35.46 +
   35.47 +    public static final Function TRUE =
   35.48 +        new Function() {
   35.49 +            public int invoke(FunctionDataParser fdp, Writer out)
   35.50 +                throws IOException, TemplateException {
   35.51 +		
   35.52 +		fdp.parseData(out);
   35.53 +                return 1;
   35.54 +            }
   35.55 +        };
   35.56 +
   35.57 +    /**
   35.58 +     * Outputs it's data it has non-zero value.
   35.59 +     */
   35.60 +    public static final Function OPTIONAL =
   35.61 +        new Function() {
   35.62 +            public int invoke(FunctionDataParser fdp, Writer out)
   35.63 +                throws IOException, TemplateException {
   35.64 +
   35.65 +                StringWriter sw = new StringWriter();
   35.66 +                int s = fdp.parseData(sw);
   35.67 +                sw.close();
   35.68 +                String data = sw.toString();
   35.69 +
   35.70 +                if (s != 0) {
   35.71 +                    out.write(data);
   35.72 +                    return 1;
   35.73 +                } else {
   35.74 +                    return 0;
   35.75 +                }
   35.76 +            }
   35.77 +        };
   35.78 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/src/kryshen/tema/functions/ReplaceWriter.java	Thu Dec 14 23:22:05 2006 +0300
    36.3 @@ -0,0 +1,154 @@
    36.4 +/*
    36.5 + *  Copyright (C) 2006 Mikhail A. Kryshen
    36.6 + *
    36.7 + *  This program is free software; you can redistribute it and/or modify
    36.8 + *  it under the terms of the GNU General Public License as published by
    36.9 + *  the Free Software Foundation; either version 2 of the License, or
   36.10 + *  (at your option) any later version.
   36.11 + *
   36.12 + *  This program is distributed in the hope that it will be useful,
   36.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.15 + *  GNU General Public License for more details.
   36.16 + *
   36.17 + *  You should have received a copy of the GNU General Public License
   36.18 + *  along with this program; if not, write to the Free Software
   36.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   36.20 + *
   36.21 + *  $Id: ReplaceWriter.java,v 1.2 2006/12/14 14:39:26 mikhail Exp $
   36.22 + */
   36.23 +
   36.24 +package kryshen.tema.functions;
   36.25 +
   36.26 +import java.io.Writer;
   36.27 +import java.io.FilterWriter;
   36.28 +import java.io.IOException;
   36.29 +
   36.30 +import java.util.LinkedList;
   36.31 +import java.util.Iterator;
   36.32 +
   36.33 +/**
   36.34 + * FilterWriter which replaces characters with escape strings.
   36.35 + *
   36.36 + * @author Mikhail A. Kryshen
   36.37 + */
   36.38 +class ReplaceWriter extends FilterWriter {
   36.39 +    private String[] patterns;
   36.40 +    private String[] replaces;
   36.41 +
   36.42 +    private String prefix;
   36.43 +    private String postfix;
   36.44 +
   36.45 +    private int maxPatternLength = 0;
   36.46 +
   36.47 +    /** Have this Writer processed any data? */
   36.48 +    private boolean processedData = false;
   36.49 +
   36.50 +    private StringBuffer buffer = new StringBuffer();
   36.51 +
   36.52 +    public ReplaceWriter(Writer w, String pattern, String replace) {
   36.53 +        this(w, new String[]{pattern}, new String[]{replace});
   36.54 +    }
   36.55 +
   36.56 +    public ReplaceWriter(Writer w, String pattern, String replace,
   36.57 +                         String prefix, String postfix) {
   36.58 +
   36.59 +        this(w, new String[]{pattern}, new String[]{replace}, 
   36.60 +             prefix, postfix);
   36.61 +    }
   36.62 +
   36.63 +    public ReplaceWriter(Writer w, String[] patterns, String[] replaces) {
   36.64 +        this(w, patterns, replaces, null, null);
   36.65 +    }
   36.66 +
   36.67 +    public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 
   36.68 +                         String prefix, String postfix) {
   36.69 +	super(w);
   36.70 +        
   36.71 +	this.patterns = patterns;
   36.72 +	this.replaces = replaces;
   36.73 +        
   36.74 +        this.prefix = prefix;
   36.75 +        this.postfix = postfix;
   36.76 +        
   36.77 +	for (int i = 0; i < patterns.length; i++) {
   36.78 +	    int length = patterns[i].length();
   36.79 +	    if (length > maxPatternLength)
   36.80 +		maxPatternLength = length;
   36.81 +	}
   36.82 +    }
   36.83 +
   36.84 +    private boolean processBuffer(int minLength) throws IOException {
   36.85 +        if (buffer.length() == 0) return false;
   36.86 +
   36.87 +        if (!processedData) {
   36.88 +            if (prefix != null)
   36.89 +                super.write(prefix, 0, prefix.length());
   36.90 +            processedData = true;
   36.91 +        }
   36.92 +
   36.93 +        int k;
   36.94 +	for (k = 0; minLength + k < buffer.length(); k++) {
   36.95 +	    for (int i = 0; i < patterns.length; i++) {
   36.96 +		String pattern = patterns[i];
   36.97 +		int length = pattern.length();
   36.98 +
   36.99 +                if (length + k > buffer.length())
  36.100 +                    continue;
  36.101 +
  36.102 +		boolean match = true;
  36.103 +
  36.104 +		for (int j = 0; j < length; j++) {
  36.105 +		    if (pattern.charAt(j) != buffer.charAt(j + k)) {
  36.106 +			match = false;
  36.107 +                        break;
  36.108 +		    }
  36.109 +		}
  36.110 +
  36.111 +		if (match) {
  36.112 +                    super.write(buffer.substring(0, k), 0, k);
  36.113 +                    buffer.delete(0, k + length);
  36.114 +                    super.write(replaces[i], 0, replaces[i].length());
  36.115 +		    return true;
  36.116 +		}
  36.117 +	    }
  36.118 +	}
  36.119 +
  36.120 +        super.write(buffer.substring(0, k), 0, k);
  36.121 +        buffer.delete(0, k);
  36.122 +
  36.123 +        return false;
  36.124 +    }
  36.125 +
  36.126 +    public void write(int c) throws IOException {
  36.127 +	buffer.append((char)c);
  36.128 +	processBuffer(maxPatternLength);
  36.129 +    }
  36.130 +
  36.131 +    public void write(char[] cbuf, int off, int len) throws IOException {
  36.132 +	for (int i = off; i < off + len; i++) {
  36.133 +	    buffer.append(cbuf[i]);
  36.134 +	}
  36.135 +	processBuffer(maxPatternLength);
  36.136 +    }
  36.137 +
  36.138 +    public void write(String str, int off, int len) throws IOException {
  36.139 +        buffer.append(str.substring(off, off + len));
  36.140 +	processBuffer(maxPatternLength);
  36.141 +    }
  36.142 +
  36.143 +    public void finish() throws IOException {
  36.144 +        while (processBuffer(0));
  36.145 +
  36.146 +//         super.write(buffer.toString(), 0, buffer.length());
  36.147 +//         buffer.delete(0, buffer.length());
  36.148 +
  36.149 +        if (processedData && postfix != null)
  36.150 +            super.write(postfix, 0, postfix.length());
  36.151 +    }
  36.152 +
  36.153 +    public void close() throws IOException {
  36.154 +        finish();
  36.155 +        super.close();
  36.156 +    }
  36.157 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/src/kryshen/tema/functions/Standard.java	Thu Dec 14 23:22:05 2006 +0300
    37.3 @@ -0,0 +1,258 @@
    37.4 +/*
    37.5 + *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    37.6 + *
    37.7 + *  This program is free software; you can redistribute it and/or modify
    37.8 + *  it under the terms of the GNU General Public License as published by
    37.9 + *  the Free Software Foundation; either version 2 of the License, or
   37.10 + *  (at your option) any later version.
   37.11 + *
   37.12 + *  This program is distributed in the hope that it will be useful,
   37.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.15 + *  GNU General Public License for more details.
   37.16 + *
   37.17 + *  You should have received a copy of the GNU General Public License
   37.18 + *  along with this program; if not, write to the Free Software
   37.19 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   37.20 + *
   37.21 + *  $Id: Standard.java,v 1.5 2006/12/14 14:39:26 mikhail Exp $
   37.22 + */
   37.23 +
   37.24 +package kryshen.tema.functions;
   37.25 +
   37.26 +import java.io.*;
   37.27 +import java.util.*;
   37.28 +import java.net.*;
   37.29 +
   37.30 +import java.sql.SQLException;
   37.31 +import java.sql.PreparedStatement;
   37.32 +
   37.33 +import kryshen.tema.*;
   37.34 +
   37.35 +/**
   37.36 + * Standard TEMA functions.
   37.37 + */
   37.38 +public class Standard {
   37.39 +    public static final Function SET =
   37.40 +        new Function() {
   37.41 +            public int invoke(FunctionDataParser fdp, Writer out)
   37.42 +                throws IOException, TemplateException {
   37.43 +
   37.44 +                String arg0 = fdp.getNextArg();
   37.45 +                String arg1 = fdp.getData();
   37.46 +                
   37.47 +                fdp.getTemplateParser().setValue(arg0, arg1);
   37.48 +                
   37.49 +		out.write(arg0);
   37.50 +                return 1;
   37.51 +            }
   37.52 +        };
   37.53 +
   37.54 +    /* prepare:qury_name sql_statement */
   37.55 +    public static final Function PREPARE =
   37.56 +        new Function() {
   37.57 +            public int invoke(FunctionDataParser fdp, Writer out)
   37.58 +                throws IOException, TemplateException {
   37.59 +
   37.60 +                String arg0 = fdp.getNextArg();
   37.61 +                String data = fdp.getData();
   37.62 +
   37.63 +		PreparedStatement statement;
   37.64 +
   37.65 +		try {
   37.66 +		    statement = Tema.getDbConnection()
   37.67 +                        .prepareStatement(data);
   37.68 +		} catch (SQLException e) {
   37.69 +		    throw new TemplateException
   37.70 +                        (e.getMessage(), e, fdp.getTemplateReader());
   37.71 +		}
   37.72 +                
   37.73 +                fdp.getTemplateParser().setValue(arg0, statement);   
   37.74 +             
   37.75 +		out.write(arg0);
   37.76 +                return 1;
   37.77 +            }
   37.78 +        };
   37.79 +
   37.80 +    /* query:sql_query template arg1 arg2 ... argN */
   37.81 +    public static final Function QUERY =
   37.82 +        new Function() {
   37.83 +           public int invoke(FunctionDataParser fdp, Writer out)
   37.84 +                throws IOException, TemplateException {
   37.85 +                
   37.86 +                String arg0 = fdp.getNextArg();
   37.87 +                String arg1 = fdp.getNextArg();
   37.88 +		List<String> args = fdp.getArgs();				
   37.89 +
   37.90 +		TemplateParser tp = fdp.getTemplateParser();
   37.91 +
   37.92 +                TemplateReader tr = 
   37.93 +                    new TemplateReader(new StringReader(arg1),
   37.94 +                                       fdp.getTemplateReader());
   37.95 +
   37.96 +		try {
   37.97 +		    return Tema.query
   37.98 +			(tr, (PreparedStatement)tp.getValue(arg0),
   37.99 +			 args, tp, out);
  37.100 +		} catch (SQLException e) {
  37.101 +		    throw new TemplateException
  37.102 +                        (e.getMessage(), e, fdp.getTemplateReader());
  37.103 +		}
  37.104 +            }
  37.105 +        };
  37.106 +
  37.107 +    public static final Function REPLACE =
  37.108 +        new Function() {
  37.109 +	    public int invoke(FunctionDataParser fdp, Writer out)
  37.110 +		throws IOException, TemplateException {		
  37.111 +
  37.112 +                String arg0 = fdp.getNextArg();
  37.113 +                String arg1 = fdp.getNextArg();
  37.114 +
  37.115 +                ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1);
  37.116 +
  37.117 +                int ret = fdp.parseData(rw);
  37.118 +                rw.finish();
  37.119 +                return ret;
  37.120 +            }
  37.121 +        };
  37.122 +
  37.123 +    public static final Function LOAD =
  37.124 +
  37.125 +        new Function() {
  37.126 +            public int invoke(FunctionDataParser fdp, Writer out)
  37.127 +                throws IOException, TemplateException {
  37.128 +                
  37.129 +                final String name = fdp.getNextArg();
  37.130 +                final String className = fdp.getNextArg();
  37.131 +
  37.132 +                List<URL> urls = new ArrayList<URL>(1);
  37.133 +
  37.134 +                while (fdp.hasMoreData()) {
  37.135 +                    urls.add(new URL(fdp.getNextArg()));                    
  37.136 +                }
  37.137 +                
  37.138 +                ClassLoader loader = this.getClass().getClassLoader();
  37.139 +
  37.140 +                if (urls.size() > 0) {
  37.141 +                    loader = new URLClassLoader
  37.142 +                        (urls.toArray(new URL[0]), loader);
  37.143 +                }                
  37.144 +
  37.145 +                Class<Function> functionClass;
  37.146 +                Function function;
  37.147 +
  37.148 +                try {
  37.149 +                    functionClass = loadFunctionClass(loader, className);
  37.150 +                } catch (ClassNotFoundException e) {
  37.151 +                    throw new TemplateException
  37.152 +                        ("Class not found", e, fdp.getTemplateReader());
  37.153 +                } catch (ClassCastException e) {
  37.154 +                    throw new TemplateException
  37.155 +                        ("Not a function class", e, fdp.getTemplateReader());
  37.156 +                }
  37.157 +                
  37.158 +                try {
  37.159 +                    function = functionClass.newInstance();
  37.160 +                } catch (InstantiationException e) {
  37.161 +                    throw new TemplateException
  37.162 +                        ("Could not load class", e, fdp.getTemplateReader());
  37.163 +                } catch (IllegalAccessException e) {
  37.164 +                    throw new TemplateException
  37.165 +                        ("Could not load class", e, fdp.getTemplateReader());
  37.166 +                }
  37.167 +
  37.168 +                fdp.getTemplateParser().registerFunction(name, function);
  37.169 +                                
  37.170 +
  37.171 +                out.write(name);
  37.172 +                return 1;
  37.173 +            }
  37.174 +        };
  37.175 +
  37.176 +    public static final Function NULL_OUTPUT =
  37.177 +        new Function() {
  37.178 +	    public int invoke(FunctionDataParser fdp, Writer out)
  37.179 +		throws IOException, TemplateException {		
  37.180 +
  37.181 +		/* Write nothing. */
  37.182 +		return fdp.parseData(new Writer() {
  37.183 +                    public void close() {}
  37.184 +                    public void flush() {}
  37.185 +                    public void write(char[] cbuf, int off, int len) {}
  37.186 +                });
  37.187 +            }
  37.188 +        };
  37.189 +
  37.190 +    public static final Function XML_ESCAPE =
  37.191 +        new Function() {
  37.192 +	    public int invoke(FunctionDataParser fdp, Writer out)
  37.193 +		throws IOException, TemplateException {		
  37.194 +
  37.195 +                final String[] chars = {"&", "<", ">", "`", "\""};
  37.196 +                final String[] escape = {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"};
  37.197 +
  37.198 +                ReplaceWriter rw = new ReplaceWriter(out, chars, escape);
  37.199 +
  37.200 +                int ret = fdp.parseData(rw);
  37.201 +                rw.finish();
  37.202 +                return ret;
  37.203 +            }
  37.204 +        };
  37.205 +
  37.206 +    public static final Function XML_CDATA =
  37.207 +        new Function() {
  37.208 +	    public int invoke(FunctionDataParser fdp, Writer out)
  37.209 +		throws IOException, TemplateException {		
  37.210 +
  37.211 +                ReplaceWriter rw = new ReplaceWriter
  37.212 +                    (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>");
  37.213 +
  37.214 +                int ret = fdp.parseData(rw);
  37.215 +                rw.finish();
  37.216 +                return ret;
  37.217 +            }
  37.218 +        };
  37.219 +
  37.220 +
  37.221 +    @SuppressWarnings("unchecked")
  37.222 +    private static Class<Function> loadFunctionClass
  37.223 +        (ClassLoader loader, String className)
  37.224 +        throws ClassNotFoundException {
  37.225 +        
  37.226 +        return (Class<Function>)loader.loadClass(className);
  37.227 +    }
  37.228 +
  37.229 +    /**
  37.230 +     * Update file (copy if newer).
  37.231 +     *
  37.232 +     * @param src source file.
  37.233 +     * @param dest destination file.
  37.234 +     *
  37.235 +     * @trows IOException on copying error.
  37.236 +     */
  37.237 +    private static void copyFile(File src, File dest) throws IOException {
  37.238 +	System.err.print("Copying " + src + "... ");
  37.239 +	
  37.240 +	if (src.lastModified() < dest.lastModified()) {
  37.241 +	    System.err.println(dest + " is up to date.");
  37.242 +	    return;
  37.243 +	}
  37.244 +
  37.245 +	File parent = dest.getParentFile();
  37.246 +	if (parent != null) parent.mkdirs();
  37.247 +
  37.248 +        InputStream in = new FileInputStream(src);
  37.249 +        OutputStream out = new FileOutputStream(dest);
  37.250 +        
  37.251 +        byte[] buffer = new byte[1024];
  37.252 +        int len;
  37.253 +        while ((len = in.read(buffer)) > 0) {
  37.254 +            out.write(buffer, 0, len);
  37.255 +        }
  37.256 +        in.close();
  37.257 +        out.close();
  37.258 +
  37.259 +	System.err.println("saved " + dest + ".");
  37.260 +    }
  37.261 +}
    38.1 Binary file test/Hello.class has changed
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/test/Hello.java	Thu Dec 14 23:22:05 2006 +0300
    39.3 @@ -0,0 +1,21 @@
    39.4 +import java.io.Writer;
    39.5 +import java.io.IOException;
    39.6 +import kryshen.tema.*;
    39.7 +
    39.8 +/**
    39.9 + * Test function class.
   39.10 + * 
   39.11 + * @author Mikhail A. Kryshen
   39.12 + */
   39.13 +public class Hello extends Function {
   39.14 +    public Hello() {}
   39.15 +
   39.16 +    public int invoke(FunctionDataParser fdp, Writer out)
   39.17 +        throws IOException, TemplateException {
   39.18 +        
   39.19 +        out.write("Hello, ");
   39.20 +        fdp.parseData(out);
   39.21 +
   39.22 +        return 1;
   39.23 +    }
   39.24 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/test/demo	Thu Dec 14 23:22:05 2006 +0300
    40.3 @@ -0,0 +1,4 @@
    40.4 +#!/bin/sh
    40.5 +
    40.6 +#java -jar ../dist/tema.jar
    40.7 +java -classpath .:../dist/tema.jar kryshen.tema.Tema
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/test/demo.bat	Thu Dec 14 23:22:05 2006 +0300
    41.3 @@ -0,0 +1,1 @@
    41.4 +java -classpath .:..\dist\tema.jar kryshen.tema.Tema
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/test/include.template	Thu Dec 14 23:22:05 2006 +0300
    42.3 @@ -0,0 +1,1 @@
    42.4 +<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%>
    42.5 \ No newline at end of file
    43.1 --- a/test/inctest.template	Tue May 16 18:04:09 2006 +0400
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,1 +0,0 @@
    43.4 -<%test:1 2 3%>
    44.1 --- a/test/macrotest	Tue May 16 18:04:09 2006 +0400
    44.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3 @@ -1,3 +0,0 @@
    44.4 -#!/bin/sh
    44.5 -
    44.6 -java -jar ../dist/tema.jar
    45.1 --- a/test/main.template	Tue May 16 18:04:09 2006 +0400
    45.2 +++ b/test/main.template	Thu Dec 14 23:22:05 2006 +0300
    45.3 @@ -1,3 +1,28 @@
    45.4 -<%define`test [%nextarg:%]+[%nextarg:%]=[%data:]%>
    45.5 -<%include`inctest.template%>
    45.6 -<%test:<%test:ab cd x%> [%\<%test\1 2 3%>%] y%>
    45.7 +[%!\ UTF-8 text %]
    45.8 +
    45.9 +п▓я▀п╡п╬п╢ я┌п╣п╨я│я┌п╟:
   45.10 +test text
   45.11 +
   45.12 +п▓я▀п╡п╬п╢ я│п©п╣я├п╦п╟п╩я▄п╫я▀я┘ я│п╦п╪п╡п╬п╩п╬п╡:
   45.13 +[%\<%test%>%]
   45.14 +
   45.15 +п▓п╨п╩я▌я┤п╣п╫п╦п╣ я└п╟п╧п╩п╟ я│ п╬п╠я┼я▐п╡п╩п╣п╫п╦п╣п╪ я└я┐п╫п╨я├п╦п╦:
   45.16 +<%include:include.template%>
   45.17 +
   45.18 +п▓я▀п╥п╬п╡ п╫п╬п╡п╬п╧ я└я┐п╫п╨я├п╦п╦:
   45.19 +<%test:1 2 3%>
   45.20 +
   45.21 +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ read:
   45.22 +<%read\include.template%>
   45.23 +
   45.24 +п≈п╟пЁя─я┐п╥п╨п╟ я└я┐п╫п╨я├п╦п╦ п╦п╥ п╨п╩п╟я│я│п╟:
   45.25 +<%load\hello Hello%>
   45.26 +
   45.27 +п▓я▀п©п╬п╩п╣п╫п╣п╫п╦п╣ п╥п╟пЁя─я┐п╤п╣п╫п╫п╬п╧ я└я┐п╫п╨я├п╦п╦:
   45.28 +<%hello\TEMA%>
   45.29 +
   45.30 +пёя│п╩п╬п╡п╫п╬п╣ п╡я▀п©п╬п╩п╫п╣п╫п╦п╣:
   45.31 +<%optional:<%true:%>True%> <%optional:<%false:%>False%>
   45.32 +
   45.33 +п╒п╣я│я┌п╦я─п╬п╡п╟п╫п╦п╣ xml_escape:
   45.34 +<%xml_escape\x < a & b%>
    46.1 --- a/test/tema.properties	Tue May 16 18:04:09 2006 +0400
    46.2 +++ b/test/tema.properties	Thu Dec 14 23:22:05 2006 +0300
    46.3 @@ -1,16 +1,16 @@
    46.4  # Data source configuration
    46.5 -# resource          : jdbc:odbc:biotopes-data
    46.6 +# resource          : jdbc:odbc:database
    46.7  # driver            : sun.jdbc.odbc.JdbcOdbcDriver
    46.8  
    46.9  # Base directory for images and files
   46.10 -# resource_base     : C:\\biotopes\\db
   46.11 +# resource_base     : .
   46.12  
   46.13  # Template to start processing with
   46.14  main_template     : main.template
   46.15  
   46.16  # File encodings
   46.17 -# input_encoding    : ISO-8859-5
   46.18 -# output_encoding   : ISO-8859-5
   46.19 +input_encoding    : UTF-8
   46.20 +output_encoding   : UTF-8
   46.21  
   46.22  # Cache templates
   46.23  # cache_read        : true