Mercurial > hg > tema
changeset 0:1d2fe61a3a62 release_0_1
Tema 0.1 (imported from CVS).
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/build.xml Tue May 16 18:04:09 2006 +0400 1.3 @@ -0,0 +1,33 @@ 1.4 +<?xml version="1.0"?> 1.5 +<project name="tema" default="dist" basedir="."> 1.6 + 1.7 + <property name="src" value="src"/> 1.8 + <property name="build" value="build"/> 1.9 + <property name="dist" value="dist"/> 1.10 + <property name="res" value="res"/> 1.11 + <property name="jar_file" value="tema.jar"/> 1.12 + 1.13 + <target name="init"> 1.14 + <tstamp/> 1.15 + <mkdir dir="${build}"/> 1.16 + </target> 1.17 + 1.18 + <target name="compile" depends="init"> 1.19 + <javac srcdir="${src}" destdir="${build}" 1.20 + deprecation="on" optimize="on" debug="on"/> 1.21 + </target> 1.22 + 1.23 + <target name="dist" depends="compile"> 1.24 + <jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf"> 1.25 + <fileset dir="${build}" includes="**/*.class"/> 1.26 + </jar> 1.27 + </target> 1.28 + 1.29 + <target name="clean"> 1.30 + <delete> 1.31 + <fileset dir="${build}" includes="**/*.class"/> 1.32 + </delete> 1.33 + <delete file="${dist}/${jar_file}"/> 1.34 + </target> 1.35 + 1.36 +</project>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/dist/biotopes/biotope-top.sql Tue May 16 18:04:09 2006 +0400 2.3 @@ -0,0 +1,20 @@ 2.4 +SELECT t1.*, 2.5 + 2.6 +(SELECT t2.rusname FROM biotopelist AS t2 2.7 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND 2.8 +Right(t2.rangcode, 8) = '00000000') AS class0, 2.9 + 2.10 +(SELECT t2.rusname FROM biotopelist AS t2 2.11 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND 2.12 +Right(t2.rangcode, 6) = '000000') AS class1, 2.13 + 2.14 +(SELECT t2.rusname FROM biotopelist AS t2 2.15 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND 2.16 +Right(t2.rangcode, 4) = '0000') AS class2, 2.17 + 2.18 +(SELECT t2.rusname FROM biotopelist AS t2 2.19 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND 2.20 +Right(t2.rangcode, 2) = '00') AS class3 2.21 + 2.22 +FROM biotopelist AS t1 2.23 +WHERE Right(t1.rangcode, 2) <> '00' AND rusname
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/dist/biotopes/biotope.sql Tue May 16 18:04:09 2006 +0400 3.3 @@ -0,0 +1,24 @@ 3.4 +SELECT t1.*, 3.5 + 3.6 +(SELECT t2.rusname FROM biotopelist AS t2 3.7 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) 3.8 +AND Right(t2.rangcode, 8) = '00000000' 3.9 +AND Right(t1.rangcode, 8) <> '00000000') AS class0, 3.10 + 3.11 +(SELECT t2.rusname FROM biotopelist AS t2 3.12 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) 3.13 +AND Right(t2.rangcode, 6) = '000000' 3.14 +AND Right(t1.rangcode, 6) <> '000000') AS class1, 3.15 + 3.16 +(SELECT t2.rusname FROM biotopelist AS t2 3.17 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) 3.18 +AND Right(t2.rangcode, 4) = '0000' 3.19 +AND Right(t1.rangcode, 4) <> '0000') AS class2, 3.20 + 3.21 +(SELECT t2.rusname FROM biotopelist AS t2 3.22 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) 3.23 +AND Right(t2.rangcode, 2) = '00' 3.24 +AND Right(t1.rangcode, 2) <> '00') AS class3 3.25 + 3.26 +FROM biotopelist AS t1 3.27 +WHERE rusname
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/dist/biotopes/biotope.template Tue May 16 18:04:09 2006 +0400 4.3 @@ -0,0 +1,17 @@ 4.4 +<?xml version="1.0" encoding="ISO-8859-5"?> 4.5 +<!DOCTYPE _ SYSTEM "brief.dtd"> 4.6 +<!-- rangcode: <%xml_escape get\rangcode%> --> 4.7 +<_ show="0"> 4.8 + < display="0"> 4.9 + <%optional:<_ ="1" file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> 4.10 +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> 4.11 + </> 4.12 + <><%xml_escape get\rusname%></> 4.13 + <><%xml_escape get\class0%></> 4.14 + <1><%xml_escape get\class1%></1> 4.15 + <2><%xml_escape get\class2%></2> 4.16 + <3><%xml_escape get\class3%></3> 4.17 + <_ rows="3"><%xml_cdata get\descript%></_> 4.18 + <_ rows="3"><%xml_cdata get\geobotdescr%></_> 4.19 + <_><%xml_escape get\contributors%></_> 4.20 +</_>
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/dist/biotopes/brief.dtd Tue May 16 18:04:09 2006 +0400 5.3 @@ -0,0 +1,27 @@ 5.4 +<?xml encoding="ISO-8859-5"?> 5.5 +<!ELEMENT _ (?, , , 1, 2, 3, _, _, _)> 5.6 +<!ELEMENT (|_)*> 5.7 +<!ELEMENT EMPTY> 5.8 +<!ELEMENT _ EMPTY> 5.9 +<!ELEMENT (#PCDATA)> 5.10 +<!ELEMENT (#PCDATA)> 5.11 +<!ELEMENT 1 (#PCDATA)> 5.12 +<!ELEMENT 2 (#PCDATA)> 5.13 +<!ELEMENT 3 (#PCDATA)> 5.14 +<!ELEMENT _ (#PCDATA)> 5.15 +<!ELEMENT _ (#PCDATA)> 5.16 +<!ELEMENT _ (#PCDATA)> 5.17 +<!ATTLIST _ show (0|1) "1"> 5.18 +<!ATTLIST 5.19 + display CDATA #FIXED "0"> 5.20 +<!ATTLIST 5.21 + num ID #REQUIRED 5.22 + file CDATA #REQUIRED 5.23 + big CDATA #REQUIRED 5.24 + text CDATA #IMPLIED 5.25 + CDATA #IMPLIED> 5.26 +<!ATTLIST _ 5.27 + num ID #REQUIRED 5.28 + file CDATA #REQUIRED> 5.29 +<!ATTLIST _ rows CDATA #FIXED "3"> 5.30 +<!ATTLIST _ rows CDATA #FIXED "3">
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/dist/biotopes/class.sql Tue May 16 18:04:09 2006 +0400 6.3 @@ -0,0 +1,7 @@ 6.4 +SELECT t1.* 6.5 +FROM biotopelist AS t1 6.6 +WHERE rusname AND Right(t1.rangcode, 8) = '00000000' 6.7 + AND EXISTS 6.8 + (SELECT NULL FROM biotopelist AS t2 6.9 + WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) 6.10 + AND Right(t2.rangcode, 8) <> '00000000')
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/dist/biotopes/classes.template Tue May 16 18:04:09 2006 +0400 7.3 @@ -0,0 +1,5 @@ 7.4 +<?xml version="1.0" encoding="ISO-8859-5"?> 7.5 +<><%query:class_sql [%\ 7.6 + <!-- rangcode: <%xml_escape get\rangcode%> --> 7.7 + < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%> 7.8 +</>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/dist/biotopes/main.template Tue May 16 18:04:09 2006 +0400 8.3 @@ -0,0 +1,11 @@ 8.4 +<%!: 8.5 + <%prepare:biotope_sql <%read\biotope.sql%>%> 8.6 + <%prepare:photo_sql <%read\photo.sql%>%> 8.7 + <%prepare:class_sql <%read\class.sql%>%> 8.8 + <%prepare:plant_sql <%read\plant.sql%>%> 8.9 + 8.10 + <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> 8.11 + 8.12 + <%write:classes.xml <%include\classes.template%>%> 8.13 + <%write:plants.xml <%include\plants.template%>%> 8.14 +%>
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/dist/biotopes/photo.sql Tue May 16 18:04:09 2006 +0400 9.3 @@ -0,0 +1,1 @@ 9.4 +SELECT * from photos WHERE biotope = ?
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/dist/biotopes/photo.template Tue May 16 18:04:09 2006 +0400 10.3 @@ -0,0 +1,3 @@ 10.4 + < num="<%xml_escape get\NUMBER%>" <%optional:="<%xml_escape get\authphoto%>" %>text="" 10.5 + file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 10.6 + big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/dist/biotopes/plant.sql Tue May 16 18:04:09 2006 +0400 11.3 @@ -0,0 +1,3 @@ 11.4 +SELECT t1.* 11.5 +FROM biotopelist AS t1 11.6 +WHERE rusname AND Right(t1.rangcode, 2) <> '00'
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/dist/biotopes/plants.template Tue May 16 18:04:09 2006 +0400 12.3 @@ -0,0 +1,5 @@ 12.4 +<?xml version="1.0" encoding="ISO-8859-5"?> 12.5 +<><%query:plant_sql [%\ 12.6 + <!-- rangcode: <%xml_escape get\rangcode%> --> 12.7 + <><%xml_escape get\rusname%></>%]%> 12.8 +</>
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/dist/biotopes/tema.properties Tue May 16 18:04:09 2006 +0400 13.3 @@ -0,0 +1,22 @@ 13.4 +# Data source configuration 13.5 +resource : jdbc:odbc:biotopes-data 13.6 +driver : sun.jdbc.odbc.JdbcOdbcDriver 13.7 + 13.8 +# Base directory for images and files 13.9 +resource_base : C:\\biotopes\\db 13.10 + 13.11 +# Template to start processing with 13.12 +main_template : main.template 13.13 + 13.14 +# File encodings 13.15 +input_encoding : ISO-8859-5 13.16 +output_encoding : ISO-8859-5 13.17 + 13.18 +# Cache templates 13.19 +cache_read : true 13.20 + 13.21 +# Output main_template parsing result to stderr 13.22 +#output : stderr 13.23 + 13.24 +# File to output error messages (redirect stderr) 13.25 +#log : tema.log
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/dist/readme.html Tue May 16 18:04:09 2006 +0400 14.3 @@ -0,0 +1,86 @@ 14.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 14.5 + "DTD/xhtml1-transitional.dtd"> 14.6 + 14.7 +<html> 14.8 + 14.9 +<head> 14.10 + <title>DbReader</title> 14.11 + <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" /> 14.12 +</head> 14.13 + 14.14 +<body> 14.15 +<h1>DbReader</h1> 14.16 + 14.17 +<h2> </h2> 14.18 +<ol> 14.19 +<li> .</li> 14.20 + 14.21 +<li> :<br /> 14.22 + Windows 2000: // (ODBC), biotopes-data.mdb.</li> 14.23 + 14.24 +<li> :<br /> 14.25 + dbreader.properties , :<br /> 14.26 + <code>resource: jdbc:odbc:<em></em></code><br /> 14.27 + , ( biotopephotos maps):<br /> 14.28 + <code>resource_base: C:\\biotopes</code><br /> 14.29 +( '\' )</li> 14.30 + 14.31 +<li> :<br /> 14.32 +<code>dbreader.bat</code> <br /> 14.33 +<code>java -jar dbreader.jar</code>.<br /> 14.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 - . 14.35 + 14.36 + :<br /> 14.37 + <code>java -Dru.karrc.dbreader.<em></em>=<em></em> -jar dbreader.jar</code><br /> 14.38 +(: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li> 14.39 +</ol> 14.40 + 14.41 +<h2> </h2> 14.42 + 14.43 +<p> biotope.sql ( , dbreader.properties), biotope.template, .</p> 14.44 +<p> : <code><%<em>_</em>[:|\]<em></em>%></code>, <em> </em> - , . , .</p> 14.45 + 14.46 +<h3> </h3> 14.47 + 14.48 +<ul> 14.49 + <li><code>:</code> - .</li> 14.50 + <li><code>\</code> - . <code><%</code> <code>%></code> (<code><%\<%%></code> <code><%\%%>></code>).</li> 14.51 +</ul> 14.52 + 14.53 +<h3></h3> 14.54 + 14.55 +<ul> 14.56 + <li><code><%get:<em></em>%></code><br /> 14.57 + .</li> 14.58 + 14.59 + <li><code><%optional:<em></em>%></code><br /> 14.60 + <em></em>, , , .</li> 14.61 + 14.62 + <li><code><%escape:<em></em>%></code><br /> 14.63 + "" ( ).</li> 14.64 + 14.65 + <li><code><%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%></code><br /> 14.66 + <em></em>.sql <em></em>.template. '?'.</li> 14.67 + 14.68 + <li><code><%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%></code><br /> 14.69 + <em>_</em> ( "resource_base") , <em>_</em>. , . 14.70 + , <code><%image:...%></code> <em>_</em>, - .</li> 14.71 + 14.72 + <li><code><%copy:<em>_</em> <em>_</em>%></code><br /> 14.73 + <em>_</em> ( "resource_base") <em>_</em>. , <code><%copy:...%></code> <em>_</em>, - .</li> 14.74 +</ul> 14.75 + 14.76 +<h3> </h3> 14.77 + 14.78 +<p><code>NUMBER</code> - . 14.79 + , invoke, <code>SUPER.</code> (: <code>SUPER.NUMBER</code>).</p> 14.80 + 14.81 +<h3></h3> 14.82 + 14.83 +<p> name :</p> 14.84 +<p><code><%escape get:name%></code></p> 14.85 + 14.86 +<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru"> </a></i></p> 14.87 + 14.88 +</body> 14.89 +</html>
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/dist/readme.txt Tue May 16 18:04:09 2006 +0400 15.3 @@ -0,0 +1,63 @@ 15.4 +text/plain; charset=UTF-8 15.5 + 15.6 +Установка программы 15.7 +------------------- 15.8 + 15.9 +1. Распаковать архив. 15.10 + 15.11 +2. Установить источник данных: 15.12 +в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes.mdb. 15.13 + 15.14 +3. Настроить программу: 15.15 +В файле dbreader.properties указать имя, присвоенное источнику данных: 15.16 + "resource: jdbc:odbc:<имя>" 15.17 +и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps): 15.18 + "resource_base: C:\\biotopes" 15.19 +(символ '\' необходимо дублировать) 15.20 + 15.21 +4. Запуск программы: dbreader.bat или "java -jar dbreader.jar" 15.22 +Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с http://java.sun.com/j2se/1.5.0/download.jsp. Возможно, будет работать и со старыми версиями JRE - не проверял. 15.23 + 15.24 +Все значения файла конфигурации можно переопределять при запуске программы: 15.25 + команда "java -Dru.karrc.dbreader.<ключ>=<значение> -jar dbreader.jar" 15.26 +(например: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar") 15.27 + 15.28 + 15.29 +Работа программы 15.30 +---------------- 15.31 + 15.32 +Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения. 15.33 + 15.34 +Формат инструкций: "<%список_функций[:|\]данные%>", список функций - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней. 15.35 + 15.36 +Разделители между списком функций и данными: 15.37 +':' - данные будут обрабатываться рекурсивно. 15.38 +'\' - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов "<%" и "%>" ("<%\<%%>" и "<%\%%>>"). 15.39 + 15.40 +Функции: 15.41 +<%get:<имя>%> - заменяется на значение встроенной переменной или колонки запроса. 15.42 + 15.43 +<%optional:<текст>%> 15.44 +Заменяется на <текст>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку. 15.45 + 15.46 +<%escape:<текст>%> 15.47 +Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации). 15.48 + 15.49 +<%invoke:<имя> <парам1> <парам2> ... <парамN>%> 15.50 +Выполняет запрос с параметрами <имя>.sql и заменяется на результаты обработки шаблона <имя>.template. Значения параметров подставляются в запрос вместо символа '?'. 15.51 + 15.52 +<%image:<исх_файл> <кон_файл> <формат> [<макс_ширина>] [<макс_высота>]%> 15.53 +Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. 15.54 +При успешном выполнении, инструкция "<%!image ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. 15.55 + 15.56 +<%copy:<исх_файл> <кон_файл>%> 15.57 +Копирует файл <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base"). 15.58 +При успешном выполнении, инструкция "<%!copy ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. 15.59 + 15.60 +Встроенные переменные: 15.61 +NUMBER - порядковый номер строки результата выполнения запроса. 15.62 +Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить "SUPER." (например: "SUPER.NUMBER"). 15.63 + 15.64 +Пример: 15.65 +Следующая инструкция получит значение из столбца name и заменит в нем специальные символы: 15.66 +<%escape get:name%>
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/dist/tema Tue May 16 18:04:09 2006 +0400 16.3 @@ -0,0 +1,3 @@ 16.4 +#!/bin/sh 16.5 + 16.6 +java -jar tema.jar
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/dist/tema.bat Tue May 16 18:04:09 2006 +0400 17.3 @@ -0,0 +1,1 @@ 17.4 +java -jar tema.jar
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/dist/tema.properties Tue May 16 18:04:09 2006 +0400 18.3 @@ -0,0 +1,22 @@ 18.4 +# Data source configuration 18.5 +# resource : jdbc:odbc:biotopes-data 18.6 +# driver : sun.jdbc.odbc.JdbcOdbcDriver 18.7 + 18.8 +# Base directory for images and files 18.9 +# resource_base : C:\\biotopes\\db 18.10 + 18.11 +# Template to start processing with 18.12 +main_template : main.template 18.13 + 18.14 +# File encodings 18.15 +# input_encoding : ISO-8859-5 18.16 +# output_encoding : ISO-8859-5 18.17 + 18.18 +# Cache templates 18.19 +cache_read : true 18.20 + 18.21 +# Output main_template parsing result to stderr 18.22 +#output : stderr 18.23 + 18.24 +# File to output error messages (redirect stderr) 18.25 +#log : tema.log
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/doc/article.txt Tue May 16 18:04:09 2006 +0400 19.3 @@ -0,0 +1,391 @@ 19.4 +* XML- . 19.5 + 19.6 + " 19.7 +" Microsoft Access XML- 19.8 + DbReader. 19.9 + 19.10 + DbReader 19.11 + . 19.12 + 19.13 + . 19.14 + SQL-, 19.15 +. 19.16 + 19.17 + 19.18 +* : 19.19 + 19.20 + <%<_>{:|\}<>%> 19.21 + 19.22 + 19.23 +<_> - , . 19.24 + . 19.25 +<> - , . 19.26 + 19.27 + 19.28 +* : 19.29 + 19.30 + [<_>][<>] 19.31 + 19.32 + 19.33 +<_> - , . 19.34 + . 19.35 +<> - , . 19.36 + . , 19.37 + , . 19.38 + 19.39 + , 19.40 + : 19.41 +: - , 19.42 +\ - . 19.43 + 19.44 + , , 19.45 + , 19.46 + . 19.47 + 19.48 + - . 19.49 + - . , 19.50 + - 19.51 +. 19.52 + 19.53 + '<', '>' '[', ']'. 19.54 + 19.55 + 19.56 +* : 19.57 + 19.58 +: set 19.59 +: <> 19.60 +: <> 19.61 +: <> 19.62 +: <> 19.63 + : 1 19.64 + 19.65 +: get 19.66 +: <> 19.67 +: <>. 19.68 + : 1, , 0 - . 19.69 + 19.70 +: prepare 19.71 +: <> 19.72 +: <> 19.73 +: SQL- <> , 19.74 + <>. 19.75 +: <> 19.76 + : 1 19.77 + 19.78 +: query 19.79 +: <_> <> <1> ... <N> 19.80 +: , 19.81 + prepare. 19.82 + '?'. 19.83 + , <>. 19.84 + <> NUMBER, 19.85 + . , 19.86 + , 19.87 + <> SUPER.<_>. 19.88 + 19.89 +: <> 19.90 + . 19.91 + : . 19.92 + 19.93 +: optional 19.94 +: <> 19.95 +: <>, 19.96 + 0, - . 19.97 + : 1, - , 0 - . 19.98 + 19.99 +: image 19.100 +: <_> <_> <> [<_> [<_>]] 19.101 +: <_> ( 19.102 + "resource_base") 19.103 + , 19.104 + <_>. , 19.105 + . 19.106 +: <_> , - . 19.107 + : 1 , 0 - . 19.108 + 19.109 +: copy 19.110 +: <_> <_> 19.111 +: <_> <_> 19.112 + ( <_> 19.113 + "resource_base"). 19.114 +: <_> , - . 19.115 + : 1 , 0 - . 19.116 + 19.117 +: write 19.118 +: <_> 19.119 +: <> 19.120 +: <> <_>. 19.121 +: <_> , - . 19.122 + : 1 , 0 - . 19.123 + 19.124 +: read 19.125 +: <_> 19.126 +: <_>. 19.127 +: , 19.128 + - . 19.129 + : 1 , 0 - . 19.130 + 19.131 +: include 19.132 +: <_> 19.133 +: <_>. 19.134 +: . 19.135 + : , . 19.136 + 19.137 +: ! 19.138 +: <> 19.139 +: . 19.140 +: . 19.141 + : , . 19.142 + 19.143 +: replace 19.144 +: <1> <2> 19.145 +: <> 19.146 +: , <1> 19.147 + <2>. 19.148 + : , . 19.149 + 19.150 +: xml_escape 19.151 +: <> 19.152 +: <>, 19.153 + '&', '<', '>', '`', '\' 19.154 + XML. 19.155 + : , . 19.156 + 19.157 +: xml_cdata 19.158 +: <> 19.159 +: XML CDATA. 19.160 + : , . 19.161 + 19.162 + DbReader : 19.163 +, Java. 19.164 + 19.165 + 19.166 +* DbReader 19.167 + " " Microsoft Access 19.168 + XML- 19.169 + 19.170 + " 19.171 + " ( ): 19.172 + 19.173 +biotopelist (code, rangcode, rusname, engname, descript, geobotdescr, 19.174 + contributors, descrdate) 19.175 + 19.176 + code - , ; 19.177 + rangcode - ABBCCDDEE, , BB, CC, DD, - 19.178 + , ; 19.179 + rusname, engname, descript, geobotdescr - ; 19.180 + descrdate - . 19.181 + 19.182 +photos (biotope, photo, authphoto) 19.183 + 19.184 + biotope - , code biotopelist; 19.185 + photo - ; 19.186 + authphoto - . 19.187 + 19.188 + xml- biotopelist, 19.189 + , , 19.190 + . 19.191 + 19.192 + xml- 19.193 + DbReader ( biotope.template): 19.194 + 19.195 +---------------------------------------------------------------------- 19.196 +<?xml version="1.0" encoding="ISO-8859-5"?> 19.197 +<!DOCTYPE _ SYSTEM "brief.dtd"> 19.198 +<!-- rangcode: <%xml_escape get\rangcode%> --> 19.199 +<_ show="0"> 19.200 + < display="0"> 19.201 + <%optional:<_ ="1" 19.202 + file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> 19.203 +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> 19.204 + </> 19.205 + <><%xml_escape get\rusname%></> 19.206 + <><%xml_escape get\class0%></> 19.207 + <1><%xml_escape get\class1%></1> 19.208 + <2><%xml_escape get\class2%></2> 19.209 + <3><%xml_escape get\class3%></3> 19.210 + <_ rows="3"><%xml_cdata get\descript%></_> 19.211 + <_ rows="3"><%xml_cdata get\geobotdescr%></_> 19.212 + <_><%xml_escape get\contributors%></_> 19.213 +</_> 19.214 +---------------------------------------------------------------------- 19.215 + 19.216 + SQL-, 19.217 + rangcode, rusname, class0, class1, class2, 19.218 +class3, descript, geobotdescr contributors ( biotope.sql): 19.219 + 19.220 +---------------------------------------------------------------------- 19.221 +SELECT t1.*, 19.222 + 19.223 +(SELECT t2.rusname FROM biotopelist AS t2 19.224 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) 19.225 +AND Right(t2.rangcode, 8) = '00000000' 19.226 +AND Right(t1.rangcode, 8) <> '00000000') AS class0, 19.227 + 19.228 +(SELECT t2.rusname FROM biotopelist AS t2 19.229 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) 19.230 +AND Right(t2.rangcode, 6) = '000000' 19.231 +AND Right(t1.rangcode, 6) <> '000000') AS class1, 19.232 + 19.233 +(SELECT t2.rusname FROM biotopelist AS t2 19.234 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) 19.235 +AND Right(t2.rangcode, 4) = '0000' 19.236 +AND Right(t1.rangcode, 4) <> '0000') AS class2, 19.237 + 19.238 +(SELECT t2.rusname FROM biotopelist AS t2 19.239 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) 19.240 +AND Right(t2.rangcode, 2) = '00' 19.241 +AND Right(t1.rangcode, 2) <> '00') AS class3 19.242 + 19.243 +FROM biotopelist AS t1 19.244 +WHERE rusname 19.245 +---------------------------------------------------------------------- 19.246 + 19.247 + biotope.template <%include\photo.template%>, 19.248 + ( photo.template): 19.249 + 19.250 +---------------------------------------------------------------------- 19.251 + < num="<%xml_escape get\NUMBER%>" 19.252 + <%optional:="<%xml_escape get\authphoto%>" %>text="" 19.253 + file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 19.254 + big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/> 19.255 +---------------------------------------------------------------------- 19.256 + 19.257 + SQL- 19.258 +(photo.sql): 19.259 + 19.260 +---------------------------------------------------------------------- 19.261 +SELECT * from photos WHERE biotope = ? 19.262 +---------------------------------------------------------------------- 19.263 + 19.264 +, ( classes.template): 19.265 + 19.266 +---------------------------------------------------------------------- 19.267 +<?xml version="1.0" encoding="ISO-8859-5"?> 19.268 +<><%query:class_sql [%\ 19.269 + <!-- rangcode: <%xml_escape get\rangcode%> --> 19.270 + < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%> 19.271 +</> 19.272 +---------------------------------------------------------------------- 19.273 + 19.274 + SQL- (class.sql): 19.275 + 19.276 +---------------------------------------------------------------------- 19.277 +SELECT t1.* 19.278 +FROM biotopelist AS t1 19.279 +WHERE rusname AND Right(t1.rangcode, 8) = '00000000' 19.280 + AND EXISTS 19.281 + (SELECT NULL FROM biotopelist AS t2 19.282 + WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) 19.283 + AND Right(t2.rangcode, 8) <> '00000000') 19.284 +---------------------------------------------------------------------- 19.285 + 19.286 +, ( plants.template): 19.287 + 19.288 +---------------------------------------------------------------------- 19.289 +<?xml version="1.0" encoding="ISO-8859-5"?> 19.290 +<><%query:plant_sql [%\ 19.291 + <!-- rangcode: <%xml_escape get\rangcode%> --> 19.292 + <><%xml_escape get\rusname%></>%]%> 19.293 +</> 19.294 +---------------------------------------------------------------------- 19.295 + 19.296 + SQL- (plant.sql): 19.297 + 19.298 +---------------------------------------------------------------------- 19.299 +SELECT t1.* 19.300 +FROM biotopelist AS t1 19.301 +WHERE rusname AND Right(t1.rangcode, 2) <> '00' 19.302 +---------------------------------------------------------------------- 19.303 + 19.304 + DbReader index.template, 19.305 + SQL- 19.306 +: 19.307 + 19.308 +---------------------------------------------------------------------- 19.309 +<%!: 19.310 + <%prepare:biotope_sql <%read\biotope.sql%>%> 19.311 + <%prepare:photo_sql <%read\photo.sql%>%> 19.312 + <%prepare:class_sql <%read\class.sql%>%> 19.313 + <%prepare:plant_sql <%read\plant.sql%>%> 19.314 + 19.315 + <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> 19.316 + 19.317 + <%write:classes.xml <%include\classes.template%>%> 19.318 + <%write:plants.xml <%include\plants.template%>%> 19.319 +%> 19.320 +---------------------------------------------------------------------- 19.321 + 19.322 + XML-: 19.323 + 19.324 +---------------------------------------------------------------------- 19.325 +<?xml version="1.0" encoding="ISO-8859-5"?> 19.326 +<!DOCTYPE _ SYSTEM "brief.dtd"> 19.327 +<!-- rangcode: E04020302 --> 19.328 +<_ show="0"> 19.329 + < display="0"> 19.330 + < num="1" =" .." text="" 19.331 + file="images/3_1.jpg" 19.332 + big="images/big/3_1.jpg"/> 19.333 + < num="2" =" .." text="" 19.334 + file="images/3_2.jpg" 19.335 + big="images/big/3_2.jpg"/> 19.336 + </> 19.337 + <>Betula sp. - Avenella flexuosa - Polytrichum commune</> 19.338 + <>E. </> 19.339 + <1> </1> 19.340 + <2></2> 19.341 + <3></3> 19.342 + <_ rows="3"><![CDATA[ . 5 - 7 , , , .]]></_> 19.343 + <_ rows="3"></_> 19.344 + <_></_> 19.345 +</_> 19.346 +---------------------------------------------------------------------- 19.347 + 19.348 + 19.349 +* DbReader 19.350 + 19.351 + DbReader Java 19.352 + : 19.353 + 19.354 +ru.karrc.dbreader.DbReader: c . 19.355 +, 19.356 + JDBC, . 19.357 + 19.358 +ru.karrc.dbreader.TemplateParser: , 19.359 + . 19.360 + 19.361 +ru.karrc.dbreader.Function: . 19.362 +DbReader . 19.363 + 19.364 +ru.karrc.dbreader.FunctionDataParser: 19.365 +. , 19.366 +. 19.367 + TemplateParser. 19.368 + 19.369 +ru.karrc.dbreader.Functions: 19.370 + , Function. 19.371 + 19.372 +ru.karrc.dbreader.TemplateParser: , 19.373 + . 19.374 + 19.375 + , , 19.376 + . 19.377 + 19.378 + 19.379 +* . 19.380 + 19.381 + : 8, 19.382 + Java- ( ): 27, 19.383 + : 1311, 19.384 + ( ): 812, 19.385 + : 180. 19.386 + 19.387 + 19.388 +* 19.389 + 19.390 + DbReader, 19.391 + 19.392 + . 19.393 +DbReader " " 19.394 + XML- .
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/sample/class.xml Tue May 16 18:04:09 2006 +0400 20.3 @@ -0,0 +1,9 @@ 20.4 +<?xml version="1.0" encoding="ISO-8859-5"?> 20.5 +<> 20.6 + < id="1"> </> 20.7 + < id="2"> </> 20.8 + < id="3"> </> 20.9 + < id="4">, </> 20.10 + < id="5"> </> 20.11 + < id="6"> </> 20.12 +</>
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/sample/plants.xml Tue May 16 18:04:09 2006 +0400 21.3 @@ -0,0 +1,6 @@ 21.4 +<?xml version="1.0" encoding="ISO-8859-5"?> 21.5 +<> 21.6 + <>Betula sp.</> 21.7 + <>Calamagrostis arundinacea</> 21.8 + <>Geranium sylvaticum</> 21.9 +</>
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/src/Manifest.mf Tue May 16 18:04:09 2006 +0400 22.3 @@ -0,0 +1,2 @@ 22.4 +Manifest-Version: 1.0 22.5 +Main-Class: kryshen.tema.Tema
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/src/kryshen/tema/Function.java Tue May 16 18:04:09 2006 +0400 23.3 @@ -0,0 +1,22 @@ 23.4 +/* 23.5 + * Copyright (C) 2005, 2006 Mikhail A. Kryshen 23.6 + * 23.7 + * $Id: Function.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 23.8 + */ 23.9 + 23.10 +package kryshen.tema; 23.11 + 23.12 +import java.io.*; 23.13 +import java.util.*; 23.14 +import java.sql.ResultSet; 23.15 + 23.16 +public abstract class Function { 23.17 + public final String name; 23.18 + 23.19 + protected Function(String name) { 23.20 + this.name = name; 23.21 + } 23.22 + 23.23 + public abstract int invoke(FunctionDataParser fdp, Writer out) 23.24 + throws IOException, TemplateException; 23.25 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/src/kryshen/tema/FunctionDataParser.java Tue May 16 18:04:09 2006 +0400 24.3 @@ -0,0 +1,122 @@ 24.4 +/* 24.5 + * Copyright (C) 2006 Mikhail A. Kryshen 24.6 + * 24.7 + * $Id: FunctionDataParser.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.io.*; 24.13 +import java.util.*; 24.14 + 24.15 +import static kryshen.tema.TemplateParser.Result; 24.16 +import static kryshen.tema.TemplateParser.FunctionData; 24.17 +import static kryshen.tema.TemplateParser.Terminator; 24.18 + 24.19 +/** 24.20 + * Parser for a function data. 24.21 + * 24.22 + * @author Mikhail A. Kryshen 24.23 + */ 24.24 +public class FunctionDataParser { 24.25 + static final char[] ARG_SEPARATORS = TemplateParser.LIST_SEPARATORS; 24.26 + 24.27 + private TemplateParser tp; 24.28 + private FunctionData fd; 24.29 + private Reader in; 24.30 + 24.31 + private boolean available = true; 24.32 + private boolean first = true; 24.33 + 24.34 + FunctionDataParser(TemplateParser tp, FunctionData fd, 24.35 + Reader in) { 24.36 + this.tp = tp; 24.37 + this.fd = fd; 24.38 + this.in = in; 24.39 + } 24.40 + 24.41 + private TemplateParser.Result parseData(Writer out, boolean argument) 24.42 + throws IOException, TemplateException { 24.43 + 24.44 + if (!available) 24.45 + throw new TemplateException 24.46 + ("Unexpected end of instruction data."); 24.47 + 24.48 + TemplateParser.Result r; 24.49 + 24.50 + if (fd == FunctionData.RECURSIVE) { 24.51 + r = tp.parse(in, out, true, 24.52 + argument ? ARG_SEPARATORS : null, 24.53 + (argument || !first) ? ARG_SEPARATORS : null); 24.54 + } else if (fd == FunctionData.NONRECURSIVE) { 24.55 + r = tp.parse(in, out, false, 24.56 + argument ? ARG_SEPARATORS : null, 24.57 + (argument || !first) ? ARG_SEPARATORS : null); 24.58 + } else if (fd == FunctionData.SUBFUNCTION && argument) { 24.59 + /* Subfunction can pass a list of arguments */ 24.60 + StringWriter sw = new StringWriter(); 24.61 + tp.parseFunction(in, sw); 24.62 + sw.close(); 24.63 + in = new StringReader(sw.toString()); 24.64 + fd = FunctionData.NONRECURSIVE; 24.65 + r = parseData(out, true); 24.66 + } else if (fd == FunctionData.SUBFUNCTION) { 24.67 + r = new Result(null, tp.parseFunction(in, out), false); 24.68 + } else { 24.69 + throw new IllegalArgumentException("Invalid FunctiodData: " + fd); 24.70 + } 24.71 + 24.72 + if (r.terminator != TemplateParser.Terminator.SEPARATOR) 24.73 + available = false; // No more function data available. 24.74 + 24.75 + first = false; 24.76 + return r; 24.77 + } 24.78 + 24.79 + public int parseData(Writer out) throws IOException, TemplateException { 24.80 + return parseData(out, false).substitutions; 24.81 + } 24.82 + 24.83 + public String getData() throws IOException, TemplateException { 24.84 + StringWriter sw = new StringWriter(); 24.85 + parseData(sw); 24.86 + sw.close(); 24.87 + return sw.toString(); 24.88 + } 24.89 + 24.90 + public int parseNextArg(Writer out) throws IOException, TemplateException { 24.91 + TemplateParser.Result r = parseData(out, true); 24.92 + 24.93 + // Ignore empty arguments. 24.94 + while (r.empty && available) { 24.95 + r = parseData(out, true); 24.96 + } 24.97 + 24.98 + return r.substitutions; 24.99 + } 24.100 + 24.101 + public String getNextArg() throws IOException, TemplateException { 24.102 + StringWriter sw = new StringWriter(); 24.103 + parseNextArg(sw); 24.104 + sw.close(); 24.105 + return sw.toString(); 24.106 + } 24.107 + 24.108 + public List<String> getArgs() throws IOException, TemplateException { 24.109 + List<String> l = new ArrayList<String>(); 24.110 + 24.111 + while (available) { 24.112 + l.add(getNextArg()); 24.113 + } 24.114 + 24.115 + return l; 24.116 + } 24.117 + 24.118 + public boolean hasMoreData() { 24.119 + return available; 24.120 + } 24.121 + 24.122 + public TemplateParser getTemplateParser() { 24.123 + return tp; 24.124 + } 24.125 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/src/kryshen/tema/Functions.java Tue May 16 18:04:09 2006 +0400 25.3 @@ -0,0 +1,336 @@ 25.4 +/* 25.5 + * Copyright (C) 2005, 2006 Mikhail A. Kryshen 25.6 + * 25.7 + * $Id: Functions.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.*; 25.13 +import java.util.*; 25.14 + 25.15 +import java.sql.SQLException; 25.16 +import java.sql.PreparedStatement; 25.17 + 25.18 +import kryshen.tema.functions.*; 25.19 + 25.20 +public class Functions { 25.21 + public static final Function GET = 25.22 + new Function("get") { 25.23 + public int invoke(FunctionDataParser fdp, Writer out) 25.24 + throws IOException, TemplateException { 25.25 + 25.26 + String name = fdp.getData(); 25.27 + return fdp.getTemplateParser().parseVariable(name, out); 25.28 + } 25.29 + }; 25.30 + 25.31 + public static final Function SET = 25.32 + new Function("set") { 25.33 + public int invoke(FunctionDataParser fdp, Writer out) 25.34 + throws IOException, TemplateException { 25.35 + 25.36 + String arg0 = fdp.getNextArg(); 25.37 + String arg1 = fdp.getData(); 25.38 + 25.39 + fdp.getTemplateParser().setValue(arg0, arg1); 25.40 + 25.41 + out.write(arg0); 25.42 + return 1; 25.43 + } 25.44 + }; 25.45 + 25.46 + /* prepare:qury_name sql_statement */ 25.47 + public static final Function PREPARE = 25.48 + new Function("prepare") { 25.49 + public int invoke(FunctionDataParser fdp, Writer out) 25.50 + throws IOException, TemplateException { 25.51 + 25.52 + String arg0 = fdp.getNextArg(); 25.53 + String data = fdp.getData(); 25.54 + 25.55 + PreparedStatement statement; 25.56 + 25.57 + try { 25.58 + statement = Tema.connection.prepareStatement(data); 25.59 + } catch (SQLException e) { 25.60 + throw new TemplateException(e.getMessage(), e); 25.61 + } 25.62 + 25.63 + fdp.getTemplateParser().setValue(arg0, statement); 25.64 + 25.65 + out.write(arg0); 25.66 + return 1; 25.67 + } 25.68 + }; 25.69 + 25.70 + public static final Function OPTIONAL = 25.71 + new Function("optional") { 25.72 + public int invoke(FunctionDataParser fdp, Writer out) 25.73 + throws IOException, TemplateException { 25.74 + 25.75 + StringWriter sw = new StringWriter(); 25.76 + int s = fdp.parseData(sw); 25.77 + sw.close(); 25.78 + String data = sw.toString(); 25.79 + 25.80 + if (s > 0) { 25.81 + out.write(data); 25.82 + return 1; 25.83 + } else { 25.84 + return 0; 25.85 + } 25.86 + } 25.87 + }; 25.88 + 25.89 + public static final Function IMAGE = 25.90 + new Function("image") { 25.91 + public int invoke(FunctionDataParser fdp, Writer out) 25.92 + throws IOException, TemplateException { 25.93 + 25.94 + String arg0 = fdp.getNextArg(); 25.95 + String arg1 = fdp.getNextArg(); 25.96 + String arg2 = fdp.getNextArg(); 25.97 + int arg3 = fdp.hasMoreData() ? 25.98 + Integer.parseInt(fdp.getNextArg()) : -1; 25.99 + int arg4 = fdp.hasMoreData() ? 25.100 + Integer.parseInt(fdp.getNextArg()) : -1; 25.101 + 25.102 + File source = new File 25.103 + (Tema.getProperty("resource_base"), arg0); 25.104 + 25.105 + try { 25.106 + ImageConverter.convert 25.107 + (source, /* source file */ 25.108 + new File(arg1), /* dest file */ 25.109 + arg2, /* format */ 25.110 + arg3, /* max width */ 25.111 + arg4); /* max height */ 25.112 + } catch (Exception e) { 25.113 + System.err.println(e); 25.114 + return 0; 25.115 + } 25.116 + 25.117 + out.write(arg1); 25.118 + return 1; 25.119 + } 25.120 + }; 25.121 + 25.122 + public static final Function COPY = 25.123 + new Function("copy") { 25.124 + public int invoke(FunctionDataParser fdp, Writer out) 25.125 + throws IOException, TemplateException { 25.126 + 25.127 + String arg0 = fdp.getNextArg(); 25.128 + String arg1 = fdp.getNextArg(); 25.129 + 25.130 + File source = new File 25.131 + (Tema.getProperty("resource_base"), arg0); 25.132 + File dest = new File(arg1); 25.133 + 25.134 + try { 25.135 + copyFile(source, dest); 25.136 + } catch (IOException e) { 25.137 + System.err.println(e); 25.138 + return 0; 25.139 + } 25.140 + out.write(arg1); 25.141 + return 1; 25.142 + } 25.143 + }; 25.144 + 25.145 + /* query:sql_query template arg1 arg2 ... argN */ 25.146 + public static final Function QUERY = 25.147 + new Function("query") { 25.148 + public int invoke(FunctionDataParser fdp, Writer out) 25.149 + throws IOException, TemplateException { 25.150 + 25.151 + String arg0 = fdp.getNextArg(); 25.152 + String arg1 = fdp.getNextArg(); 25.153 + List<String> args = fdp.getArgs(); 25.154 + 25.155 + TemplateParser tp = fdp.getTemplateParser(); 25.156 + 25.157 + try { 25.158 + return Tema.query 25.159 + (arg1, (PreparedStatement)tp.getValue(arg0), 25.160 + args, tp, out); 25.161 + } catch (SQLException e) { 25.162 + throw new TemplateException(e.getMessage(), e); 25.163 + } 25.164 + } 25.165 + }; 25.166 + 25.167 + public static final Function WRITE = 25.168 + new Function("write") { 25.169 + public int invoke(FunctionDataParser fdp, Writer out) 25.170 + throws IOException, TemplateException { 25.171 + 25.172 + String arg0 = fdp.getNextArg(); 25.173 + 25.174 + System.err.println("Writing " + arg0 + "..."); 25.175 + 25.176 + Writer fw; 25.177 + 25.178 + try { 25.179 + fw = Tema.createFileWriter(arg0); 25.180 + } catch (IOException e) { 25.181 + System.err.println(e); 25.182 + return 0; 25.183 + } 25.184 + 25.185 + try { 25.186 + fdp.parseData(fw); 25.187 + } finally { 25.188 + fw.close(); 25.189 + } 25.190 + 25.191 + out.write(arg0); 25.192 + 25.193 + System.err.println("Saved " + arg0 + "."); 25.194 + return 1; 25.195 + } 25.196 + }; 25.197 + 25.198 + public static final Function READ = 25.199 + new Function("read") { 25.200 + public int invoke(FunctionDataParser fdp, Writer out) 25.201 + throws IOException, TemplateException { 25.202 + 25.203 + String filename = fdp.getData(); 25.204 + String file; 25.205 + 25.206 + try { 25.207 + file = Tema.readFile(new File(filename)); 25.208 + } catch (IOException e) { 25.209 + System.err.println(e); 25.210 + return 0; 25.211 + } 25.212 + 25.213 + out.write(file); 25.214 + return 1; 25.215 + } 25.216 + }; 25.217 + 25.218 + public static final Function INCLUDE = 25.219 + new Function("include") { 25.220 + public int invoke(FunctionDataParser fdp, Writer out) 25.221 + throws IOException, TemplateException { 25.222 + 25.223 + String filename = fdp.getData(); 25.224 + 25.225 + Reader fin = new BufferedReader 25.226 + (Tema.createCachedFileReader(new File(filename))); 25.227 + 25.228 + int r = fdp.getTemplateParser().parse(fin, out); 25.229 + 25.230 + fin.close(); 25.231 + return r; 25.232 + } 25.233 + }; 25.234 + 25.235 + public static final Function NULL_OUTPUT = 25.236 + new Function("!") { 25.237 + public int invoke(FunctionDataParser fdp, Writer out) 25.238 + throws IOException, TemplateException { 25.239 + 25.240 + /* Write nothing. */ 25.241 + return fdp.parseData(new Writer() { 25.242 + public void close() {} 25.243 + public void flush() {} 25.244 + public void write(char[] cbuf, int off, int len) {} 25.245 + }); 25.246 + } 25.247 + }; 25.248 + 25.249 + public static final Function REPLACE = 25.250 + new Function("replace") { 25.251 + public int invoke(FunctionDataParser fdp, Writer out) 25.252 + throws IOException, TemplateException { 25.253 + 25.254 + String arg0 = fdp.getNextArg(); 25.255 + String arg1 = fdp.getNextArg(); 25.256 + 25.257 + ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1); 25.258 + 25.259 + int ret = fdp.parseData(rw); 25.260 + rw.finish(); 25.261 + return ret; 25.262 + } 25.263 + }; 25.264 + 25.265 + public static final Function XML_ESCAPE = 25.266 + new Function("xml_escape") { 25.267 + public int invoke(FunctionDataParser fdp, Writer out) 25.268 + throws IOException, TemplateException { 25.269 + 25.270 + final String[] chars = {"&", "<", ">", "`", "\""}; 25.271 + final String[] escape = {"&", "<", ">", "'", """}; 25.272 + 25.273 + ReplaceWriter rw = new ReplaceWriter(out, chars, escape); 25.274 + 25.275 + int ret = fdp.parseData(rw); 25.276 + rw.finish(); 25.277 + return ret; 25.278 + } 25.279 + }; 25.280 + 25.281 + public static final Function XML_CDATA = 25.282 + new Function("xml_cdata") { 25.283 + public int invoke(FunctionDataParser fdp, Writer out) 25.284 + throws IOException, TemplateException { 25.285 + 25.286 + ReplaceWriter rw = new ReplaceWriter 25.287 + (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>"); 25.288 + 25.289 + int ret = fdp.parseData(rw); 25.290 + rw.finish(); 25.291 + return ret; 25.292 + } 25.293 + }; 25.294 + 25.295 + public static final Function DEFINE = new Define(); 25.296 + 25.297 + private static void copyFile(File src, File dest) throws IOException { 25.298 + System.err.print("Copying " + src + "... "); 25.299 + 25.300 + if (src.lastModified() < dest.lastModified()) { 25.301 + System.err.println(dest + " is up to date."); 25.302 + return; 25.303 + } 25.304 + 25.305 + File parent = dest.getParentFile(); 25.306 + if (parent != null) parent.mkdirs(); 25.307 + 25.308 + InputStream in = new FileInputStream(src); 25.309 + OutputStream out = new FileOutputStream(dest); 25.310 + 25.311 + byte[] buffer = new byte[1024]; 25.312 + int len; 25.313 + while ((len = in.read(buffer)) > 0) { 25.314 + out.write(buffer, 0, len); 25.315 + } 25.316 + in.close(); 25.317 + out.close(); 25.318 + 25.319 + System.err.println("saved " + dest + "."); 25.320 + } 25.321 + 25.322 + static void registerAllFunctions(TemplateParser p) { 25.323 + p.registerFunction(GET); 25.324 + p.registerFunction(SET); 25.325 + p.registerFunction(OPTIONAL); 25.326 + p.registerFunction(IMAGE); 25.327 + p.registerFunction(COPY); 25.328 + p.registerFunction(QUERY); 25.329 + p.registerFunction(PREPARE); 25.330 + p.registerFunction(WRITE); 25.331 + p.registerFunction(READ); 25.332 + p.registerFunction(INCLUDE); 25.333 + p.registerFunction(NULL_OUTPUT); 25.334 + p.registerFunction(REPLACE); 25.335 + p.registerFunction(XML_ESCAPE); 25.336 + p.registerFunction(XML_CDATA); 25.337 + p.registerFunction(DEFINE); 25.338 + } 25.339 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/kryshen/tema/ImageConverter.java Tue May 16 18:04:09 2006 +0400 26.3 @@ -0,0 +1,184 @@ 26.4 +/* 26.5 + * Copyright (C) 2005, 2006 Mikhail A. Kryshen 26.6 + * 26.7 + * $Id: ImageConverter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 26.8 + */ 26.9 + 26.10 +package kryshen.tema; 26.11 + 26.12 +import java.util.*; 26.13 +import java.io.*; 26.14 +import java.awt.*; 26.15 +import java.awt.image.*; 26.16 +import java.awt.geom.AffineTransform; 26.17 +import javax.imageio.*; 26.18 +import javax.imageio.stream.*; 26.19 + 26.20 +/** 26.21 + * Class defines static method to convert images to specified format. 26.22 + * 26.23 + * @author Mikhail A. Kryshen 26.24 + */ 26.25 +class ImageConverter { 26.26 + 26.27 + static void convert(File source, File dest, String format, 26.28 + int maxWidth, int maxHeight) 26.29 + throws IOException, InterruptedException { 26.30 + 26.31 + System.err.print("Converting image " + source + "... "); 26.32 + 26.33 + if (source.lastModified() < dest.lastModified()) { 26.34 + System.err.println(dest + " is up to date."); 26.35 + return; 26.36 + } 26.37 + 26.38 + BufferedImage image = ImageIO.read(source); 26.39 + 26.40 + //int type = image.getType(); 26.41 + //final int type = BufferedImage.TYPE_INT_RGB; 26.42 + //ColorModel cm = image.getColorModel(); 26.43 + 26.44 + int w = image.getWidth(null); 26.45 + int h = image.getHeight(null); 26.46 + 26.47 + //boolean scale = false; 26.48 + 26.49 + float scale = 1f; 26.50 + 26.51 + if (maxWidth > 0 && w > maxWidth) 26.52 + scale = (float)maxWidth / w; 26.53 + 26.54 + if (maxHeight > 0 && h * scale > maxHeight) 26.55 + scale = (float)maxHeight / h; 26.56 + 26.57 + if (scale != 1f) { 26.58 + w *= scale; h *= scale; 26.59 + 26.60 +// ColorModel cm = image.getColorModel(); 26.61 +// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); 26.62 +// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); 26.63 +// BufferedImage scaled = new BufferedImage 26.64 +// (cm, raster, alphaPremultiplied, null); 26.65 + 26.66 +// BufferedImage scaled = new BufferedImage(w, h, image.getType()); 26.67 + 26.68 + 26.69 + Image scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH); 26.70 + 26.71 + ColorModel cm = image.getColorModel(); 26.72 + boolean alphaPremultiplied = image.isAlphaPremultiplied(); 26.73 + WritableRaster raster = cm.createCompatibleWritableRaster(w, h); 26.74 + image = new BufferedImage(cm, raster, alphaPremultiplied, null); 26.75 + 26.76 + Graphics g = image.getGraphics(); 26.77 + g.drawImage(scaled, 0, 0, null); 26.78 + g.dispose(); 26.79 + 26.80 +// image = scale(image, scaled, scale); 26.81 +// Graphics2D g = scaled.createGraphics(); 26.82 +// g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 26.83 +// RenderingHints.VALUE_INTERPOLATION_BILINEAR); 26.84 +// System.err.print(" " + g.drawImage(image, 0, 0, w, h, null) + " "); 26.85 +// g.dispose(); 26.86 +// image = scaled; 26.87 + } 26.88 + 26.89 + File parent = dest.getParentFile(); 26.90 + if (parent != null) parent.mkdirs(); 26.91 + 26.92 + ImageIO.write(image, format, dest); 26.93 + System.err.println("saved " + dest + "."); 26.94 + } 26.95 + 26.96 +// public static ColorModel getColorModel(Image image) 26.97 +// throws InterruptedException { 26.98 + 26.99 +// PixelGrabber grabby = new PixelGrabber(image, 0, 0, 1, 1, false); 26.100 +// if (!grabby.grabPixels()) 26.101 +// throw new RuntimeException("pixel grab fails"); 26.102 +// return grabby.getColorModel(); 26.103 +// } 26.104 + 26.105 +// private static BufferedImage scale(BufferedImage image, 26.106 +// BufferedImage dest, 26.107 +// float scale) { 26.108 + 26.109 +// AffineTransform tx = new AffineTransform(); 26.110 +// tx.scale(scale, scale); 26.111 + 26.112 +// AffineTransformOp op = new AffineTransformOp 26.113 +// (tx, AffineTransformOp.TYPE_BILINEAR); 26.114 + 26.115 +// return op.filter(image, dest); 26.116 +// } 26.117 + 26.118 + // TEST 26.119 + 26.120 + public static void main(String[] args) 26.121 + throws IOException, InterruptedException { 26.122 + 26.123 + convert(new File(args[0]), new File(args[1]), "png", 300, 300); 26.124 + } 26.125 + 26.126 + 26.127 +// public static BufferedImage toBufferedImage(Image image, ColorModel cm) { 26.128 +// if (image instanceof BufferedImage) 26.129 +// return (BufferedImage)image; 26.130 + 26.131 +// int w = image.getWidth(null); 26.132 +// int h = image.getHeight(null); 26.133 + 26.134 +// boolean alphaPremultiplied = cm.isAlphaPremultiplied(); 26.135 +// WritableRaster raster = cm.createCompatibleWritableRaster(w, h); 26.136 +// BufferedImage result = new BufferedImage(cm, raster, alphaPremultiplied, null); 26.137 +// Graphics2D g = result.createGraphics(); 26.138 + 26.139 +// g.drawImage(image, 0, 0, null); 26.140 +// g.dispose(); 26.141 + 26.142 +// return result; 26.143 +// } 26.144 +} 26.145 + 26.146 + 26.147 +// This is how I'd recommend it in JDK1.4 using javax.imageio.ImageIO to 26.148 +// do the reading/writing and Java2D to do the scaling. 26.149 + 26.150 +// // read in the original image 26.151 +// BufferedImage in = ImageIO.read(new File("in.jpg")); 26.152 + 26.153 +// // create a new image of the smaller size 26.154 +// BufferedImage out = new BufferedImage(newWidth, newHeight); 26.155 + 26.156 +// // get the graphics associated with the new image 26.157 +// Graphics g = out.getGraphics(); 26.158 + 26.159 +// // draw the original image into the new image, scaling 26.160 +// // on the fly 26.161 +// g.drawImage(in, newWidth, newHeight, null); 26.162 + 26.163 +// // dispose the graphics object 26.164 +// g.dispose(); 26.165 + 26.166 +// // write out the new image 26.167 +// ImagIO.write("out.jpg", "jpeg", new File("out.jpg")); 26.168 + 26.169 +// ------------------------------------------ 26.170 + 26.171 +// For nicer scaling, you could add a rendering hint to the graphics 26.172 +// object before painting. 26.173 + 26.174 +// ie. 26.175 + 26.176 +// Graphics2D g2d = (Graphics2D)g; 26.177 +// g2d.setRenderingHint(RenderingHints.KEY_INTEPOLATION, 26.178 +// RenderingHints.VALUE_INTERPOLATION_BILINEAR); 26.179 + 26.180 +// or use VALUE_INTERPOLATION_BICUBIC for the best. 26.181 + 26.182 +// But as you can guess, nicer == slower. 26.183 + 26.184 +// Shannon Hickey 26.185 +// shann...@swingteam.com 26.186 +// Swing Team http://TheSwingConnection.com http://TheJavaTutorial.com 26.187 +// Java Software, a division of Sun Microsystems, Inc.
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/src/kryshen/tema/ReplaceWriter.java Tue May 16 18:04:09 2006 +0400 27.3 @@ -0,0 +1,140 @@ 27.4 +/* 27.5 + * Copyright (C) 2006 Mikhail A. Kryshen 27.6 + * 27.7 + * $Id: ReplaceWriter.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 27.8 + */ 27.9 + 27.10 +package kryshen.tema; 27.11 + 27.12 +import java.io.Writer; 27.13 +import java.io.FilterWriter; 27.14 +import java.io.IOException; 27.15 + 27.16 +import java.util.LinkedList; 27.17 +import java.util.Iterator; 27.18 + 27.19 +/** 27.20 + * FilterWriter which replaces characters with escape strings. 27.21 + * 27.22 + * @author Mikhail A. Kryshen 27.23 + */ 27.24 +class ReplaceWriter extends FilterWriter { 27.25 + private String[] patterns; 27.26 + private String[] replaces; 27.27 + 27.28 + private String prefix; 27.29 + private String postfix; 27.30 + 27.31 + private int maxPatternLength = 0; 27.32 + 27.33 + /** Had this Writer processed any data? */ 27.34 + private boolean processedData = false; 27.35 + 27.36 + private StringBuffer buffer = new StringBuffer(); 27.37 + 27.38 + public ReplaceWriter(Writer w, String pattern, String replace) { 27.39 + this(w, new String[]{pattern}, new String[]{replace}); 27.40 + } 27.41 + 27.42 + public ReplaceWriter(Writer w, String pattern, String replace, 27.43 + String prefix, String postfix) { 27.44 + 27.45 + this(w, new String[]{pattern}, new String[]{replace}, 27.46 + prefix, postfix); 27.47 + } 27.48 + 27.49 + public ReplaceWriter(Writer w, String[] patterns, String[] replaces) { 27.50 + this(w, patterns, replaces, null, null); 27.51 + } 27.52 + 27.53 + public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 27.54 + String prefix, String postfix) { 27.55 + super(w); 27.56 + 27.57 + this.patterns = patterns; 27.58 + this.replaces = replaces; 27.59 + 27.60 + this.prefix = prefix; 27.61 + this.postfix = postfix; 27.62 + 27.63 + for (int i = 0; i < patterns.length; i++) { 27.64 + int length = patterns[i].length(); 27.65 + if (length > maxPatternLength) 27.66 + maxPatternLength = length; 27.67 + } 27.68 + } 27.69 + 27.70 + private boolean processBuffer(int minLength) throws IOException { 27.71 + if (buffer.length() == 0) return false; 27.72 + 27.73 + if (!processedData) { 27.74 + if (prefix != null) 27.75 + super.write(prefix, 0, prefix.length()); 27.76 + processedData = true; 27.77 + } 27.78 + 27.79 + int k; 27.80 + for (k = 0; minLength + k < buffer.length(); k++) { 27.81 + for (int i = 0; i < patterns.length; i++) { 27.82 + String pattern = patterns[i]; 27.83 + int length = pattern.length(); 27.84 + 27.85 + if (length + k > buffer.length()) 27.86 + continue; 27.87 + 27.88 + boolean match = true; 27.89 + 27.90 + for (int j = 0; j < length; j++) { 27.91 + if (pattern.charAt(j) != buffer.charAt(j + k)) { 27.92 + match = false; 27.93 + break; 27.94 + } 27.95 + } 27.96 + 27.97 + if (match) { 27.98 + super.write(buffer.substring(0, k), 0, k); 27.99 + buffer.delete(0, k + length); 27.100 + super.write(replaces[i], 0, replaces[i].length()); 27.101 + return true; 27.102 + } 27.103 + } 27.104 + } 27.105 + 27.106 + super.write(buffer.substring(0, k), 0, k); 27.107 + buffer.delete(0, k); 27.108 + 27.109 + return false; 27.110 + } 27.111 + 27.112 + public void write(int c) throws IOException { 27.113 + buffer.append((char)c); 27.114 + processBuffer(maxPatternLength); 27.115 + } 27.116 + 27.117 + public void write(char[] cbuf, int off, int len) throws IOException { 27.118 + for (int i = off; i < off + len; i++) { 27.119 + buffer.append(cbuf[i]); 27.120 + } 27.121 + processBuffer(maxPatternLength); 27.122 + } 27.123 + 27.124 + public void write(String str, int off, int len) throws IOException { 27.125 + buffer.append(str.substring(off, off + len)); 27.126 + processBuffer(maxPatternLength); 27.127 + } 27.128 + 27.129 + public void finish() throws IOException { 27.130 + while (processBuffer(0)); 27.131 + 27.132 +// super.write(buffer.toString(), 0, buffer.length()); 27.133 +// buffer.delete(0, buffer.length()); 27.134 + 27.135 + if (processedData && postfix != null) 27.136 + super.write(postfix, 0, postfix.length()); 27.137 + } 27.138 + 27.139 + public void close() throws IOException { 27.140 + finish(); 27.141 + super.close(); 27.142 + } 27.143 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/src/kryshen/tema/Tema.java Tue May 16 18:04:09 2006 +0400 28.3 @@ -0,0 +1,237 @@ 28.4 +/* 28.5 + * Copyright (C) 2005, 2006 Mikhail A. Kryshen 28.6 + * 28.7 + * $Id: Tema.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 28.8 + */ 28.9 + 28.10 +package kryshen.tema; 28.11 + 28.12 +import java.sql.Driver; 28.13 +import java.sql.DriverManager; 28.14 +import java.sql.Connection; 28.15 +import java.sql.Statement; 28.16 +import java.sql.PreparedStatement; 28.17 +import java.sql.ResultSet; 28.18 +import java.sql.ResultSetMetaData; 28.19 +import java.sql.SQLException; 28.20 + 28.21 +import java.util.Map; 28.22 +import java.util.HashMap; 28.23 +import java.util.Properties; 28.24 +import java.util.List; 28.25 +import java.util.Collections; 28.26 + 28.27 +import java.io.*; 28.28 + 28.29 +/** 28.30 + * Tema main class. 28.31 + * 28.32 + * @author Mikhail A. Kryshen 28.33 + */ 28.34 +public class Tema { 28.35 + private static final String CONFIG_FILE = "tema.properties"; 28.36 + private static final String ENV_PREFIX = "kryshen.tema."; 28.37 + 28.38 + private static Properties config = new Properties(); 28.39 + static Connection connection = null; 28.40 + 28.41 + private static String inputEncoding; 28.42 + private static String outputEncoding; 28.43 + 28.44 + static Map<File, String> fileCache = null; 28.45 + 28.46 + public static void main(String[] args) 28.47 + throws IOException, TemplateException, SQLException, 28.48 + ClassNotFoundException, InstantiationException, 28.49 + IllegalAccessException { 28.50 + 28.51 + InputStream configIn = new FileInputStream(CONFIG_FILE); 28.52 + config.load(configIn); 28.53 + configIn.close(); 28.54 + 28.55 + String logFile = getProperty("log"); 28.56 + if (logFile != null && logFile.length() > 0) 28.57 + System.setErr(new PrintStream(new FileOutputStream(logFile))); 28.58 + 28.59 + if (Boolean.parseBoolean(getProperty("cache_read")) == true) 28.60 + fileCache = new HashMap<File, String>(); 28.61 + 28.62 + inputEncoding = getProperty("input_encoding", "iso-8859-1"); 28.63 + outputEncoding = getProperty("output_encoding", "iso-8859-1"); 28.64 + 28.65 + String resourceProperty = getProperty("resource"); 28.66 + 28.67 + if (resourceProperty != null) { 28.68 + String driverProperty = getProperty("driver"); 28.69 + if (driverProperty != null) { 28.70 + // Register driver. 28.71 + Driver d = (Driver)Class.forName(driverProperty).newInstance(); 28.72 + } 28.73 + 28.74 + // Open connection. 28.75 + connection = DriverManager.getConnection(resourceProperty); 28.76 + } 28.77 + 28.78 +// String maxFilesString = getProperty("max_output_files"); 28.79 +// int maxFiles = -1; 28.80 +// if (maxFilesString != null) 28.81 +// maxFiles = Integer.parseInt(maxFilesString); 28.82 + 28.83 + String main = getProperty("main_template"); 28.84 + String output = getProperty("output"); 28.85 + 28.86 + Writer out; 28.87 + 28.88 + if ("stderr".equals(output)) 28.89 + out = new OutputStreamWriter(System.err); 28.90 + else 28.91 + out = new OutputStreamWriter(System.out); 28.92 + 28.93 + InputStream is = new FileInputStream(main); 28.94 + Reader in = new BufferedReader(new InputStreamReader(is, inputEncoding)); 28.95 + 28.96 + TemplateParser p = new TemplateParser(); 28.97 + try { 28.98 + p.parse(in, out); 28.99 + } finally { 28.100 + in.close(); 28.101 + out.flush(); 28.102 + } 28.103 + 28.104 + System.err.println("Done"); 28.105 + } 28.106 + 28.107 +// private static void readEscapes() { 28.108 +// for (int i = 1;; i++) { 28.109 +// String pattern = getProperty("escape_char_" + i); 28.110 + 28.111 +// if (pattern == null) break; 28.112 + 28.113 +// escapes.put(pattern.charAt(0), 28.114 +// getProperty("escape_string_" + i)); 28.115 +// } 28.116 +// } 28.117 + 28.118 + /** 28.119 + * Get configuration property. 28.120 + */ 28.121 + static String getProperty(String name) { 28.122 + String value = System.getProperty(ENV_PREFIX + name); 28.123 + if (value != null) return value; 28.124 + return config.getProperty(name); 28.125 + } 28.126 + 28.127 + /** 28.128 + * Get configuration property. 28.129 + */ 28.130 + static String getProperty(String name, String fallback) { 28.131 + String value = getProperty(name); 28.132 + if (value != null) return value; 28.133 + return fallback; 28.134 + } 28.135 + 28.136 + /** 28.137 + * Process subquery and template. 28.138 + * 28.139 + * @param template template to fill with data. 28.140 + * @param ps query statement to execute. 28.141 + * @param args list of query parameters. 28.142 + * @param superParser invoking object. 28.143 + * @param out Writer to output processed data. 28.144 + * 28.145 + * @return number of processed rows in query result. 28.146 + */ 28.147 + static int query(String template, PreparedStatement ps, 28.148 + List<String> args, 28.149 + TemplateParser superParser, 28.150 + Writer out) 28.151 + throws IOException, SQLException, TemplateException { 28.152 + 28.153 + StringReader templateReader = new StringReader(template); 28.154 + 28.155 + int i = 1; 28.156 + 28.157 + for (String arg : args) { 28.158 + ps.setString(i++, arg); 28.159 + } 28.160 + 28.161 + ResultSet r = ps.executeQuery(); 28.162 + ResultSetMetaData rm = r.getMetaData(); 28.163 + int columnCount = rm.getColumnCount(); 28.164 + 28.165 + String[] names = new String[columnCount]; 28.166 + 28.167 + for (int j = 0; j < columnCount; j++) { 28.168 + names[j] = rm.getColumnName(j + 1); 28.169 + } 28.170 + 28.171 + TemplateParser p = new TemplateParser(superParser); 28.172 + 28.173 + for (i = 1; r.next(); i++) { 28.174 + p.clearValues(); 28.175 + 28.176 + for (int j = 0; j < columnCount; j++) { 28.177 + Object value = r.getObject(j + 1); 28.178 + if (r.wasNull()) value = null; 28.179 + 28.180 + p.setValue(names[j], value); 28.181 + } 28.182 + 28.183 + p.setValue("NUMBER", i); 28.184 + p.parse(templateReader, out); 28.185 + templateReader.reset(); 28.186 + } 28.187 + 28.188 + r.close(); 28.189 + ps.clearParameters(); 28.190 + return i - 1; 28.191 + } 28.192 + 28.193 + static Writer createFileWriter(String filename) throws IOException { 28.194 + OutputStream os = new FileOutputStream(filename); 28.195 + return new OutputStreamWriter(os, Tema.outputEncoding); 28.196 + } 28.197 + 28.198 + static Reader createFileReader(File file) throws IOException { 28.199 + InputStream is = new FileInputStream(file); 28.200 + return new InputStreamReader(is, Tema.inputEncoding); 28.201 + } 28.202 + 28.203 + static Reader createCachedFileReader(File file) throws IOException { 28.204 + if (fileCache != null) return new StringReader(readFile(file)); 28.205 + else return createFileReader(file); 28.206 + } 28.207 + 28.208 + /** 28.209 + * Read text file. 28.210 + */ 28.211 + static String readFile(File file) throws IOException { 28.212 + String data; 28.213 + 28.214 + if (fileCache != null) { 28.215 + data = fileCache.get(file); 28.216 + if (data != null) return data; 28.217 + } 28.218 + 28.219 + Reader r = new BufferedReader(createFileReader(file)); 28.220 + 28.221 + // FIXME: possible overflow (long -> int). 28.222 + StringBuffer sb = new StringBuffer((int)file.length()); 28.223 + 28.224 + try { 28.225 + for (int c = r.read(); c >= 0; c = r.read()) { 28.226 + sb.append((char)c); 28.227 + } 28.228 + } finally { 28.229 + r.close(); 28.230 + } 28.231 + 28.232 + data = sb.toString(); 28.233 + 28.234 + if (fileCache != null) { 28.235 + fileCache.put(file, data); 28.236 + } 28.237 + 28.238 + return data; 28.239 + } 28.240 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/src/kryshen/tema/TemplateException.java Tue May 16 18:04:09 2006 +0400 29.3 @@ -0,0 +1,24 @@ 29.4 +/* 29.5 + * Copyright (C) 2006 Mikhail A. Kryshen 29.6 + * 29.7 + * $Id: TemplateException.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 29.8 + */ 29.9 + 29.10 +package kryshen.tema; 29.11 + 29.12 +/** 29.13 + * Signals that template parsing fails. 29.14 + * 29.15 + * @author Mikhail A. Kryshen 29.16 + */ 29.17 +public class TemplateException extends Exception { 29.18 + // TODO: store the number of template line with error. 29.19 + 29.20 + public TemplateException(String message) { 29.21 + super(message); 29.22 + } 29.23 + 29.24 + public TemplateException(String message, Throwable cause) { 29.25 + super(message, cause); 29.26 + } 29.27 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/src/kryshen/tema/TemplateParser.java Tue May 16 18:04:09 2006 +0400 30.3 @@ -0,0 +1,287 @@ 30.4 +/* 30.5 + * Copyright (C) 2005, 2006 Mikhail A. Kryshen 30.6 + * 30.7 + * $Id: TemplateParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 30.8 + */ 30.9 + 30.10 +package kryshen.tema; 30.11 + 30.12 +import java.io.*; 30.13 +import java.util.*; 30.14 + 30.15 +/** 30.16 + * Parser for DbReader templates. 30.17 + * 30.18 + * @author Mikhail A. Kryshen 30.19 + */ 30.20 +public class TemplateParser { 30.21 + static final String SUPER = "SUPER."; 30.22 + 30.23 + /* Brackets. */ 30.24 + static final char[] BR_LEFT = {'<', '['}; 30.25 + static final char[] BR_RIGHT = {'>', ']'}; 30.26 + 30.27 + static final char BR_IN = '%'; 30.28 + 30.29 + /* Separators. */ 30.30 + static final char[] REC_DATA_SEPARATORS = {':'}; 30.31 + static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; 30.32 + static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'}; 30.33 + 30.34 + static enum FunctionData { 30.35 + SUBFUNCTION, RECURSIVE, NONRECURSIVE; 30.36 + }; 30.37 + 30.38 + static enum Terminator { 30.39 + EOF, BRACKET, SEPARATOR; 30.40 + }; 30.41 + 30.42 + static class Result { 30.43 + Terminator terminator; 30.44 + int substitutions; 30.45 + 30.46 + /** No text had been parsed. */ 30.47 + boolean empty; 30.48 + 30.49 + Result(Terminator terminator, int substitutions, boolean empty) { 30.50 + this.terminator = terminator; 30.51 + this.substitutions = substitutions; 30.52 + this.empty = empty; 30.53 + } 30.54 + 30.55 + Result() { 30.56 + this(null, 0, true); 30.57 + } 30.58 + }; 30.59 + 30.60 + private Map<String, Function> functions = new HashMap<String, Function>(); 30.61 + 30.62 + private Map<String, Object> variables = new HashMap<String, Object>(); 30.63 + private TemplateParser superParser; 30.64 + 30.65 + private int termBracket = -1; 30.66 + 30.67 + public TemplateParser() { 30.68 + this(null); 30.69 + } 30.70 + 30.71 + public TemplateParser(TemplateParser superParser) { 30.72 + this.superParser = superParser; 30.73 + 30.74 + Functions.registerAllFunctions(this); 30.75 + } 30.76 + 30.77 + public void registerFunction(Function f) { 30.78 + functions.put(f.name, f); 30.79 + } 30.80 + 30.81 + public int parse(Reader in, Writer out) 30.82 + throws IOException, TemplateException { 30.83 + 30.84 + return parse(in, out, true, null, null).substitutions; 30.85 + } 30.86 + 30.87 + /** 30.88 + * Parse template. 30.89 + * 30.90 + * @param in Reader to read template data. 30.91 + * @param out Writer to write processed data. 30.92 + * @param recursive enables recursive processing. 30.93 + * @param separators characters which terminate parsing block. 30.94 + * @param leading characters to ignore at the beginning of the block. 30.95 + */ 30.96 + Result parse(Reader in, Writer out, boolean recursive, 30.97 + char[] separators, char[] leading) 30.98 + throws IOException, TemplateException { 30.99 + 30.100 + Result result = new Result(); 30.101 + int lc = -1; 30.102 + 30.103 + while (true) { 30.104 + int c = in.read(); 30.105 + 30.106 + if (leading != null && isSeparator(c, leading)) 30.107 + continue; 30.108 + else 30.109 + leading = null; 30.110 + 30.111 + boolean leftBracket = false; 30.112 + int index; 30.113 + 30.114 + for (index = 0; index < BR_LEFT.length; index++) { 30.115 + if (lc == BR_LEFT[index]) { 30.116 + leftBracket = true; 30.117 + break; 30.118 + } 30.119 + } 30.120 + 30.121 + if (recursive && leftBracket && c == BR_IN) { 30.122 + 30.123 + lc = -1; 30.124 + int tb = termBracket; 30.125 + termBracket = BR_RIGHT[index]; 30.126 + result.substitutions += parseFunction(in, out); 30.127 + termBracket = tb; 30.128 + 30.129 + } else if (lc == BR_IN && c == termBracket) { 30.130 + 30.131 + lc = -1; 30.132 + result.terminator = Terminator.BRACKET; 30.133 + break; 30.134 + 30.135 + } else { 30.136 + 30.137 + if (lc >= 0) 30.138 + out.write(lc); 30.139 + 30.140 + lc = c; 30.141 + } 30.142 + 30.143 + if (c < 0) { 30.144 + result.terminator = Terminator.EOF; 30.145 + break; 30.146 + } else if (separators != null && isSeparator(c, separators)) { 30.147 + result.terminator = Terminator.SEPARATOR; 30.148 + break; 30.149 + } 30.150 + 30.151 + result.empty = false; 30.152 + } 30.153 + 30.154 + return result; 30.155 + } 30.156 + 30.157 + int parseVariable(String name, Writer out) 30.158 + throws IOException, TemplateException { 30.159 + 30.160 + Object ovalue = getValue(name); 30.161 + if (ovalue == null) 30.162 + return 0; 30.163 + 30.164 + String svalue = ovalue.toString(); 30.165 + 30.166 + if (svalue == null || svalue.length() == 0) 30.167 + return 0; 30.168 + 30.169 + out.write(svalue); 30.170 + return 1; 30.171 + } 30.172 + 30.173 + boolean isSeparator(int c, char[] separators) { 30.174 + for (char p : separators) { 30.175 + if (c == p) return true; 30.176 + } 30.177 + 30.178 + return false; 30.179 + } 30.180 + 30.181 + int parseFunction(Reader in, Writer out) 30.182 + throws IOException, TemplateException { 30.183 + 30.184 + StringBuffer sb = new StringBuffer(); 30.185 + 30.186 + while (true) { 30.187 + int c = in.read(); 30.188 + 30.189 + if (isSeparator(c, LIST_SEPARATORS)) { 30.190 + return invokeFunction(sb.toString(), 30.191 + FunctionData.SUBFUNCTION, 30.192 + in, out); 30.193 + } else if (isSeparator(c, REC_DATA_SEPARATORS)) { 30.194 + return invokeFunction(sb.toString(), 30.195 + FunctionData.RECURSIVE, 30.196 + in, out); 30.197 + } else if (isSeparator(c, NONREC_DATA_SEPARATORS)) { 30.198 + return invokeFunction(sb.toString(), 30.199 + FunctionData.NONRECURSIVE, 30.200 + in, out); 30.201 + } else if (c < 0) { 30.202 + System.err.println("Error: unexpected end of file."); 30.203 + return 0; 30.204 + } else { 30.205 + sb.append((char)c); 30.206 + } 30.207 + } 30.208 + } 30.209 + 30.210 + private int invokeFunction(String name, FunctionData fd, 30.211 + Reader in, Writer out) 30.212 + throws IOException, TemplateException { 30.213 + 30.214 + FunctionDataParser fdp = new FunctionDataParser(this, fd, in); 30.215 + 30.216 + if ("".equals(name)) { 30.217 + return fdp.parseData(out); 30.218 + } 30.219 + 30.220 + Function f = getFunction(name); 30.221 + 30.222 + if (f == null) { 30.223 + throw new TemplateException("Unknown function: " + name); 30.224 + } 30.225 + 30.226 + int r = f.invoke(fdp, out); 30.227 + 30.228 + if (fdp.hasMoreData()) { 30.229 + /* Skip remaining function data. */ 30.230 + fdp.parseData(new Writer() { 30.231 + public void close() {} 30.232 + public void flush() {} 30.233 + public void write(char[] cbuf, int off, int len) {} 30.234 + }); 30.235 + } 30.236 + 30.237 + return r; 30.238 + } 30.239 + 30.240 + Function getFunction(String name) throws TemplateException { 30.241 + Function function = functions.get(name); 30.242 + if (function != null) return function; 30.243 + 30.244 + if (superParser != null) { 30.245 + if (name.startsWith(SUPER)) 30.246 + return superParser.getFunction(name.substring(SUPER.length())); 30.247 + else 30.248 + return superParser.getFunction(name); 30.249 + } 30.250 + 30.251 + return null; 30.252 + } 30.253 + 30.254 + Object getValue(String name) throws TemplateException { 30.255 + Object value = variables.get(name); 30.256 + if (value != null) return value; 30.257 + 30.258 + if (superParser != null) { 30.259 + if (name.startsWith(SUPER)) 30.260 + return superParser.getValue(name.substring(SUPER.length())); 30.261 + else 30.262 + return superParser.getValue(name); 30.263 + } 30.264 + 30.265 + return null; 30.266 + } 30.267 + 30.268 + void setValue(String name, Object value) { 30.269 + variables.put(name, value); 30.270 + } 30.271 + 30.272 + void clearValues() { 30.273 + variables.clear(); 30.274 + } 30.275 + 30.276 + // TEST 30.277 + public static void main(String[] args) 30.278 + throws IOException, TemplateException { 30.279 + 30.280 + TemplateParser p = new TemplateParser(); 30.281 + 30.282 + FileReader in = new FileReader("parser.in"); 30.283 + FileWriter out = new FileWriter("parser.out"); 30.284 + 30.285 + p.parse(in, out); 30.286 + 30.287 + in.close(); 30.288 + out.close(); 30.289 + } 30.290 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/src/kryshen/tema/functions/Define.java Tue May 16 18:04:09 2006 +0400 31.3 @@ -0,0 +1,59 @@ 31.4 +/* 31.5 + * Copyright (C) 2006 Mikhail A. Kryshen 31.6 + * 31.7 + * $Id: Define.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ 31.8 + */ 31.9 + 31.10 +package kryshen.tema.functions; 31.11 + 31.12 +import java.io.*; 31.13 +import java.util.*; 31.14 + 31.15 +import kryshen.tema.*; 31.16 + 31.17 +public class Define extends Function { 31.18 + public Define() { 31.19 + super("define"); 31.20 + } 31.21 + 31.22 + public int invoke(FunctionDataParser fdp, Writer out) 31.23 + throws IOException, TemplateException { 31.24 + 31.25 + final String arg0 = fdp.getNextArg(); 31.26 + final String data = fdp.getData(); 31.27 + 31.28 + Function newFunction = new Function(arg0) { 31.29 + public int invoke(final FunctionDataParser fdp, final Writer out) 31.30 + throws IOException, TemplateException { 31.31 + 31.32 + TemplateParser functionParser = 31.33 + new TemplateParser(fdp.getTemplateParser()); 31.34 + 31.35 + functionParser.registerFunction(new Function("nextarg") { 31.36 + public int invoke(FunctionDataParser unusedFdp, 31.37 + final Writer out) 31.38 + throws IOException, TemplateException { 31.39 + 31.40 + return fdp.parseNextArg(out); 31.41 + } 31.42 + }); 31.43 + 31.44 + functionParser.registerFunction(new Function("data") { 31.45 + public int invoke(FunctionDataParser unusedFdp, 31.46 + final Writer out) 31.47 + throws IOException, TemplateException { 31.48 + 31.49 + return fdp.parseData(out); 31.50 + } 31.51 + }); 31.52 + 31.53 + return functionParser.parse(new StringReader(data), out); 31.54 + } 31.55 + }; 31.56 + 31.57 + fdp.getTemplateParser().registerFunction(newFunction); 31.58 + 31.59 + out.write(arg0); 31.60 + return 1; 31.61 + } 31.62 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/test/inctest.template Tue May 16 18:04:09 2006 +0400 32.3 @@ -0,0 +1,1 @@ 32.4 +<%test:1 2 3%>
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/test/macrotest Tue May 16 18:04:09 2006 +0400 33.3 @@ -0,0 +1,3 @@ 33.4 +#!/bin/sh 33.5 + 33.6 +java -jar ../dist/tema.jar
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/test/main.template Tue May 16 18:04:09 2006 +0400 34.3 @@ -0,0 +1,3 @@ 34.4 +<%define`test [%nextarg:%]+[%nextarg:%]=[%data:]%> 34.5 +<%include`inctest.template%> 34.6 +<%test:<%test:ab cd x%> [%\<%test\1 2 3%>%] y%>
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/test/tema.properties Tue May 16 18:04:09 2006 +0400 35.3 @@ -0,0 +1,22 @@ 35.4 +# Data source configuration 35.5 +# resource : jdbc:odbc:biotopes-data 35.6 +# driver : sun.jdbc.odbc.JdbcOdbcDriver 35.7 + 35.8 +# Base directory for images and files 35.9 +# resource_base : C:\\biotopes\\db 35.10 + 35.11 +# Template to start processing with 35.12 +main_template : main.template 35.13 + 35.14 +# File encodings 35.15 +# input_encoding : ISO-8859-5 35.16 +# output_encoding : ISO-8859-5 35.17 + 35.18 +# Cache templates 35.19 +# cache_read : true 35.20 + 35.21 +# Output main_template parsing result to stderr 35.22 +# output : stderr 35.23 + 35.24 +# File to output error messages (redirect stderr) 35.25 +# log : dbreader.log