changeset 0:1d2fe61a3a62 release_0_1

Tema 0.1 (imported from CVS).
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 16 May 2006 18:04:09 +0400
parents
children 548a93c24e55
files build.xml dist/biotopes/biotope-top.sql dist/biotopes/biotope.sql dist/biotopes/biotope.template dist/biotopes/brief.dtd dist/biotopes/class.sql dist/biotopes/classes.template dist/biotopes/main.template dist/biotopes/photo.sql dist/biotopes/photo.template dist/biotopes/plant.sql dist/biotopes/plants.template dist/biotopes/tema.properties dist/readme.html dist/readme.txt dist/tema dist/tema.bat dist/tema.properties doc/article.txt sample/class.xml sample/plants.xml src/Manifest.mf 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/functions/Define.java test/inctest.template test/macrotest test/main.template test/tema.properties
diffstat 35 files changed, 2201 insertions(+), 0 deletions(-) [+]
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>&lt;%<em>_</em>[:|\]<em></em>%&gt;</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>&lt;%</code>  <code>%&gt;</code> (<code>&lt;%\&lt;%%&gt;</code>  <code>&lt;%\%%&gt;&gt;</code>).</li>
   14.51 +</ul>
   14.52 +
   14.53 +<h3></h3>
   14.54 +
   14.55 +<ul>
   14.56 +  <li><code>&lt;%get:<em></em>%&gt;</code><br />
   14.57 +         .</li>
   14.58 +
   14.59 +  <li><code>&lt;%optional:<em></em>%&gt;</code><br />
   14.60 +    <em></em>,     ,    ,     .</li>
   14.61 +
   14.62 +  <li><code>&lt;%escape:<em></em>%&gt;</code><br />
   14.63 +     ""  (     ).</li>
   14.64 +
   14.65 +  <li><code>&lt;%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%&gt;</code><br />
   14.66 +      <em></em>.sql       <em></em>.template.        '?'.</li>
   14.67 +
   14.68 +  <li><code>&lt;%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%&gt;</code><br />
   14.69 +      <em>_</em> (     "resource_base")      ,    <em>_</em>.      ,    .
   14.70 +  ,  <code>&lt;%image:...%&gt;</code>     <em>_</em>,  -   .</li>
   14.71 +
   14.72 +  <li><code>&lt;%copy:<em>_</em> <em>_</em>%&gt;</code><br />
   14.73 +    <em>_</em> (     "resource_base")  <em>_</em>.   ,  <code>&lt;%copy:...%&gt;</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>&lt;%escape get:name%&gt;</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 = {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"};
  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