changeset 2:6c41a0b43e58 release_0_3

Tema 0.3 (imported from CVS).
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 19 Feb 2008 20:32:17 +0300
parents 548a93c24e55
children a20217d78068
files .cvsignore COPYING COPYING.LESSER COPYING.apache NOTICE TODO build.xml dist/.cvsignore 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/doc/article.txt dist/biotopes/doc/readme.html dist/biotopes/doc/readme.txt 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/lib/commons-cli-1.1.jar dist/tema.properties doc/.cvsignore doc/manual/.cvsignore doc/manual/document.tema doc/manual/index.html doc/manual/manual.tema misc/biotopes/biotope-top.sql misc/biotopes/biotope.sql misc/biotopes/biotope.template misc/biotopes/brief.dtd misc/biotopes/class.sql misc/biotopes/classes.template misc/biotopes/doc/article.txt misc/biotopes/doc/readme.html misc/biotopes/doc/readme.txt misc/biotopes/main.template misc/biotopes/photo.sql misc/biotopes/photo.template misc/biotopes/plant.sql misc/biotopes/plants.template misc/biotopes/tema.properties misc/manual-ru-old/index.html misc/util/header misc/util/header.gpl misc/util/update_headers.pl nbproject/.cvsignore nbproject/project.xml res/kryshen/tema/demo/demo.template src/Manifest.mf src/kryshen/tema/Context.java src/kryshen/tema/Function.java src/kryshen/tema/FunctionDataParser.java src/kryshen/tema/Functions.java src/kryshen/tema/GlobalContext.java src/kryshen/tema/Tema.java src/kryshen/tema/TemplateException.java src/kryshen/tema/TemplateParser.java src/kryshen/tema/TemplateReader.java src/kryshen/tema/ant/TemaTask.java src/kryshen/tema/demo/DemoFrame.java src/kryshen/tema/demo/Hello.java src/kryshen/tema/functions/Control.java src/kryshen/tema/functions/Database.java src/kryshen/tema/functions/Define.java src/kryshen/tema/functions/IO.java src/kryshen/tema/functions/ImageConverter.java src/kryshen/tema/functions/Logics.java src/kryshen/tema/functions/ReplaceWriter.java src/kryshen/tema/functions/Standard.java src/kryshen/tema/functions/Strings.java src/kryshen/tema/io/CopyWriter.java src/kryshen/tema/io/NullWriter.java src/kryshen/tema/io/ReplaceWriter.java src/kryshen/tema/io/TemplateReader.java test/demo test/demo.bat test/include.template test/main.template test/tema.properties
diffstat 83 files changed, 5514 insertions(+), 2664 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.cvsignore	Tue Feb 19 20:32:17 2008 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +build
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/COPYING	Tue Feb 19 20:32:17 2008 +0300
     2.3 @@ -0,0 +1,674 @@
     2.4 +                    GNU GENERAL PUBLIC LICENSE
     2.5 +                       Version 3, 29 June 2007
     2.6 +
     2.7 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
     2.8 + Everyone is permitted to copy and distribute verbatim copies
     2.9 + of this license document, but changing it is not allowed.
    2.10 +
    2.11 +                            Preamble
    2.12 +
    2.13 +  The GNU General Public License is a free, copyleft license for
    2.14 +software and other kinds of works.
    2.15 +
    2.16 +  The licenses for most software and other practical works are designed
    2.17 +to take away your freedom to share and change the works.  By contrast,
    2.18 +the GNU General Public License is intended to guarantee your freedom to
    2.19 +share and change all versions of a program--to make sure it remains free
    2.20 +software for all its users.  We, the Free Software Foundation, use the
    2.21 +GNU General Public License for most of our software; it applies also to
    2.22 +any other work released this way by its authors.  You can apply it to
    2.23 +your programs, too.
    2.24 +
    2.25 +  When we speak of free software, we are referring to freedom, not
    2.26 +price.  Our General Public Licenses are designed to make sure that you
    2.27 +have the freedom to distribute copies of free software (and charge for
    2.28 +them if you wish), that you receive source code or can get it if you
    2.29 +want it, that you can change the software or use pieces of it in new
    2.30 +free programs, and that you know you can do these things.
    2.31 +
    2.32 +  To protect your rights, we need to prevent others from denying you
    2.33 +these rights or asking you to surrender the rights.  Therefore, you have
    2.34 +certain responsibilities if you distribute copies of the software, or if
    2.35 +you modify it: responsibilities to respect the freedom of others.
    2.36 +
    2.37 +  For example, if you distribute copies of such a program, whether
    2.38 +gratis or for a fee, you must pass on to the recipients the same
    2.39 +freedoms that you received.  You must make sure that they, too, receive
    2.40 +or can get the source code.  And you must show them these terms so they
    2.41 +know their rights.
    2.42 +
    2.43 +  Developers that use the GNU GPL protect your rights with two steps:
    2.44 +(1) assert copyright on the software, and (2) offer you this License
    2.45 +giving you legal permission to copy, distribute and/or modify it.
    2.46 +
    2.47 +  For the developers' and authors' protection, the GPL clearly explains
    2.48 +that there is no warranty for this free software.  For both users' and
    2.49 +authors' sake, the GPL requires that modified versions be marked as
    2.50 +changed, so that their problems will not be attributed erroneously to
    2.51 +authors of previous versions.
    2.52 +
    2.53 +  Some devices are designed to deny users access to install or run
    2.54 +modified versions of the software inside them, although the manufacturer
    2.55 +can do so.  This is fundamentally incompatible with the aim of
    2.56 +protecting users' freedom to change the software.  The systematic
    2.57 +pattern of such abuse occurs in the area of products for individuals to
    2.58 +use, which is precisely where it is most unacceptable.  Therefore, we
    2.59 +have designed this version of the GPL to prohibit the practice for those
    2.60 +products.  If such problems arise substantially in other domains, we
    2.61 +stand ready to extend this provision to those domains in future versions
    2.62 +of the GPL, as needed to protect the freedom of users.
    2.63 +
    2.64 +  Finally, every program is threatened constantly by software patents.
    2.65 +States should not allow patents to restrict development and use of
    2.66 +software on general-purpose computers, but in those that do, we wish to
    2.67 +avoid the special danger that patents applied to a free program could
    2.68 +make it effectively proprietary.  To prevent this, the GPL assures that
    2.69 +patents cannot be used to render the program non-free.
    2.70 +
    2.71 +  The precise terms and conditions for copying, distribution and
    2.72 +modification follow.
    2.73 +
    2.74 +                       TERMS AND CONDITIONS
    2.75 +
    2.76 +  0. Definitions.
    2.77 +
    2.78 +  "This License" refers to version 3 of the GNU General Public License.
    2.79 +
    2.80 +  "Copyright" also means copyright-like laws that apply to other kinds of
    2.81 +works, such as semiconductor masks.
    2.82 +
    2.83 +  "The Program" refers to any copyrightable work licensed under this
    2.84 +License.  Each licensee is addressed as "you".  "Licensees" and
    2.85 +"recipients" may be individuals or organizations.
    2.86 +
    2.87 +  To "modify" a work means to copy from or adapt all or part of the work
    2.88 +in a fashion requiring copyright permission, other than the making of an
    2.89 +exact copy.  The resulting work is called a "modified version" of the
    2.90 +earlier work or a work "based on" the earlier work.
    2.91 +
    2.92 +  A "covered work" means either the unmodified Program or a work based
    2.93 +on the Program.
    2.94 +
    2.95 +  To "propagate" a work means to do anything with it that, without
    2.96 +permission, would make you directly or secondarily liable for
    2.97 +infringement under applicable copyright law, except executing it on a
    2.98 +computer or modifying a private copy.  Propagation includes copying,
    2.99 +distribution (with or without modification), making available to the
   2.100 +public, and in some countries other activities as well.
   2.101 +
   2.102 +  To "convey" a work means any kind of propagation that enables other
   2.103 +parties to make or receive copies.  Mere interaction with a user through
   2.104 +a computer network, with no transfer of a copy, is not conveying.
   2.105 +
   2.106 +  An interactive user interface displays "Appropriate Legal Notices"
   2.107 +to the extent that it includes a convenient and prominently visible
   2.108 +feature that (1) displays an appropriate copyright notice, and (2)
   2.109 +tells the user that there is no warranty for the work (except to the
   2.110 +extent that warranties are provided), that licensees may convey the
   2.111 +work under this License, and how to view a copy of this License.  If
   2.112 +the interface presents a list of user commands or options, such as a
   2.113 +menu, a prominent item in the list meets this criterion.
   2.114 +
   2.115 +  1. Source Code.
   2.116 +
   2.117 +  The "source code" for a work means the preferred form of the work
   2.118 +for making modifications to it.  "Object code" means any non-source
   2.119 +form of a work.
   2.120 +
   2.121 +  A "Standard Interface" means an interface that either is an official
   2.122 +standard defined by a recognized standards body, or, in the case of
   2.123 +interfaces specified for a particular programming language, one that
   2.124 +is widely used among developers working in that language.
   2.125 +
   2.126 +  The "System Libraries" of an executable work include anything, other
   2.127 +than the work as a whole, that (a) is included in the normal form of
   2.128 +packaging a Major Component, but which is not part of that Major
   2.129 +Component, and (b) serves only to enable use of the work with that
   2.130 +Major Component, or to implement a Standard Interface for which an
   2.131 +implementation is available to the public in source code form.  A
   2.132 +"Major Component", in this context, means a major essential component
   2.133 +(kernel, window system, and so on) of the specific operating system
   2.134 +(if any) on which the executable work runs, or a compiler used to
   2.135 +produce the work, or an object code interpreter used to run it.
   2.136 +
   2.137 +  The "Corresponding Source" for a work in object code form means all
   2.138 +the source code needed to generate, install, and (for an executable
   2.139 +work) run the object code and to modify the work, including scripts to
   2.140 +control those activities.  However, it does not include the work's
   2.141 +System Libraries, or general-purpose tools or generally available free
   2.142 +programs which are used unmodified in performing those activities but
   2.143 +which are not part of the work.  For example, Corresponding Source
   2.144 +includes interface definition files associated with source files for
   2.145 +the work, and the source code for shared libraries and dynamically
   2.146 +linked subprograms that the work is specifically designed to require,
   2.147 +such as by intimate data communication or control flow between those
   2.148 +subprograms and other parts of the work.
   2.149 +
   2.150 +  The Corresponding Source need not include anything that users
   2.151 +can regenerate automatically from other parts of the Corresponding
   2.152 +Source.
   2.153 +
   2.154 +  The Corresponding Source for a work in source code form is that
   2.155 +same work.
   2.156 +
   2.157 +  2. Basic Permissions.
   2.158 +
   2.159 +  All rights granted under this License are granted for the term of
   2.160 +copyright on the Program, and are irrevocable provided the stated
   2.161 +conditions are met.  This License explicitly affirms your unlimited
   2.162 +permission to run the unmodified Program.  The output from running a
   2.163 +covered work is covered by this License only if the output, given its
   2.164 +content, constitutes a covered work.  This License acknowledges your
   2.165 +rights of fair use or other equivalent, as provided by copyright law.
   2.166 +
   2.167 +  You may make, run and propagate covered works that you do not
   2.168 +convey, without conditions so long as your license otherwise remains
   2.169 +in force.  You may convey covered works to others for the sole purpose
   2.170 +of having them make modifications exclusively for you, or provide you
   2.171 +with facilities for running those works, provided that you comply with
   2.172 +the terms of this License in conveying all material for which you do
   2.173 +not control copyright.  Those thus making or running the covered works
   2.174 +for you must do so exclusively on your behalf, under your direction
   2.175 +and control, on terms that prohibit them from making any copies of
   2.176 +your copyrighted material outside their relationship with you.
   2.177 +
   2.178 +  Conveying under any other circumstances is permitted solely under
   2.179 +the conditions stated below.  Sublicensing is not allowed; section 10
   2.180 +makes it unnecessary.
   2.181 +
   2.182 +  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
   2.183 +
   2.184 +  No covered work shall be deemed part of an effective technological
   2.185 +measure under any applicable law fulfilling obligations under article
   2.186 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
   2.187 +similar laws prohibiting or restricting circumvention of such
   2.188 +measures.
   2.189 +
   2.190 +  When you convey a covered work, you waive any legal power to forbid
   2.191 +circumvention of technological measures to the extent such circumvention
   2.192 +is effected by exercising rights under this License with respect to
   2.193 +the covered work, and you disclaim any intention to limit operation or
   2.194 +modification of the work as a means of enforcing, against the work's
   2.195 +users, your or third parties' legal rights to forbid circumvention of
   2.196 +technological measures.
   2.197 +
   2.198 +  4. Conveying Verbatim Copies.
   2.199 +
   2.200 +  You may convey verbatim copies of the Program's source code as you
   2.201 +receive it, in any medium, provided that you conspicuously and
   2.202 +appropriately publish on each copy an appropriate copyright notice;
   2.203 +keep intact all notices stating that this License and any
   2.204 +non-permissive terms added in accord with section 7 apply to the code;
   2.205 +keep intact all notices of the absence of any warranty; and give all
   2.206 +recipients a copy of this License along with the Program.
   2.207 +
   2.208 +  You may charge any price or no price for each copy that you convey,
   2.209 +and you may offer support or warranty protection for a fee.
   2.210 +
   2.211 +  5. Conveying Modified Source Versions.
   2.212 +
   2.213 +  You may convey a work based on the Program, or the modifications to
   2.214 +produce it from the Program, in the form of source code under the
   2.215 +terms of section 4, provided that you also meet all of these conditions:
   2.216 +
   2.217 +    a) The work must carry prominent notices stating that you modified
   2.218 +    it, and giving a relevant date.
   2.219 +
   2.220 +    b) The work must carry prominent notices stating that it is
   2.221 +    released under this License and any conditions added under section
   2.222 +    7.  This requirement modifies the requirement in section 4 to
   2.223 +    "keep intact all notices".
   2.224 +
   2.225 +    c) You must license the entire work, as a whole, under this
   2.226 +    License to anyone who comes into possession of a copy.  This
   2.227 +    License will therefore apply, along with any applicable section 7
   2.228 +    additional terms, to the whole of the work, and all its parts,
   2.229 +    regardless of how they are packaged.  This License gives no
   2.230 +    permission to license the work in any other way, but it does not
   2.231 +    invalidate such permission if you have separately received it.
   2.232 +
   2.233 +    d) If the work has interactive user interfaces, each must display
   2.234 +    Appropriate Legal Notices; however, if the Program has interactive
   2.235 +    interfaces that do not display Appropriate Legal Notices, your
   2.236 +    work need not make them do so.
   2.237 +
   2.238 +  A compilation of a covered work with other separate and independent
   2.239 +works, which are not by their nature extensions of the covered work,
   2.240 +and which are not combined with it such as to form a larger program,
   2.241 +in or on a volume of a storage or distribution medium, is called an
   2.242 +"aggregate" if the compilation and its resulting copyright are not
   2.243 +used to limit the access or legal rights of the compilation's users
   2.244 +beyond what the individual works permit.  Inclusion of a covered work
   2.245 +in an aggregate does not cause this License to apply to the other
   2.246 +parts of the aggregate.
   2.247 +
   2.248 +  6. Conveying Non-Source Forms.
   2.249 +
   2.250 +  You may convey a covered work in object code form under the terms
   2.251 +of sections 4 and 5, provided that you also convey the
   2.252 +machine-readable Corresponding Source under the terms of this License,
   2.253 +in one of these ways:
   2.254 +
   2.255 +    a) Convey the object code in, or embodied in, a physical product
   2.256 +    (including a physical distribution medium), accompanied by the
   2.257 +    Corresponding Source fixed on a durable physical medium
   2.258 +    customarily used for software interchange.
   2.259 +
   2.260 +    b) Convey the object code in, or embodied in, a physical product
   2.261 +    (including a physical distribution medium), accompanied by a
   2.262 +    written offer, valid for at least three years and valid for as
   2.263 +    long as you offer spare parts or customer support for that product
   2.264 +    model, to give anyone who possesses the object code either (1) a
   2.265 +    copy of the Corresponding Source for all the software in the
   2.266 +    product that is covered by this License, on a durable physical
   2.267 +    medium customarily used for software interchange, for a price no
   2.268 +    more than your reasonable cost of physically performing this
   2.269 +    conveying of source, or (2) access to copy the
   2.270 +    Corresponding Source from a network server at no charge.
   2.271 +
   2.272 +    c) Convey individual copies of the object code with a copy of the
   2.273 +    written offer to provide the Corresponding Source.  This
   2.274 +    alternative is allowed only occasionally and noncommercially, and
   2.275 +    only if you received the object code with such an offer, in accord
   2.276 +    with subsection 6b.
   2.277 +
   2.278 +    d) Convey the object code by offering access from a designated
   2.279 +    place (gratis or for a charge), and offer equivalent access to the
   2.280 +    Corresponding Source in the same way through the same place at no
   2.281 +    further charge.  You need not require recipients to copy the
   2.282 +    Corresponding Source along with the object code.  If the place to
   2.283 +    copy the object code is a network server, the Corresponding Source
   2.284 +    may be on a different server (operated by you or a third party)
   2.285 +    that supports equivalent copying facilities, provided you maintain
   2.286 +    clear directions next to the object code saying where to find the
   2.287 +    Corresponding Source.  Regardless of what server hosts the
   2.288 +    Corresponding Source, you remain obligated to ensure that it is
   2.289 +    available for as long as needed to satisfy these requirements.
   2.290 +
   2.291 +    e) Convey the object code using peer-to-peer transmission, provided
   2.292 +    you inform other peers where the object code and Corresponding
   2.293 +    Source of the work are being offered to the general public at no
   2.294 +    charge under subsection 6d.
   2.295 +
   2.296 +  A separable portion of the object code, whose source code is excluded
   2.297 +from the Corresponding Source as a System Library, need not be
   2.298 +included in conveying the object code work.
   2.299 +
   2.300 +  A "User Product" is either (1) a "consumer product", which means any
   2.301 +tangible personal property which is normally used for personal, family,
   2.302 +or household purposes, or (2) anything designed or sold for incorporation
   2.303 +into a dwelling.  In determining whether a product is a consumer product,
   2.304 +doubtful cases shall be resolved in favor of coverage.  For a particular
   2.305 +product received by a particular user, "normally used" refers to a
   2.306 +typical or common use of that class of product, regardless of the status
   2.307 +of the particular user or of the way in which the particular user
   2.308 +actually uses, or expects or is expected to use, the product.  A product
   2.309 +is a consumer product regardless of whether the product has substantial
   2.310 +commercial, industrial or non-consumer uses, unless such uses represent
   2.311 +the only significant mode of use of the product.
   2.312 +
   2.313 +  "Installation Information" for a User Product means any methods,
   2.314 +procedures, authorization keys, or other information required to install
   2.315 +and execute modified versions of a covered work in that User Product from
   2.316 +a modified version of its Corresponding Source.  The information must
   2.317 +suffice to ensure that the continued functioning of the modified object
   2.318 +code is in no case prevented or interfered with solely because
   2.319 +modification has been made.
   2.320 +
   2.321 +  If you convey an object code work under this section in, or with, or
   2.322 +specifically for use in, a User Product, and the conveying occurs as
   2.323 +part of a transaction in which the right of possession and use of the
   2.324 +User Product is transferred to the recipient in perpetuity or for a
   2.325 +fixed term (regardless of how the transaction is characterized), the
   2.326 +Corresponding Source conveyed under this section must be accompanied
   2.327 +by the Installation Information.  But this requirement does not apply
   2.328 +if neither you nor any third party retains the ability to install
   2.329 +modified object code on the User Product (for example, the work has
   2.330 +been installed in ROM).
   2.331 +
   2.332 +  The requirement to provide Installation Information does not include a
   2.333 +requirement to continue to provide support service, warranty, or updates
   2.334 +for a work that has been modified or installed by the recipient, or for
   2.335 +the User Product in which it has been modified or installed.  Access to a
   2.336 +network may be denied when the modification itself materially and
   2.337 +adversely affects the operation of the network or violates the rules and
   2.338 +protocols for communication across the network.
   2.339 +
   2.340 +  Corresponding Source conveyed, and Installation Information provided,
   2.341 +in accord with this section must be in a format that is publicly
   2.342 +documented (and with an implementation available to the public in
   2.343 +source code form), and must require no special password or key for
   2.344 +unpacking, reading or copying.
   2.345 +
   2.346 +  7. Additional Terms.
   2.347 +
   2.348 +  "Additional permissions" are terms that supplement the terms of this
   2.349 +License by making exceptions from one or more of its conditions.
   2.350 +Additional permissions that are applicable to the entire Program shall
   2.351 +be treated as though they were included in this License, to the extent
   2.352 +that they are valid under applicable law.  If additional permissions
   2.353 +apply only to part of the Program, that part may be used separately
   2.354 +under those permissions, but the entire Program remains governed by
   2.355 +this License without regard to the additional permissions.
   2.356 +
   2.357 +  When you convey a copy of a covered work, you may at your option
   2.358 +remove any additional permissions from that copy, or from any part of
   2.359 +it.  (Additional permissions may be written to require their own
   2.360 +removal in certain cases when you modify the work.)  You may place
   2.361 +additional permissions on material, added by you to a covered work,
   2.362 +for which you have or can give appropriate copyright permission.
   2.363 +
   2.364 +  Notwithstanding any other provision of this License, for material you
   2.365 +add to a covered work, you may (if authorized by the copyright holders of
   2.366 +that material) supplement the terms of this License with terms:
   2.367 +
   2.368 +    a) Disclaiming warranty or limiting liability differently from the
   2.369 +    terms of sections 15 and 16 of this License; or
   2.370 +
   2.371 +    b) Requiring preservation of specified reasonable legal notices or
   2.372 +    author attributions in that material or in the Appropriate Legal
   2.373 +    Notices displayed by works containing it; or
   2.374 +
   2.375 +    c) Prohibiting misrepresentation of the origin of that material, or
   2.376 +    requiring that modified versions of such material be marked in
   2.377 +    reasonable ways as different from the original version; or
   2.378 +
   2.379 +    d) Limiting the use for publicity purposes of names of licensors or
   2.380 +    authors of the material; or
   2.381 +
   2.382 +    e) Declining to grant rights under trademark law for use of some
   2.383 +    trade names, trademarks, or service marks; or
   2.384 +
   2.385 +    f) Requiring indemnification of licensors and authors of that
   2.386 +    material by anyone who conveys the material (or modified versions of
   2.387 +    it) with contractual assumptions of liability to the recipient, for
   2.388 +    any liability that these contractual assumptions directly impose on
   2.389 +    those licensors and authors.
   2.390 +
   2.391 +  All other non-permissive additional terms are considered "further
   2.392 +restrictions" within the meaning of section 10.  If the Program as you
   2.393 +received it, or any part of it, contains a notice stating that it is
   2.394 +governed by this License along with a term that is a further
   2.395 +restriction, you may remove that term.  If a license document contains
   2.396 +a further restriction but permits relicensing or conveying under this
   2.397 +License, you may add to a covered work material governed by the terms
   2.398 +of that license document, provided that the further restriction does
   2.399 +not survive such relicensing or conveying.
   2.400 +
   2.401 +  If you add terms to a covered work in accord with this section, you
   2.402 +must place, in the relevant source files, a statement of the
   2.403 +additional terms that apply to those files, or a notice indicating
   2.404 +where to find the applicable terms.
   2.405 +
   2.406 +  Additional terms, permissive or non-permissive, may be stated in the
   2.407 +form of a separately written license, or stated as exceptions;
   2.408 +the above requirements apply either way.
   2.409 +
   2.410 +  8. Termination.
   2.411 +
   2.412 +  You may not propagate or modify a covered work except as expressly
   2.413 +provided under this License.  Any attempt otherwise to propagate or
   2.414 +modify it is void, and will automatically terminate your rights under
   2.415 +this License (including any patent licenses granted under the third
   2.416 +paragraph of section 11).
   2.417 +
   2.418 +  However, if you cease all violation of this License, then your
   2.419 +license from a particular copyright holder is reinstated (a)
   2.420 +provisionally, unless and until the copyright holder explicitly and
   2.421 +finally terminates your license, and (b) permanently, if the copyright
   2.422 +holder fails to notify you of the violation by some reasonable means
   2.423 +prior to 60 days after the cessation.
   2.424 +
   2.425 +  Moreover, your license from a particular copyright holder is
   2.426 +reinstated permanently if the copyright holder notifies you of the
   2.427 +violation by some reasonable means, this is the first time you have
   2.428 +received notice of violation of this License (for any work) from that
   2.429 +copyright holder, and you cure the violation prior to 30 days after
   2.430 +your receipt of the notice.
   2.431 +
   2.432 +  Termination of your rights under this section does not terminate the
   2.433 +licenses of parties who have received copies or rights from you under
   2.434 +this License.  If your rights have been terminated and not permanently
   2.435 +reinstated, you do not qualify to receive new licenses for the same
   2.436 +material under section 10.
   2.437 +
   2.438 +  9. Acceptance Not Required for Having Copies.
   2.439 +
   2.440 +  You are not required to accept this License in order to receive or
   2.441 +run a copy of the Program.  Ancillary propagation of a covered work
   2.442 +occurring solely as a consequence of using peer-to-peer transmission
   2.443 +to receive a copy likewise does not require acceptance.  However,
   2.444 +nothing other than this License grants you permission to propagate or
   2.445 +modify any covered work.  These actions infringe copyright if you do
   2.446 +not accept this License.  Therefore, by modifying or propagating a
   2.447 +covered work, you indicate your acceptance of this License to do so.
   2.448 +
   2.449 +  10. Automatic Licensing of Downstream Recipients.
   2.450 +
   2.451 +  Each time you convey a covered work, the recipient automatically
   2.452 +receives a license from the original licensors, to run, modify and
   2.453 +propagate that work, subject to this License.  You are not responsible
   2.454 +for enforcing compliance by third parties with this License.
   2.455 +
   2.456 +  An "entity transaction" is a transaction transferring control of an
   2.457 +organization, or substantially all assets of one, or subdividing an
   2.458 +organization, or merging organizations.  If propagation of a covered
   2.459 +work results from an entity transaction, each party to that
   2.460 +transaction who receives a copy of the work also receives whatever
   2.461 +licenses to the work the party's predecessor in interest had or could
   2.462 +give under the previous paragraph, plus a right to possession of the
   2.463 +Corresponding Source of the work from the predecessor in interest, if
   2.464 +the predecessor has it or can get it with reasonable efforts.
   2.465 +
   2.466 +  You may not impose any further restrictions on the exercise of the
   2.467 +rights granted or affirmed under this License.  For example, you may
   2.468 +not impose a license fee, royalty, or other charge for exercise of
   2.469 +rights granted under this License, and you may not initiate litigation
   2.470 +(including a cross-claim or counterclaim in a lawsuit) alleging that
   2.471 +any patent claim is infringed by making, using, selling, offering for
   2.472 +sale, or importing the Program or any portion of it.
   2.473 +
   2.474 +  11. Patents.
   2.475 +
   2.476 +  A "contributor" is a copyright holder who authorizes use under this
   2.477 +License of the Program or a work on which the Program is based.  The
   2.478 +work thus licensed is called the contributor's "contributor version".
   2.479 +
   2.480 +  A contributor's "essential patent claims" are all patent claims
   2.481 +owned or controlled by the contributor, whether already acquired or
   2.482 +hereafter acquired, that would be infringed by some manner, permitted
   2.483 +by this License, of making, using, or selling its contributor version,
   2.484 +but do not include claims that would be infringed only as a
   2.485 +consequence of further modification of the contributor version.  For
   2.486 +purposes of this definition, "control" includes the right to grant
   2.487 +patent sublicenses in a manner consistent with the requirements of
   2.488 +this License.
   2.489 +
   2.490 +  Each contributor grants you a non-exclusive, worldwide, royalty-free
   2.491 +patent license under the contributor's essential patent claims, to
   2.492 +make, use, sell, offer for sale, import and otherwise run, modify and
   2.493 +propagate the contents of its contributor version.
   2.494 +
   2.495 +  In the following three paragraphs, a "patent license" is any express
   2.496 +agreement or commitment, however denominated, not to enforce a patent
   2.497 +(such as an express permission to practice a patent or covenant not to
   2.498 +sue for patent infringement).  To "grant" such a patent license to a
   2.499 +party means to make such an agreement or commitment not to enforce a
   2.500 +patent against the party.
   2.501 +
   2.502 +  If you convey a covered work, knowingly relying on a patent license,
   2.503 +and the Corresponding Source of the work is not available for anyone
   2.504 +to copy, free of charge and under the terms of this License, through a
   2.505 +publicly available network server or other readily accessible means,
   2.506 +then you must either (1) cause the Corresponding Source to be so
   2.507 +available, or (2) arrange to deprive yourself of the benefit of the
   2.508 +patent license for this particular work, or (3) arrange, in a manner
   2.509 +consistent with the requirements of this License, to extend the patent
   2.510 +license to downstream recipients.  "Knowingly relying" means you have
   2.511 +actual knowledge that, but for the patent license, your conveying the
   2.512 +covered work in a country, or your recipient's use of the covered work
   2.513 +in a country, would infringe one or more identifiable patents in that
   2.514 +country that you have reason to believe are valid.
   2.515 +
   2.516 +  If, pursuant to or in connection with a single transaction or
   2.517 +arrangement, you convey, or propagate by procuring conveyance of, a
   2.518 +covered work, and grant a patent license to some of the parties
   2.519 +receiving the covered work authorizing them to use, propagate, modify
   2.520 +or convey a specific copy of the covered work, then the patent license
   2.521 +you grant is automatically extended to all recipients of the covered
   2.522 +work and works based on it.
   2.523 +
   2.524 +  A patent license is "discriminatory" if it does not include within
   2.525 +the scope of its coverage, prohibits the exercise of, or is
   2.526 +conditioned on the non-exercise of one or more of the rights that are
   2.527 +specifically granted under this License.  You may not convey a covered
   2.528 +work if you are a party to an arrangement with a third party that is
   2.529 +in the business of distributing software, under which you make payment
   2.530 +to the third party based on the extent of your activity of conveying
   2.531 +the work, and under which the third party grants, to any of the
   2.532 +parties who would receive the covered work from you, a discriminatory
   2.533 +patent license (a) in connection with copies of the covered work
   2.534 +conveyed by you (or copies made from those copies), or (b) primarily
   2.535 +for and in connection with specific products or compilations that
   2.536 +contain the covered work, unless you entered into that arrangement,
   2.537 +or that patent license was granted, prior to 28 March 2007.
   2.538 +
   2.539 +  Nothing in this License shall be construed as excluding or limiting
   2.540 +any implied license or other defenses to infringement that may
   2.541 +otherwise be available to you under applicable patent law.
   2.542 +
   2.543 +  12. No Surrender of Others' Freedom.
   2.544 +
   2.545 +  If conditions are imposed on you (whether by court order, agreement or
   2.546 +otherwise) that contradict the conditions of this License, they do not
   2.547 +excuse you from the conditions of this License.  If you cannot convey a
   2.548 +covered work so as to satisfy simultaneously your obligations under this
   2.549 +License and any other pertinent obligations, then as a consequence you may
   2.550 +not convey it at all.  For example, if you agree to terms that obligate you
   2.551 +to collect a royalty for further conveying from those to whom you convey
   2.552 +the Program, the only way you could satisfy both those terms and this
   2.553 +License would be to refrain entirely from conveying the Program.
   2.554 +
   2.555 +  13. Use with the GNU Affero General Public License.
   2.556 +
   2.557 +  Notwithstanding any other provision of this License, you have
   2.558 +permission to link or combine any covered work with a work licensed
   2.559 +under version 3 of the GNU Affero General Public License into a single
   2.560 +combined work, and to convey the resulting work.  The terms of this
   2.561 +License will continue to apply to the part which is the covered work,
   2.562 +but the special requirements of the GNU Affero General Public License,
   2.563 +section 13, concerning interaction through a network will apply to the
   2.564 +combination as such.
   2.565 +
   2.566 +  14. Revised Versions of this License.
   2.567 +
   2.568 +  The Free Software Foundation may publish revised and/or new versions of
   2.569 +the GNU General Public License from time to time.  Such new versions will
   2.570 +be similar in spirit to the present version, but may differ in detail to
   2.571 +address new problems or concerns.
   2.572 +
   2.573 +  Each version is given a distinguishing version number.  If the
   2.574 +Program specifies that a certain numbered version of the GNU General
   2.575 +Public License "or any later version" applies to it, you have the
   2.576 +option of following the terms and conditions either of that numbered
   2.577 +version or of any later version published by the Free Software
   2.578 +Foundation.  If the Program does not specify a version number of the
   2.579 +GNU General Public License, you may choose any version ever published
   2.580 +by the Free Software Foundation.
   2.581 +
   2.582 +  If the Program specifies that a proxy can decide which future
   2.583 +versions of the GNU General Public License can be used, that proxy's
   2.584 +public statement of acceptance of a version permanently authorizes you
   2.585 +to choose that version for the Program.
   2.586 +
   2.587 +  Later license versions may give you additional or different
   2.588 +permissions.  However, no additional obligations are imposed on any
   2.589 +author or copyright holder as a result of your choosing to follow a
   2.590 +later version.
   2.591 +
   2.592 +  15. Disclaimer of Warranty.
   2.593 +
   2.594 +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
   2.595 +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
   2.596 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
   2.597 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
   2.598 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   2.599 +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
   2.600 +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
   2.601 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
   2.602 +
   2.603 +  16. Limitation of Liability.
   2.604 +
   2.605 +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
   2.606 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
   2.607 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
   2.608 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
   2.609 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
   2.610 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
   2.611 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
   2.612 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
   2.613 +SUCH DAMAGES.
   2.614 +
   2.615 +  17. Interpretation of Sections 15 and 16.
   2.616 +
   2.617 +  If the disclaimer of warranty and limitation of liability provided
   2.618 +above cannot be given local legal effect according to their terms,
   2.619 +reviewing courts shall apply local law that most closely approximates
   2.620 +an absolute waiver of all civil liability in connection with the
   2.621 +Program, unless a warranty or assumption of liability accompanies a
   2.622 +copy of the Program in return for a fee.
   2.623 +
   2.624 +                     END OF TERMS AND CONDITIONS
   2.625 +
   2.626 +            How to Apply These Terms to Your New Programs
   2.627 +
   2.628 +  If you develop a new program, and you want it to be of the greatest
   2.629 +possible use to the public, the best way to achieve this is to make it
   2.630 +free software which everyone can redistribute and change under these terms.
   2.631 +
   2.632 +  To do so, attach the following notices to the program.  It is safest
   2.633 +to attach them to the start of each source file to most effectively
   2.634 +state the exclusion of warranty; and each file should have at least
   2.635 +the "copyright" line and a pointer to where the full notice is found.
   2.636 +
   2.637 +    <one line to give the program's name and a brief idea of what it does.>
   2.638 +    Copyright (C) <year>  <name of author>
   2.639 +
   2.640 +    This program is free software: you can redistribute it and/or modify
   2.641 +    it under the terms of the GNU General Public License as published by
   2.642 +    the Free Software Foundation, either version 3 of the License, or
   2.643 +    (at your option) any later version.
   2.644 +
   2.645 +    This program is distributed in the hope that it will be useful,
   2.646 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.647 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.648 +    GNU General Public License for more details.
   2.649 +
   2.650 +    You should have received a copy of the GNU General Public License
   2.651 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   2.652 +
   2.653 +Also add information on how to contact you by electronic and paper mail.
   2.654 +
   2.655 +  If the program does terminal interaction, make it output a short
   2.656 +notice like this when it starts in an interactive mode:
   2.657 +
   2.658 +    <program>  Copyright (C) <year>  <name of author>
   2.659 +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
   2.660 +    This is free software, and you are welcome to redistribute it
   2.661 +    under certain conditions; type `show c' for details.
   2.662 +
   2.663 +The hypothetical commands `show w' and `show c' should show the appropriate
   2.664 +parts of the General Public License.  Of course, your program's commands
   2.665 +might be different; for a GUI interface, you would use an "about box".
   2.666 +
   2.667 +  You should also get your employer (if you work as a programmer) or school,
   2.668 +if any, to sign a "copyright disclaimer" for the program, if necessary.
   2.669 +For more information on this, and how to apply and follow the GNU GPL, see
   2.670 +<http://www.gnu.org/licenses/>.
   2.671 +
   2.672 +  The GNU General Public License does not permit incorporating your program
   2.673 +into proprietary programs.  If your program is a subroutine library, you
   2.674 +may consider it more useful to permit linking proprietary applications with
   2.675 +the library.  If this is what you want to do, use the GNU Lesser General
   2.676 +Public License instead of this License.  But first, please read
   2.677 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/COPYING.LESSER	Tue Feb 19 20:32:17 2008 +0300
     3.3 @@ -0,0 +1,165 @@
     3.4 +		   GNU LESSER GENERAL PUBLIC LICENSE
     3.5 +                       Version 3, 29 June 2007
     3.6 +
     3.7 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
     3.8 + Everyone is permitted to copy and distribute verbatim copies
     3.9 + of this license document, but changing it is not allowed.
    3.10 +
    3.11 +
    3.12 +  This version of the GNU Lesser General Public License incorporates
    3.13 +the terms and conditions of version 3 of the GNU General Public
    3.14 +License, supplemented by the additional permissions listed below.
    3.15 +
    3.16 +  0. Additional Definitions. 
    3.17 +
    3.18 +  As used herein, "this License" refers to version 3 of the GNU Lesser
    3.19 +General Public License, and the "GNU GPL" refers to version 3 of the GNU
    3.20 +General Public License.
    3.21 +
    3.22 +  "The Library" refers to a covered work governed by this License,
    3.23 +other than an Application or a Combined Work as defined below.
    3.24 +
    3.25 +  An "Application" is any work that makes use of an interface provided
    3.26 +by the Library, but which is not otherwise based on the Library.
    3.27 +Defining a subclass of a class defined by the Library is deemed a mode
    3.28 +of using an interface provided by the Library.
    3.29 +
    3.30 +  A "Combined Work" is a work produced by combining or linking an
    3.31 +Application with the Library.  The particular version of the Library
    3.32 +with which the Combined Work was made is also called the "Linked
    3.33 +Version".
    3.34 +
    3.35 +  The "Minimal Corresponding Source" for a Combined Work means the
    3.36 +Corresponding Source for the Combined Work, excluding any source code
    3.37 +for portions of the Combined Work that, considered in isolation, are
    3.38 +based on the Application, and not on the Linked Version.
    3.39 +
    3.40 +  The "Corresponding Application Code" for a Combined Work means the
    3.41 +object code and/or source code for the Application, including any data
    3.42 +and utility programs needed for reproducing the Combined Work from the
    3.43 +Application, but excluding the System Libraries of the Combined Work.
    3.44 +
    3.45 +  1. Exception to Section 3 of the GNU GPL.
    3.46 +
    3.47 +  You may convey a covered work under sections 3 and 4 of this License
    3.48 +without being bound by section 3 of the GNU GPL.
    3.49 +
    3.50 +  2. Conveying Modified Versions.
    3.51 +
    3.52 +  If you modify a copy of the Library, and, in your modifications, a
    3.53 +facility refers to a function or data to be supplied by an Application
    3.54 +that uses the facility (other than as an argument passed when the
    3.55 +facility is invoked), then you may convey a copy of the modified
    3.56 +version:
    3.57 +
    3.58 +   a) under this License, provided that you make a good faith effort to
    3.59 +   ensure that, in the event an Application does not supply the
    3.60 +   function or data, the facility still operates, and performs
    3.61 +   whatever part of its purpose remains meaningful, or
    3.62 +
    3.63 +   b) under the GNU GPL, with none of the additional permissions of
    3.64 +   this License applicable to that copy.
    3.65 +
    3.66 +  3. Object Code Incorporating Material from Library Header Files.
    3.67 +
    3.68 +  The object code form of an Application may incorporate material from
    3.69 +a header file that is part of the Library.  You may convey such object
    3.70 +code under terms of your choice, provided that, if the incorporated
    3.71 +material is not limited to numerical parameters, data structure
    3.72 +layouts and accessors, or small macros, inline functions and templates
    3.73 +(ten or fewer lines in length), you do both of the following:
    3.74 +
    3.75 +   a) Give prominent notice with each copy of the object code that the
    3.76 +   Library is used in it and that the Library and its use are
    3.77 +   covered by this License.
    3.78 +
    3.79 +   b) Accompany the object code with a copy of the GNU GPL and this license
    3.80 +   document.
    3.81 +
    3.82 +  4. Combined Works.
    3.83 +
    3.84 +  You may convey a Combined Work under terms of your choice that,
    3.85 +taken together, effectively do not restrict modification of the
    3.86 +portions of the Library contained in the Combined Work and reverse
    3.87 +engineering for debugging such modifications, if you also do each of
    3.88 +the following:
    3.89 +
    3.90 +   a) Give prominent notice with each copy of the Combined Work that
    3.91 +   the Library is used in it and that the Library and its use are
    3.92 +   covered by this License.
    3.93 +
    3.94 +   b) Accompany the Combined Work with a copy of the GNU GPL and this license
    3.95 +   document.
    3.96 +
    3.97 +   c) For a Combined Work that displays copyright notices during
    3.98 +   execution, include the copyright notice for the Library among
    3.99 +   these notices, as well as a reference directing the user to the
   3.100 +   copies of the GNU GPL and this license document.
   3.101 +
   3.102 +   d) Do one of the following:
   3.103 +
   3.104 +       0) Convey the Minimal Corresponding Source under the terms of this
   3.105 +       License, and the Corresponding Application Code in a form
   3.106 +       suitable for, and under terms that permit, the user to
   3.107 +       recombine or relink the Application with a modified version of
   3.108 +       the Linked Version to produce a modified Combined Work, in the
   3.109 +       manner specified by section 6 of the GNU GPL for conveying
   3.110 +       Corresponding Source.
   3.111 +
   3.112 +       1) Use a suitable shared library mechanism for linking with the
   3.113 +       Library.  A suitable mechanism is one that (a) uses at run time
   3.114 +       a copy of the Library already present on the user's computer
   3.115 +       system, and (b) will operate properly with a modified version
   3.116 +       of the Library that is interface-compatible with the Linked
   3.117 +       Version. 
   3.118 +
   3.119 +   e) Provide Installation Information, but only if you would otherwise
   3.120 +   be required to provide such information under section 6 of the
   3.121 +   GNU GPL, and only to the extent that such information is
   3.122 +   necessary to install and execute a modified version of the
   3.123 +   Combined Work produced by recombining or relinking the
   3.124 +   Application with a modified version of the Linked Version. (If
   3.125 +   you use option 4d0, the Installation Information must accompany
   3.126 +   the Minimal Corresponding Source and Corresponding Application
   3.127 +   Code. If you use option 4d1, you must provide the Installation
   3.128 +   Information in the manner specified by section 6 of the GNU GPL
   3.129 +   for conveying Corresponding Source.)
   3.130 +
   3.131 +  5. Combined Libraries.
   3.132 +
   3.133 +  You may place library facilities that are a work based on the
   3.134 +Library side by side in a single library together with other library
   3.135 +facilities that are not Applications and are not covered by this
   3.136 +License, and convey such a combined library under terms of your
   3.137 +choice, if you do both of the following:
   3.138 +
   3.139 +   a) Accompany the combined library with a copy of the same work based
   3.140 +   on the Library, uncombined with any other library facilities,
   3.141 +   conveyed under the terms of this License.
   3.142 +
   3.143 +   b) Give prominent notice with the combined library that part of it
   3.144 +   is a work based on the Library, and explaining where to find the
   3.145 +   accompanying uncombined form of the same work.
   3.146 +
   3.147 +  6. Revised Versions of the GNU Lesser General Public License.
   3.148 +
   3.149 +  The Free Software Foundation may publish revised and/or new versions
   3.150 +of the GNU Lesser General Public License from time to time. Such new
   3.151 +versions will be similar in spirit to the present version, but may
   3.152 +differ in detail to address new problems or concerns.
   3.153 +
   3.154 +  Each version is given a distinguishing version number. If the
   3.155 +Library as you received it specifies that a certain numbered version
   3.156 +of the GNU Lesser General Public License "or any later version"
   3.157 +applies to it, you have the option of following the terms and
   3.158 +conditions either of that published version or of any later version
   3.159 +published by the Free Software Foundation. If the Library as you
   3.160 +received it does not specify a version number of the GNU Lesser
   3.161 +General Public License, you may choose any version of the GNU Lesser
   3.162 +General Public License ever published by the Free Software Foundation.
   3.163 +
   3.164 +  If the Library as you received it specifies that a proxy can decide
   3.165 +whether future versions of the GNU Lesser General Public License shall
   3.166 +apply, that proxy's public statement of acceptance of any version is
   3.167 +permanent authorization for you to choose that version for the
   3.168 +Library.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/COPYING.apache	Tue Feb 19 20:32:17 2008 +0300
     4.3 @@ -0,0 +1,202 @@
     4.4 +                                 Apache License
     4.5 +                           Version 2.0, January 2004
     4.6 +                        http://www.apache.org/licenses/
     4.7 +
     4.8 +   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
     4.9 +
    4.10 +   1. Definitions.
    4.11 +
    4.12 +      "License" shall mean the terms and conditions for use, reproduction,
    4.13 +      and distribution as defined by Sections 1 through 9 of this document.
    4.14 +
    4.15 +      "Licensor" shall mean the copyright owner or entity authorized by
    4.16 +      the copyright owner that is granting the License.
    4.17 +
    4.18 +      "Legal Entity" shall mean the union of the acting entity and all
    4.19 +      other entities that control, are controlled by, or are under common
    4.20 +      control with that entity. For the purposes of this definition,
    4.21 +      "control" means (i) the power, direct or indirect, to cause the
    4.22 +      direction or management of such entity, whether by contract or
    4.23 +      otherwise, or (ii) ownership of fifty percent (50%) or more of the
    4.24 +      outstanding shares, or (iii) beneficial ownership of such entity.
    4.25 +
    4.26 +      "You" (or "Your") shall mean an individual or Legal Entity
    4.27 +      exercising permissions granted by this License.
    4.28 +
    4.29 +      "Source" form shall mean the preferred form for making modifications,
    4.30 +      including but not limited to software source code, documentation
    4.31 +      source, and configuration files.
    4.32 +
    4.33 +      "Object" form shall mean any form resulting from mechanical
    4.34 +      transformation or translation of a Source form, including but
    4.35 +      not limited to compiled object code, generated documentation,
    4.36 +      and conversions to other media types.
    4.37 +
    4.38 +      "Work" shall mean the work of authorship, whether in Source or
    4.39 +      Object form, made available under the License, as indicated by a
    4.40 +      copyright notice that is included in or attached to the work
    4.41 +      (an example is provided in the Appendix below).
    4.42 +
    4.43 +      "Derivative Works" shall mean any work, whether in Source or Object
    4.44 +      form, that is based on (or derived from) the Work and for which the
    4.45 +      editorial revisions, annotations, elaborations, or other modifications
    4.46 +      represent, as a whole, an original work of authorship. For the purposes
    4.47 +      of this License, Derivative Works shall not include works that remain
    4.48 +      separable from, or merely link (or bind by name) to the interfaces of,
    4.49 +      the Work and Derivative Works thereof.
    4.50 +
    4.51 +      "Contribution" shall mean any work of authorship, including
    4.52 +      the original version of the Work and any modifications or additions
    4.53 +      to that Work or Derivative Works thereof, that is intentionally
    4.54 +      submitted to Licensor for inclusion in the Work by the copyright owner
    4.55 +      or by an individual or Legal Entity authorized to submit on behalf of
    4.56 +      the copyright owner. For the purposes of this definition, "submitted"
    4.57 +      means any form of electronic, verbal, or written communication sent
    4.58 +      to the Licensor or its representatives, including but not limited to
    4.59 +      communication on electronic mailing lists, source code control systems,
    4.60 +      and issue tracking systems that are managed by, or on behalf of, the
    4.61 +      Licensor for the purpose of discussing and improving the Work, but
    4.62 +      excluding communication that is conspicuously marked or otherwise
    4.63 +      designated in writing by the copyright owner as "Not a Contribution."
    4.64 +
    4.65 +      "Contributor" shall mean Licensor and any individual or Legal Entity
    4.66 +      on behalf of whom a Contribution has been received by Licensor and
    4.67 +      subsequently incorporated within the Work.
    4.68 +
    4.69 +   2. Grant of Copyright License. Subject to the terms and conditions of
    4.70 +      this License, each Contributor hereby grants to You a perpetual,
    4.71 +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    4.72 +      copyright license to reproduce, prepare Derivative Works of,
    4.73 +      publicly display, publicly perform, sublicense, and distribute the
    4.74 +      Work and such Derivative Works in Source or Object form.
    4.75 +
    4.76 +   3. Grant of Patent License. Subject to the terms and conditions of
    4.77 +      this License, each Contributor hereby grants to You a perpetual,
    4.78 +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    4.79 +      (except as stated in this section) patent license to make, have made,
    4.80 +      use, offer to sell, sell, import, and otherwise transfer the Work,
    4.81 +      where such license applies only to those patent claims licensable
    4.82 +      by such Contributor that are necessarily infringed by their
    4.83 +      Contribution(s) alone or by combination of their Contribution(s)
    4.84 +      with the Work to which such Contribution(s) was submitted. If You
    4.85 +      institute patent litigation against any entity (including a
    4.86 +      cross-claim or counterclaim in a lawsuit) alleging that the Work
    4.87 +      or a Contribution incorporated within the Work constitutes direct
    4.88 +      or contributory patent infringement, then any patent licenses
    4.89 +      granted to You under this License for that Work shall terminate
    4.90 +      as of the date such litigation is filed.
    4.91 +
    4.92 +   4. Redistribution. You may reproduce and distribute copies of the
    4.93 +      Work or Derivative Works thereof in any medium, with or without
    4.94 +      modifications, and in Source or Object form, provided that You
    4.95 +      meet the following conditions:
    4.96 +
    4.97 +      (a) You must give any other recipients of the Work or
    4.98 +          Derivative Works a copy of this License; and
    4.99 +
   4.100 +      (b) You must cause any modified files to carry prominent notices
   4.101 +          stating that You changed the files; and
   4.102 +
   4.103 +      (c) You must retain, in the Source form of any Derivative Works
   4.104 +          that You distribute, all copyright, patent, trademark, and
   4.105 +          attribution notices from the Source form of the Work,
   4.106 +          excluding those notices that do not pertain to any part of
   4.107 +          the Derivative Works; and
   4.108 +
   4.109 +      (d) If the Work includes a "NOTICE" text file as part of its
   4.110 +          distribution, then any Derivative Works that You distribute must
   4.111 +          include a readable copy of the attribution notices contained
   4.112 +          within such NOTICE file, excluding those notices that do not
   4.113 +          pertain to any part of the Derivative Works, in at least one
   4.114 +          of the following places: within a NOTICE text file distributed
   4.115 +          as part of the Derivative Works; within the Source form or
   4.116 +          documentation, if provided along with the Derivative Works; or,
   4.117 +          within a display generated by the Derivative Works, if and
   4.118 +          wherever such third-party notices normally appear. The contents
   4.119 +          of the NOTICE file are for informational purposes only and
   4.120 +          do not modify the License. You may add Your own attribution
   4.121 +          notices within Derivative Works that You distribute, alongside
   4.122 +          or as an addendum to the NOTICE text from the Work, provided
   4.123 +          that such additional attribution notices cannot be construed
   4.124 +          as modifying the License.
   4.125 +
   4.126 +      You may add Your own copyright statement to Your modifications and
   4.127 +      may provide additional or different license terms and conditions
   4.128 +      for use, reproduction, or distribution of Your modifications, or
   4.129 +      for any such Derivative Works as a whole, provided Your use,
   4.130 +      reproduction, and distribution of the Work otherwise complies with
   4.131 +      the conditions stated in this License.
   4.132 +
   4.133 +   5. Submission of Contributions. Unless You explicitly state otherwise,
   4.134 +      any Contribution intentionally submitted for inclusion in the Work
   4.135 +      by You to the Licensor shall be under the terms and conditions of
   4.136 +      this License, without any additional terms or conditions.
   4.137 +      Notwithstanding the above, nothing herein shall supersede or modify
   4.138 +      the terms of any separate license agreement you may have executed
   4.139 +      with Licensor regarding such Contributions.
   4.140 +
   4.141 +   6. Trademarks. This License does not grant permission to use the trade
   4.142 +      names, trademarks, service marks, or product names of the Licensor,
   4.143 +      except as required for reasonable and customary use in describing the
   4.144 +      origin of the Work and reproducing the content of the NOTICE file.
   4.145 +
   4.146 +   7. Disclaimer of Warranty. Unless required by applicable law or
   4.147 +      agreed to in writing, Licensor provides the Work (and each
   4.148 +      Contributor provides its Contributions) on an "AS IS" BASIS,
   4.149 +      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   4.150 +      implied, including, without limitation, any warranties or conditions
   4.151 +      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   4.152 +      PARTICULAR PURPOSE. You are solely responsible for determining the
   4.153 +      appropriateness of using or redistributing the Work and assume any
   4.154 +      risks associated with Your exercise of permissions under this License.
   4.155 +
   4.156 +   8. Limitation of Liability. In no event and under no legal theory,
   4.157 +      whether in tort (including negligence), contract, or otherwise,
   4.158 +      unless required by applicable law (such as deliberate and grossly
   4.159 +      negligent acts) or agreed to in writing, shall any Contributor be
   4.160 +      liable to You for damages, including any direct, indirect, special,
   4.161 +      incidental, or consequential damages of any character arising as a
   4.162 +      result of this License or out of the use or inability to use the
   4.163 +      Work (including but not limited to damages for loss of goodwill,
   4.164 +      work stoppage, computer failure or malfunction, or any and all
   4.165 +      other commercial damages or losses), even if such Contributor
   4.166 +      has been advised of the possibility of such damages.
   4.167 +
   4.168 +   9. Accepting Warranty or Additional Liability. While redistributing
   4.169 +      the Work or Derivative Works thereof, You may choose to offer,
   4.170 +      and charge a fee for, acceptance of support, warranty, indemnity,
   4.171 +      or other liability obligations and/or rights consistent with this
   4.172 +      License. However, in accepting such obligations, You may act only
   4.173 +      on Your own behalf and on Your sole responsibility, not on behalf
   4.174 +      of any other Contributor, and only if You agree to indemnify,
   4.175 +      defend, and hold each Contributor harmless for any liability
   4.176 +      incurred by, or claims asserted against, such Contributor by reason
   4.177 +      of your accepting any such warranty or additional liability.
   4.178 +
   4.179 +   END OF TERMS AND CONDITIONS
   4.180 +
   4.181 +   APPENDIX: How to apply the Apache License to your work.
   4.182 +
   4.183 +      To apply the Apache License to your work, attach the following
   4.184 +      boilerplate notice, with the fields enclosed by brackets "[]"
   4.185 +      replaced with your own identifying information. (Don't include
   4.186 +      the brackets!)  The text should be enclosed in the appropriate
   4.187 +      comment syntax for the file format. We also recommend that a
   4.188 +      file or class name and description of purpose be included on the
   4.189 +      same "printed page" as the copyright notice for easier
   4.190 +      identification within third-party archives.
   4.191 +
   4.192 +   Copyright [yyyy] [name of copyright owner]
   4.193 +
   4.194 +   Licensed under the Apache License, Version 2.0 (the "License");
   4.195 +   you may not use this file except in compliance with the License.
   4.196 +   You may obtain a copy of the License at
   4.197 +
   4.198 +       http://www.apache.org/licenses/LICENSE-2.0
   4.199 +
   4.200 +   Unless required by applicable law or agreed to in writing, software
   4.201 +   distributed under the License is distributed on an "AS IS" BASIS,
   4.202 +   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   4.203 +   See the License for the specific language governing permissions and
   4.204 +   limitations under the License.
   4.205 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/NOTICE	Tue Feb 19 20:32:17 2008 +0300
     5.3 @@ -0,0 +1,13 @@
     5.4 +Tema
     5.5 +Copyright 2006-2008 Mikhail Kryshen <mikhail@kryshen.pp.ru>
     5.6 +
     5.7 +This is free software. You may redistribute copies of it under the terms of
     5.8 +the GNU Lesser General Public License version 3 or later.
     5.9 +
    5.10 +
    5.11 +
    5.12 +Apache Commons CLI
    5.13 +Copyright 2001-2007 The Apache Software Foundation
    5.14 +
    5.15 +This product includes software developed by
    5.16 +The Apache Software Foundation (http://www.apache.org/).
     6.1 --- a/TODO	Thu Dec 14 23:22:05 2006 +0300
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,1 +0,0 @@
     6.4 -if, <, >, =, +, -, *, /
     7.1 --- a/build.xml	Thu Dec 14 23:22:05 2006 +0300
     7.2 +++ b/build.xml	Tue Feb 19 20:32:17 2008 +0300
     7.3 @@ -1,44 +1,113 @@
     7.4  <?xml version="1.0"?>
     7.5  <project name="tema" default="dist" basedir=".">
     7.6 -
     7.7 +    
     7.8 +    <property name="version"  value="0.3"/>
     7.9 +    
    7.10      <property name="src"      value="src"/>
    7.11      <property name="build"    value="build"/>
    7.12      <property name="dist"     value="dist"/>
    7.13      <property name="res"      value="res"/>
    7.14      <property name="doc"      value="doc"/>
    7.15 +    <property name="lib"      value="${dist}/lib"/>
    7.16      <property name="jar_file" value="tema.jar"/>
    7.17 -
    7.18 +    
    7.19 +    <property name="ant_jar" value="/usr/share/java/ant.jar"/>
    7.20 +    
    7.21 +    <path id="project.libs">
    7.22 +        <fileset dir="${lib}">
    7.23 +            <include name="**/*.jar"/>
    7.24 +        </fileset>
    7.25 +    </path>
    7.26 +    
    7.27      <target name="init">
    7.28 -	<tstamp/>
    7.29 -	<mkdir dir="${build}"/>
    7.30 +        <tstamp/>
    7.31 +        <mkdir dir="${build}"/>
    7.32      </target>
    7.33 -
    7.34 +    
    7.35      <target name="compile" depends="init">
    7.36          <javac srcdir="${src}" destdir="${build}"
    7.37                 deprecation="on" optimize="on" debug="on">
    7.38 -          <!-- <compilerarg value="-Xlint:unchecked"/> -->
    7.39 +            <compilerarg value="-Xlint:unchecked"/>
    7.40 +            <classpath refid="project.libs"/>
    7.41          </javac>
    7.42 +        
    7.43 +        <copy todir="${build}">
    7.44 +            <fileset dir="${res}"/>
    7.45 +        </copy>
    7.46 +    </target>
    7.47 +    
    7.48 +    <target name="dist" depends="compile">
    7.49 +        <jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf">
    7.50 +            <fileset dir="${build}" includes="**/*.class"/>
    7.51 +            <fileset dir="${build}" includes="**/*.template"/>
    7.52 +        </jar>
    7.53 +    </target>
    7.54 +      
    7.55 +    <target name="run" depends="compile">
    7.56 +        <java classname="kryshen.tema.Tema" fork="true">
    7.57 +            <classpath>
    7.58 +                <pathelement location="${build}"/>
    7.59 +                <path refid="project.libs"/>
    7.60 +            </classpath>
    7.61 +        </java>
    7.62 +    </target>
    7.63 +    
    7.64 +    <target name="run.demo" depends="compile">
    7.65 +        <java classname="kryshen.tema.Tema" fork="true">
    7.66 +            <classpath>
    7.67 +                <pathelement location="${build}"/>
    7.68 +                <path refid="project.libs"/>
    7.69 +            </classpath>
    7.70 +            <arg value="-demo"/>
    7.71 +        </java>        
    7.72 +    </target>
    7.73 +    
    7.74 +    <target name="doc.manual" depends="dist">
    7.75 +        <taskdef name="tema"
    7.76 +                 classname="kryshen.tema.ant.TemaTask"
    7.77 +                 classpath="${dist}/tema.jar"/>
    7.78 +                 
    7.79 +        <tema infile="${doc}/manual/manual.tema"
    7.80 +              outfile="${doc}/manual/manual.html"
    7.81 +              basedir="${doc}/manual"/>
    7.82      </target>
    7.83  
    7.84 -    <target name="dist" depends="compile">
    7.85 -	<jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf">
    7.86 -	    <fileset dir="${build}" includes="**/*.class"/>
    7.87 -	    <fileset dir="${res}" includes="**/*"/>
    7.88 -	</jar>
    7.89 -    </target>
    7.90 -
    7.91 -    <target name="javadoc" depends="init">
    7.92 +    <target name="doc.api" depends="init">
    7.93          <javadoc destdir="${doc}/api" sourcepath="${src}"
    7.94                   packagenames="kryshen.tema.*">
    7.95 +            <classpath> 
    7.96 +                <path refid="project.libs"/>
    7.97 +                <pathelement location="${ant_jar}"/>
    7.98 +            </classpath>
    7.99          </javadoc>
   7.100      </target>
   7.101 - 
   7.102 -    <target name="clean">
   7.103 -	<delete>
   7.104 -	    <fileset dir="${build}" includes="**/*.class"/>
   7.105 -	</delete>
   7.106 -	<delete file="${dist}/${jar_file}"/>
   7.107 -	<delete dir="${doc}/api"/>
   7.108 +    
   7.109 +    <target name="package.tar" depends="dist,doc.manual,doc.api">
   7.110 +        <tar destfile="${dist}/${ant.project.name}-${version}.tar.gz"
   7.111 +             compression="gzip">
   7.112 +            <tarfileset dir="${basedir}"
   7.113 +                        prefix="${ant.project.name}-${version}">
   7.114 +                <exclude name="${build}/**"/>
   7.115 +                <exclude name="misc/**"/>
   7.116 +                <exclude name="test/**"/>
   7.117 +                <exclude name="nbproject/**"/>
   7.118 +                <exclude name="${dist}/${ant.project.name}-*.tar.gz"/>
   7.119 +                <exclude name="${dist}/tema"/>
   7.120 +            </tarfileset>
   7.121 +            <tarfileset dir="${basedir}"
   7.122 +                        prefix="${ant.project.name}-${version}"
   7.123 +                        mode="755">
   7.124 +                <include name="${dist}/tema"/>
   7.125 +            </tarfileset>
   7.126 +        </tar>
   7.127 +    </target>
   7.128 +    
   7.129 +    <target name="clean" depends="init">
   7.130 +        <delete>
   7.131 +            <fileset dir="${build}" includes="**/*.class"/>
   7.132 +        </delete>
   7.133 +        <delete file="${dist}/${jar_file}"/>
   7.134 +        <delete dir="${doc}/api"/>
   7.135      </target>
   7.136      
   7.137  </project>
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/dist/.cvsignore	Tue Feb 19 20:32:17 2008 +0300
     8.3 @@ -0,0 +1,2 @@
     8.4 +tema.jar
     8.5 +tema-*.tar.gz
     9.1 --- a/dist/biotopes/biotope-top.sql	Thu Dec 14 23:22:05 2006 +0300
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,20 +0,0 @@
     9.4 -SELECT t1.*,
     9.5 -
     9.6 -(SELECT t2.rusname FROM biotopelist AS t2
     9.7 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND
     9.8 -Right(t2.rangcode, 8) = '00000000') AS class0,
     9.9 -
    9.10 -(SELECT t2.rusname FROM biotopelist AS t2
    9.11 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND
    9.12 -Right(t2.rangcode, 6) = '000000') AS class1,
    9.13 -
    9.14 -(SELECT t2.rusname FROM biotopelist AS t2
    9.15 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND
    9.16 -Right(t2.rangcode, 4) = '0000') AS class2,
    9.17 -
    9.18 -(SELECT t2.rusname FROM biotopelist AS t2
    9.19 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND
    9.20 -Right(t2.rangcode, 2) = '00') AS class3
    9.21 -
    9.22 -FROM biotopelist AS t1
    9.23 -WHERE Right(t1.rangcode, 2) <> '00' AND rusname
    10.1 --- a/dist/biotopes/biotope.sql	Thu Dec 14 23:22:05 2006 +0300
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,24 +0,0 @@
    10.4 -SELECT t1.*,
    10.5 -
    10.6 -(SELECT t2.rusname FROM biotopelist AS t2
    10.7 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
    10.8 -AND Right(t2.rangcode, 8)  = '00000000'
    10.9 -AND Right(t1.rangcode, 8) <> '00000000') AS class0,
   10.10 -
   10.11 -(SELECT t2.rusname FROM biotopelist AS t2
   10.12 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
   10.13 -AND Right(t2.rangcode, 6)  = '000000'
   10.14 -AND Right(t1.rangcode, 6) <> '000000') AS class1,
   10.15 -
   10.16 -(SELECT t2.rusname FROM biotopelist AS t2
   10.17 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
   10.18 -AND Right(t2.rangcode, 4)  = '0000'
   10.19 -AND Right(t1.rangcode, 4) <> '0000') AS class2,
   10.20 -
   10.21 -(SELECT t2.rusname FROM biotopelist AS t2
   10.22 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
   10.23 -AND Right(t2.rangcode, 2)  = '00'
   10.24 -AND Right(t1.rangcode, 2) <> '00') AS class3
   10.25 -
   10.26 -FROM biotopelist AS t1
   10.27 -WHERE rusname
    11.1 --- a/dist/biotopes/biotope.template	Thu Dec 14 23:22:05 2006 +0300
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,17 +0,0 @@
    11.4 -<?xml version="1.0" encoding="ISO-8859-5"?>
    11.5 -<!DOCTYPE _ SYSTEM "brief.dtd">
    11.6 -<!-- rangcode: <%xml_escape db\rangcode%> -->
    11.7 -<_ show="0">
    11.8 -  < display="0">
    11.9 -    <%optional:<_ ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\code%>.png png%>"/>%>
   11.10 -<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
   11.11 -  </>
   11.12 -  <><%xml_escape db\rusname%></>
   11.13 -  <><%xml_escape db\class0%></>
   11.14 -  <1><%xml_escape db\class1%></1>
   11.15 -  <2><%xml_escape db\class2%></2>
   11.16 -  <3><%xml_escape db\class3%></3>
   11.17 -  <_ rows="3"><%xml_cdata db\descript%></_>
   11.18 -  <_ rows="3"><%xml_cdata db\geobotdescr%></_>
   11.19 -  <_><%xml_escape db\contributors%></_>
   11.20 -</_>
    12.1 --- a/dist/biotopes/brief.dtd	Thu Dec 14 23:22:05 2006 +0300
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,27 +0,0 @@
    12.4 -<?xml encoding="ISO-8859-5"?>
    12.5 -<!ELEMENT _ (?, , , 1, 2, 3, _, _, _)>
    12.6 -<!ELEMENT  (|_)*>
    12.7 -<!ELEMENT  EMPTY>
    12.8 -<!ELEMENT _ EMPTY>
    12.9 -<!ELEMENT  (#PCDATA)>
   12.10 -<!ELEMENT  (#PCDATA)>
   12.11 -<!ELEMENT 1 (#PCDATA)>
   12.12 -<!ELEMENT 2 (#PCDATA)>
   12.13 -<!ELEMENT 3 (#PCDATA)>
   12.14 -<!ELEMENT _ (#PCDATA)>
   12.15 -<!ELEMENT _ (#PCDATA)>
   12.16 -<!ELEMENT _ (#PCDATA)>
   12.17 -<!ATTLIST _ show (0|1) "1"> 
   12.18 -<!ATTLIST 
   12.19 -	display CDATA #FIXED "0">
   12.20 -<!ATTLIST 
   12.21 -	num ID #REQUIRED
   12.22 -	file CDATA #REQUIRED
   12.23 -	big CDATA #REQUIRED
   12.24 -	text CDATA #IMPLIED
   12.25 -	 CDATA #IMPLIED>
   12.26 -<!ATTLIST _
   12.27 -	num ID #REQUIRED
   12.28 -	file CDATA #REQUIRED>
   12.29 -<!ATTLIST _ rows CDATA #FIXED "3">
   12.30 -<!ATTLIST _ rows CDATA #FIXED "3">
    13.1 --- a/dist/biotopes/class.sql	Thu Dec 14 23:22:05 2006 +0300
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,7 +0,0 @@
    13.4 -SELECT t1.*
    13.5 -FROM biotopelist AS t1
    13.6 -WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
    13.7 -  AND EXISTS
    13.8 -    (SELECT NULL FROM biotopelist AS t2
    13.9 -     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
   13.10 -     AND Right(t2.rangcode, 8) <> '00000000')
    14.1 --- a/dist/biotopes/classes.template	Thu Dec 14 23:22:05 2006 +0300
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,5 +0,0 @@
    14.4 -<?xml version="1.0" encoding="ISO-8859-5"?>
    14.5 -<><%query:class_sql [%\
    14.6 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
    14.7 -  < id="<%get\NUMBER%>"><%xml_escape db\rusname%></>%]%>
    14.8 -</>
    15.1 --- a/dist/biotopes/doc/article.txt	Thu Dec 14 23:22:05 2006 +0300
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,391 +0,0 @@
    15.4 -*     XML-  .
    15.5 -
    15.6 -      " 
    15.7 -"   Microsoft Access  XML- 
    15.8 -       DbReader.
    15.9 -
   15.10 - DbReader     
   15.11 -      .  
   15.12 -        
   15.13 -    .   
   15.14 - SQL-,     
   15.15 -.
   15.16 -
   15.17 -
   15.18 -*  :
   15.19 -
   15.20 -    <%<_>{:|\}<>%>
   15.21 -   
   15.22 -
   15.23 -<_> -   ,  .
   15.24 -      .
   15.25 -<> - ,  .
   15.26 -
   15.27 -
   15.28 -*  :
   15.29 -
   15.30 -    [<_>][<>]
   15.31 -  
   15.32 -
   15.33 -<_> -   ,  .
   15.34 -      .
   15.35 -<> - ,      .
   15.36 -      .  ,   
   15.37 -    ,   .
   15.38 -
   15.39 -      ,  
   15.40 -  :
   15.41 -: -  ,
   15.42 -\ -   .
   15.43 -
   15.44 -        ,  ,
   15.45 -  ,        
   15.46 -   .
   15.47 -
   15.48 -     -  .  
   15.49 - -      .  ,
   15.50 -    -    
   15.51 -.
   15.52 -
   15.53 -  '<', '>'    '[', ']'.
   15.54 -
   15.55 -
   15.56 -*  :
   15.57 -
   15.58 -:      set
   15.59 -:    <>
   15.60 -:        <>
   15.61 -:        <>
   15.62 -:    <>
   15.63 - : 1
   15.64 -
   15.65 -:      get
   15.66 -:    <>
   15.67 -:      <>. 
   15.68 - : 1,     , 0 - .
   15.69 -
   15.70 -:      prepare
   15.71 -:    <>
   15.72 -:        <>
   15.73 -:      SQL- <>  ,
   15.74 -                   <>.
   15.75 -:    <>
   15.76 - : 1
   15.77 -
   15.78 -:      query
   15.79 -:    <_> <> <1> ... <N>
   15.80 -:        ,   
   15.81 -               prepare.    
   15.82 -                 '?'.    
   15.83 -              ,    <>.  
   15.84 -               <>    NUMBER,
   15.85 -                  . ,
   15.86 -                 ,   
   15.87 -              <>   SUPER.<_>.
   15.88 -
   15.89 -:       <>   
   15.90 -              .
   15.91 - :    .
   15.92 -
   15.93 -:      optional
   15.94 -:        <>
   15.95 -:    <>,      
   15.96 -                  0,  -  .
   15.97 - : 1,   -  , 0 - .
   15.98 -
   15.99 -:      image
  15.100 -:    <_> <_> <> [<_> [<_>]]
  15.101 -:         <_> ( 
  15.102 -                 "resource_base") 
  15.103 -                  ,   
  15.104 -              <_>.      , 
  15.105 -                . 
  15.106 -:    <_>   ,   - .
  15.107 - : 1   , 0 - .
  15.108 -
  15.109 -:      copy
  15.110 -:    <_> <_>
  15.111 -:       <_>   <_>
  15.112 -	      ( <_>  
  15.113 -                "resource_base").
  15.114 -:    <_>   ,   - .
  15.115 - : 1   , 0 - .
  15.116 -
  15.117 -:      write
  15.118 -:    <_>
  15.119 -:        <>
  15.120 -:      <>   <_>.
  15.121 -:    <_>   ,   - .
  15.122 - : 1   , 0 - .
  15.123 -
  15.124 -:      read
  15.125 -:        <_>
  15.126 -:       <_>.
  15.127 -:        , 
  15.128 -               - .
  15.129 - : 1   , 0 - .
  15.130 -
  15.131 -:      include
  15.132 -:        <_>
  15.133 -:         <_>.
  15.134 -:      .
  15.135 - :  ,    .
  15.136 -
  15.137 -:      !
  15.138 -:        <>
  15.139 -:     .
  15.140 -:    .
  15.141 - :  ,     .
  15.142 -
  15.143 -:      replace
  15.144 -:    <1> <2>
  15.145 -:        <>
  15.146 -:    ,     <1>
  15.147 -	       <2>.
  15.148 - :  ,     .
  15.149 -
  15.150 -:      xml_escape
  15.151 -:        <>
  15.152 -:     <>,    
  15.153 -              '&', '<', '>', '`', '\'   
  15.154 -	       XML.
  15.155 - :  ,     .
  15.156 -
  15.157 -:      xml_cdata
  15.158 -:        <>
  15.159 -:        XML CDATA.
  15.160 - :  ,     .
  15.161 -
  15.162 - DbReader :     
  15.163 -,       Java.
  15.164 -
  15.165 -
  15.166 -*   DbReader    
  15.167 -  "  "   Microsoft Access 
  15.168 -  XML-    
  15.169 -
  15.170 -       "
  15.171 - " (   ):
  15.172 -
  15.173 -biotopelist (code, rangcode, rusname, engname, descript, geobotdescr,
  15.174 -             contributors, descrdate)
  15.175 -
  15.176 -  code - ,  ;
  15.177 -  rangcode -    ABBCCDDEE,  , BB, CC, DD,  - 
  15.178 -             ,   ;
  15.179 -  rusname, engname, descript, geobotdescr -  ;
  15.180 -  descrdate - .
  15.181 -
  15.182 -photos (biotope, photo, authphoto)
  15.183 -
  15.184 -  biotope - ,   code  biotopelist;
  15.185 -  photo -   ;
  15.186 -  authphoto - .
  15.187 -
  15.188 -  xml-     biotopelist, 
  15.189 -  ,    ,  
  15.190 -   .
  15.191 -
  15.192 -  xml-     
  15.193 - DbReader ( biotope.template):
  15.194 -
  15.195 -----------------------------------------------------------------------
  15.196 -<?xml version="1.0" encoding="ISO-8859-5"?>
  15.197 -<!DOCTYPE _ SYSTEM "brief.dtd">
  15.198 -<!-- rangcode: <%xml_escape get\rangcode%> -->
  15.199 -<_ show="0">
  15.200 -  < display="0">
  15.201 -    <%optional:<_ ="1"
  15.202 -    file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%>
  15.203 -<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
  15.204 -  </>
  15.205 -  <><%xml_escape get\rusname%></>
  15.206 -  <><%xml_escape get\class0%></>
  15.207 -  <1><%xml_escape get\class1%></1>
  15.208 -  <2><%xml_escape get\class2%></2>
  15.209 -  <3><%xml_escape get\class3%></3>
  15.210 -  <_ rows="3"><%xml_cdata get\descript%></_>
  15.211 -  <_ rows="3"><%xml_cdata get\geobotdescr%></_>
  15.212 -  <_><%xml_escape get\contributors%></_>
  15.213 -</_>
  15.214 -----------------------------------------------------------------------
  15.215 -
  15.216 - SQL-,    
  15.217 -   rangcode, rusname, class0, class1, class2,
  15.218 -class3, descript, geobotdescr  contributors ( biotope.sql):
  15.219 -
  15.220 -----------------------------------------------------------------------
  15.221 -SELECT t1.*,
  15.222 -
  15.223 -(SELECT t2.rusname FROM biotopelist AS t2
  15.224 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  15.225 -AND Right(t2.rangcode, 8)  = '00000000'
  15.226 -AND Right(t1.rangcode, 8) <> '00000000') AS class0,
  15.227 -
  15.228 -(SELECT t2.rusname FROM biotopelist AS t2
  15.229 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
  15.230 -AND Right(t2.rangcode, 6)  = '000000'
  15.231 -AND Right(t1.rangcode, 6) <> '000000') AS class1,
  15.232 -
  15.233 -(SELECT t2.rusname FROM biotopelist AS t2
  15.234 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
  15.235 -AND Right(t2.rangcode, 4)  = '0000'
  15.236 -AND Right(t1.rangcode, 4) <> '0000') AS class2,
  15.237 -
  15.238 -(SELECT t2.rusname FROM biotopelist AS t2
  15.239 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
  15.240 -AND Right(t2.rangcode, 2)  = '00'
  15.241 -AND Right(t1.rangcode, 2) <> '00') AS class3
  15.242 -
  15.243 -FROM biotopelist AS t1
  15.244 -WHERE rusname
  15.245 -----------------------------------------------------------------------
  15.246 -
  15.247 - biotope.template   <%include\photo.template%>,
  15.248 -    ( photo.template):
  15.249 -
  15.250 -----------------------------------------------------------------------
  15.251 -    < num="<%xml_escape get\NUMBER%>"
  15.252 -       <%optional:="<%xml_escape get\authphoto%>" %>text="" 
  15.253 -       file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 
  15.254 -        big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
  15.255 -----------------------------------------------------------------------
  15.256 -
  15.257 - SQL-    
  15.258 -(photo.sql):
  15.259 -
  15.260 -----------------------------------------------------------------------
  15.261 -SELECT * from photos WHERE biotope = ?
  15.262 -----------------------------------------------------------------------
  15.263 -
  15.264 -,    ( classes.template):
  15.265 -
  15.266 -----------------------------------------------------------------------
  15.267 -<?xml version="1.0" encoding="ISO-8859-5"?>
  15.268 -<><%query:class_sql [%\
  15.269 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
  15.270 -  < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%>
  15.271 -</>
  15.272 -----------------------------------------------------------------------
  15.273 -
  15.274 - SQL- (class.sql):
  15.275 -
  15.276 -----------------------------------------------------------------------
  15.277 -SELECT t1.*
  15.278 -FROM biotopelist AS t1
  15.279 -WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
  15.280 -  AND EXISTS
  15.281 -    (SELECT NULL FROM biotopelist AS t2
  15.282 -     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  15.283 -     AND Right(t2.rangcode, 8) <> '00000000')
  15.284 -----------------------------------------------------------------------
  15.285 -
  15.286 -,    ( plants.template):
  15.287 -
  15.288 -----------------------------------------------------------------------
  15.289 -<?xml version="1.0" encoding="ISO-8859-5"?>
  15.290 -<><%query:plant_sql [%\
  15.291 -  <!-- rangcode: <%xml_escape get\rangcode%> -->
  15.292 -  <><%xml_escape get\rusname%></>%]%>
  15.293 -</>
  15.294 -----------------------------------------------------------------------
  15.295 -
  15.296 - SQL- (plant.sql):
  15.297 -
  15.298 -----------------------------------------------------------------------
  15.299 -SELECT t1.*
  15.300 -FROM biotopelist AS t1
  15.301 -WHERE rusname AND Right(t1.rangcode, 2) <> '00'
  15.302 -----------------------------------------------------------------------
  15.303 -
  15.304 - DbReader      index.template,
  15.305 -     SQL-  
  15.306 -:
  15.307 -
  15.308 -----------------------------------------------------------------------
  15.309 -<%!:
  15.310 -  <%prepare:biotope_sql <%read\biotope.sql%>%>
  15.311 -  <%prepare:photo_sql <%read\photo.sql%>%>
  15.312 -  <%prepare:class_sql <%read\class.sql%>%>
  15.313 -  <%prepare:plant_sql <%read\plant.sql%>%>
  15.314 -
  15.315 -  <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%>
  15.316 -
  15.317 -  <%write:classes.xml <%include\classes.template%>%>
  15.318 -  <%write:plants.xml <%include\plants.template%>%>
  15.319 -%>
  15.320 -----------------------------------------------------------------------
  15.321 -
  15.322 -  XML-:
  15.323 -
  15.324 -----------------------------------------------------------------------
  15.325 -<?xml version="1.0" encoding="ISO-8859-5"?>
  15.326 -<!DOCTYPE _ SYSTEM "brief.dtd">
  15.327 -<!-- rangcode: E04020302 -->
  15.328 -<_ show="0">
  15.329 -  < display="0">    
  15.330 -    < num="1" =" .." text="" 
  15.331 -                file="images/3_1.jpg" 
  15.332 -                big="images/big/3_1.jpg"/>
  15.333 -    < num="2" =" .." text="" 
  15.334 -                file="images/3_2.jpg" 
  15.335 -                big="images/big/3_2.jpg"/>
  15.336 -  </>
  15.337 -  <>Betula sp. - Avenella flexuosa - Polytrichum commune</>
  15.338 -  <>E.  </>
  15.339 -  <1> </1>
  15.340 -  <2></2>
  15.341 -  <3></3>
  15.342 -  <_ rows="3"><![CDATA[       .   5 - 7            ,   ,   ,   .]]></_>
  15.343 -  <_ rows="3"></_>
  15.344 -  <_></_>
  15.345 -</_>
  15.346 -----------------------------------------------------------------------
  15.347 -
  15.348 -
  15.349 -*   DbReader
  15.350 -
  15.351 - DbReader     Java  
  15.352 -   :
  15.353 -
  15.354 -ru.karrc.dbreader.DbReader: c   . 
  15.355 -,       
  15.356 - JDBC,    .
  15.357 -
  15.358 -ru.karrc.dbreader.TemplateParser:   ,
  15.359 -    .
  15.360 -
  15.361 -ru.karrc.dbreader.Function:  .   
  15.362 -DbReader   .
  15.363 -
  15.364 -ru.karrc.dbreader.FunctionDataParser:  
  15.365 -.      , 
  15.366 -.       
  15.367 - TemplateParser.
  15.368 -
  15.369 -ru.karrc.dbreader.Functions:     
  15.370 - ,  Function.
  15.371 -
  15.372 -ru.karrc.dbreader.TemplateParser: ,   
  15.373 -    .
  15.374 -
  15.375 - ,    , 
  15.376 -    .
  15.377 -
  15.378 -
  15.379 -*    .
  15.380 -
  15.381 -   : 8,
  15.382 - Java- ( ): 27,
  15.383 -    : 1311,
  15.384 -   (    ): 812,
  15.385 -  : 180.
  15.386 -
  15.387 -
  15.388 -* 
  15.389 -
  15.390 -     DbReader, 
  15.391 -      
  15.392 -      .   
  15.393 -DbReader   "  " 
  15.394 -  XML-    .
    16.1 --- a/dist/biotopes/doc/readme.html	Thu Dec 14 23:22:05 2006 +0300
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,86 +0,0 @@
    16.4 -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    16.5 -          "DTD/xhtml1-transitional.dtd">
    16.6 -
    16.7 -<html>
    16.8 -
    16.9 -<head>
   16.10 -  <title>DbReader</title>
   16.11 -  <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" />
   16.12 -</head>
   16.13 -
   16.14 -<body>
   16.15 -<h1>DbReader</h1>
   16.16 -
   16.17 -<h2> </h2>
   16.18 -<ol>
   16.19 -<li> .</li>
   16.20 -
   16.21 -<li>  :<br />
   16.22 - Windows 2000:  //  (ODBC),  biotopes-data.mdb.</li>
   16.23 -
   16.24 -<li> :<br />
   16.25 -  dbreader.properties  ,   :<br />
   16.26 -    <code>resource: jdbc:odbc:<em></em></code><br />
   16.27 -   ,       ( biotopephotos  maps):<br />
   16.28 -    <code>resource_base: C:\\biotopes</code><br />
   16.29 -( '\'  )</li>
   16.30 -
   16.31 -<li> :<br />
   16.32 -<code>dbreader.bat</code> <br />
   16.33 -<code>java -jar dbreader.jar</code>.<br />
   16.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 -  .
   16.35 -
   16.36 -        :<br />
   16.37 - <code>java -Dru.karrc.dbreader.<em></em>=<em></em> -jar dbreader.jar</code><br />
   16.38 -(: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li>
   16.39 -</ol>
   16.40 -
   16.41 -<h2> </h2>
   16.42 -
   16.43 -<p>   biotope.sql ( ,   dbreader.properties),     biotope.template,         .</p>
   16.44 -<p> : <code>&lt;%<em>_</em>[:|\]<em></em>%&gt;</code>, <em> </em> -    ,    .    ,     .</p>
   16.45 -
   16.46 -<h3>     </h3>
   16.47 -
   16.48 -<ul>
   16.49 -  <li><code>:</code> -    .</li>
   16.50 -  <li><code>\</code> -      .       <code>&lt;%</code>  <code>%&gt;</code> (<code>&lt;%\&lt;%%&gt;</code>  <code>&lt;%\%%&gt;&gt;</code>).</li>
   16.51 -</ul>
   16.52 -
   16.53 -<h3></h3>
   16.54 -
   16.55 -<ul>
   16.56 -  <li><code>&lt;%get:<em></em>%&gt;</code><br />
   16.57 -         .</li>
   16.58 -
   16.59 -  <li><code>&lt;%optional:<em></em>%&gt;</code><br />
   16.60 -    <em></em>,     ,    ,     .</li>
   16.61 -
   16.62 -  <li><code>&lt;%escape:<em></em>%&gt;</code><br />
   16.63 -     ""  (     ).</li>
   16.64 -
   16.65 -  <li><code>&lt;%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%&gt;</code><br />
   16.66 -      <em></em>.sql       <em></em>.template.        '?'.</li>
   16.67 -
   16.68 -  <li><code>&lt;%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%&gt;</code><br />
   16.69 -      <em>_</em> (     "resource_base")      ,    <em>_</em>.      ,    .
   16.70 -  ,  <code>&lt;%image:...%&gt;</code>     <em>_</em>,  -   .</li>
   16.71 -
   16.72 -  <li><code>&lt;%copy:<em>_</em> <em>_</em>%&gt;</code><br />
   16.73 -    <em>_</em> (     "resource_base")  <em>_</em>.   ,  <code>&lt;%copy:...%&gt;</code>     <em>_</em>,  -   .</li>
   16.74 -</ul>
   16.75 -
   16.76 -<h3> </h3>
   16.77 -
   16.78 -<p><code>NUMBER</code> -      .
   16.79 -    ,          invoke,      <code>SUPER.</code> (: <code>SUPER.NUMBER</code>).</p>
   16.80 -
   16.81 -<h3></h3>
   16.82 -
   16.83 -<p>      name      :</p>
   16.84 -<p><code>&lt;%escape get:name%&gt;</code></p>
   16.85 -
   16.86 -<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru"> </a></i></p>
   16.87 -
   16.88 -</body>
   16.89 -</html>
    17.1 --- a/dist/biotopes/doc/readme.txt	Thu Dec 14 23:22:05 2006 +0300
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,63 +0,0 @@
    17.4 -text/plain; charset=UTF-8
    17.5 -
    17.6 -Установка программы
    17.7 --------------------
    17.8 -
    17.9 -1. Распаковать архив.
   17.10 -
   17.11 -2. Установить источник данных:
   17.12 -в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes.mdb.
   17.13 -
   17.14 -3. Настроить программу:
   17.15 -В файле dbreader.properties указать имя, присвоенное источнику данных:
   17.16 -    "resource: jdbc:odbc:<имя>"
   17.17 -и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):
   17.18 -    "resource_base: C:\\biotopes"
   17.19 -(символ '\' необходимо дублировать)
   17.20 -
   17.21 -4. Запуск программы: dbreader.bat или "java -jar dbreader.jar"
   17.22 -Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с http://java.sun.com/j2se/1.5.0/download.jsp. Возможно, будет работать и со старыми версиями JRE - не проверял.
   17.23 -
   17.24 -Все значения файла конфигурации можно переопределять при запуске программы:
   17.25 -    команда "java -Dru.karrc.dbreader.<ключ>=<значение> -jar dbreader.jar"
   17.26 -(например: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar")
   17.27 -
   17.28 -
   17.29 -Работа программы
   17.30 -----------------
   17.31 -
   17.32 -Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.
   17.33 -
   17.34 -Формат инструкций: "<%список_функций[:|\]данные%>", список функций - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.
   17.35 -
   17.36 -Разделители между списком функций и данными:
   17.37 -':' - данные будут обрабатываться рекурсивно.
   17.38 -'\' - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов "<%" и "%>" ("<%\<%%>" и "<%\%%>>").
   17.39 -
   17.40 -Функции:
   17.41 -<%get:<имя>%> - заменяется на значение встроенной переменной или колонки запроса.
   17.42 -
   17.43 -<%optional:<текст>%>
   17.44 -Заменяется на <текст>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.
   17.45 -
   17.46 -<%escape:<текст>%>
   17.47 -Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).
   17.48 -
   17.49 -<%invoke:<имя> <парам1> <парам2> ... <парамN>%>
   17.50 -Выполняет запрос с параметрами <имя>.sql и заменяется на результаты обработки шаблона <имя>.template. Значения параметров подставляются в запрос вместо символа '?'.
   17.51 -
   17.52 -<%image:<исх_файл> <кон_файл> <формат> [<макс_ширина>] [<макс_высота>]%>
   17.53 -Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены.
   17.54 -При успешном выполнении, инструкция "<%!image ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку.
   17.55 -
   17.56 -<%copy:<исх_файл> <кон_файл>%>
   17.57 -Копирует файл <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base").
   17.58 -При успешном выполнении, инструкция "<%!copy ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку.
   17.59 -
   17.60 -Встроенные переменные:
   17.61 -NUMBER - порядковый номер строки результата выполнения запроса.
   17.62 -Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить "SUPER." (например: "SUPER.NUMBER").
   17.63 -
   17.64 -Пример:
   17.65 -Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:
   17.66 -<%escape get:name%>
    18.1 --- a/dist/biotopes/main.template	Thu Dec 14 23:22:05 2006 +0300
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,11 +0,0 @@
    18.4 -<%!:
    18.5 -  <%prepare:biotope_sql <%read\biotope.sql%>%>
    18.6 -  <%prepare:photo_sql <%read\photo.sql%>%>
    18.7 -  <%prepare:class_sql <%read\class.sql%>%>
    18.8 -  <%prepare:plant_sql <%read\plant.sql%>%>
    18.9 -
   18.10 -  <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%>
   18.11 -
   18.12 -  <%write:classes.xml <%include\classes.template%>%>
   18.13 -  <%write:plants.xml <%include\plants.template%>%>
   18.14 -%>
    19.1 --- a/dist/biotopes/photo.sql	Thu Dec 14 23:22:05 2006 +0300
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,1 +0,0 @@
    19.4 -SELECT * from photos WHERE biotope = ?
    20.1 --- a/dist/biotopes/photo.template	Thu Dec 14 23:22:05 2006 +0300
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,3 +0,0 @@
    20.4 -    < num="<%number\%>" <%optional:="<%xml_escape db\authphoto%>" %>text="" 
    20.5 -                file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" 
    20.6 -                big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
    21.1 --- a/dist/biotopes/plant.sql	Thu Dec 14 23:22:05 2006 +0300
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,3 +0,0 @@
    21.4 -SELECT t1.*
    21.5 -FROM biotopelist AS t1
    21.6 -WHERE rusname AND Right(t1.rangcode, 2) <> '00'
    22.1 --- a/dist/biotopes/plants.template	Thu Dec 14 23:22:05 2006 +0300
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,5 +0,0 @@
    22.4 -<?xml version="1.0" encoding="ISO-8859-5"?>
    22.5 -<><%query:plant_sql [%\
    22.6 -  <!-- rangcode: <%xml_escape db\rangcode%> -->
    22.7 -  <><%xml_escape db\rusname%></>%]%>
    22.8 -</>
    23.1 --- a/dist/biotopes/tema.properties	Thu Dec 14 23:22:05 2006 +0300
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,22 +0,0 @@
    23.4 -# Data source configuration
    23.5 -resource          : jdbc:odbc:biotopes-data
    23.6 -driver            : sun.jdbc.odbc.JdbcOdbcDriver
    23.7 -
    23.8 -# Base directory for images and files
    23.9 -resource_base     : C:\\biotopes\\db
   23.10 -
   23.11 -# Template to start processing with
   23.12 -main_template     : main.template
   23.13 -
   23.14 -# File encodings
   23.15 -input_encoding    : ISO-8859-5
   23.16 -output_encoding   : ISO-8859-5
   23.17 -
   23.18 -# Cache templates
   23.19 -cache_read        : true
   23.20 -
   23.21 -# Output main_template parsing result to stderr
   23.22 -#output            : stderr
   23.23 -
   23.24 -# File to output error messages (redirect stderr)
   23.25 -#log               : tema.log
    24.1 Binary file dist/lib/commons-cli-1.1.jar has changed
    25.1 --- a/dist/tema.properties	Thu Dec 14 23:22:05 2006 +0300
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,22 +0,0 @@
    25.4 -# Data source configuration
    25.5 -# resource          : jdbc:odbc:biotopes-data
    25.6 -# driver            : sun.jdbc.odbc.JdbcOdbcDriver
    25.7 -
    25.8 -# Base directory for images and files
    25.9 -# resource_base     : C:\\biotopes\\db
   25.10 -
   25.11 -# Template to start processing with
   25.12 -main_template     : main.template
   25.13 -
   25.14 -# File encodings
   25.15 -# input_encoding    : UTF-8
   25.16 -# output_encoding   : UTF-8
   25.17 -
   25.18 -# Cache templates
   25.19 -# cache_read        : true
   25.20 -
   25.21 -# Output main_template parsing result to stderr
   25.22 -# output            : stderr
   25.23 -
   25.24 -# File to output error messages (redirect stderr)
   25.25 -# log               : tema.log
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/doc/.cvsignore	Tue Feb 19 20:32:17 2008 +0300
    26.3 @@ -0,0 +1,1 @@
    26.4 +api
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/doc/manual/.cvsignore	Tue Feb 19 20:32:17 2008 +0300
    27.3 @@ -0,0 +1,1 @@
    27.4 +manual.html
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/doc/manual/document.tema	Tue Feb 19 20:32:17 2008 +0300
    28.3 @@ -0,0 +1,107 @@
    28.4 +[%\
    28.5 +  Macro definitions used in manual.tema to generate HTML document.
    28.6 +%]
    28.7 +
    28.8 +[%!\
    28.9 +  Create HTML document.
   28.10 +  Arguments are read in pairs (name value) until "content" name is found.
   28.11 +  Then follows the document content.
   28.12 +
   28.13 +  TODO: generate TOC.
   28.14 +%]
   28.15 +<%define#document
   28.16 +  <%silent while#
   28.17 +    <%if:<%not equal:<%set:arg <%next_arg:%>%> content%>
   28.18 +      <%export:<%arg:%> <%next_arg:%>%>
   28.19 +    %>
   28.20 +  %>\\
   28.21 +<%if:<%not embedded:%>
   28.22 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   28.23 +
   28.24 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   28.25 +
   28.26 +<head>
   28.27 +  <title><%html_escape title:%></title>
   28.28 +  <meta http-equiv="Content-Type" content="text/html; charset=<%charset:%>" />
   28.29 +  <meta name="generator" content="<%tema:%>" />
   28.30 +</head>
   28.31 +
   28.32 +<body>
   28.33 +<h1><%html_escape title:%><%optional:<br /><%html_escape subtitle:%>%></h1>
   28.34 +%>\
   28.35 +<%html_escape data:%>
   28.36 +<%if:<%not embedded:%>
   28.37 +</body>
   28.38 +</html>
   28.39 +%>\
   28.40 +%>
   28.41 +
   28.42 +<%set:charset iso-8859-1%>
   28.43 +<%set:escape <%char:0%>%>
   28.44 +
   28.45 +[%!\
   28.46 +  Create HTML tag.
   28.47 +%]
   28.48 +<%define#tag <%false:<%escape:%><<%data:%><%escape:%>>%>%>
   28.49 +
   28.50 +[%!\
   28.51 +  Escape special HTML characters (except those preceded with <%escape:%>).
   28.52 +%]
   28.53 +<%define#html_escape
   28.54 +  <%replace:<%escape:%> <%:%>
   28.55 +  <%regex_replace_all:(?<!<%escape:%>)-- &ndash;
   28.56 +  <%regex_replace_all:(?<!<%escape:%>)--- &mdash;
   28.57 +  <%regex_replace_all:(?<!<%escape:%>)< &lt;
   28.58 +  <%regex_replace_all:(?<!<%escape:%>)> &gt;
   28.59 +  <%regex_replace_all:(?<!<%escape:%>)& &amp;
   28.60 +    <%data:%>\\
   28.61 +  %>%>%>%>%>%>\
   28.62 +%>
   28.63 +
   28.64 +<%define#section
   28.65 +  <%tag:h2<%if:<%first_section:%> <%: class="first"%>%>%><%data:%><%tag:/h2%>\\
   28.66 +  <%unset:first_section%>\\
   28.67 +%>
   28.68 +
   28.69 +<%define#subsection <%tag:h3%><%data:%><%tag:/h3%>%>
   28.70 +
   28.71 +<%define#par <%tag:p%><%data:%><%tag:/p%>%>
   28.72 +
   28.73 +<%define#itemize
   28.74 +<%tag:ul%>
   28.75 +<%while#\
   28.76 +  <%tag:li%><%next_arg:%><%tag:/li%>
   28.77 +%>\
   28.78 +<%tag:/ul%>
   28.79 +%>
   28.80 +
   28.81 +<%define#code <%tag:code%><%replace:-- <%escape:%>-- <%data:%>%><%tag:/code%>%>
   28.82 +
   28.83 +<%define#emph <%tag:i%><%data:%><%tag:/i%>%>
   28.84 +
   28.85 +<%define#link
   28.86 +  <%silent set:url <%next_arg:%>%>\\
   28.87 +  <%tag:a href="<%url:%>"%>\\
   28.88 +    <%if_else:<%has_more_data:%>
   28.89 +      <%data:%>
   28.90 +      <%url:%>%>\\
   28.91 +  <%tag:/a%>\\
   28.92 +%>
   28.93 +
   28.94 +<%define#function
   28.95 +  <%silent set:name <%next_arg:%>%>\\
   28.96 +  <%silent while#
   28.97 +    <%set:<%next_arg:%> <%next_arg:%>%>
   28.98 +  %>\\
   28.99 +  <%tag:div%>
  28.100 +    <%tag:b%><%name:%><%tag:/b%><%tag:br /%>
  28.101 +  <%tag:/div%>
  28.102 +  <%optional:<%tag:div style="padding-left:1em; margin-bottom: 0.5em;"%>
  28.103 +    <%description:%>
  28.104 +  <%tag:/div%>%>
  28.105 +  <%tag:div style="padding-left:1em; margin-bottom: 1em;"%>
  28.106 +    <%optional:<%tag:b%>Arguments:<%tag:/b%> <%arguments:%><%tag:br /%>%>
  28.107 +    <%optional:<%tag:b%>Data:<%tag:/b%> <%input_data:%><%tag:br /%>%>
  28.108 +    <%optional:<%tag:b%>Output:<%tag:/b%> <%output:%><%tag:br /%>%>
  28.109 +  <%tag:/div%>
  28.110 +%>
    29.1 --- a/doc/manual/index.html	Thu Dec 14 23:22:05 2006 +0300
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,358 +0,0 @@
    29.4 -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    29.5 -          "DTD/xhtml1-transitional.dtd">
    29.6 -
    29.7 -<html>
    29.8 -
    29.9 -<head>
   29.10 -  <title>Макропроцессор TEMA</title>
   29.11 -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   29.12 -</head>
   29.13 -
   29.14 -<body>
   29.15 -<h1>Макропроцессор TEMA</h1>
   29.16 -
   29.17 -Макропроцессор TEMA обрабатывает заданные шаблоны текстовых файлов и
   29.18 -заменяет найденные в них инструкции на результаты их выполнения.
   29.19 -
   29.20 -<p><b>Формат инструкций</b></p>
   29.21 -
   29.22 -<blockquote>
   29.23 -  <code>&lt;%<i>список_функций</i>{:|\|`}<i>данные</i>%&gt;</code>  
   29.24 -</blockquote>
   29.25 -<p>
   29.26 -где<br />
   29.27 -
   29.28 -<code><i>список_функций</i></code> - список имен функций, разделенных
   29.29 -    пробелами. Может быть пустым.<br />
   29.30 -<code><i>данные</i></code> - данные, передаваемые функции.
   29.31 -</p>
   29.32 -
   29.33 -<p><b>Формат данных</b></p>
   29.34 -
   29.35 -<blockquote>
   29.36 -  <code>
   29.37 -    [<i>список_аргументов</i>][<i>текст</i>]
   29.38 -  </code>
   29.39 -</blockquote>
   29.40 -<p>
   29.41 -где<br />
   29.42 -
   29.43 -<code><i>список_аргументов</i></code> - список аргументов функции, разделенных пробелами.
   29.44 -    Может быть пустым.<br />
   29.45 -<code><i>текст</i></code> - текст, передаваемый функции без разбиения на аргументы.
   29.46 -    Может быть пустым. Количество аргументов, после которого следует
   29.47 -    текст, зависит от функции.
   29.48 -</p><p>
   29.49 -Разделитель между списком функций и данными определяет, как должны
   29.50 -обрабатываться данные функции:
   29.51 -</p><p>
   29.52 -<code>:</code> - рекурсивная обработка,<br />
   29.53 -<code>\</code> или <code>`</code> - передать без обработки.
   29.54 -</p><p>
   29.55 -Если в списке функций задано две и более функции, они выполняются,
   29.56 -начиная с последней, так что каждая функция получает в качестве данных
   29.57 -результат выполнения следующей функции.
   29.58 -</p><p>
   29.59 -Каждая функция имеет код возврата - целое число. Код возврата
   29.60 -инструкции - код возврата первой в списке функции. Код возврата,
   29.61 -получаемый при обработке текста - сумма кодов возврата обработанных
   29.62 -инструкций (как правило, смысл этого значения - количество инструкций,
   29.63 -замененных на непустой текст).
   29.64 -</p><p>
   29.65 -Кроме скобок '&lt;', '&gt;', можно использовать скобки '[', ']'.
   29.66 -</p>
   29.67 -
   29.68 -
   29.69 -<h2>Функции</h2>
   29.70 -
   29.71 -<p><code><b>set</b></code></p>
   29.72 -
   29.73 -<table>
   29.74 -<tr><td>Аргументы:</td>
   29.75 -<td><i>имя</i></td></tr>
   29.76 -
   29.77 -<tr><td>Текст:</td>
   29.78 -<td><i>значение</i></td></tr>
   29.79 -
   29.80 -<tr><td>Действие:</td>
   29.81 -<td>Устанавливает значение переменной <i>имя</i>.</td></tr>
   29.82 -
   29.83 -<tr><td>Результат:</td>
   29.84 -<td><i>имя</i></td></tr>
   29.85 -
   29.86 -<tr><td>Код возврата:</td>
   29.87 -<td>1</td></tr>
   29.88 -</table>
   29.89 -
   29.90 -<p><code><b>define</b></code></p>
   29.91 -
   29.92 -<table>
   29.93 -<tr><td>Аргументы:</td>
   29.94 -<td><i>имя</i></td></tr>
   29.95 -
   29.96 -<tr><td>Текст:</td>
   29.97 -<td><i>шаблон</i></td></tr>
   29.98 -
   29.99 -<tr><td>Действие:</td><td>Определяет новую функцию <i>имя</i>, при
  29.100 -вызове которой обрабатывается <i>шаблон</i>. При обработке доступны
  29.101 -функции <code>nextarg</code> для получения очередного аргумента
  29.102 -вызываемой функции и <code>data</code> для получения текста.</td></tr>
  29.103 -
  29.104 -<tr><td>Результат:</td>
  29.105 -<td><i>имя</i></td></tr>
  29.106 -
  29.107 -<tr><td>Код возврата:</td>
  29.108 -<td>1</td></tr>
  29.109 -</table>
  29.110 -
  29.111 -<p><code><b>load</b></code></p>
  29.112 -
  29.113 -<table>
  29.114 -<tr><td>Аргументы:</td>
  29.115 -<td><i>имя</i> <i>имя_класса</i></td></tr>
  29.116 -
  29.117 -<tr><td>Действие:</td>
  29.118 -
  29.119 -<td>Определяет новую функцию <i>имя</i>. Реализация функции определена
  29.120 -Java-классом <i>имя_класса</i>, наследующим класс
  29.121 -<code>kryshen.tema.Function</code>.</td></tr>
  29.122 -
  29.123 -<tr><td>Результат:</td>
  29.124 -<td><i>имя</i></td></tr>
  29.125 -
  29.126 -<tr><td>Код возврата:</td>
  29.127 -<td>1</td></tr>
  29.128 -</table>
  29.129 -
  29.130 -<p><code><b>prepare</b></code></p>
  29.131 -
  29.132 -<table>
  29.133 -<tr><td>Аргументы:</td>
  29.134 -<td><i>имя</i></td></tr>
  29.135 -
  29.136 -<tr><td>Текст:</td>
  29.137 -<td><i>запрос</i></td></tr>
  29.138 -
  29.139 -<tr><td>Действие:</td>
  29.140 -<td>Подготавливает SQL-запрос <i>запрос</i> для выполнения, записывает
  29.141 -подготовленный запрос в переменную <i>имя</i>.</td></tr>
  29.142 -
  29.143 -<tr><td>Результат:</td>
  29.144 -<td><i>имя</i></td></tr>
  29.145 -
  29.146 -<tr><td>Код возврата:</td>
  29.147 -<td>1</td></tr>
  29.148 -</table>
  29.149 -
  29.150 -<p><code><b>query</b></code></p>
  29.151 -
  29.152 -<table>
  29.153 -<tr><td>Аргументы:</td>
  29.154 -<td><i>имя_запроса</i> <i>шаблон</i> <i>парам1</i> ... <i>парамN</i></td></tr>
  29.155 -
  29.156 -<tr><td>Действие:</td>
  29.157 -<td>Выполняет запрос с параметрами, подготовленный с помощью функции
  29.158 -prepare. Значения параметров подставляются в запрос вместо символа
  29.159 -'?'. Значения полей ответа доступны с помощью функции <code>db</code>,
  29.160 -как переменные шаблона <i>шаблон</i>. При обработки шаблона также
  29.161 -определяется переменная <code>number</code>, содержащая номер текущей
  29.162 -строки ответа.</td></tr>
  29.163 -
  29.164 -<tr><td>Результат:</td>
  29.165 -<td>результат обработки шаблона <i>шаблон</i> для каждой строки
  29.166 -ответа.</td></tr>
  29.167 -
  29.168 -<tr><td>Код возврата:</td>
  29.169 -<td>Количество полученных строк ответа.</td></tr>
  29.170 -</table>
  29.171 -
  29.172 -<p><code><b>optional</b></code></p>
  29.173 -
  29.174 -<table>
  29.175 -<tr><td>Текст:</td>
  29.176 -<td><i>данные</i></td></tr>
  29.177 -
  29.178 -<tr><td>Результат:</td><td><i>данные</i>, если при обработке данных
  29.179 -был получен код возврата отличный от 0, иначе - пустая
  29.180 -строка.</td></tr>
  29.181 -
  29.182 -<tr><td>Код возврата:</td>
  29.183 -<td>1, если результат - пустая строка, 0 - иначе.</td></tr>
  29.184 -</table>
  29.185 -
  29.186 -<p><code><b>image</b></code></p>
  29.187 -
  29.188 -<table>
  29.189 -<tr><td>Аргументы:</td>
  29.190 -<td><i>исх_файл</i> <i>кон_файл</i> <i>формат</i> [<i>макс_ширина</i>
  29.191 -[<i>макс_высота</i>]]</td></tr>
  29.192 -
  29.193 -<tr><td>Действие:</td>
  29.194 -<td>Загружает изображение из файла <i>исх_файл</i> (путь определяется
  29.195 -относительно конфигурационного параметра "resource_base") и
  29.196 -преобразует его в указанный формат, сохраняя результат в
  29.197 -<i>кон_файл</i>. Если заданы максимальная высота и ширина, большие
  29.198 -изображения будут уменьшены.</td></tr>
  29.199 -
  29.200 -<tr><td>Результат:</td>
  29.201 -<td><i>кон_файл</i> при успешном выполнении, пустая строка - иначе.</td></tr>
  29.202 -
  29.203 -<tr><td>Код возврата:</td>
  29.204 -<td>1 при успешном выполнении, 0 - иначе.</td></tr>
  29.205 -</table>
  29.206 -
  29.207 -
  29.208 -<p><code><b>copy</b></code></p>
  29.209 -
  29.210 -<table>
  29.211 -<tr><td>Аргументы:</td><td><i>исх_файл</i> <i>кон_файл</i></td></tr>
  29.212 -
  29.213 -<tr><td>Действие:</td><td>Копирует файл <i>исх_файл</i> в файл
  29.214 -<i>кон_файл</i> (путь <i>исх_файл</i> определяется относительно
  29.215 -конфигурационного параметра "resource_base").</td></tr>
  29.216 -
  29.217 -<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении,
  29.218 -пустая строка - иначе.</td></tr>
  29.219 -
  29.220 -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  29.221 -иначе.</td></tr>
  29.222 -</table>
  29.223 -
  29.224 -<p><code><b>write</b></code></p>
  29.225 -
  29.226 -<table>
  29.227 -<tr><td>Аргументы:</td><td><i>имя_файла</i></td></tr>
  29.228 -
  29.229 -<tr><td>Текст:</td><td><i>данные</i></td></tr>
  29.230 -
  29.231 -<tr><td>Действие:</td><td>Записывает <i>данные</i> в файл
  29.232 -<i>исх_файл</i>.</td></tr>
  29.233 -
  29.234 -<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении,
  29.235 -пустая строка - иначе.</td></tr>
  29.236 -
  29.237 -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  29.238 -иначе.</td></tr>
  29.239 -</table>
  29.240 -
  29.241 -<p><code><b>read</b></code></p>
  29.242 -
  29.243 -<table>
  29.244 -<tr><td>Текст:</td><td><i>имя_файла</i></td></tr>
  29.245 -<tr><td>Действие:</td><td>Читает файл <i>имя_файла</i>.</td></tr>
  29.246 -<tr><td>Результат:</td><td>прочитанные данные при успешном выполнении,
  29.247 -  пустая строка - иначе.</td></tr>
  29.248 -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  29.249 -иначе.</td></tr>
  29.250 -</table>
  29.251 -
  29.252 -<p><code><b>include</b></code></p>
  29.253 -
  29.254 -<table>
  29.255 -<tr><td>Текст:</td><td><i>имя_файла</i></td></tr>
  29.256 -<tr><td>Действие:</td><td>включает шаблон из файла
  29.257 -<i>имя_файла</i>.</td></tr>
  29.258 -<tr><td>Результат:</td><td>результат обработки шаблона.</td></tr>
  29.259 -<tr><td>Код возврата:</td><td>код возврата, полученный при обработке
  29.260 -шаблона.</td></tr>
  29.261 -</table>
  29.262 -
  29.263 -<p><code><b>!</b></code></p>
  29.264 -
  29.265 -<table>
  29.266 -<tr><td>Текст:</td><td><i>данные</i></td></tr>
  29.267 -
  29.268 -<tr><td>Действие:</td><td>нет.</td></tr>
  29.269 -
  29.270 -<tr><td>Результат:</td><td>нет.</td></tr>
  29.271 -
  29.272 -<tr><td>Код возврата:</td><td>код возврата, полученный при обработке
  29.273 -текста данных.</td></tr>
  29.274 -</table>
  29.275 -
  29.276 -<p><code><b>replace</b></code></p>
  29.277 -
  29.278 -<table>
  29.279 -<tr><td>Аргументы:</td><td><i>стр1</i> <i>стр2</i></td></tr>
  29.280 -
  29.281 -<tr><td>Текст:</td><td><i>данные</i></td></tr>
  29.282 -
  29.283 -<tr><td>Результат:</td><td>данные, с замененными вхождениями подстроки
  29.284 -<i>стр1</i> на <i>стр2</i>.</td></tr>
  29.285 -
  29.286 -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  29.287 -текста данных.</td></tr>
  29.288 -</table>
  29.289 -
  29.290 -<p><code><b>xml_escape</b></code></p>
  29.291 -
  29.292 -<table>
  29.293 -<tr><td>Текст:</td><td><i>данные</i></td></tr>
  29.294 -<tr><td>Результат:</td><td>текст <i>данные</i>, в котором символы
  29.295 -'&amp;', '&lt;', '&gt;', '`', '\' заменены на соответствующие сущности
  29.296 -XML.</td></tr>
  29.297 -
  29.298 -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  29.299 -текста данных.</td></tr>
  29.300 -</table>
  29.301 -
  29.302 -<p><code><b>xml_cdata</b></code></p>
  29.303 -
  29.304 -<table>
  29.305 -<tr><td>Текст:</td><td><i>данные</i></td></tr>
  29.306 -
  29.307 -<tr><td>Результат:</td><td>данные в виде блока XML CDATA.</td></tr>
  29.308 -
  29.309 -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  29.310 -текста данных.  </td></tr>
  29.311 -</table>
  29.312 -
  29.313 -<p>
  29.314 -Макропроцессор TEMA расширяем: возможно добавление в систему новых
  29.315 -функций, реализованных в виде классов на языке Java.
  29.316 -</p>
  29.317 -
  29.318 -<h2>Запуск</h2>
  29.319 -
  29.320 -<p>java -jar tema.jar [<i>опции</i>]
  29.321 -</p><p>
  29.322 -Опции:
  29.323 -</p>
  29.324 -<table>
  29.325 -<tr><td>-d[emo]</td><td>Демонстрационный режим</td></tr>
  29.326 -<tr><td>-v[ersion]</td><td>Вывод версии</td></tr>
  29.327 -<tr><td>-h[help] -u[sage]</td><td>Вывод справки</td></tr>
  29.328 -</table>
  29.329 -
  29.330 -<p>
  29.331 -При запуске читается файл "tema.properties" из текущего каталога.<br />
  29.332 -Пример файла "tema.properties":
  29.333 -</p>
  29.334 -
  29.335 -<pre>
  29.336 -# Настройка источника данных
  29.337 -# resource          : jdbc:odbc:database
  29.338 -# driver            : sun.jdbc.odbc.JdbcOdbcDriver
  29.339 -
  29.340 -# Базовый каталог ресурсов
  29.341 -# resource_base     : .
  29.342 -
  29.343 -# Шаблон, с которого начинается обработка
  29.344 -main_template     : main.template
  29.345 -
  29.346 -# Кодировки файлов
  29.347 -# input_encoding    : UTF-8
  29.348 -# output_encoding   : UTF-8
  29.349 -
  29.350 -# Кэширование шаблонов
  29.351 -# cache_read        : true
  29.352 -
  29.353 -# Вывод результата разбора шаблона main.template в stderr
  29.354 -# output            : stderr
  29.355 -
  29.356 -# Вывод сообщений об ошибках в файл
  29.357 -# log               : dbreader.log
  29.358 -</pre>
  29.359 -
  29.360 -</body>
  29.361 -</html>
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/doc/manual/manual.tema	Tue Feb 19 20:32:17 2008 +0300
    30.3 @@ -0,0 +1,253 @@
    30.4 +[%!\
    30.5 +  Tema User Manual.
    30.6 +%]\\
    30.7 +
    30.8 +<%silent include:document.tema%>\\
    30.9 +
   30.10 +<%document:
   30.11 +  title    <%:Tema -- template macro processor%>
   30.12 +  author   <%:Mikhail Kryshen%>
   30.13 +  content
   30.14 +
   30.15 +<%section:Introduction%>
   30.16 +
   30.17 +<%par:Tema is a macro processor and template engine. It reads the input file 
   30.18 +recursively expanding any macro found in the text.%>
   30.19 +
   30.20 +<%par:Distinctive features:%>
   30.21 +<%itemize:
   30.22 +  <%:Extensible: implement new functions as Java classes.%>
   30.23 +  <%:Database access.%>
   30.24 +  <%:Processes and outputs data as early as possible (function could start 
   30.25 +     to output data before all it's arguments are read and parsed).%>
   30.26 +  <%:Apache Ant integration.%>
   30.27 +%>
   30.28 +
   30.29 +<%par:Tema macro has the following syntax:%>
   30.30 +
   30.31 +<%par:[%code\<%function_list{:|#|\|`}[escape]text%>[escape]%]%>
   30.32 +
   30.33 +<%par:<%code:function_list%> is the list of text-processing functions.
   30.34 +Functions will be applied to text in reverse order.%>
   30.35 +
   30.36 +<%par:<%code:text%> could contain space-separated list of arguments 
   30.37 +followed by arbitrary data. Number of arguments is determined by the last
   30.38 +function in the <%code:function_list%>.%>
   30.39 +
   30.40 +<%par:<%code\[arg1 arg2...] [data]%>%>
   30.41 +
   30.42 +<%par:The text is separated from the list of functions by one of the 
   30.43 +following characters:%>
   30.44 +
   30.45 +<%itemize:
   30.46 +  <%\':' -- process text recursively.%>
   30.47 +  <%\'#' -- parse text but do not replace any embedded macro.%>
   30.48 +  <%\'\', '`' -- do not parse text (ignore any '<%' sequences).%>
   30.49 +%>
   30.50 +
   30.51 +<%par:<%code:escape%> is either '\' or '\\':%>
   30.52 +
   30.53 +<%itemize:
   30.54 +  <%:<%:\%> -- the following newline symbol will be removed;%>
   30.55 +  <%:<%:\\%> -- the following sequence of the whitespace characters will be removed.%>
   30.56 +%>
   30.57 +
   30.58 +<%par:You could use <%\'[%' and '%]'%> character sequences to denote macro
   30.59 +as an alternative to [%\'<%' and '%>'%].%>
   30.60 +
   30.61 +<%par:Every function returns integer value. The general convention is to 
   30.62 +return non-zero for successful operation. The value of the macro substitution 
   30.63 +is the return value of the first function in the function list. The value of
   30.64 +any Tema text is the sum value of all macro in the text, except the value of
   30.65 +the text without any macro equals -1.%>
   30.66 +
   30.67 +<%par:Internally, Tema function could be represented by any Java object.
   30.68 +Instances of kryshen.tema.Function and kryshen.tema.Context are handled
   30.69 +specially. For any other type of object, function output would be the value 
   30.70 +returned by the method <%code:toString()%>.%>
   30.71 +
   30.72 +<%section:Built-in functions%>
   30.73 +
   30.74 +<%par emph:Notice: some functions are not yet described in this manual.
   30.75 +For the complete list of built-in functions refer to the API documentation
   30.76 +and source code.%>
   30.77 +
   30.78 +<%function:tema
   30.79 +  output  <%:Tema version%>
   30.80 +%>
   30.81 +
   30.82 +<%function:echo  
   30.83 +  output  <%:function data%>
   30.84 +%>
   30.85 +
   30.86 +<%function:!
   30.87 +  output      nothing
   30.88 +  description <%:Ignores the input text (':' separator works as '#').
   30.89 +    Use for commenting (e.g. <%code\[%!\ comment %]%>).%>
   30.90 +%>
   30.91 +
   30.92 +<%function:silent  
   30.93 +  output  nothing
   30.94 +%>
   30.95 +
   30.96 +<%function:set
   30.97 +  arguments   <%:definition name%>
   30.98 +  input_data  <%:variable value%>
   30.99 +  output      <%:function data%>
  30.100 +  description <%:Defines new function as a static variable.%>
  30.101 +%>
  30.102 +
  30.103 +<%function:define
  30.104 +  arguments   <%:name, code%>
  30.105 +  description <%:\\
  30.106 +    Defines new function. 
  30.107 +    Use <%code:next_arg%>, <%code:data%>, and <%code:has_more_data%> 
  30.108 +    functions to access function arguments.%>
  30.109 +  output      <%:name%> 
  30.110 +%>
  30.111 +
  30.112 +[%!\ TODO: next_arg, data, has_more_data %]\\
  30.113 +
  30.114 +<%function:export
  30.115 +  arguments   <%:definition name%>
  30.116 +  input_data  <%:static variable value (optional)%>
  30.117 +  output      <%:function data%>
  30.118 +  description <%:Exports the definition to the global (outermost) context.%>
  30.119 +%>
  30.120 +
  30.121 +<%function:unset
  30.122 +  arguments   <%:def1, def2, ...%>
  30.123 +  output      <%:nothing%>
  30.124 +  description <%:Unsets the definitions.%>
  30.125 +%>
  30.126 +
  30.127 +<%function:invoke
  30.128 +  arguments   <%:function, arg1, arg2, ..., data%>
  30.129 +  output      <%:function output%>
  30.130 +  description <%:Invokes function.%>
  30.131 +%>
  30.132 +
  30.133 +<%function:load
  30.134 +  arguments   <%:name, class, url1, url2, ...%>
  30.135 +  output      <%:name%>
  30.136 +  description <%:Instantiate specified class as a Tema function definition.
  30.137 +    URL arguments are optional.%>
  30.138 +%>
  30.139 +
  30.140 +<%function:super
  30.141 +  input_data  <%:code%>
  30.142 +  output      <%:output generated by the code%>
  30.143 +  description <%:Evaluates the specified template code in the super-context
  30.144 +    (i.e. context of the calling function or context executing 
  30.145 +    the database query).%>
  30.146 +%>
  30.147 +
  30.148 +<%function:replace
  30.149 +  arguments   <%:s1, s2, data%>
  30.150 +  description <%:\\
  30.151 +    Replaces all occurrences of <%code:s1%> with <%code:s2%> in data.%>
  30.152 +%>
  30.153 +
  30.154 +[%!\ TODO: all functions defined in Strings.java %]\\
  30.155 +
  30.156 +<%subsection:Input / output%>
  30.157 +
  30.158 +<%function:copy
  30.159 +  arguments   <%:src, dest%>
  30.160 +  description <%:Copies file <%code:src%> to <%code:dest%>.%>
  30.161 +  output      <%:dest%> 
  30.162 +%>
  30.163 +
  30.164 +<%function:write
  30.165 +  arguments   <%:name%>
  30.166 +  input_data  <%:text%>
  30.167 +  description <%:Writes text to file.%> 
  30.168 +  output      <%:name%>
  30.169 +%>
  30.170 +
  30.171 +<%function:read
  30.172 +  arguments   <%:name%>
  30.173 +  description <%:Reads file.%> 
  30.174 +  output      <%:File contents.%>
  30.175 +%>
  30.176 +
  30.177 +<%function:include
  30.178 +  arguments   <%:name%>
  30.179 +  description <%:Includes template.%> 
  30.180 +  output      <%:Result of processing the template.%>
  30.181 +%>
  30.182 +
  30.183 +<%function:file
  30.184 +  arguments   <%:base, name%>
  30.185 +  output      <%:Path constructed from the base directory and file name.%> 
  30.186 +%>
  30.187 +
  30.188 +<%subsection:Conditionals%>
  30.189 +
  30.190 +<%function:optional
  30.191 +  input_data  <%:text%>
  30.192 +  output      <%:Function data if it's value is non-zero or empty text.%>
  30.193 +%>
  30.194 +
  30.195 +<%function:while
  30.196 +  input_data  <%:code%>
  30.197 +  description <%:Repeatedly outputs it's evaluated data while it has non-zero value.%>
  30.198 +%>
  30.199 +
  30.200 +[%!\ TODO: all functions defined in Control.java %]\\
  30.201 +
  30.202 +<%subsection:Database%>
  30.203 +
  30.204 +<%function:db_connect
  30.205 +  arguments   <%:connection name%>
  30.206 +  input_data  <%:resource%>
  30.207 +  description <%:Establishes connection with the database.
  30.208 +    Load the appropriate database driver using the <%code:load%> function
  30.209 +    before using <%code:db_connect%> 
  30.210 +    (e.g. [%code\<%load:driver sun.jdbc.odbc.JdbcOdbcDriver%>%]).%>
  30.211 +%>
  30.212 +
  30.213 +<%function:db_prepare
  30.214 +  arguments   <%:query name, connection name%>
  30.215 +  input_data  <%:SQL statement%>
  30.216 +%>
  30.217 +
  30.218 +<%function:db_query
  30.219 +  arguments   <%:query, template, arg1, arg2, ...%>
  30.220 +  description <%:Executes query, evaluating the template for each result row.%>
  30.221 +%>
  30.222 +
  30.223 +<%function:db
  30.224 +  input_data  <%:column name%>
  30.225 +  output      <%:value from the query result.%>
  30.226 +  description <%:Available in the template for the <%code:db_query%> function.%>  
  30.227 +%>
  30.228 +
  30.229 +<%function:db_row
  30.230 +  output      <%:current row number in the result set.%>
  30.231 +  description <%:Available in the template for the <%code:db_query%> function.%>  
  30.232 +%>
  30.233 +
  30.234 +[%!\ TODO: all functions defined in ImageConverter.java %]\\
  30.235 +
  30.236 +<%section:Running Tema%>
  30.237 +
  30.238 +<%par:Change to the dist subdirectory in the distribution package and
  30.239 +issue the following command:%>
  30.240 +
  30.241 +<%par:<%code:java -jar tema.jar [options] [files]%>%>
  30.242 +
  30.243 +<%par:The following options are recognized:%>
  30.244 +<%itemize:
  30.245 +  <%:<%code:--demo%> --- run demo console with a code example;%>
  30.246 +  <%:<%code:-h, --help%> --- print help message;%>
  30.247 +  <%:<%code:--input-encoding <arg>%> --- set the input encoding;%>
  30.248 +  <%:<%code:--log <arg>%> --- log all error messages to the specified file;%>
  30.249 +  <%:<%code:-o, --output <arg>%> --- set the output file;%>
  30.250 +  <%:<%code:--output-encoding <arg>%> --- set the output encoding;%>
  30.251 +  <%:<%code:-v, --version%> --- print the version information and exit.%>
  30.252 +%>
  30.253 +
  30.254 +<%section:Homepage%>
  30.255 +
  30.256 +<%par link:http://kryshen.pp.ru/tema/%>
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/misc/biotopes/biotope-top.sql	Tue Feb 19 20:32:17 2008 +0300
    31.3 @@ -0,0 +1,20 @@
    31.4 +SELECT t1.*,
    31.5 +
    31.6 +(SELECT t2.rusname FROM biotopelist AS t2
    31.7 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND
    31.8 +Right(t2.rangcode, 8) = '00000000') AS class0,
    31.9 +
   31.10 +(SELECT t2.rusname FROM biotopelist AS t2
   31.11 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND
   31.12 +Right(t2.rangcode, 6) = '000000') AS class1,
   31.13 +
   31.14 +(SELECT t2.rusname FROM biotopelist AS t2
   31.15 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND
   31.16 +Right(t2.rangcode, 4) = '0000') AS class2,
   31.17 +
   31.18 +(SELECT t2.rusname FROM biotopelist AS t2
   31.19 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND
   31.20 +Right(t2.rangcode, 2) = '00') AS class3
   31.21 +
   31.22 +FROM biotopelist AS t1
   31.23 +WHERE Right(t1.rangcode, 2) <> '00' AND rusname
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/misc/biotopes/biotope.sql	Tue Feb 19 20:32:17 2008 +0300
    32.3 @@ -0,0 +1,24 @@
    32.4 +SELECT t1.*,
    32.5 +
    32.6 +(SELECT t2.rusname FROM biotopelist AS t2
    32.7 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
    32.8 +AND Right(t2.rangcode, 8)  = '00000000'
    32.9 +AND Right(t1.rangcode, 8) <> '00000000') AS class0,
   32.10 +
   32.11 +(SELECT t2.rusname FROM biotopelist AS t2
   32.12 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
   32.13 +AND Right(t2.rangcode, 6)  = '000000'
   32.14 +AND Right(t1.rangcode, 6) <> '000000') AS class1,
   32.15 +
   32.16 +(SELECT t2.rusname FROM biotopelist AS t2
   32.17 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
   32.18 +AND Right(t2.rangcode, 4)  = '0000'
   32.19 +AND Right(t1.rangcode, 4) <> '0000') AS class2,
   32.20 +
   32.21 +(SELECT t2.rusname FROM biotopelist AS t2
   32.22 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
   32.23 +AND Right(t2.rangcode, 2)  = '00'
   32.24 +AND Right(t1.rangcode, 2) <> '00') AS class3
   32.25 +
   32.26 +FROM biotopelist AS t1
   32.27 +WHERE rusname
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/misc/biotopes/biotope.template	Tue Feb 19 20:32:17 2008 +0300
    33.3 @@ -0,0 +1,17 @@
    33.4 +<?xml version="1.0" encoding="ISO-8859-5"?>
    33.5 +<!DOCTYPE _ SYSTEM "brief.dtd">
    33.6 +<!-- rangcode: <%xml_escape db\rangcode%> -->
    33.7 +<_ show="0">
    33.8 +  < display="0">
    33.9 +    <%optional:<_ ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\code%>.png png%>"/>%>
   33.10 +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
   33.11 +  </>
   33.12 +  <><%xml_escape db\rusname%></>
   33.13 +  <><%xml_escape db\class0%></>
   33.14 +  <1><%xml_escape db\class1%></1>
   33.15 +  <2><%xml_escape db\class2%></2>
   33.16 +  <3><%xml_escape db\class3%></3>
   33.17 +  <_ rows="3"><%xml_cdata db\descript%></_>
   33.18 +  <_ rows="3"><%xml_cdata db\geobotdescr%></_>
   33.19 +  <_><%xml_escape db\contributors%></_>
   33.20 +</_>
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/misc/biotopes/brief.dtd	Tue Feb 19 20:32:17 2008 +0300
    34.3 @@ -0,0 +1,27 @@
    34.4 +<?xml encoding="ISO-8859-5"?>
    34.5 +<!ELEMENT _ (?, , , 1, 2, 3, _, _, _)>
    34.6 +<!ELEMENT  (|_)*>
    34.7 +<!ELEMENT  EMPTY>
    34.8 +<!ELEMENT _ EMPTY>
    34.9 +<!ELEMENT  (#PCDATA)>
   34.10 +<!ELEMENT  (#PCDATA)>
   34.11 +<!ELEMENT 1 (#PCDATA)>
   34.12 +<!ELEMENT 2 (#PCDATA)>
   34.13 +<!ELEMENT 3 (#PCDATA)>
   34.14 +<!ELEMENT _ (#PCDATA)>
   34.15 +<!ELEMENT _ (#PCDATA)>
   34.16 +<!ELEMENT _ (#PCDATA)>
   34.17 +<!ATTLIST _ show (0|1) "1"> 
   34.18 +<!ATTLIST 
   34.19 +	display CDATA #FIXED "0">
   34.20 +<!ATTLIST 
   34.21 +	num ID #REQUIRED
   34.22 +	file CDATA #REQUIRED
   34.23 +	big CDATA #REQUIRED
   34.24 +	text CDATA #IMPLIED
   34.25 +	 CDATA #IMPLIED>
   34.26 +<!ATTLIST _
   34.27 +	num ID #REQUIRED
   34.28 +	file CDATA #REQUIRED>
   34.29 +<!ATTLIST _ rows CDATA #FIXED "3">
   34.30 +<!ATTLIST _ rows CDATA #FIXED "3">
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/misc/biotopes/class.sql	Tue Feb 19 20:32:17 2008 +0300
    35.3 @@ -0,0 +1,7 @@
    35.4 +SELECT t1.*
    35.5 +FROM biotopelist AS t1
    35.6 +WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
    35.7 +  AND EXISTS
    35.8 +    (SELECT NULL FROM biotopelist AS t2
    35.9 +     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
   35.10 +     AND Right(t2.rangcode, 8) <> '00000000')
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/misc/biotopes/classes.template	Tue Feb 19 20:32:17 2008 +0300
    36.3 @@ -0,0 +1,5 @@
    36.4 +<?xml version="1.0" encoding="ISO-8859-5"?>
    36.5 +<><%query:class_sql [%\
    36.6 +  <!-- rangcode: <%xml_escape get\rangcode%> -->
    36.7 +  < id="<%get\NUMBER%>"><%xml_escape db\rusname%></>%]%>
    36.8 +</>
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/misc/biotopes/doc/article.txt	Tue Feb 19 20:32:17 2008 +0300
    37.3 @@ -0,0 +1,391 @@
    37.4 +*     XML-  .
    37.5 +
    37.6 +      " 
    37.7 +"   Microsoft Access  XML- 
    37.8 +       DbReader.
    37.9 +
   37.10 + DbReader     
   37.11 +      .  
   37.12 +        
   37.13 +    .   
   37.14 + SQL-,     
   37.15 +.
   37.16 +
   37.17 +
   37.18 +*  :
   37.19 +
   37.20 +    <%<_>{:|\}<>%>
   37.21 +   
   37.22 +
   37.23 +<_> -   ,  .
   37.24 +      .
   37.25 +<> - ,  .
   37.26 +
   37.27 +
   37.28 +*  :
   37.29 +
   37.30 +    [<_>][<>]
   37.31 +  
   37.32 +
   37.33 +<_> -   ,  .
   37.34 +      .
   37.35 +<> - ,      .
   37.36 +      .  ,   
   37.37 +    ,   .
   37.38 +
   37.39 +      ,  
   37.40 +  :
   37.41 +: -  ,
   37.42 +\ -   .
   37.43 +
   37.44 +        ,  ,
   37.45 +  ,        
   37.46 +   .
   37.47 +
   37.48 +     -  .  
   37.49 + -      .  ,
   37.50 +    -    
   37.51 +.
   37.52 +
   37.53 +  '<', '>'    '[', ']'.
   37.54 +
   37.55 +
   37.56 +*  :
   37.57 +
   37.58 +:      set
   37.59 +:    <>
   37.60 +:        <>
   37.61 +:        <>
   37.62 +:    <>
   37.63 + : 1
   37.64 +
   37.65 +:      get
   37.66 +:    <>
   37.67 +:      <>. 
   37.68 + : 1,     , 0 - .
   37.69 +
   37.70 +:      prepare
   37.71 +:    <>
   37.72 +:        <>
   37.73 +:      SQL- <>  ,
   37.74 +                   <>.
   37.75 +:    <>
   37.76 + : 1
   37.77 +
   37.78 +:      query
   37.79 +:    <_> <> <1> ... <N>
   37.80 +:        ,   
   37.81 +               prepare.    
   37.82 +                 '?'.    
   37.83 +              ,    <>.  
   37.84 +               <>    NUMBER,
   37.85 +                  . ,
   37.86 +                 ,   
   37.87 +              <>   SUPER.<_>.
   37.88 +
   37.89 +:       <>   
   37.90 +              .
   37.91 + :    .
   37.92 +
   37.93 +:      optional
   37.94 +:        <>
   37.95 +:    <>,      
   37.96 +                  0,  -  .
   37.97 + : 1,   -  , 0 - .
   37.98 +
   37.99 +:      image
  37.100 +:    <_> <_> <> [<_> [<_>]]
  37.101 +:         <_> ( 
  37.102 +                 "resource_base") 
  37.103 +                  ,   
  37.104 +              <_>.      , 
  37.105 +                . 
  37.106 +:    <_>   ,   - .
  37.107 + : 1   , 0 - .
  37.108 +
  37.109 +:      copy
  37.110 +:    <_> <_>
  37.111 +:       <_>   <_>
  37.112 +	      ( <_>  
  37.113 +                "resource_base").
  37.114 +:    <_>   ,   - .
  37.115 + : 1   , 0 - .
  37.116 +
  37.117 +:      write
  37.118 +:    <_>
  37.119 +:        <>
  37.120 +:      <>   <_>.
  37.121 +:    <_>   ,   - .
  37.122 + : 1   , 0 - .
  37.123 +
  37.124 +:      read
  37.125 +:        <_>
  37.126 +:       <_>.
  37.127 +:        , 
  37.128 +               - .
  37.129 + : 1   , 0 - .
  37.130 +
  37.131 +:      include
  37.132 +:        <_>
  37.133 +:         <_>.
  37.134 +:      .
  37.135 + :  ,    .
  37.136 +
  37.137 +:      !
  37.138 +:        <>
  37.139 +:     .
  37.140 +:    .
  37.141 + :  ,     .
  37.142 +
  37.143 +:      replace
  37.144 +:    <1> <2>
  37.145 +:        <>
  37.146 +:    ,     <1>
  37.147 +	       <2>.
  37.148 + :  ,     .
  37.149 +
  37.150 +:      xml_escape
  37.151 +:        <>
  37.152 +:     <>,    
  37.153 +              '&', '<', '>', '`', '\'   
  37.154 +	       XML.
  37.155 + :  ,     .
  37.156 +
  37.157 +:      xml_cdata
  37.158 +:        <>
  37.159 +:        XML CDATA.
  37.160 + :  ,     .
  37.161 +
  37.162 + DbReader :     
  37.163 +,       Java.
  37.164 +
  37.165 +
  37.166 +*   DbReader    
  37.167 +  "  "   Microsoft Access 
  37.168 +  XML-    
  37.169 +
  37.170 +       "
  37.171 + " (   ):
  37.172 +
  37.173 +biotopelist (code, rangcode, rusname, engname, descript, geobotdescr,
  37.174 +             contributors, descrdate)
  37.175 +
  37.176 +  code - ,  ;
  37.177 +  rangcode -    ABBCCDDEE,  , BB, CC, DD,  - 
  37.178 +             ,   ;
  37.179 +  rusname, engname, descript, geobotdescr -  ;
  37.180 +  descrdate - .
  37.181 +
  37.182 +photos (biotope, photo, authphoto)
  37.183 +
  37.184 +  biotope - ,   code  biotopelist;
  37.185 +  photo -   ;
  37.186 +  authphoto - .
  37.187 +
  37.188 +  xml-     biotopelist, 
  37.189 +  ,    ,  
  37.190 +   .
  37.191 +
  37.192 +  xml-     
  37.193 + DbReader ( biotope.template):
  37.194 +
  37.195 +----------------------------------------------------------------------
  37.196 +<?xml version="1.0" encoding="ISO-8859-5"?>
  37.197 +<!DOCTYPE _ SYSTEM "brief.dtd">
  37.198 +<!-- rangcode: <%xml_escape get\rangcode%> -->
  37.199 +<_ show="0">
  37.200 +  < display="0">
  37.201 +    <%optional:<_ ="1"
  37.202 +    file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%>
  37.203 +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%>
  37.204 +  </>
  37.205 +  <><%xml_escape get\rusname%></>
  37.206 +  <><%xml_escape get\class0%></>
  37.207 +  <1><%xml_escape get\class1%></1>
  37.208 +  <2><%xml_escape get\class2%></2>
  37.209 +  <3><%xml_escape get\class3%></3>
  37.210 +  <_ rows="3"><%xml_cdata get\descript%></_>
  37.211 +  <_ rows="3"><%xml_cdata get\geobotdescr%></_>
  37.212 +  <_><%xml_escape get\contributors%></_>
  37.213 +</_>
  37.214 +----------------------------------------------------------------------
  37.215 +
  37.216 + SQL-,    
  37.217 +   rangcode, rusname, class0, class1, class2,
  37.218 +class3, descript, geobotdescr  contributors ( biotope.sql):
  37.219 +
  37.220 +----------------------------------------------------------------------
  37.221 +SELECT t1.*,
  37.222 +
  37.223 +(SELECT t2.rusname FROM biotopelist AS t2
  37.224 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  37.225 +AND Right(t2.rangcode, 8)  = '00000000'
  37.226 +AND Right(t1.rangcode, 8) <> '00000000') AS class0,
  37.227 +
  37.228 +(SELECT t2.rusname FROM biotopelist AS t2
  37.229 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3)
  37.230 +AND Right(t2.rangcode, 6)  = '000000'
  37.231 +AND Right(t1.rangcode, 6) <> '000000') AS class1,
  37.232 +
  37.233 +(SELECT t2.rusname FROM biotopelist AS t2
  37.234 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5)
  37.235 +AND Right(t2.rangcode, 4)  = '0000'
  37.236 +AND Right(t1.rangcode, 4) <> '0000') AS class2,
  37.237 +
  37.238 +(SELECT t2.rusname FROM biotopelist AS t2
  37.239 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7)
  37.240 +AND Right(t2.rangcode, 2)  = '00'
  37.241 +AND Right(t1.rangcode, 2) <> '00') AS class3
  37.242 +
  37.243 +FROM biotopelist AS t1
  37.244 +WHERE rusname
  37.245 +----------------------------------------------------------------------
  37.246 +
  37.247 + biotope.template   <%include\photo.template%>,
  37.248 +    ( photo.template):
  37.249 +
  37.250 +----------------------------------------------------------------------
  37.251 +    < num="<%xml_escape get\NUMBER%>"
  37.252 +       <%optional:="<%xml_escape get\authphoto%>" %>text="" 
  37.253 +       file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" 
  37.254 +        big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/>
  37.255 +----------------------------------------------------------------------
  37.256 +
  37.257 + SQL-    
  37.258 +(photo.sql):
  37.259 +
  37.260 +----------------------------------------------------------------------
  37.261 +SELECT * from photos WHERE biotope = ?
  37.262 +----------------------------------------------------------------------
  37.263 +
  37.264 +,    ( classes.template):
  37.265 +
  37.266 +----------------------------------------------------------------------
  37.267 +<?xml version="1.0" encoding="ISO-8859-5"?>
  37.268 +<><%query:class_sql [%\
  37.269 +  <!-- rangcode: <%xml_escape get\rangcode%> -->
  37.270 +  < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%>
  37.271 +</>
  37.272 +----------------------------------------------------------------------
  37.273 +
  37.274 + SQL- (class.sql):
  37.275 +
  37.276 +----------------------------------------------------------------------
  37.277 +SELECT t1.*
  37.278 +FROM biotopelist AS t1
  37.279 +WHERE rusname AND Right(t1.rangcode, 8)  = '00000000'
  37.280 +  AND EXISTS
  37.281 +    (SELECT NULL FROM biotopelist AS t2
  37.282 +     WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1)
  37.283 +     AND Right(t2.rangcode, 8) <> '00000000')
  37.284 +----------------------------------------------------------------------
  37.285 +
  37.286 +,    ( plants.template):
  37.287 +
  37.288 +----------------------------------------------------------------------
  37.289 +<?xml version="1.0" encoding="ISO-8859-5"?>
  37.290 +<><%query:plant_sql [%\
  37.291 +  <!-- rangcode: <%xml_escape get\rangcode%> -->
  37.292 +  <><%xml_escape get\rusname%></>%]%>
  37.293 +</>
  37.294 +----------------------------------------------------------------------
  37.295 +
  37.296 + SQL- (plant.sql):
  37.297 +
  37.298 +----------------------------------------------------------------------
  37.299 +SELECT t1.*
  37.300 +FROM biotopelist AS t1
  37.301 +WHERE rusname AND Right(t1.rangcode, 2) <> '00'
  37.302 +----------------------------------------------------------------------
  37.303 +
  37.304 + DbReader      index.template,
  37.305 +     SQL-  
  37.306 +:
  37.307 +
  37.308 +----------------------------------------------------------------------
  37.309 +<%!:
  37.310 +  <%prepare:biotope_sql <%read\biotope.sql%>%>
  37.311 +  <%prepare:photo_sql <%read\photo.sql%>%>
  37.312 +  <%prepare:class_sql <%read\class.sql%>%>
  37.313 +  <%prepare:plant_sql <%read\plant.sql%>%>
  37.314 +
  37.315 +  <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%>
  37.316 +
  37.317 +  <%write:classes.xml <%include\classes.template%>%>
  37.318 +  <%write:plants.xml <%include\plants.template%>%>
  37.319 +%>
  37.320 +----------------------------------------------------------------------
  37.321 +
  37.322 +  XML-:
  37.323 +
  37.324 +----------------------------------------------------------------------
  37.325 +<?xml version="1.0" encoding="ISO-8859-5"?>
  37.326 +<!DOCTYPE _ SYSTEM "brief.dtd">
  37.327 +<!-- rangcode: E04020302 -->
  37.328 +<_ show="0">
  37.329 +  < display="0">    
  37.330 +    < num="1" =" .." text="" 
  37.331 +                file="images/3_1.jpg" 
  37.332 +                big="images/big/3_1.jpg"/>
  37.333 +    < num="2" =" .." text="" 
  37.334 +                file="images/3_2.jpg" 
  37.335 +                big="images/big/3_2.jpg"/>
  37.336 +  </>
  37.337 +  <>Betula sp. - Avenella flexuosa - Polytrichum commune</>
  37.338 +  <>E.  </>
  37.339 +  <1> </1>
  37.340 +  <2></2>
  37.341 +  <3></3>
  37.342 +  <_ rows="3"><![CDATA[       .   5 - 7            ,   ,   ,   .]]></_>
  37.343 +  <_ rows="3"></_>
  37.344 +  <_></_>
  37.345 +</_>
  37.346 +----------------------------------------------------------------------
  37.347 +
  37.348 +
  37.349 +*   DbReader
  37.350 +
  37.351 + DbReader     Java  
  37.352 +   :
  37.353 +
  37.354 +ru.karrc.dbreader.DbReader: c   . 
  37.355 +,       
  37.356 + JDBC,    .
  37.357 +
  37.358 +ru.karrc.dbreader.TemplateParser:   ,
  37.359 +    .
  37.360 +
  37.361 +ru.karrc.dbreader.Function:  .   
  37.362 +DbReader   .
  37.363 +
  37.364 +ru.karrc.dbreader.FunctionDataParser:  
  37.365 +.      , 
  37.366 +.       
  37.367 + TemplateParser.
  37.368 +
  37.369 +ru.karrc.dbreader.Functions:     
  37.370 + ,  Function.
  37.371 +
  37.372 +ru.karrc.dbreader.TemplateParser: ,   
  37.373 +    .
  37.374 +
  37.375 + ,    , 
  37.376 +    .
  37.377 +
  37.378 +
  37.379 +*    .
  37.380 +
  37.381 +   : 8,
  37.382 + Java- ( ): 27,
  37.383 +    : 1311,
  37.384 +   (    ): 812,
  37.385 +  : 180.
  37.386 +
  37.387 +
  37.388 +* 
  37.389 +
  37.390 +     DbReader, 
  37.391 +      
  37.392 +      .   
  37.393 +DbReader   "  " 
  37.394 +  XML-    .
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/misc/biotopes/doc/readme.html	Tue Feb 19 20:32:17 2008 +0300
    38.3 @@ -0,0 +1,86 @@
    38.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    38.5 +          "DTD/xhtml1-transitional.dtd">
    38.6 +
    38.7 +<html>
    38.8 +
    38.9 +<head>
   38.10 +  <title>DbReader</title>
   38.11 +  <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" />
   38.12 +</head>
   38.13 +
   38.14 +<body>
   38.15 +<h1>DbReader</h1>
   38.16 +
   38.17 +<h2> </h2>
   38.18 +<ol>
   38.19 +<li> .</li>
   38.20 +
   38.21 +<li>  :<br />
   38.22 + Windows 2000:  //  (ODBC),  biotopes-data.mdb.</li>
   38.23 +
   38.24 +<li> :<br />
   38.25 +  dbreader.properties  ,   :<br />
   38.26 +    <code>resource: jdbc:odbc:<em></em></code><br />
   38.27 +   ,       ( biotopephotos  maps):<br />
   38.28 +    <code>resource_base: C:\\biotopes</code><br />
   38.29 +( '\'  )</li>
   38.30 +
   38.31 +<li> :<br />
   38.32 +<code>dbreader.bat</code> <br />
   38.33 +<code>java -jar dbreader.jar</code>.<br />
   38.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 -  .
   38.35 +
   38.36 +        :<br />
   38.37 + <code>java -Dru.karrc.dbreader.<em></em>=<em></em> -jar dbreader.jar</code><br />
   38.38 +(: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li>
   38.39 +</ol>
   38.40 +
   38.41 +<h2> </h2>
   38.42 +
   38.43 +<p>   biotope.sql ( ,   dbreader.properties),     biotope.template,         .</p>
   38.44 +<p> : <code>&lt;%<em>_</em>[:|\]<em></em>%&gt;</code>, <em> </em> -    ,    .    ,     .</p>
   38.45 +
   38.46 +<h3>     </h3>
   38.47 +
   38.48 +<ul>
   38.49 +  <li><code>:</code> -    .</li>
   38.50 +  <li><code>\</code> -      .       <code>&lt;%</code>  <code>%&gt;</code> (<code>&lt;%\&lt;%%&gt;</code>  <code>&lt;%\%%&gt;&gt;</code>).</li>
   38.51 +</ul>
   38.52 +
   38.53 +<h3></h3>
   38.54 +
   38.55 +<ul>
   38.56 +  <li><code>&lt;%get:<em></em>%&gt;</code><br />
   38.57 +         .</li>
   38.58 +
   38.59 +  <li><code>&lt;%optional:<em></em>%&gt;</code><br />
   38.60 +    <em></em>,     ,    ,     .</li>
   38.61 +
   38.62 +  <li><code>&lt;%escape:<em></em>%&gt;</code><br />
   38.63 +     ""  (     ).</li>
   38.64 +
   38.65 +  <li><code>&lt;%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%&gt;</code><br />
   38.66 +      <em></em>.sql       <em></em>.template.        '?'.</li>
   38.67 +
   38.68 +  <li><code>&lt;%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%&gt;</code><br />
   38.69 +      <em>_</em> (     "resource_base")      ,    <em>_</em>.      ,    .
   38.70 +  ,  <code>&lt;%image:...%&gt;</code>     <em>_</em>,  -   .</li>
   38.71 +
   38.72 +  <li><code>&lt;%copy:<em>_</em> <em>_</em>%&gt;</code><br />
   38.73 +    <em>_</em> (     "resource_base")  <em>_</em>.   ,  <code>&lt;%copy:...%&gt;</code>     <em>_</em>,  -   .</li>
   38.74 +</ul>
   38.75 +
   38.76 +<h3> </h3>
   38.77 +
   38.78 +<p><code>NUMBER</code> -      .
   38.79 +    ,          invoke,      <code>SUPER.</code> (: <code>SUPER.NUMBER</code>).</p>
   38.80 +
   38.81 +<h3></h3>
   38.82 +
   38.83 +<p>      name      :</p>
   38.84 +<p><code>&lt;%escape get:name%&gt;</code></p>
   38.85 +
   38.86 +<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru"> </a></i></p>
   38.87 +
   38.88 +</body>
   38.89 +</html>
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/misc/biotopes/doc/readme.txt	Tue Feb 19 20:32:17 2008 +0300
    39.3 @@ -0,0 +1,63 @@
    39.4 +text/plain; charset=UTF-8
    39.5 +
    39.6 +Установка программы
    39.7 +-------------------
    39.8 +
    39.9 +1. Распаковать архив.
   39.10 +
   39.11 +2. Установить источник данных:
   39.12 +в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes.mdb.
   39.13 +
   39.14 +3. Настроить программу:
   39.15 +В файле dbreader.properties указать имя, присвоенное источнику данных:
   39.16 +    "resource: jdbc:odbc:<имя>"
   39.17 +и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps):
   39.18 +    "resource_base: C:\\biotopes"
   39.19 +(символ '\' необходимо дублировать)
   39.20 +
   39.21 +4. Запуск программы: dbreader.bat или "java -jar dbreader.jar"
   39.22 +Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с http://java.sun.com/j2se/1.5.0/download.jsp. Возможно, будет работать и со старыми версиями JRE - не проверял.
   39.23 +
   39.24 +Все значения файла конфигурации можно переопределять при запуске программы:
   39.25 +    команда "java -Dru.karrc.dbreader.<ключ>=<значение> -jar dbreader.jar"
   39.26 +(например: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar")
   39.27 +
   39.28 +
   39.29 +Работа программы
   39.30 +----------------
   39.31 +
   39.32 +Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения.
   39.33 +
   39.34 +Формат инструкций: "<%список_функций[:|\]данные%>", список функций - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней.
   39.35 +
   39.36 +Разделители между списком функций и данными:
   39.37 +':' - данные будут обрабатываться рекурсивно.
   39.38 +'\' - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов "<%" и "%>" ("<%\<%%>" и "<%\%%>>").
   39.39 +
   39.40 +Функции:
   39.41 +<%get:<имя>%> - заменяется на значение встроенной переменной или колонки запроса.
   39.42 +
   39.43 +<%optional:<текст>%>
   39.44 +Заменяется на <текст>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку.
   39.45 +
   39.46 +<%escape:<текст>%>
   39.47 +Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации).
   39.48 +
   39.49 +<%invoke:<имя> <парам1> <парам2> ... <парамN>%>
   39.50 +Выполняет запрос с параметрами <имя>.sql и заменяется на результаты обработки шаблона <имя>.template. Значения параметров подставляются в запрос вместо символа '?'.
   39.51 +
   39.52 +<%image:<исх_файл> <кон_файл> <формат> [<макс_ширина>] [<макс_высота>]%>
   39.53 +Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены.
   39.54 +При успешном выполнении, инструкция "<%!image ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку.
   39.55 +
   39.56 +<%copy:<исх_файл> <кон_файл>%>
   39.57 +Копирует файл <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base").
   39.58 +При успешном выполнении, инструкция "<%!copy ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку.
   39.59 +
   39.60 +Встроенные переменные:
   39.61 +NUMBER - порядковый номер строки результата выполнения запроса.
   39.62 +Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить "SUPER." (например: "SUPER.NUMBER").
   39.63 +
   39.64 +Пример:
   39.65 +Следующая инструкция получит значение из столбца name и заменит в нем специальные символы:
   39.66 +<%escape get:name%>
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/misc/biotopes/main.template	Tue Feb 19 20:32:17 2008 +0300
    40.3 @@ -0,0 +1,11 @@
    40.4 +<%!:
    40.5 +  <%prepare:biotope_sql <%read\biotope.sql%>%>
    40.6 +  <%prepare:photo_sql <%read\photo.sql%>%>
    40.7 +  <%prepare:class_sql <%read\class.sql%>%>
    40.8 +  <%prepare:plant_sql <%read\plant.sql%>%>
    40.9 +
   40.10 +  <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%>
   40.11 +
   40.12 +  <%write:classes.xml <%include\classes.template%>%>
   40.13 +  <%write:plants.xml <%include\plants.template%>%>
   40.14 +%>
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/misc/biotopes/photo.sql	Tue Feb 19 20:32:17 2008 +0300
    41.3 @@ -0,0 +1,1 @@
    41.4 +SELECT * from photos WHERE biotope = ?
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/misc/biotopes/photo.template	Tue Feb 19 20:32:17 2008 +0300
    42.3 @@ -0,0 +1,3 @@
    42.4 +    < num="<%number\%>" <%optional:="<%xml_escape db\authphoto%>" %>text="" 
    42.5 +                file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" 
    42.6 +                big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/misc/biotopes/plant.sql	Tue Feb 19 20:32:17 2008 +0300
    43.3 @@ -0,0 +1,3 @@
    43.4 +SELECT t1.*
    43.5 +FROM biotopelist AS t1
    43.6 +WHERE rusname AND Right(t1.rangcode, 2) <> '00'
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/misc/biotopes/plants.template	Tue Feb 19 20:32:17 2008 +0300
    44.3 @@ -0,0 +1,5 @@
    44.4 +<?xml version="1.0" encoding="ISO-8859-5"?>
    44.5 +<><%query:plant_sql [%\
    44.6 +  <!-- rangcode: <%xml_escape db\rangcode%> -->
    44.7 +  <><%xml_escape db\rusname%></>%]%>
    44.8 +</>
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/misc/biotopes/tema.properties	Tue Feb 19 20:32:17 2008 +0300
    45.3 @@ -0,0 +1,22 @@
    45.4 +# Data source configuration
    45.5 +resource          : jdbc:odbc:biotopes-data
    45.6 +driver            : sun.jdbc.odbc.JdbcOdbcDriver
    45.7 +
    45.8 +# Base directory for images and files
    45.9 +resource_base     : C:\\biotopes\\db
   45.10 +
   45.11 +# Template to start processing with
   45.12 +main_template     : main.template
   45.13 +
   45.14 +# File encodings
   45.15 +input_encoding    : ISO-8859-5
   45.16 +output_encoding   : ISO-8859-5
   45.17 +
   45.18 +# Cache templates
   45.19 +cache_read        : true
   45.20 +
   45.21 +# Output main_template parsing result to stderr
   45.22 +#output            : stderr
   45.23 +
   45.24 +# File to output error messages (redirect stderr)
   45.25 +#log               : tema.log
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/misc/manual-ru-old/index.html	Tue Feb 19 20:32:17 2008 +0300
    46.3 @@ -0,0 +1,370 @@
    46.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    46.5 +          "DTD/xhtml1-transitional.dtd">
    46.6 +
    46.7 +<html>
    46.8 +
    46.9 +<head>
   46.10 +  <title>Макропроцессор TEMA</title>
   46.11 +  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   46.12 +</head>
   46.13 +
   46.14 +<body>
   46.15 +<h1>Макропроцессор TEMA</h1>
   46.16 +
   46.17 +<p>Макропроцессор TEMA обрабатывает заданные шаблоны текстовых файлов и
   46.18 +заменяет найденные в них инструкции на результаты их выполнения.
   46.19 +</p><p>
   46.20 +Особенности:
   46.21 +</p>
   46.22 +<ul>
   46.23 +  <li>Расширяемость: возможно динамически подключать новые функии,
   46.24 +  реализованные в виде классов на Java.</li>
   46.25 +  <li>Работа с базами данных: использование SQL-запросов для получения
   46.26 +  данных.</li>
   46.27 +  <li>Поточная обработка данных: инструкции обрабатываются по мере
   46.28 +  чтения текста без необходимости загрузки файла в оперативную память
   46.29 +  и выполнения полного синтаксического разбора.</li>
   46.30 +</ul>
   46.31 +
   46.32 +<p><b>Формат инструкций</b></p>
   46.33 +
   46.34 +<blockquote>
   46.35 +  <code>&lt;%<i>список_функций</i>{:|\|`}<i>данные</i>%&gt;</code>  
   46.36 +</blockquote>
   46.37 +<p>
   46.38 +где<br />
   46.39 +
   46.40 +<code><i>список_функций</i></code> - список имен функций, разделенных
   46.41 +    пробелами. Может быть пустым.<br />
   46.42 +<code><i>данные</i></code> - данные, передаваемые функции.
   46.43 +</p>
   46.44 +
   46.45 +<p><b>Формат данных</b></p>
   46.46 +
   46.47 +<blockquote>
   46.48 +  <code>
   46.49 +    [<i>список_аргументов</i>][<i>текст</i>]
   46.50 +  </code>
   46.51 +</blockquote>
   46.52 +<p>
   46.53 +где<br />
   46.54 +
   46.55 +<code><i>список_аргументов</i></code> - список аргументов функции, разделенных пробелами.
   46.56 +    Может быть пустым.<br />
   46.57 +<code><i>текст</i></code> - текст, передаваемый функции без разбиения на аргументы.
   46.58 +    Может быть пустым. Количество аргументов, после которого следует
   46.59 +    текст, зависит от функции.
   46.60 +</p><p>
   46.61 +Разделитель между списком функций и данными определяет, как должны
   46.62 +обрабатываться данные функции:
   46.63 +</p><p>
   46.64 +<code>:</code> - рекурсивная обработка,<br />
   46.65 +<code>\</code> или <code>`</code> - передать без обработки.
   46.66 +</p><p>
   46.67 +Если в списке функций задано две и более функции, они выполняются,
   46.68 +начиная с последней, так что каждая функция получает в качестве данных
   46.69 +результат выполнения следующей функции.
   46.70 +</p><p>
   46.71 +Каждая функция имеет код возврата - целое число. Код возврата
   46.72 +инструкции - код возврата первой в списке функции. Код возврата,
   46.73 +получаемый при обработке текста - сумма кодов возврата обработанных
   46.74 +инструкций (как правило, смысл этого значения - количество инструкций,
   46.75 +замененных на непустой текст).
   46.76 +</p><p>
   46.77 +Кроме скобок '&lt;', '&gt;', можно использовать скобки '[', ']'.
   46.78 +</p>
   46.79 +
   46.80 +
   46.81 +<h2>Функции</h2>
   46.82 +
   46.83 +<p><code><b>set</b></code></p>
   46.84 +
   46.85 +<table>
   46.86 +<tr><td>Аргументы:</td>
   46.87 +<td><i>имя</i></td></tr>
   46.88 +
   46.89 +<tr><td>Текст:</td>
   46.90 +<td><i>значение</i></td></tr>
   46.91 +
   46.92 +<tr><td>Действие:</td>
   46.93 +<td>Устанавливает значение переменной <i>имя</i>.</td></tr>
   46.94 +
   46.95 +<tr><td>Результат:</td>
   46.96 +<td><i>имя</i></td></tr>
   46.97 +
   46.98 +<tr><td>Код возврата:</td>
   46.99 +<td>1</td></tr>
  46.100 +</table>
  46.101 +
  46.102 +<p><code><b>define</b></code></p>
  46.103 +
  46.104 +<table>
  46.105 +<tr><td>Аргументы:</td>
  46.106 +<td><i>имя</i></td></tr>
  46.107 +
  46.108 +<tr><td>Текст:</td>
  46.109 +<td><i>шаблон</i></td></tr>
  46.110 +
  46.111 +<tr><td>Действие:</td><td>Определяет новую функцию <i>имя</i>, при
  46.112 +вызове которой обрабатывается <i>шаблон</i>. При обработке доступны
  46.113 +функции <code>nextarg</code> для получения очередного аргумента
  46.114 +вызываемой функции и <code>data</code> для получения текста.</td></tr>
  46.115 +
  46.116 +<tr><td>Результат:</td>
  46.117 +<td><i>имя</i></td></tr>
  46.118 +
  46.119 +<tr><td>Код возврата:</td>
  46.120 +<td>1</td></tr>
  46.121 +</table>
  46.122 +
  46.123 +<p><code><b>load</b></code></p>
  46.124 +
  46.125 +<table>
  46.126 +<tr><td>Аргументы:</td>
  46.127 +<td><i>имя</i> <i>имя_класса</i></td></tr>
  46.128 +
  46.129 +<tr><td>Действие:</td>
  46.130 +
  46.131 +<td>Определяет новую функцию <i>имя</i>. Реализация функции определена
  46.132 +Java-классом <i>имя_класса</i>, наследующим класс
  46.133 +<code>kryshen.tema.Function</code>.</td></tr>
  46.134 +
  46.135 +<tr><td>Результат:</td>
  46.136 +<td><i>имя</i></td></tr>
  46.137 +
  46.138 +<tr><td>Код возврата:</td>
  46.139 +<td>1</td></tr>
  46.140 +</table>
  46.141 +
  46.142 +<p><code><b>prepare</b></code></p>
  46.143 +
  46.144 +<table>
  46.145 +<tr><td>Аргументы:</td>
  46.146 +<td><i>имя</i></td></tr>
  46.147 +
  46.148 +<tr><td>Текст:</td>
  46.149 +<td><i>запрос</i></td></tr>
  46.150 +
  46.151 +<tr><td>Действие:</td>
  46.152 +<td>Подготавливает SQL-запрос <i>запрос</i> для выполнения, записывает
  46.153 +подготовленный запрос в переменную <i>имя</i>.</td></tr>
  46.154 +
  46.155 +<tr><td>Результат:</td>
  46.156 +<td><i>имя</i></td></tr>
  46.157 +
  46.158 +<tr><td>Код возврата:</td>
  46.159 +<td>1</td></tr>
  46.160 +</table>
  46.161 +
  46.162 +<p><code><b>query</b></code></p>
  46.163 +
  46.164 +<table>
  46.165 +<tr><td>Аргументы:</td>
  46.166 +<td><i>имя_запроса</i> <i>шаблон</i> <i>парам1</i> ... <i>парамN</i></td></tr>
  46.167 +
  46.168 +<tr><td>Действие:</td>
  46.169 +<td>Выполняет запрос с параметрами, подготовленный с помощью функции
  46.170 +prepare. Значения параметров подставляются в запрос вместо символа
  46.171 +'?'. Значения полей ответа доступны с помощью функции <code>db</code>,
  46.172 +как переменные шаблона <i>шаблон</i>. При обработки шаблона также
  46.173 +определяется переменная <code>number</code>, содержащая номер текущей
  46.174 +строки ответа.</td></tr>
  46.175 +
  46.176 +<tr><td>Результат:</td>
  46.177 +<td>результат обработки шаблона <i>шаблон</i> для каждой строки
  46.178 +ответа.</td></tr>
  46.179 +
  46.180 +<tr><td>Код возврата:</td>
  46.181 +<td>Количество полученных строк ответа.</td></tr>
  46.182 +</table>
  46.183 +
  46.184 +<p><code><b>optional</b></code></p>
  46.185 +
  46.186 +<table>
  46.187 +<tr><td>Текст:</td>
  46.188 +<td><i>данные</i></td></tr>
  46.189 +
  46.190 +<tr><td>Результат:</td><td><i>данные</i>, если при обработке данных
  46.191 +был получен код возврата отличный от 0, иначе - пустая
  46.192 +строка.</td></tr>
  46.193 +
  46.194 +<tr><td>Код возврата:</td>
  46.195 +<td>1, если результат - пустая строка, 0 - иначе.</td></tr>
  46.196 +</table>
  46.197 +
  46.198 +<p><code><b>image</b></code></p>
  46.199 +
  46.200 +<table>
  46.201 +<tr><td>Аргументы:</td>
  46.202 +<td><i>исх_файл</i> <i>кон_файл</i> <i>формат</i> [<i>макс_ширина</i>
  46.203 +[<i>макс_высота</i>]]</td></tr>
  46.204 +
  46.205 +<tr><td>Действие:</td>
  46.206 +<td>Загружает изображение из файла <i>исх_файл</i> (путь определяется
  46.207 +относительно конфигурационного параметра "resource_base") и
  46.208 +преобразует его в указанный формат, сохраняя результат в
  46.209 +<i>кон_файл</i>. Если заданы максимальная высота и ширина, большие
  46.210 +изображения будут уменьшены.</td></tr>
  46.211 +
  46.212 +<tr><td>Результат:</td>
  46.213 +<td><i>кон_файл</i> при успешном выполнении, пустая строка - иначе.</td></tr>
  46.214 +
  46.215 +<tr><td>Код возврата:</td>
  46.216 +<td>1 при успешном выполнении, 0 - иначе.</td></tr>
  46.217 +</table>
  46.218 +
  46.219 +
  46.220 +<p><code><b>copy</b></code></p>
  46.221 +
  46.222 +<table>
  46.223 +<tr><td>Аргументы:</td><td><i>исх_файл</i> <i>кон_файл</i></td></tr>
  46.224 +
  46.225 +<tr><td>Действие:</td><td>Копирует файл <i>исх_файл</i> в файл
  46.226 +<i>кон_файл</i> (путь <i>исх_файл</i> определяется относительно
  46.227 +конфигурационного параметра "resource_base").</td></tr>
  46.228 +
  46.229 +<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении,
  46.230 +пустая строка - иначе.</td></tr>
  46.231 +
  46.232 +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  46.233 +иначе.</td></tr>
  46.234 +</table>
  46.235 +
  46.236 +<p><code><b>write</b></code></p>
  46.237 +
  46.238 +<table>
  46.239 +<tr><td>Аргументы:</td><td><i>имя_файла</i></td></tr>
  46.240 +
  46.241 +<tr><td>Текст:</td><td><i>данные</i></td></tr>
  46.242 +
  46.243 +<tr><td>Действие:</td><td>Записывает <i>данные</i> в файл
  46.244 +<i>исх_файл</i>.</td></tr>
  46.245 +
  46.246 +<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении,
  46.247 +пустая строка - иначе.</td></tr>
  46.248 +
  46.249 +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  46.250 +иначе.</td></tr>
  46.251 +</table>
  46.252 +
  46.253 +<p><code><b>read</b></code></p>
  46.254 +
  46.255 +<table>
  46.256 +<tr><td>Текст:</td><td><i>имя_файла</i></td></tr>
  46.257 +<tr><td>Действие:</td><td>Читает файл <i>имя_файла</i>.</td></tr>
  46.258 +<tr><td>Результат:</td><td>прочитанные данные при успешном выполнении,
  46.259 +  пустая строка - иначе.</td></tr>
  46.260 +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 -
  46.261 +иначе.</td></tr>
  46.262 +</table>
  46.263 +
  46.264 +<p><code><b>include</b></code></p>
  46.265 +
  46.266 +<table>
  46.267 +<tr><td>Текст:</td><td><i>имя_файла</i></td></tr>
  46.268 +<tr><td>Действие:</td><td>включает шаблон из файла
  46.269 +<i>имя_файла</i>.</td></tr>
  46.270 +<tr><td>Результат:</td><td>результат обработки шаблона.</td></tr>
  46.271 +<tr><td>Код возврата:</td><td>код возврата, полученный при обработке
  46.272 +шаблона.</td></tr>
  46.273 +</table>
  46.274 +
  46.275 +<p><code><b>!</b></code></p>
  46.276 +
  46.277 +<table>
  46.278 +<tr><td>Текст:</td><td><i>данные</i></td></tr>
  46.279 +
  46.280 +<tr><td>Действие:</td><td>нет.</td></tr>
  46.281 +
  46.282 +<tr><td>Результат:</td><td>нет.</td></tr>
  46.283 +
  46.284 +<tr><td>Код возврата:</td><td>код возврата, полученный при обработке
  46.285 +текста данных.</td></tr>
  46.286 +</table>
  46.287 +
  46.288 +<p><code><b>replace</b></code></p>
  46.289 +
  46.290 +<table>
  46.291 +<tr><td>Аргументы:</td><td><i>стр1</i> <i>стр2</i></td></tr>
  46.292 +
  46.293 +<tr><td>Текст:</td><td><i>данные</i></td></tr>
  46.294 +
  46.295 +<tr><td>Результат:</td><td>данные, с замененными вхождениями подстроки
  46.296 +<i>стр1</i> на <i>стр2</i>.</td></tr>
  46.297 +
  46.298 +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  46.299 +текста данных.</td></tr>
  46.300 +</table>
  46.301 +
  46.302 +<p><code><b>xml_escape</b></code></p>
  46.303 +
  46.304 +<table>
  46.305 +<tr><td>Текст:</td><td><i>данные</i></td></tr>
  46.306 +<tr><td>Результат:</td><td>текст <i>данные</i>, в котором символы
  46.307 +'&amp;', '&lt;', '&gt;', '`', '\' заменены на соответствующие сущности
  46.308 +XML.</td></tr>
  46.309 +
  46.310 +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  46.311 +текста данных.</td></tr>
  46.312 +</table>
  46.313 +
  46.314 +<p><code><b>xml_cdata</b></code></p>
  46.315 +
  46.316 +<table>
  46.317 +<tr><td>Текст:</td><td><i>данные</i></td></tr>
  46.318 +
  46.319 +<tr><td>Результат:</td><td>данные в виде блока XML CDATA.</td></tr>
  46.320 +
  46.321 +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке
  46.322 +текста данных.  </td></tr>
  46.323 +</table>
  46.324 +
  46.325 +<p>
  46.326 +Макропроцессор TEMA расширяем: возможно добавление в систему новых
  46.327 +функций, реализованных в виде классов на языке Java.
  46.328 +</p>
  46.329 +
  46.330 +<h2>Запуск</h2>
  46.331 +
  46.332 +<p>java -jar tema.jar [<i>опции</i>]
  46.333 +</p><p>
  46.334 +Опции:
  46.335 +</p>
  46.336 +<table>
  46.337 +<tr><td>-d[emo]</td><td>Демонстрационный режим</td></tr>
  46.338 +<tr><td>-v[ersion]</td><td>Вывод версии</td></tr>
  46.339 +<tr><td>-h[help] -u[sage]</td><td>Вывод справки</td></tr>
  46.340 +</table>
  46.341 +
  46.342 +<p>
  46.343 +При запуске читается файл "tema.properties" из текущего каталога.<br />
  46.344 +Пример файла "tema.properties":
  46.345 +</p>
  46.346 +
  46.347 +<pre>
  46.348 +# Настройка источника данных
  46.349 +# resource          : jdbc:odbc:database
  46.350 +# driver            : sun.jdbc.odbc.JdbcOdbcDriver
  46.351 +
  46.352 +# Базовый каталог ресурсов
  46.353 +# resource_base     : .
  46.354 +
  46.355 +# Шаблон, с которого начинается обработка
  46.356 +main_template     : main.template
  46.357 +
  46.358 +# Кодировки файлов
  46.359 +# input_encoding    : UTF-8
  46.360 +# output_encoding   : UTF-8
  46.361 +
  46.362 +# Кэширование шаблонов
  46.363 +# cache_read        : true
  46.364 +
  46.365 +# Вывод результата разбора шаблона main.template в stderr
  46.366 +# output            : stderr
  46.367 +
  46.368 +# Вывод сообщений об ошибках в файл
  46.369 +# log               : dbreader.log
  46.370 +</pre>
  46.371 +
  46.372 +</body>
  46.373 +</html>
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/misc/util/header	Tue Feb 19 20:32:17 2008 +0300
    47.3 @@ -0,0 +1,21 @@
    47.4 +/*
    47.5 + *  Copyright 2006-2008 Mikhail Kryshen
    47.6 + *
    47.7 + *  This file is part of Tema.
    47.8 + *
    47.9 + *  Tema is free software: you can redistribute it and/or modify it
   47.10 + *  under the terms of the GNU Lesser General Public License as
   47.11 + *  published by the Free Software Foundation, either version 3 of the
   47.12 + *  License, or (at your option) any later version.
   47.13 + *
   47.14 + *  Tema is distributed in the hope that it will be useful,
   47.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   47.17 + *  GNU Lesser General Public License for more details.
   47.18 + *
   47.19 + *  You should have received a copy of the 
   47.20 + *  GNU Lesser General Public License along with Tema.  
   47.21 + *  If not, see <http://www.gnu.org/licenses/>.
   47.22 + *
   47.23 + *  $Id: $
   47.24 + */
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/misc/util/header.gpl	Tue Feb 19 20:32:17 2008 +0300
    48.3 @@ -0,0 +1,20 @@
    48.4 +/*
    48.5 + *  Copyright (C) 2006, 2007, 2008 Mikhail Kryshen
    48.6 + *
    48.7 + *  This file is part of Tema.
    48.8 + *
    48.9 + *  Tema is free software: you can redistribute it and/or modify it
   48.10 + *  under the terms of the GNU General Public License as published by
   48.11 + *  the Free Software Foundation, either version 3 of the License, or
   48.12 + *  (at your option) any later version.
   48.13 + *
   48.14 + *  Tema is distributed in the hope that it will be useful,
   48.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.17 + *  GNU General Public License for more details.
   48.18 + *
   48.19 + *  You should have received a copy of the GNU General Public License
   48.20 + *  along with Tema.  If not, see <http://www.gnu.org/licenses/>.
   48.21 + *
   48.22 + *  $Id: header.gpl,v 1.1 2008/02/16 16:56:34 mikhail Exp $
   48.23 + */
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/misc/util/update_headers.pl	Tue Feb 19 20:32:17 2008 +0300
    49.3 @@ -0,0 +1,36 @@
    49.4 +#!/usr/bin/perl
    49.5 +
    49.6 +use File::Find;
    49.7 +
    49.8 +undef $/;
    49.9 +
   49.10 +my $src = "../../src";
   49.11 +my $header_file = "header";
   49.12 +
   49.13 +open (FILE, "$header_file");
   49.14 +my $header = <FILE>;
   49.15 +close(FILE);
   49.16 +
   49.17 +find (\&update_header, $src);
   49.18 +
   49.19 +sub update_header
   49.20 +{
   49.21 +   my $code;
   49.22 +   
   49.23 +   if ( $File::Find::name !~ /^.*\.java$/ )
   49.24 +   {
   49.25 +     return;
   49.26 +   }
   49.27 +
   49.28 +   print $File::Find::name."\n";   
   49.29 +   open(FILE, "$_") or die "error opening file";
   49.30 +  
   49.31 +   $code = <FILE>;
   49.32 +   $code =~ s|(^[[:space:]]*/\*.*?\*/[[:space:]]*?\n\|^)|$header|s;
   49.33 +   
   49.34 +   close(FILE);
   49.35 +
   49.36 +   open(FILE, ">$_") or die "error opening file";
   49.37 +   print FILE $code;
   49.38 +   close(FILE);
   49.39 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/nbproject/.cvsignore	Tue Feb 19 20:32:17 2008 +0300
    50.3 @@ -0,0 +1,1 @@
    50.4 +private
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/nbproject/project.xml	Tue Feb 19 20:32:17 2008 +0300
    51.3 @@ -0,0 +1,81 @@
    51.4 +<?xml version="1.0" encoding="UTF-8"?>
    51.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
    51.6 +    <type>org.netbeans.modules.ant.freeform</type>
    51.7 +    <configuration>
    51.8 +        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
    51.9 +            <!-- Do not use Project Properties customizer when editing this file manually. -->
   51.10 +            <name>TEMA</name>
   51.11 +            <properties/>
   51.12 +            <folders>
   51.13 +                <source-folder>
   51.14 +                    <label>src</label>
   51.15 +                    <type>java</type>
   51.16 +                    <location>src</location>
   51.17 +                </source-folder>
   51.18 +                <source-folder>
   51.19 +                    <label>test</label>
   51.20 +                    <type>java</type>
   51.21 +                    <location>test</location>
   51.22 +                </source-folder>
   51.23 +            </folders>
   51.24 +            <ide-actions>
   51.25 +                <action name="build">
   51.26 +                    <target>compile</target>
   51.27 +                </action>
   51.28 +                <action name="clean">
   51.29 +                    <target>clean</target>
   51.30 +                </action>
   51.31 +                <action name="javadoc">
   51.32 +                    <target>doc.api</target>
   51.33 +                </action>
   51.34 +                <action name="rebuild">
   51.35 +                    <target>clean</target>
   51.36 +                    <target>compile</target>
   51.37 +                </action>
   51.38 +                <action name="run">
   51.39 +                    <target>run.demo</target>
   51.40 +                </action>
   51.41 +            </ide-actions>
   51.42 +            <view>
   51.43 +                <items>
   51.44 +                    <source-folder style="packages">
   51.45 +                        <label>src</label>
   51.46 +                        <location>src</location>
   51.47 +                    </source-folder>
   51.48 +                    <source-folder style="packages">
   51.49 +                        <label>test</label>
   51.50 +                        <location>test</location>
   51.51 +                    </source-folder>
   51.52 +                    <source-file>
   51.53 +                        <location>build.xml</location>
   51.54 +                    </source-file>
   51.55 +                </items>
   51.56 +                <context-menu>
   51.57 +                    <ide-action name="build"/>
   51.58 +                    <ide-action name="rebuild"/>
   51.59 +                    <ide-action name="clean"/>
   51.60 +                    <ide-action name="javadoc"/>
   51.61 +                    <ide-action name="run"/>
   51.62 +                    <action>
   51.63 +                        <label>Compile manual</label>
   51.64 +                        <target>doc.manual</target>
   51.65 +                    </action>
   51.66 +                </context-menu>
   51.67 +            </view>
   51.68 +            <subprojects/>
   51.69 +        </general-data>
   51.70 +        <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/2">
   51.71 +            <compilation-unit>
   51.72 +                <package-root>src</package-root>
   51.73 +                <classpath mode="compile">build:dist/lib/commons-cli-1.1.jar:../../../../../usr/share/java/ant.jar</classpath>
   51.74 +                <source-level>1.5</source-level>
   51.75 +            </compilation-unit>
   51.76 +            <compilation-unit>
   51.77 +                <package-root>test</package-root>
   51.78 +                <unit-tests/>
   51.79 +                <classpath mode="compile">build</classpath>
   51.80 +                <source-level>1.5</source-level>
   51.81 +            </compilation-unit>
   51.82 +        </java-data>
   51.83 +    </configuration>
   51.84 +</project>
    52.1 --- a/res/kryshen/tema/demo/demo.template	Thu Dec 14 23:22:05 2006 +0300
    52.2 +++ b/res/kryshen/tema/demo/demo.template	Tue Feb 19 20:32:17 2008 +0300
    52.3 @@ -1,25 +1,34 @@
    52.4 -[%!\ TEMA demo template %]
    52.5 +[%!\
    52.6 +  Tema demo template 
    52.7 +%]\\
    52.8  
    52.9 -Вывод текста:
   52.10 -test text
   52.11 +<%tema:%>
   52.12  
   52.13 -Вывод специальных символов:
   52.14 -[%\<%test%>%]
   52.15 +Escaping special character sequences:
   52.16 +[%\<%test:%>%]
   52.17  
   52.18 -Объявление функции:
   52.19 -<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%>   
   52.20 +Macro definition:
   52.21 +<%define#test
   52.22 +  arg1:<%next_arg:%>, arg2:<%next_arg:%>, data:<%data:%>.%>
   52.23  
   52.24 -Вызов новой функции:
   52.25 -<%test:1 2 3%>
   52.26 +Invoke defined macro:
   52.27 +<%test:1 2 3 4 5%>
   52.28  
   52.29 -Загрузка функции из класса:
   52.30 +Define macro implemented as a Java class:
   52.31  <%load\hello kryshen.tema.demo.Hello%>
   52.32  
   52.33 -Выполенение загруженной функции:
   52.34 -<%hello\TEMA%>
   52.35 +Invoke defined macro:
   52.36 +<%hello\Tema%>
   52.37  
   52.38 -Условное выполнение:
   52.39 -<%optional:<%true:%>True%> <%optional:<%false:%>False%>
   52.40 +Conditional output:
   52.41 +<%optional:<%true:%>True%>\
   52.42 +<%optional:<%false:%>False%>
   52.43  
   52.44 -Тестирование xml_escape:
   52.45 +Cycle:
   52.46 +<%silent define#cycle_test
   52.47 +  Arguments list: <%while#"<%next_arg:%>" %>\
   52.48 +%>\
   52.49 +<%cycle_test:1 2 3 <%:4 5%>%>
   52.50 +
   52.51 +Escaping special characters in XML:
   52.52  <%xml_escape\x < a & b%>
    53.1 --- a/src/Manifest.mf	Thu Dec 14 23:22:05 2006 +0300
    53.2 +++ b/src/Manifest.mf	Tue Feb 19 20:32:17 2008 +0300
    53.3 @@ -1,2 +1,3 @@
    53.4  Manifest-Version: 1.0
    53.5  Main-Class: kryshen.tema.Tema
    53.6 +Class-Path: lib/commons-cli-1.1.jar
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/src/kryshen/tema/Context.java	Tue Feb 19 20:32:17 2008 +0300
    54.3 @@ -0,0 +1,130 @@
    54.4 +/*
    54.5 + *  Copyright 2006-2008 Mikhail Kryshen
    54.6 + *
    54.7 + *  This file is part of Tema.
    54.8 + *
    54.9 + *  Tema is free software: you can redistribute it and/or modify it
   54.10 + *  under the terms of the GNU Lesser General Public License as
   54.11 + *  published by the Free Software Foundation, either version 3 of the
   54.12 + *  License, or (at your option) any later version.
   54.13 + *
   54.14 + *  Tema is distributed in the hope that it will be useful,
   54.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.17 + *  GNU Lesser General Public License for more details.
   54.18 + *
   54.19 + *  You should have received a copy of the 
   54.20 + *  GNU Lesser General Public License along with Tema.  
   54.21 + *  If not, see <http://www.gnu.org/licenses/>.
   54.22 + *
   54.23 + *  $Id: Context.java,v 1.11 2008/02/19 16:21:00 mikhail Exp $
   54.24 + */
   54.25 +
   54.26 +package kryshen.tema;
   54.27 +
   54.28 +import java.io.File;
   54.29 +import java.util.HashMap;
   54.30 +import java.util.Map;
   54.31 +
   54.32 +/**
   54.33 + * Tema template context.
   54.34 + *
   54.35 + * @author Mikhail Kryshen
   54.36 + */
   54.37 +public class Context {
   54.38 +    private Map<String, Object> definitions = new HashMap<String, Object>();
   54.39 +    private Context superContext;
   54.40 +    private File baseDir;
   54.41 +    
   54.42 +    public Context() {
   54.43 +        this(null, null);
   54.44 +    }
   54.45 +    
   54.46 +    public Context(Context superContext) {
   54.47 +        this(superContext, null);
   54.48 +    }
   54.49 +    
   54.50 +    public Context(File baseDir) {
   54.51 +        this(null, baseDir);
   54.52 +    }
   54.53 +    
   54.54 +    public Context(Context superContext, File baseDir) {
   54.55 +        this.superContext = superContext;
   54.56 +        this.baseDir = baseDir;
   54.57 +        
   54.58 +        definitions.put("this", this);
   54.59 +        
   54.60 +        if (superContext != null)
   54.61 +            definitions.put("super", superContext);
   54.62 +    }
   54.63 +    
   54.64 +    public void clear() {
   54.65 +        definitions.clear();
   54.66 +    }
   54.67 +    
   54.68 +    public boolean export(String name) {
   54.69 +        Object value = definitions.get(name);
   54.70 +        
   54.71 +        if (value == null)
   54.72 +            return false;
   54.73 +        
   54.74 +        export(name, value);
   54.75 +        return true;
   54.76 +    }
   54.77 +    
   54.78 +    public void export(String name, Object value) {
   54.79 +        if (superContext == null) {
   54.80 +            set(name, value);
   54.81 +            return;
   54.82 +        }
   54.83 +        
   54.84 +        definitions.remove(name);
   54.85 +        superContext.export(name, value);
   54.86 +    }
   54.87 +    
   54.88 +    public Object get(String name) throws TemplateException {
   54.89 +        Object value = definitions.get(name);
   54.90 +        
   54.91 +        if (value == null && superContext != null)
   54.92 +            return superContext.get(name);
   54.93 +        
   54.94 +        return value;
   54.95 +    }
   54.96 +    
   54.97 +    /**
   54.98 +     * Set the definition value.
   54.99 +     *
  54.100 +     * @param name Variable name.
  54.101 +     * @param value New variable value.
  54.102 +     */
  54.103 +    public void set(String name, Object value) {
  54.104 +        definitions.put(name, value);
  54.105 +    }
  54.106 +    
  54.107 +    /**
  54.108 +     * Remove the definition recursively.
  54.109 +     * 
  54.110 +     * @param name Definition name.
  54.111 +     * @return true if the definition was found and removed.
  54.112 +     */
  54.113 +    public boolean unset(String name) {
  54.114 +        if (definitions.remove(name) != null)
  54.115 +            return true;
  54.116 +        
  54.117 +        if (superContext != null)
  54.118 +            return superContext.unset(name);
  54.119 +        
  54.120 +        return false;
  54.121 +    }
  54.122 +    
  54.123 +    /**
  54.124 +     * Returns base directory which should be used to resolve
  54.125 +     * relative path names in template.
  54.126 +     */
  54.127 +    public File getBaseDirectory() {
  54.128 +        if (baseDir == null && superContext != null)
  54.129 +            return superContext.getBaseDirectory();
  54.130 +        
  54.131 +        return baseDir;
  54.132 +    }
  54.133 +}
    55.1 --- a/src/kryshen/tema/Function.java	Thu Dec 14 23:22:05 2006 +0300
    55.2 +++ b/src/kryshen/tema/Function.java	Tue Feb 19 20:32:17 2008 +0300
    55.3 @@ -1,33 +1,34 @@
    55.4  /*
    55.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    55.6 + *  Copyright 2006-2008 Mikhail Kryshen
    55.7   *
    55.8 - *  This program is free software; you can redistribute it and/or modify
    55.9 - *  it under the terms of the GNU General Public License as published by
   55.10 - *  the Free Software Foundation; either version 2 of the License, or
   55.11 - *  (at your option) any later version.
   55.12 + *  This file is part of Tema.
   55.13   *
   55.14 - *  This program is distributed in the hope that it will be useful,
   55.15 + *  Tema is free software: you can redistribute it and/or modify it
   55.16 + *  under the terms of the GNU Lesser General Public License as
   55.17 + *  published by the Free Software Foundation, either version 3 of the
   55.18 + *  License, or (at your option) any later version.
   55.19 + *
   55.20 + *  Tema is distributed in the hope that it will be useful,
   55.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.23 - *  GNU General Public License for more details.
   55.24 + *  GNU Lesser General Public License for more details.
   55.25   *
   55.26 - *  You should have received a copy of the GNU General Public License
   55.27 - *  along with this program; if not, write to the Free Software
   55.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   55.29 + *  You should have received a copy of the 
   55.30 + *  GNU Lesser General Public License along with Tema.  
   55.31 + *  If not, see <http://www.gnu.org/licenses/>.
   55.32   *
   55.33 - *  $Id: Function.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   55.34 + *  $Id: Function.java,v 1.13 2008/02/19 16:21:00 mikhail Exp $
   55.35   */
   55.36  
   55.37  package kryshen.tema;
   55.38  
   55.39 -import java.io.*;
   55.40 -import java.util.*;
   55.41 -import java.sql.ResultSet;
   55.42 +import java.io.IOException;
   55.43 +import java.io.Writer;
   55.44  
   55.45  /**
   55.46 - * Abstact class for TEMA functions.
   55.47 + * Abstact class for Tema functions.
   55.48   *
   55.49 - * @author Mikhail A. Kryshen
   55.50 + * @author Mikhail Kryshen
   55.51   */
   55.52  public abstract class Function {
   55.53  
    56.1 --- a/src/kryshen/tema/FunctionDataParser.java	Thu Dec 14 23:22:05 2006 +0300
    56.2 +++ b/src/kryshen/tema/FunctionDataParser.java	Tue Feb 19 20:32:17 2008 +0300
    56.3 @@ -1,140 +1,204 @@
    56.4  /*
    56.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    56.6 + *  Copyright 2006-2008 Mikhail Kryshen
    56.7   *
    56.8 - *  This program is free software; you can redistribute it and/or modify
    56.9 - *  it under the terms of the GNU General Public License as published by
   56.10 - *  the Free Software Foundation; either version 2 of the License, or
   56.11 - *  (at your option) any later version.
   56.12 + *  This file is part of Tema.
   56.13   *
   56.14 - *  This program is distributed in the hope that it will be useful,
   56.15 + *  Tema is free software: you can redistribute it and/or modify it
   56.16 + *  under the terms of the GNU Lesser General Public License as
   56.17 + *  published by the Free Software Foundation, either version 3 of the
   56.18 + *  License, or (at your option) any later version.
   56.19 + *
   56.20 + *  Tema is distributed in the hope that it will be useful,
   56.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   56.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   56.23 - *  GNU General Public License for more details.
   56.24 + *  GNU Lesser General Public License for more details.
   56.25   *
   56.26 - *  You should have received a copy of the GNU General Public License
   56.27 - *  along with this program; if not, write to the Free Software
   56.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   56.29 + *  You should have received a copy of the 
   56.30 + *  GNU Lesser General Public License along with Tema.  
   56.31 + *  If not, see <http://www.gnu.org/licenses/>.
   56.32   *
   56.33 - *  $Id: FunctionDataParser.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   56.34 + *  $Id: FunctionDataParser.java,v 1.27 2008/02/16 17:56:34 mikhail Exp $
   56.35   */
   56.36  
   56.37  package kryshen.tema;
   56.38  
   56.39 -import java.io.*;
   56.40 -import java.util.*;
   56.41 -
   56.42 +import java.io.File;
   56.43 +import java.io.IOException;
   56.44 +import java.io.StringWriter;
   56.45 +import java.io.Writer;
   56.46 +import java.util.ArrayList;
   56.47 +import java.util.List;
   56.48  import static kryshen.tema.TemplateParser.Result;
   56.49 -import static kryshen.tema.TemplateParser.FunctionData;
   56.50 +import static kryshen.tema.TemplateParser.DataFormat;
   56.51 +import kryshen.tema.TemplateParser.DataFormat;
   56.52  import static kryshen.tema.TemplateParser.Terminator;
   56.53 +import kryshen.tema.io.CopyWriter;
   56.54 +import kryshen.tema.io.NullWriter;
   56.55 +import kryshen.tema.io.TemplateReader;
   56.56  
   56.57  /**
   56.58   * Parser for a function data.
   56.59   *
   56.60 - * @author Mikhail A. Kryshen
   56.61 + * @author Mikhail Kryshen
   56.62   */
   56.63  public class FunctionDataParser {
   56.64      static final char[] ARG_SEPARATORS = TemplateParser.LIST_SEPARATORS;
   56.65 -
   56.66 +    
   56.67      private TemplateParser tp;
   56.68 -    private FunctionData fd;
   56.69 +    private DataFormat fd;
   56.70      private TemplateReader in;
   56.71 -
   56.72 +    
   56.73      private boolean available = true;
   56.74 -    private boolean first = true;
   56.75 -
   56.76 -    FunctionDataParser(TemplateParser tp, FunctionData fd,
   56.77 -                       TemplateReader in) {
   56.78 +    
   56.79 +    private int lastReturnCode = 0;
   56.80 +    
   56.81 +    FunctionDataParser(TemplateParser tp, DataFormat fd, TemplateReader in)
   56.82 +    throws IOException, TemplateException {
   56.83          this.tp = tp;
   56.84          this.fd = fd;
   56.85          this.in = in;
   56.86 +        
   56.87 +        // Check for empty function data.
   56.88 +        checkAvailable();
   56.89      }
   56.90 -
   56.91 -    private TemplateParser.Result parseData(Writer out, boolean argument)
   56.92 -	throws IOException, TemplateException {
   56.93 +    
   56.94 +    private void checkAvailable() throws IOException, TemplateException {
   56.95 +        if (tp.checkCloseBracket(in)) {
   56.96 +            // Complete parsing the instruction.
   56.97 +            skipData();
   56.98 +        }
   56.99 +    }
  56.100 +    
  56.101 +    private int parseData(Writer out, boolean argument, boolean skip)
  56.102 +    throws IOException, TemplateException {
  56.103          
  56.104          if (!available)
  56.105              throw new TemplateException
  56.106 -		("Unexpected end of instruction data.", in);
  56.107 -
  56.108 +                    ("Unexpected end of instruction data.", in);
  56.109 +        
  56.110 +        DataFormat fd = skip ? this.fd.noCall() : this.fd;
  56.111 +        
  56.112          TemplateParser.Result r;
  56.113 -
  56.114 -        if (fd == FunctionData.RECURSIVE) {
  56.115 -            r = tp.parse(in, out, true, 
  56.116 -                         argument ? ARG_SEPARATORS : null,
  56.117 -                         (argument || !first) ? ARG_SEPARATORS : null);
  56.118 -        } else if (fd == FunctionData.NONRECURSIVE) {
  56.119 -            r = tp.parse(in, out, false, 
  56.120 -                         argument ? ARG_SEPARATORS : null,
  56.121 -                         (argument || !first) ? ARG_SEPARATORS : null);
  56.122 -        } else if (fd == FunctionData.SUBFUNCTION && argument) {
  56.123 -            // Subfunction can pass a list of arguments
  56.124 -            StringWriter sw = new StringWriter();
  56.125 -            tp.parseFunction(in, sw);
  56.126 -            sw.close();
  56.127 -            in = new TemplateReader(new StringReader(sw.toString()), in);
  56.128 -            fd = FunctionData.NONRECURSIVE;
  56.129 -            r = parseData(out, true);
  56.130 -        } else if (fd == FunctionData.SUBFUNCTION) {
  56.131 -            r = new Result(null, tp.parseFunction(in, out), false);
  56.132 +        
  56.133 +//        if (fd.subfunction && argument) {
  56.134 +//            // Allow subfunction to pass a list of arguments
  56.135 +//            StringWriter sw = new StringWriter();
  56.136 +//            tp.parse(in, sw, fd);
  56.137 +//            sw.close();
  56.138 +//            in = new TemplateReader(new StringReader(sw.toString()), in);
  56.139 +//            this.fd = DataFormat.VERBATIM;
  56.140 +//            r = parseData(out, true, false);
  56.141 +//        } else
  56.142 +        if (fd.subfunction) {
  56.143 +            r = tp.parse(in, out, fd);
  56.144 +        } else if (argument) {
  56.145 +            // Skip duplicate separators before argument.
  56.146 +            tp.skip(in, ARG_SEPARATORS);
  56.147 +            
  56.148 +            r = tp.parse(in, out, fd, ARG_SEPARATORS);
  56.149 +            
  56.150 +            // Skip duplicate separators after argument.
  56.151 +            if (r.terminator == Terminator.SEPARATOR) {
  56.152 +                tp.skip(in, ARG_SEPARATORS);
  56.153 +                checkAvailable();
  56.154 +            }
  56.155          } else {
  56.156 -            throw new IllegalArgumentException("Invalid FunctiodData: " + fd);
  56.157 +            r = tp.parse(in, out, fd, null);
  56.158          }
  56.159 -
  56.160 -        if (r.terminator != TemplateParser.Terminator.SEPARATOR)
  56.161 +        
  56.162 +        if (r.terminator != Terminator.SEPARATOR)
  56.163              available = false; // No more function data available.
  56.164 -
  56.165 -        first = false;
  56.166 -        return r;
  56.167 +        
  56.168 +        lastReturnCode = r.retCode;
  56.169 +        return r.retCode;
  56.170      }
  56.171 -
  56.172 +    
  56.173 +    /**
  56.174 +     * Parse function data.
  56.175 +     */
  56.176      public int parseData(Writer out) throws IOException, TemplateException {
  56.177 -        return parseData(out, false).retCode; 
  56.178 +        return parseData(out, false, false);
  56.179      }
  56.180 -
  56.181 -    public String getData() throws IOException, TemplateException {        
  56.182 +    
  56.183 +    /**
  56.184 +     * Skip function data (do not call any functions).
  56.185 +     */
  56.186 +    public void skipData() throws IOException, TemplateException {
  56.187 +        parseData(NullWriter.INSTANCE, false, true);
  56.188 +    }
  56.189 +    
  56.190 +    /**
  56.191 +     * Get function data as string.
  56.192 +     */
  56.193 +    public String getData() throws IOException, TemplateException {
  56.194          StringWriter sw = new StringWriter();
  56.195          parseData(sw);
  56.196          sw.close();
  56.197          return sw.toString();
  56.198      }
  56.199 -
  56.200 +    
  56.201 +    /**
  56.202 +     * Parse function data into specified <code>Writer</code>.
  56.203 +     * Returns copy of the parsed data as string.
  56.204 +     */
  56.205 +    public String getData(Writer out) throws IOException, TemplateException {
  56.206 +        StringWriter sw = new StringWriter();
  56.207 +        parseData(new CopyWriter(sw, out));
  56.208 +        sw.close();
  56.209 +        return sw.toString();
  56.210 +    }
  56.211 +    
  56.212      public int parseNextArg(Writer out) throws IOException, TemplateException {
  56.213 -        TemplateParser.Result r = parseData(out, true);
  56.214 -
  56.215 -        // Ignore empty arguments.
  56.216 -        while (r.empty && available) {
  56.217 -            r = parseData(out, true);
  56.218 -        }
  56.219 -
  56.220 -        return r.retCode;
  56.221 +        return parseData(out, true, false);
  56.222      }
  56.223 -
  56.224 -    public String getNextArg() throws IOException, TemplateException {        
  56.225 +    
  56.226 +    public void skipNextArg() throws IOException, TemplateException {
  56.227 +        parseData(NullWriter.INSTANCE, true, true);
  56.228 +    }
  56.229 +    
  56.230 +    public String getNextArg() throws IOException, TemplateException {
  56.231          StringWriter sw = new StringWriter();
  56.232          parseNextArg(sw);
  56.233          sw.close();
  56.234          return sw.toString();
  56.235      }
  56.236 -
  56.237 +    
  56.238      public List<String> getArgs() throws IOException, TemplateException {
  56.239 -	List<String> l = new ArrayList<String>();
  56.240 -
  56.241 -	while (available) {
  56.242 -	    l.add(getNextArg());
  56.243 -	}
  56.244 -	
  56.245 -	return l;
  56.246 +        List<String> l = new ArrayList<String>();
  56.247 +        
  56.248 +        while (available) {
  56.249 +            l.add(getNextArg());
  56.250 +        }
  56.251 +        
  56.252 +        return l;
  56.253      }
  56.254 -
  56.255 +    
  56.256      public boolean hasMoreData() {
  56.257          return available;
  56.258      }
  56.259 -
  56.260 +    
  56.261 +    public int getLastReturnCode() {
  56.262 +        return lastReturnCode;
  56.263 +    }
  56.264 +    
  56.265      public TemplateParser getTemplateParser() {
  56.266          return tp;
  56.267      }
  56.268      
  56.269 +    public Context getContext() {
  56.270 +        return tp.getContext();
  56.271 +    }
  56.272 +    
  56.273      public TemplateReader getTemplateReader() {
  56.274          return in;
  56.275      }
  56.276 +    
  56.277 +    public File createFile(String path) {
  56.278 +        File file = new File(path);
  56.279 +        
  56.280 +        if (file.isAbsolute())
  56.281 +            return file;
  56.282 +        
  56.283 +        return new File(tp.getContext().getBaseDirectory(), path);
  56.284 +    }
  56.285  }
    57.1 --- a/src/kryshen/tema/Functions.java	Thu Dec 14 23:22:05 2006 +0300
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,70 +0,0 @@
    57.4 -/*
    57.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    57.6 - *
    57.7 - *  This program is free software; you can redistribute it and/or modify
    57.8 - *  it under the terms of the GNU General Public License as published by
    57.9 - *  the Free Software Foundation; either version 2 of the License, or
   57.10 - *  (at your option) any later version.
   57.11 - *
   57.12 - *  This program is distributed in the hope that it will be useful,
   57.13 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   57.14 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   57.15 - *  GNU General Public License for more details.
   57.16 - *
   57.17 - *  You should have received a copy of the GNU General Public License
   57.18 - *  along with this program; if not, write to the Free Software
   57.19 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   57.20 - *
   57.21 - *  $Id: Functions.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $
   57.22 - */
   57.23 -
   57.24 -package kryshen.tema;
   57.25 -
   57.26 -import java.io.*;
   57.27 -import java.util.*;
   57.28 -
   57.29 -import kryshen.tema.functions.*;
   57.30 -
   57.31 -/**
   57.32 - * Standard TEMA functions.
   57.33 - *
   57.34 - * @author Mikhail A. Kryshen
   57.35 - */
   57.36 -public class Functions {
   57.37 -    // TODO: arithmetics, conditions
   57.38 -
   57.39 -    /**
   57.40 -     * Register all standard functions.
   57.41 -     *
   57.42 -     * @param p TemplateParser to register functions in.
   57.43 -     */
   57.44 -    static void registerAllFunctions(TemplateParser p) {
   57.45 -        p.registerFunction("!",          Standard.NULL_OUTPUT);
   57.46 -        p.registerFunction("set",        Standard.SET);
   57.47 -        p.registerFunction("load",       Standard.LOAD);
   57.48 -        p.registerFunction("query",      Standard.QUERY);
   57.49 -        p.registerFunction("prepare",    Standard.PREPARE);
   57.50 -        p.registerFunction("replace",    Standard.REPLACE);
   57.51 -        p.registerFunction("xml_escape", Standard.XML_ESCAPE);
   57.52 -        p.registerFunction("xml_cdata",  Standard.XML_CDATA);
   57.53 -
   57.54 -        p.registerFunction("define",     Define.DEFINE);
   57.55 -
   57.56 -        p.registerFunction("write",      IO.WRITE);
   57.57 -        p.registerFunction("read",       IO.READ);
   57.58 -        p.registerFunction("include",    IO.INCLUDE);
   57.59 -        p.registerFunction("copy",       IO.COPY);
   57.60 -
   57.61 -	p.registerFunction("false",      Logics.FALSE);
   57.62 -	p.registerFunction("true",       Logics.TRUE);
   57.63 -        p.registerFunction("optional",   Logics.OPTIONAL);
   57.64 -
   57.65 -        p.registerFunction("image",      ImageConverter.IMAGE);
   57.66 -
   57.67 -	/* 
   57.68 -	   Other functuons:
   57.69 -	   db - defined in Tema.query().
   57.70 -	   nextarg, data - defined in Define.invoke().
   57.71 -	*/
   57.72 -    }
   57.73 -}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/src/kryshen/tema/GlobalContext.java	Tue Feb 19 20:32:17 2008 +0300
    58.3 @@ -0,0 +1,95 @@
    58.4 +/*
    58.5 + *  Copyright 2006-2008 Mikhail Kryshen
    58.6 + *
    58.7 + *  This file is part of Tema.
    58.8 + *
    58.9 + *  Tema is free software: you can redistribute it and/or modify it
   58.10 + *  under the terms of the GNU Lesser General Public License as
   58.11 + *  published by the Free Software Foundation, either version 3 of the
   58.12 + *  License, or (at your option) any later version.
   58.13 + *
   58.14 + *  Tema is distributed in the hope that it will be useful,
   58.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   58.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   58.17 + *  GNU Lesser General Public License for more details.
   58.18 + *
   58.19 + *  You should have received a copy of the 
   58.20 + *  GNU Lesser General Public License along with Tema.  
   58.21 + *  If not, see <http://www.gnu.org/licenses/>.
   58.22 + *
   58.23 + *  $Id: GlobalContext.java,v 1.16 2008/02/19 16:21:00 mikhail Exp $
   58.24 + */
   58.25 +
   58.26 +package kryshen.tema;
   58.27 +
   58.28 +import java.io.File;
   58.29 +import kryshen.tema.functions.Database;
   58.30 +import kryshen.tema.functions.Define;
   58.31 +import kryshen.tema.functions.IO;
   58.32 +import kryshen.tema.functions.ImageConverter;
   58.33 +import kryshen.tema.functions.Control;
   58.34 +import kryshen.tema.functions.Standard;
   58.35 +import kryshen.tema.functions.Strings;
   58.36 +
   58.37 +/**
   58.38 + * Context to hold exported variables and standard Tema definitions.
   58.39 + *
   58.40 + * @author Mikhail Kryshen
   58.41 + */
   58.42 +class GlobalContext extends Context {    
   58.43 +    
   58.44 +    GlobalContext() {
   58.45 +        super(new File(System.getProperty("user.dir")));
   58.46 +        
   58.47 +        // Register all standard functions.
   58.48 +        // TODO: arithmetics
   58.49 +        
   58.50 +        set("tema",       Standard.TEMA);
   58.51 +        set("echo",       Standard.ECHO);
   58.52 +        set("",           Standard.ECHO);
   58.53 +        set("!",          Standard.SKIP);
   58.54 +        set("silent",     Standard.SILENT);
   58.55 +        set("set",        Standard.SET);        
   58.56 +        set("unset",      Standard.UNSET);
   58.57 +        set("export",     Standard.EXPORT);
   58.58 +        set("assign",     Standard.ASSIGN);
   58.59 +        set("invoke",     Standard.INVOKE);
   58.60 +        set("load",       Standard.LOAD);
   58.61 +        
   58.62 +        set("to_upper",   Strings.TO_UPPER);
   58.63 +        set("to_lower",   Strings.TO_LOWER);
   58.64 +        set("substring",  Strings.SUBSTRING);
   58.65 +        set("equal",      Strings.EQUAL);
   58.66 +        set("xml_escape", Strings.XML_ESCAPE);
   58.67 +        set("xml_cdata",  Strings.XML_CDATA);
   58.68 +        set("char",       Strings.CHAR);
   58.69 +        set("replace",    Strings.REPLACE);
   58.70 +        set("regex_match",         Strings.REGEX_MATCH);
   58.71 +        set("regex_replace_first", Strings.REGEX_REPLACE_FIRST);
   58.72 +        set("regex_replace_all",   Strings.REGEX_REPLACE_ALL);
   58.73 +        
   58.74 +        set("define",     Define.DEFINE);
   58.75 +        
   58.76 +        set("write",      IO.WRITE);
   58.77 +        set("read",       IO.READ);
   58.78 +        set("include",    IO.INCLUDE);
   58.79 +        set("copy",       IO.COPY);
   58.80 +        set("file",       IO.FILE);
   58.81 +        
   58.82 +        set("false",      Control.FALSE);
   58.83 +        set("true",       Control.TRUE);
   58.84 +        set("not",        Control.NOT);
   58.85 +        set("optional",   Control.OPTIONAL);
   58.86 +        set("if",         Control.IF);
   58.87 +        set("if_else",    Control.IF_ELSE);
   58.88 +        set("while",      Control.WHILE);
   58.89 +        
   58.90 +        set("db_connect",    Database.CONNECT);
   58.91 +        set("db_prepare",    Database.PREPARE);
   58.92 +        set("db_query",      Database.QUERY);
   58.93 +        
   58.94 +        set("convert_image", ImageConverter.CONVERT_IMAGE);
   58.95 +        
   58.96 +        // Other functions are defined in classes Database and Define.
   58.97 +    }
   58.98 +}
    59.1 --- a/src/kryshen/tema/Tema.java	Thu Dec 14 23:22:05 2006 +0300
    59.2 +++ b/src/kryshen/tema/Tema.java	Tue Feb 19 20:32:17 2008 +0300
    59.3 @@ -1,364 +1,248 @@
    59.4  /*
    59.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    59.6 + *  Copyright 2006-2008 Mikhail Kryshen
    59.7   *
    59.8 - *  This program is free software; you can redistribute it and/or modify
    59.9 - *  it under the terms of the GNU General Public License as published by
   59.10 - *  the Free Software Foundation; either version 2 of the License, or
   59.11 - *  (at your option) any later version.
   59.12 + *  This file is part of Tema.
   59.13   *
   59.14 - *  This program is distributed in the hope that it will be useful,
   59.15 + *  Tema is free software: you can redistribute it and/or modify it
   59.16 + *  under the terms of the GNU Lesser General Public License as
   59.17 + *  published by the Free Software Foundation, either version 3 of the
   59.18 + *  License, or (at your option) any later version.
   59.19 + *
   59.20 + *  Tema is distributed in the hope that it will be useful,
   59.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   59.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   59.23 - *  GNU General Public License for more details.
   59.24 + *  GNU Lesser General Public License for more details.
   59.25   *
   59.26 - *  You should have received a copy of the GNU General Public License
   59.27 - *  along with this program; if not, write to the Free Software
   59.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   59.29 + *  You should have received a copy of the 
   59.30 + *  GNU Lesser General Public License along with Tema.  
   59.31 + *  If not, see <http://www.gnu.org/licenses/>.
   59.32   *
   59.33 - *  $Id: Tema.java,v 1.17 2006/12/14 19:44:31 mikhail Exp $
   59.34 + *  $Id: Tema.java,v 1.42 2008/02/19 17:14:34 mikhail Exp $
   59.35   */
   59.36  
   59.37  package kryshen.tema;
   59.38  
   59.39 -import java.sql.Driver;
   59.40 -import java.sql.DriverManager;
   59.41 -import java.sql.Connection;
   59.42 -import java.sql.Statement;
   59.43 -import java.sql.PreparedStatement;
   59.44 -import java.sql.ResultSet;
   59.45 -import java.sql.ResultSetMetaData;
   59.46 +import java.io.BufferedReader;
   59.47 +import java.io.BufferedWriter;
   59.48 +import java.io.File;
   59.49 +import java.io.FileInputStream;
   59.50 +import java.io.FileOutputStream;
   59.51 +import java.io.IOException;
   59.52 +import java.io.InputStream;
   59.53 +import java.io.InputStreamReader;
   59.54 +import java.io.OutputStream;
   59.55 +import java.io.OutputStreamWriter;
   59.56 +import java.io.PrintStream;
   59.57 +import java.io.Writer;
   59.58 +import java.nio.charset.Charset;
   59.59  import java.sql.SQLException;
   59.60 -
   59.61 -import java.util.Map;
   59.62 -import java.util.HashMap;
   59.63 -import java.util.Properties;
   59.64 -import java.util.List;
   59.65 -import java.util.Collections;
   59.66 -
   59.67 -import java.io.*;
   59.68 -
   59.69  import kryshen.tema.demo.DemoFrame;
   59.70 +import kryshen.tema.io.TemplateReader;
   59.71 +import org.apache.commons.cli.CommandLine;
   59.72 +import org.apache.commons.cli.CommandLineParser;
   59.73 +import org.apache.commons.cli.GnuParser;
   59.74 +import org.apache.commons.cli.HelpFormatter;
   59.75 +import org.apache.commons.cli.Options;
   59.76 +import org.apache.commons.cli.ParseException;
   59.77  
   59.78  /**
   59.79   * Tema main class.
   59.80   *
   59.81 - * @author Mikhail A. Kryshen
   59.82 + * @author Mikhail Kryshen
   59.83   */
   59.84  public class Tema {
   59.85 -    public static final String TITLE = "TEMA";
   59.86 -    public static final String VERSION = "0.1";
   59.87 -    public static final String AUTHOR = "Mikhail A. Kryshen";
   59.88 -
   59.89 -    private static final String CONFIG_FILE = "tema.properties";
   59.90 -    private static final String ENV_PREFIX = "kryshen.tema.";
   59.91 -
   59.92 -    private static Properties config = new Properties();
   59.93 -    private static Connection connection = null;
   59.94 -
   59.95 -    private static String inputEncoding;
   59.96 -    private static String outputEncoding;
   59.97 -
   59.98 -    private static Map<File, String> fileCache = null;
   59.99 -
  59.100 -    public static void main(String[] args) 
  59.101 -	throws IOException, SQLException,
  59.102 -	       ClassNotFoundException, InstantiationException, 
  59.103 -	       IllegalAccessException {
  59.104 -	
  59.105 +    public static final String TITLE = "Tema";
  59.106 +    public static final String VERSION = "0.3";
  59.107 +    public static final String AUTHOR = "Mikhail Kryshen";    
  59.108 +    public static final String COPYRIGHT = 
  59.109 +            "Copyright 2008 Mikhail Kryshen <mikhail@kryshen.pp.ru>";
  59.110 +    public static final String LICENSE = 
  59.111 +            "This is free software. " + 
  59.112 +            "You may redistribute copies of it under the terms of" + 
  59.113 +            System.getProperty("line.separator") + 
  59.114 +            "the GNU Lesser General Public License version 3 or later" + 
  59.115 +            System.getProperty("line.separator") + 
  59.116 +            "<http://gnu.org/licenses/lgpl.html>.";
  59.117 +        
  59.118 +    private static final String DEFAULT_CHARSET =
  59.119 +            Charset.defaultCharset().name();
  59.120 +    
  59.121 +    private static String inputEncoding = DEFAULT_CHARSET;
  59.122 +    private static String outputEncoding = DEFAULT_CHARSET;
  59.123 +    
  59.124 +    public static void main(String[] args)
  59.125 +    throws IOException, SQLException,
  59.126 +            ClassNotFoundException, InstantiationException,
  59.127 +            IllegalAccessException {
  59.128 +        
  59.129          boolean demo = false;
  59.130          boolean version = false;
  59.131          boolean help = false;
  59.132 -
  59.133 -        // Parse arguments.
  59.134 -        for (int i = 0; i < args.length; i++) {
  59.135 -            if ("-demo".equals(args[i]) || 
  59.136 -                "-d".equals(args[i])) {
  59.137 -                demo = true;
  59.138 -            } else if ("-version".equals(args[i]) ||
  59.139 -                       "-v".equals(args[i])) {
  59.140 -                version = true;
  59.141 -            } else if ("-help".equals(args[i]) ||
  59.142 -                       "-h".equals(args[i]) ||
  59.143 -                       "-usage".equals(args[i]) ||
  59.144 -                       "-u".equals(args[i])) {
  59.145 -                help = true;
  59.146 -            } else {
  59.147 -                System.err.println("Invalid option: " + args[i]);
  59.148 -                return;
  59.149 -            }
  59.150 +        
  59.151 +        Options options = new Options();
  59.152 +        
  59.153 +        options.addOption(null, "demo", false, "demo mode");
  59.154 +        options.addOption("v", "version", false,
  59.155 +                "print the version information and exit");
  59.156 +        options.addOption("h", "help", false,
  59.157 +                "print this help message");
  59.158 +        options.addOption("o", "output", true,
  59.159 +                "output file");
  59.160 +        options.addOption(null, "log", true,
  59.161 +                "log all error messages to file");
  59.162 +        options.addOption(null, "input-encoding", true,
  59.163 +                "input encoding");
  59.164 +        options.addOption(null, "output-encoding", true,
  59.165 +                "output encoding");
  59.166 +        
  59.167 +        CommandLineParser parser = new GnuParser();
  59.168 +        CommandLine line;
  59.169 +        
  59.170 +        try {
  59.171 +            line = parser.parse(options, args );
  59.172 +        } catch (ParseException ex) {
  59.173 +            System.err.println(ex.getMessage());
  59.174 +            System.exit(1);
  59.175 +            return; // to avoid "not initialized" compile-time errors.
  59.176          }
  59.177 -
  59.178 -        if (version || help) {
  59.179 -            System.err.println(TITLE + " " + VERSION + " by " + AUTHOR);        
  59.180 -
  59.181 -            if (help) {
  59.182 -                PrintStream err = System.err;
  59.183 -                
  59.184 -                err.println();
  59.185 -                err.println("Usage: tema [OPTIONS]");
  59.186 -                err.println();
  59.187 -                err.println("Options:");
  59.188 -                err.println("  -d[emo]             Demo mode");
  59.189 -                err.println("  -v[ersion]          Print version");
  59.190 -                err.println("  -h[help] -u[sage]   Print this help message");
  59.191 -            }
  59.192 +        
  59.193 +        if (line.hasOption("version")) {
  59.194 +            System.err.println(TITLE + " " + VERSION);
  59.195 +            System.err.println(COPYRIGHT);
  59.196 +            System.err.println(LICENSE);
  59.197              return;
  59.198          }
  59.199 -
  59.200 -        if (demo) {
  59.201 -            // Run in demo mode.
  59.202 +        
  59.203 +        if (line.hasOption("help")) {
  59.204 +            HelpFormatter formatter = new HelpFormatter();
  59.205 +            formatter.printHelp("tema [options] [files]", options);
  59.206 +            return;
  59.207 +        }       
  59.208 +        
  59.209 +        if (line.hasOption("input-encoding")) {
  59.210 +            inputEncoding = line.getOptionValue("input-encoding");
  59.211 +        }
  59.212 +        
  59.213 +        if (line.hasOption("output-encoding")) {
  59.214 +            outputEncoding = line.getOptionValue("output-encoding");
  59.215 +        }
  59.216 +        
  59.217 +        if (line.hasOption("log")) {
  59.218 +            System.setErr(new PrintStream
  59.219 +                    (new FileOutputStream(line.getOptionValue("log"))));
  59.220 +        }
  59.221 +        
  59.222 +        if (line.hasOption("demo")) {
  59.223 +            // Open the demo console.
  59.224              DemoFrame df = new DemoFrame();
  59.225              df.pack();
  59.226              df.setVisible(true);
  59.227              return;
  59.228          }
  59.229 -
  59.230 -        process();
  59.231 +        
  59.232 +        Writer out;
  59.233 +        
  59.234 +        if (line.hasOption("output")) {
  59.235 +            File outfile = new File(line.getOptionValue("output"));
  59.236 +            out = createFileWriter(outfile);
  59.237 +        } else {
  59.238 +            out = new OutputStreamWriter(System.out, outputEncoding) {
  59.239 +                @Override
  59.240 +                public void write(int c) throws IOException {
  59.241 +                    super.write(c);
  59.242 +                    if (c == '\r' || c == '\n')
  59.243 +                        flush();
  59.244 +                }
  59.245 +                
  59.246 +                @Override
  59.247 +                public void write(char cbuf[], int off, int len)
  59.248 +                throws IOException {
  59.249 +                    super.write(cbuf, off, len);
  59.250 +                    flush();
  59.251 +                }
  59.252 +                
  59.253 +                @Override
  59.254 +                public void write(String str, int off, int len)
  59.255 +                throws IOException {
  59.256 +                    super.write(str, off, len);
  59.257 +                    flush();
  59.258 +                }
  59.259 +            };
  59.260 +        }
  59.261 +        
  59.262 +        String[] files = line.getArgs();
  59.263 +        
  59.264 +        if (files.length == 0) {
  59.265 +            TemplateReader in = createTemplateReader(System.in);
  59.266 +            if (!process(in, out)) {
  59.267 +                System.exit(1);
  59.268 +            }
  59.269 +        }
  59.270 +        
  59.271 +        for (String file: files) {
  59.272 +            TemplateReader in = createTemplateReader(new File(file));
  59.273 +            if (!process(in, out)) {
  59.274 +                System.exit(1);
  59.275 +            }
  59.276 +        }
  59.277 +        
  59.278 +        out.close();
  59.279      }
  59.280 -
  59.281 -    /**
  59.282 -     * Standard execution.
  59.283 -     */
  59.284 -    private static void process()
  59.285 -        throws IOException, SQLException,
  59.286 -               ClassNotFoundException, InstantiationException, 
  59.287 -               IllegalAccessException {
  59.288 -
  59.289 -        InputStream configIn = new FileInputStream(CONFIG_FILE);
  59.290 -        config.load(configIn);
  59.291 -        configIn.close();
  59.292 +    
  59.293 +    private static boolean process(TemplateReader in, Writer out)
  59.294 +    throws IOException {
  59.295          
  59.296 -        configure();
  59.297 -	
  59.298 -	String main = getProperty("main_template");
  59.299 -	String output = getProperty("output");
  59.300 -	
  59.301 -	Writer out;
  59.302 -
  59.303 -	if ("stderr".equals(output))
  59.304 -	    out = new OutputStreamWriter(System.err);
  59.305 -	else
  59.306 -	    out = new OutputStreamWriter(System.out);
  59.307 -
  59.308 -        TemplateReader in = createTemplateReader(new File(main));
  59.309          TemplateParser p = new TemplateParser();
  59.310 -        TemplateException te = null;
  59.311 -
  59.312 -	try {
  59.313 -	    p.parse(in, out);
  59.314 +        TemplateException ex = null;
  59.315 +                        
  59.316 +        p.getContext().set("input_encoding",  inputEncoding);
  59.317 +        p.getContext().set("output_encoding", outputEncoding);
  59.318 +        
  59.319 +        try {
  59.320 +            p.parse(in, out);
  59.321          } catch (TemplateException e) {
  59.322 -            te = e;
  59.323 -	} finally {
  59.324 -	    in.close();
  59.325 -	    out.flush();
  59.326 -	}  
  59.327 -
  59.328 -        if (te != null) {
  59.329 -            System.err.println(te.getMessage());
  59.330 -            if (te.getCause() != null) {
  59.331 -                System.err.println("Caused by " + te.getCause());
  59.332 +            ex = e;
  59.333 +        } finally {
  59.334 +            in.close();
  59.335 +        }
  59.336 +        
  59.337 +        if (ex != null) {
  59.338 +            System.err.println(ex.getMessage());
  59.339 +            if (ex.getCause() != null) {
  59.340 +                System.err.println("Caused by " + ex.getCause());
  59.341              }
  59.342 -        } else {
  59.343 -            System.err.println("Done");
  59.344 +            return false;
  59.345          }
  59.346 +        
  59.347 +        return true;
  59.348      }
  59.349 -
  59.350 -    private static void configure() 
  59.351 -        throws IOException, SQLException, IllegalAccessException,
  59.352 -               ClassNotFoundException, InstantiationException {
  59.353 -
  59.354 -        String logFile = getProperty("log");
  59.355 -        if (logFile != null && logFile.length() > 0)
  59.356 -            System.setErr(new PrintStream(new FileOutputStream(logFile)));
  59.357 -
  59.358 -	if (Boolean.parseBoolean(getProperty("cache_read")) == true)
  59.359 -	    fileCache = new HashMap<File, String>();
  59.360 -
  59.361 -	inputEncoding = getProperty("input_encoding", "iso-8859-1");
  59.362 -	outputEncoding = getProperty("output_encoding", "iso-8859-1");
  59.363 -
  59.364 -	String resourceProperty = getProperty("resource");
  59.365 -
  59.366 -	if (resourceProperty != null) {
  59.367 -	    String driverProperty = getProperty("driver");
  59.368 -	    if (driverProperty != null) {
  59.369 -		// Register driver.  
  59.370 -		Driver d = (Driver)Class.forName(driverProperty).newInstance();
  59.371 -	    }
  59.372 -	
  59.373 -	    // Open connection.
  59.374 -	    connection = DriverManager.getConnection(resourceProperty);
  59.375 -	}
  59.376 +    
  59.377 +    public static BufferedWriter createFileWriter(File file)
  59.378 +    throws IOException {
  59.379 +        
  59.380 +        OutputStream os = new FileOutputStream(file);
  59.381 +        return new BufferedWriter
  59.382 +                (new OutputStreamWriter(os, Tema.outputEncoding));
  59.383      }
  59.384 -
  59.385      
  59.386 -
  59.387 -    /**
  59.388 -     * Get configuration property.
  59.389 -     */
  59.390 -    public static String getProperty(String name) {
  59.391 -        String value = System.getProperty(ENV_PREFIX + name);
  59.392 -        if (value != null) return value;
  59.393 -        return config.getProperty(name);
  59.394 +    public static BufferedReader createFileReader(File file)
  59.395 +    throws IOException {
  59.396 +        
  59.397 +        InputStream is = new FileInputStream(file);
  59.398 +        return new BufferedReader
  59.399 +                (new InputStreamReader(is, Tema.inputEncoding));
  59.400      }
  59.401 -
  59.402 -    /**
  59.403 -     * Get configuration property.
  59.404 -     */
  59.405 -    public static String getProperty(String name, String fallback) {
  59.406 -	String value = getProperty(name);
  59.407 -	if (value != null) return value;
  59.408 -	return fallback;
  59.409 +    
  59.410 +    public static TemplateReader createTemplateReader(File file)
  59.411 +    throws IOException {
  59.412 +        
  59.413 +        return new TemplateReader(createFileReader(file), file.getPath());
  59.414      }
  59.415 -
  59.416 -    /**
  59.417 -     * Process database query.
  59.418 -     *
  59.419 -     * @param templateReader reader for the template 
  59.420 -     *                       to fill with data.
  59.421 -     * @param ps query statement to execute.
  59.422 -     * @param args list of query parameters.
  59.423 -     * @param superParser invoking object.
  59.424 -     * @param out Writer to output processed data.
  59.425 -     *
  59.426 -     * @return number of processed rows in query result.
  59.427 -     */
  59.428 -    public static int query(TemplateReader templateReader,
  59.429 -                            PreparedStatement ps,
  59.430 -                            List<String> args,
  59.431 -                            TemplateParser superParser, 
  59.432 -                            Writer out)
  59.433 -	throws IOException, SQLException, TemplateException {
  59.434 -
  59.435 -	int i = 1;
  59.436 -
  59.437 -	for (String arg : args) {
  59.438 -	    ps.setString(i++, arg);
  59.439 -	}
  59.440 -	
  59.441 -	ResultSet r = ps.executeQuery();
  59.442 -	ResultSetMetaData rm = r.getMetaData();
  59.443 -	int columnCount = rm.getColumnCount();
  59.444 -
  59.445 -	String[] names = new String[columnCount];
  59.446 -	
  59.447 -	for (int j = 0; j < columnCount; j++) {
  59.448 -	    names[j] = rm.getColumnName(j + 1);
  59.449 -	}
  59.450 -
  59.451 -	final TemplateParser p = new TemplateParser(superParser);
  59.452 -	final HashMap<String, Object> fields = new HashMap<String, Object>();
  59.453 -
  59.454 -        p.registerFunction("db", new Function() {
  59.455 -                public int invoke(FunctionDataParser fdp, 
  59.456 -                                  final Writer out)
  59.457 -                    throws IOException, TemplateException {
  59.458 -                    
  59.459 -                    String name = fdp.getData();
  59.460 -                    Object value = fields.get(name);
  59.461 -		    
  59.462 -                    return p.parseValue(value, out);
  59.463 -                }
  59.464 -            });
  59.465 -
  59.466 -	for (i = 1; r.next(); i++) {
  59.467 -
  59.468 -	    for (int j = 0; j < columnCount; j++) {
  59.469 -		Object value = r.getObject(j + 1);
  59.470 -		if (r.wasNull()) value = null;
  59.471 -                
  59.472 -		fields.put(names[j], value);
  59.473 -	    }
  59.474 -
  59.475 -	    p.setValue("number", i);
  59.476 -            p.parse(templateReader, out);
  59.477 -	    templateReader.reset();
  59.478 -            fields.clear();
  59.479 -	}
  59.480 -
  59.481 -	r.close();
  59.482 -	ps.clearParameters();
  59.483 -	return i - 1;
  59.484 -    }
  59.485 -
  59.486 -    public static BufferedWriter createFileWriter(String filename) 
  59.487 -        throws IOException {
  59.488 -
  59.489 -	OutputStream os = new FileOutputStream(filename);
  59.490 -	return new BufferedWriter
  59.491 -            (new OutputStreamWriter(os, Tema.outputEncoding));
  59.492 -    }
  59.493 -
  59.494 -    public static BufferedReader createFileReader(File file)
  59.495 -        throws IOException {
  59.496 -
  59.497 -	InputStream is = new FileInputStream(file);
  59.498 -	return new BufferedReader
  59.499 -            (new InputStreamReader(is, Tema.inputEncoding));
  59.500 -    }
  59.501 -
  59.502 -    public static TemplateReader createTemplateReader(File file)
  59.503 -        throws IOException {
  59.504 -
  59.505 -        return new TemplateReader
  59.506 -            (new LineNumberReader(createCachedFileReader(file)), file.getPath());
  59.507 -    }
  59.508 -
  59.509 -    /**
  59.510 -     * Creates StringReader for a cached file if caching is enabled or
  59.511 -     * a BufferedReader.
  59.512 -     *
  59.513 -     * @param file File to read.
  59.514 -     * @return Reader for a file.
  59.515 -     */
  59.516 -    public static Reader createCachedFileReader(File file) 
  59.517 -        throws IOException {
  59.518 +    
  59.519 +    public static TemplateReader createTemplateReader(InputStream in)
  59.520 +    throws IOException {
  59.521          
  59.522 -	if (fileCache != null) return new StringReader(readFile(file));
  59.523 -	else return createFileReader(file);
  59.524 -    }
  59.525 -
  59.526 -    /**
  59.527 -     * Read text file.
  59.528 -     *
  59.529 -     * @return file contents.
  59.530 -     */
  59.531 -    public static String readFile(File file) throws IOException {
  59.532 -	String data;
  59.533 -        
  59.534 -	if (fileCache != null) {
  59.535 -	    data = fileCache.get(file);	    
  59.536 -	    if (data != null) return data;
  59.537 -	}
  59.538 -        
  59.539 -        Reader r = new BufferedReader(createFileReader(file));
  59.540 -
  59.541 -        // FIXME: possible overflow (long -> int).
  59.542 -	StringBuffer sb = new StringBuffer((int)file.length());
  59.543 -
  59.544 -	try {
  59.545 - 	    for (int c = r.read(); c >= 0; c = r.read()) {
  59.546 - 		sb.append((char)c);
  59.547 - 	    }
  59.548 -	} finally {
  59.549 -	    r.close();
  59.550 -	}
  59.551 -
  59.552 -	data = sb.toString();
  59.553 -
  59.554 -	if (fileCache != null) {
  59.555 -	    fileCache.put(file, data);
  59.556 -	}
  59.557 -
  59.558 -	return data;
  59.559 -    }
  59.560 -
  59.561 -    /**
  59.562 -     * Get database connection.
  59.563 -     *
  59.564 -     * @return database connection if any was configured.
  59.565 -     */
  59.566 -    public static Connection getDbConnection() {
  59.567 -        return connection;
  59.568 +        return new TemplateReader(
  59.569 +                new InputStreamReader(in, Tema.inputEncoding));
  59.570      }
  59.571  }
    60.1 --- a/src/kryshen/tema/TemplateException.java	Thu Dec 14 23:22:05 2006 +0300
    60.2 +++ b/src/kryshen/tema/TemplateException.java	Tue Feb 19 20:32:17 2008 +0300
    60.3 @@ -1,29 +1,33 @@
    60.4  /*
    60.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    60.6 + *  Copyright 2006-2008 Mikhail Kryshen
    60.7   *
    60.8 - *  This program is free software; you can redistribute it and/or modify
    60.9 - *  it under the terms of the GNU General Public License as published by
   60.10 - *  the Free Software Foundation; either version 2 of the License, or
   60.11 - *  (at your option) any later version.
   60.12 + *  This file is part of Tema.
   60.13   *
   60.14 - *  This program is distributed in the hope that it will be useful,
   60.15 + *  Tema is free software: you can redistribute it and/or modify it
   60.16 + *  under the terms of the GNU Lesser General Public License as
   60.17 + *  published by the Free Software Foundation, either version 3 of the
   60.18 + *  License, or (at your option) any later version.
   60.19 + *
   60.20 + *  Tema is distributed in the hope that it will be useful,
   60.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   60.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   60.23 - *  GNU General Public License for more details.
   60.24 + *  GNU Lesser General Public License for more details.
   60.25   *
   60.26 - *  You should have received a copy of the GNU General Public License
   60.27 - *  along with this program; if not, write to the Free Software
   60.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   60.29 + *  You should have received a copy of the 
   60.30 + *  GNU Lesser General Public License along with Tema.  
   60.31 + *  If not, see <http://www.gnu.org/licenses/>.
   60.32   *
   60.33 - *  $Id: TemplateException.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   60.34 + *  $Id: TemplateException.java,v 1.12 2008/02/16 17:56:34 mikhail Exp $
   60.35   */
   60.36  
   60.37  package kryshen.tema;
   60.38  
   60.39 +import kryshen.tema.io.TemplateReader;
   60.40 +
   60.41  /**
   60.42   * Signals that template parsing fails.
   60.43   *
   60.44 - * @author Mikhail A. Kryshen
   60.45 + * @author Mikhail Kryshen
   60.46   */
   60.47  public class TemplateException extends Exception {
   60.48      //private String source;
    61.1 --- a/src/kryshen/tema/TemplateParser.java	Thu Dec 14 23:22:05 2006 +0300
    61.2 +++ b/src/kryshen/tema/TemplateParser.java	Tue Feb 19 20:32:17 2008 +0300
    61.3 @@ -1,296 +1,445 @@
    61.4  /*
    61.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    61.6 + *  Copyright 2006-2008 Mikhail Kryshen
    61.7   *
    61.8 - *  This program is free software; you can redistribute it and/or modify
    61.9 - *  it under the terms of the GNU General Public License as published by
   61.10 - *  the Free Software Foundation; either version 2 of the License, or
   61.11 - *  (at your option) any later version.
   61.12 + *  This file is part of Tema.
   61.13   *
   61.14 - *  This program is distributed in the hope that it will be useful,
   61.15 + *  Tema is free software: you can redistribute it and/or modify it
   61.16 + *  under the terms of the GNU Lesser General Public License as
   61.17 + *  published by the Free Software Foundation, either version 3 of the
   61.18 + *  License, or (at your option) any later version.
   61.19 + *
   61.20 + *  Tema is distributed in the hope that it will be useful,
   61.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   61.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   61.23 - *  GNU General Public License for more details.
   61.24 + *  GNU Lesser General Public License for more details.
   61.25   *
   61.26 - *  You should have received a copy of the GNU General Public License
   61.27 - *  along with this program; if not, write to the Free Software
   61.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   61.29 + *  You should have received a copy of the 
   61.30 + *  GNU Lesser General Public License along with Tema.  
   61.31 + *  If not, see <http://www.gnu.org/licenses/>.
   61.32   *
   61.33 - *  $Id: TemplateParser.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $
   61.34 + *  $Id: TemplateParser.java,v 1.58 2008/02/19 00:20:48 mikhail Exp $
   61.35   */
   61.36  
   61.37  package kryshen.tema;
   61.38  
   61.39 -import java.io.*;
   61.40 -import java.util.*;
   61.41 +import java.io.File;
   61.42 +import java.io.IOException;
   61.43 +import java.io.StringReader;
   61.44 +import java.io.Writer;
   61.45 +import kryshen.tema.io.TemplateReader;
   61.46  
   61.47  /**
   61.48 - * Parser for TEMA templates.
   61.49 + * Parser for Tema templates.
   61.50   *
   61.51 - * @author Mikhail A. Kryshen
   61.52 + * @author Mikhail Kryshen
   61.53   */
   61.54  public class TemplateParser {
   61.55 -    // TODO: report non-critical errors and warnings.
   61.56 -
   61.57 -    static final String SUPER_PREFIX = "super.";
   61.58 -
   61.59      /* Brackets. */
   61.60 -    static final char[] BR_LEFT = {'<', '['};
   61.61 -    static final char[] BR_RIGHT = {'>', ']'};
   61.62 -
   61.63 -    static final char BR_IN = '%';
   61.64 +    public static final String[] BRACKET_OPEN = {"<%", "[%"};
   61.65 +    public static final String[] BRACKET_CLOSE = {"%>", "%]"};
   61.66 +    
   61.67 +    public static final String ESCAPE_NEWLINE = "\\";
   61.68 +    public static final String ESCAPE_WHITESPACE = "\\\\";
   61.69      
   61.70      /* Separators. */
   61.71 -    static final char[] REC_DATA_SEPARATORS = {':'};
   61.72 -    static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; 
   61.73 -    static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'};
   61.74 -
   61.75 +    public static final char[] REC_DATA_SEPARATORS = {':'};
   61.76 +    public static final char[] VERBATIM_DATA_SEPARATORS = {'\\', '`'};
   61.77 +    public static final char[] NOCALL_DATA_SEPARATORS = {'#'};
   61.78 +    public static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'};
   61.79 +    
   61.80      /**
   61.81 -     * Methods of parsing function arguments and data.
   61.82 +     * Specifies how to parse function arguments and data.
   61.83       */
   61.84 -    static enum FunctionData {
   61.85 -	SUBFUNCTION, RECURSIVE, NONRECURSIVE;
   61.86 +    static enum DataFormat {
   61.87 +        RECURSIVE(true, false),
   61.88 +        VERBATIM(false, false),
   61.89 +        NOCALL(false, false),
   61.90 +        SUBFUNCTION(true, true),
   61.91 +        SUBFUNCTION_NOCALL(false, true);
   61.92 +        
   61.93 +        public final boolean call;
   61.94 +        public final boolean subfunction;
   61.95 +        
   61.96 +        DataFormat(boolean call, boolean subfunction) {
   61.97 +            this.call = call;
   61.98 +            this.subfunction = subfunction;
   61.99 +        }
  61.100 +        
  61.101 +        /**
  61.102 +         * Returns no-call equivalent to this format.
  61.103 +         */
  61.104 +        public DataFormat noCall() {
  61.105 +            if (this == RECURSIVE)
  61.106 +                return NOCALL;
  61.107 +            
  61.108 +            if (this == SUBFUNCTION)
  61.109 +                return SUBFUNCTION_NOCALL;
  61.110 +            
  61.111 +            return this;
  61.112 +        }
  61.113      };
  61.114 -
  61.115 +    
  61.116 +    /**
  61.117 +     * Specifies how the template instruction was terminated.
  61.118 +     */
  61.119      static enum Terminator {
  61.120 -	EOF, BRACKET, SEPARATOR;
  61.121 +        EOF, BRACKET, SEPARATOR;
  61.122      };
  61.123 -
  61.124 +    
  61.125 +    /**
  61.126 +     * The result of evaluating template instruction.
  61.127 +     */
  61.128      static class Result {
  61.129 -	Terminator terminator;
  61.130 -	int retCode;
  61.131 -
  61.132 +        Terminator terminator;
  61.133 +        int retCode;
  61.134 +        
  61.135          /** No text had been parsed. */
  61.136 -        boolean empty; 
  61.137 -
  61.138 -	Result(Terminator terminator, int retCode, boolean empty) {
  61.139 +        boolean empty;
  61.140 +        
  61.141 +        Result(Terminator terminator, int retCode, boolean empty) {
  61.142              this.terminator = terminator;
  61.143              this.retCode = retCode;
  61.144              this.empty = empty;
  61.145          }
  61.146 -
  61.147 +        
  61.148          Result() {
  61.149              this(null, -1, true);
  61.150 -        }       
  61.151 -    };    
  61.152 -
  61.153 -    private Map<String, Object> variables = new HashMap<String, Object>();
  61.154 -    private TemplateParser superParser;
  61.155 -
  61.156 +        }
  61.157 +    };
  61.158 +    
  61.159 +    protected final Context context;
  61.160 +    
  61.161      private int termBracket = -1;
  61.162 -
  61.163 +    
  61.164      public TemplateParser() {
  61.165 -        this(null);
  61.166 +        this.context = new Context(new GlobalContext());
  61.167      }
  61.168 -
  61.169 +    
  61.170 +    public TemplateParser(File baseDir) {
  61.171 +        this.context = new Context(new GlobalContext(), baseDir);
  61.172 +    }
  61.173 +    
  61.174      public TemplateParser(TemplateParser superParser) {
  61.175 -	this.superParser = superParser;
  61.176 -
  61.177 -        Functions.registerAllFunctions(this);
  61.178 +        this.context = new Context(superParser.context);
  61.179      }
  61.180 -
  61.181 -    public void registerFunction(String name, Function f) {
  61.182 -        variables.put(name, f);
  61.183 +    
  61.184 +    public TemplateParser(TemplateParser superParser, File baseDir) {
  61.185 +        this.context = new Context(superParser.context, baseDir);
  61.186      }
  61.187 -
  61.188 -    public int parse(TemplateReader in, Writer out) 
  61.189 -	throws IOException, TemplateException {
  61.190 -	
  61.191 -	return parse(in, out, true, null, null).retCode;
  61.192 +    
  61.193 +    public TemplateParser(Context context) {
  61.194 +        this.context = context;
  61.195      }
  61.196 -
  61.197 +    
  61.198      /**
  61.199 -     *  Parse template.
  61.200 +     * Parse template
  61.201 +     *
  61.202 +     * @param in TemplateReader to read template data.
  61.203 +     * @param out Writer for the processed data.
  61.204 +     * @throws IOException if case of I/O error.
  61.205 +     * @throws TemplateException in case of parsing error (syntax
  61.206 +     * error or invalid arguments in template instructions).
  61.207 +     */
  61.208 +    public int parse(TemplateReader in, Writer out)
  61.209 +    throws IOException, TemplateException {
  61.210 +        return parse(in, out, DataFormat.RECURSIVE, null).retCode;
  61.211 +    }
  61.212 +    
  61.213 +    Result parse(TemplateReader in, Writer out, DataFormat format)
  61.214 +    throws IOException, TemplateException {
  61.215 +        return parse(in, out, format, null);
  61.216 +    }
  61.217 +    
  61.218 +    /**
  61.219 +     * Parse template.
  61.220       *
  61.221       * @param in TemplateReader to read template data.
  61.222       * @param out Writer to write processed data.
  61.223 -     * @param recursive enables recursive processing.
  61.224 -     * @param separators characters which terminate parsing block.
  61.225 -     * @param leading characters to ignore at the beginning of the block.
  61.226 +     * @param DataFormat specifies parsing mode.
  61.227       */
  61.228 -    Result parse(TemplateReader in, Writer out, boolean recursive, 
  61.229 -                 char[] separators, char[] leading)
  61.230 -	throws IOException, TemplateException {
  61.231 -
  61.232 -	Result result = new Result();
  61.233 -	int lc = -1;
  61.234 -
  61.235 -	while (true) {
  61.236 -	    int c = in.read();
  61.237 +    Result parse(TemplateReader in, Writer out, DataFormat format,
  61.238 +            char[] separators)
  61.239 +            throws IOException, TemplateException {
  61.240 +        
  61.241 +        Result result = new Result();
  61.242 +        
  61.243 +        if (format == DataFormat.SUBFUNCTION ||
  61.244 +                format == DataFormat.SUBFUNCTION_NOCALL) {
  61.245              
  61.246 -            if (leading != null && isSeparator(c, leading))
  61.247 -                continue;
  61.248 -            else
  61.249 -                leading = null;
  61.250 -
  61.251 -            boolean leftBracket = false;
  61.252 -            int index;
  61.253 -
  61.254 -            for (index = 0; index < BR_LEFT.length; index++) {
  61.255 -                if (lc == BR_LEFT[index]) {
  61.256 -                    leftBracket = true;
  61.257 -                    break;
  61.258 +            result.retCode = parseFunction(in, out, format);
  61.259 +            result.empty = false;
  61.260 +            return result;
  61.261 +        }
  61.262 +        
  61.263 +        while (true) {
  61.264 +            if (format != DataFormat.VERBATIM) {
  61.265 +                int openBracket = matchInput(in, BRACKET_OPEN);
  61.266 +                
  61.267 +                if (openBracket >= 0) {
  61.268 +                    if (result.retCode < 0)
  61.269 +                        result.retCode = 0;
  61.270 +                    
  61.271 +                    if (!format.call) {
  61.272 +                        out.write(BRACKET_OPEN[openBracket]);
  61.273 +                    }
  61.274 +                    
  61.275 +                    int tb = termBracket;
  61.276 +                    termBracket = openBracket;
  61.277 +                    result.retCode += Math.abs(parseFunction(in, out, format));
  61.278 +                    result.empty = false;
  61.279 +                    termBracket = tb;
  61.280 +                    
  61.281 +                    if (!format.call) {
  61.282 +                        out.write(BRACKET_CLOSE[openBracket]);
  61.283 +                    }
  61.284 +                    
  61.285 +                    continue;
  61.286                  }
  61.287              }
  61.288 -
  61.289 -	    if (recursive && leftBracket && c == BR_IN) {
  61.290 -		
  61.291 -                if (result.retCode < 0)
  61.292 -                    result.retCode = 0;
  61.293 -
  61.294 -		lc = -1;
  61.295 -                int tb = termBracket;
  61.296 -                termBracket = BR_RIGHT[index];
  61.297 -		result.retCode += parseFunction(in, out);
  61.298 -                termBracket = tb;
  61.299 -		
  61.300 -	    } else if (lc == BR_IN && c == termBracket) {
  61.301 -		
  61.302 -		lc = -1;
  61.303 -		result.terminator = Terminator.BRACKET;
  61.304 -		break;
  61.305 -		
  61.306 -	    } else {
  61.307 -
  61.308 -		if (lc >= 0)
  61.309 -		    out.write(lc);
  61.310 -	    
  61.311 -		lc = c;
  61.312 -	    }
  61.313 -
  61.314 -	    if (c < 0) {
  61.315 -		result.terminator = Terminator.EOF;
  61.316 -		break; 
  61.317 -	    } else if (separators != null && isSeparator(c, separators)) {
  61.318 +            
  61.319 +            if (matchCloseBracket(in)) {
  61.320 +                result.terminator = Terminator.BRACKET;
  61.321 +                skipEscaped(in);
  61.322 +                break;
  61.323 +            }
  61.324 +            
  61.325 +            int c = in.read();
  61.326 +            
  61.327 +            if (c < 0) {
  61.328 +//                if (termBracket >= 0) {
  61.329 +//                    throw new TemplateException("Unexpected end of file", in);
  61.330 +//                }
  61.331 +                
  61.332 +                result.terminator = Terminator.EOF;
  61.333 +                break;
  61.334 +            }
  61.335 +            
  61.336 +            if (separators != null && isSeparator(c, separators)) {
  61.337                  result.terminator = Terminator.SEPARATOR;
  61.338                  break;
  61.339              }
  61.340 -
  61.341 +            
  61.342 +            out.write(c);
  61.343              result.empty = false;
  61.344 -	}
  61.345 -
  61.346 -	return result;
  61.347 +        }
  61.348 +        
  61.349 +        return result;
  61.350      }
  61.351 -
  61.352 +    
  61.353 +    /**
  61.354 +     * Check if the closing bracket sequence follows in the reader.
  61.355 +     */
  61.356 +    boolean checkCloseBracket(TemplateReader in) throws IOException {
  61.357 +        boolean match = matchCloseBracket(in);
  61.358 +        
  61.359 +        if (!match)
  61.360 +            return false;
  61.361 +        
  61.362 +        // Put the matched characters back to the stream
  61.363 +        in.unread(BRACKET_CLOSE[termBracket].toCharArray());
  61.364 +        
  61.365 +        return true;
  61.366 +    }
  61.367 +    
  61.368 +    private boolean matchCloseBracket(TemplateReader in)
  61.369 +    throws IOException {
  61.370 +        
  61.371 +        if (termBracket < 0)
  61.372 +            return false;
  61.373 +        
  61.374 +        return matchInput(in, BRACKET_CLOSE[termBracket]);
  61.375 +    }
  61.376 +    
  61.377 +    private int matchInput(TemplateReader in, String[] s)
  61.378 +    throws IOException {
  61.379 +        for (int i = 0; i < s.length; i++) {
  61.380 +            if (matchInput(in, s[i]))
  61.381 +                return i;
  61.382 +        }
  61.383 +        
  61.384 +        return -1;
  61.385 +    }
  61.386 +    
  61.387 +    private boolean matchInput(TemplateReader in, String s)
  61.388 +    throws IOException {
  61.389 +        int n = s.length();
  61.390 +        for (int k = 0; k < n; k++) {
  61.391 +            int c = in.read();
  61.392 +            
  61.393 +            if (c != s.charAt(k)) {
  61.394 +                if (c >= 0) {
  61.395 +                    in.unread(c);
  61.396 +                }
  61.397 +                
  61.398 +                for (int j = k - 1; j >= 0; j--) {
  61.399 +                    in.unread(s.charAt(j));
  61.400 +                }
  61.401 +                
  61.402 +                return false;
  61.403 +            }
  61.404 +        }
  61.405 +        
  61.406 +        return true;
  61.407 +    }
  61.408 +    
  61.409 +    void skip(TemplateReader in, char[] chars) throws IOException {
  61.410 +        readLoop:
  61.411 +            while (true) {
  61.412 +                int c = in.read();
  61.413 +                
  61.414 +                if (c < 0)
  61.415 +                    break;
  61.416 +                
  61.417 +                for (int i = 0; i < chars.length; i++) {
  61.418 +                    if (c == chars[i])
  61.419 +                        continue readLoop;
  61.420 +                }
  61.421 +                
  61.422 +                in.unread(c);
  61.423 +                break;
  61.424 +            }
  61.425 +    }
  61.426 +    
  61.427 +    private void skipEscaped(TemplateReader in) throws IOException {
  61.428 +        if (matchInput(in, ESCAPE_WHITESPACE)) {
  61.429 +            int c = in.read();
  61.430 +            
  61.431 +            if (c < 0)
  61.432 +                return;
  61.433 +            
  61.434 +            if (!Character.isWhitespace(c)) {
  61.435 +                in.unread(c);
  61.436 +                in.unread(ESCAPE_WHITESPACE.toCharArray());
  61.437 +                return;
  61.438 +            }
  61.439 +            
  61.440 +            do {
  61.441 +                c = in.read();
  61.442 +            } while (Character.isWhitespace(c));
  61.443 +            
  61.444 +            if (c >= 0)
  61.445 +                in.unread(c);
  61.446 +            
  61.447 +            return;
  61.448 +        }
  61.449 +        
  61.450 +        matchInput(in,
  61.451 +                new String[] {
  61.452 +            ESCAPE_NEWLINE + "\r\n",
  61.453 +            ESCAPE_NEWLINE + "\r",
  61.454 +            ESCAPE_NEWLINE + "\n"});
  61.455 +    }
  61.456 +    
  61.457      boolean isSeparator(int c, char[] separators) {
  61.458          for (char p : separators) {
  61.459              if (c == p) return true;
  61.460          }
  61.461 -
  61.462 +        
  61.463          return false;
  61.464      }
  61.465 -
  61.466 -    int parseFunction(TemplateReader in, Writer out)
  61.467 -	throws IOException, TemplateException {
  61.468 +    
  61.469 +    private int parseFunction(TemplateReader in, Writer out, DataFormat fd)
  61.470 +    throws IOException, TemplateException {
  61.471          
  61.472 -	StringBuffer sb = new StringBuffer();
  61.473 +        StringBuffer sb = new StringBuffer();
  61.474          
  61.475 -	while (true) {
  61.476 -	    int c = in.read();
  61.477 +        while (true) {
  61.478 +            if (termBracket >= 0 &&
  61.479 +                    matchInput(in, BRACKET_CLOSE[termBracket])) {
  61.480 +                throw new TemplateException(
  61.481 +                        "Unexpected end of instruction", in);
  61.482 +            }
  61.483 +            
  61.484 +            int c = in.read();
  61.485 +            
  61.486 +            if (c < 0)
  61.487 +                throw new TemplateException("Unexpected end of file.", in);
  61.488 +            
  61.489 +            if (!fd.call)
  61.490 +                out.write(c);
  61.491              
  61.492              if (isSeparator(c, LIST_SEPARATORS)) {
  61.493 -		return invokeFunction(sb.toString(), 
  61.494 -				      FunctionData.SUBFUNCTION,
  61.495 -				      in, out);
  61.496 +                return invoke(
  61.497 +                        fd.call ? sb.toString() : "true",
  61.498 +                        fd.call ?
  61.499 +                            DataFormat.SUBFUNCTION :
  61.500 +                            DataFormat.SUBFUNCTION_NOCALL,
  61.501 +                        in, out);
  61.502              } else if (isSeparator(c, REC_DATA_SEPARATORS)) {
  61.503 -		return invokeFunction(sb.toString(), 
  61.504 -				      FunctionData.RECURSIVE,
  61.505 -				      in, out);
  61.506 -            } else if (isSeparator(c, NONREC_DATA_SEPARATORS)) {
  61.507 -		return invokeFunction(sb.toString(), 
  61.508 -				      FunctionData.NONRECURSIVE, 
  61.509 -				      in, out);
  61.510 -            } else if (c < 0) {
  61.511 -		throw new TemplateException("Unexpected end of file.", in);
  61.512 +                skipEscaped(in);
  61.513 +                return invoke(
  61.514 +                        fd.call ? sb.toString() : "true",
  61.515 +                        fd.call ?
  61.516 +                            DataFormat.RECURSIVE :
  61.517 +                            DataFormat.NOCALL,
  61.518 +                        in, out);
  61.519 +            } else if (isSeparator(c, VERBATIM_DATA_SEPARATORS)) {
  61.520 +                return invoke(
  61.521 +                        fd.call ? sb.toString() : "true",
  61.522 +                        DataFormat.VERBATIM, in, out);
  61.523 +            } else if (isSeparator(c, NOCALL_DATA_SEPARATORS)) {
  61.524 +                skipEscaped(in);
  61.525 +                return invoke(
  61.526 +                        fd.call ? sb.toString() : "true",
  61.527 +                        DataFormat.NOCALL, in, out);
  61.528              } else {
  61.529 -		sb.append((char)c);
  61.530 -	    }
  61.531 -	}
  61.532 +                sb.append((char)c);
  61.533 +            }
  61.534 +        }
  61.535      }
  61.536 -
  61.537 -    int parseValue(Object value, Writer out) throws IOException {
  61.538 +    
  61.539 +    public int parseValue(Object value, Writer out) throws IOException {
  61.540          if (value == null)
  61.541              return 0;
  61.542 -
  61.543 +        
  61.544          String svalue = value.toString();
  61.545          
  61.546          if (svalue == null || svalue.length() == 0)
  61.547              return 0;
  61.548 -
  61.549 +        
  61.550          out.write(svalue);
  61.551          return 1;
  61.552      }
  61.553 -
  61.554 -    private int invokeFunction(String name, FunctionData fd,
  61.555 -			       TemplateReader in, Writer out)
  61.556 -	throws IOException, TemplateException {
  61.557 -
  61.558 +    
  61.559 +    private int invoke(String name, DataFormat fd,
  61.560 +            TemplateReader in, Writer out)
  61.561 +            throws IOException, TemplateException {
  61.562 +        
  61.563          FunctionDataParser fdp = new FunctionDataParser(this, fd, in);
  61.564 -
  61.565 -	if ("".equals(name)) {
  61.566 -            return fdp.parseData(out);
  61.567 -	}
  61.568 +                
  61.569 +        int r = invoke(name, fdp, out);                
  61.570          
  61.571 -        Object value = getValue(name);
  61.572 -        int r;
  61.573 -
  61.574 -        if (value instanceof Function) {            
  61.575 -            r = ((Function) value).invoke(fdp, out);           
  61.576 -        } else { 
  61.577 -            r = parseValue(value, out);
  61.578 +        if (fdp.hasMoreData()) {
  61.579 +            /* Skip remaining function data. */
  61.580 +            fdp.skipData();
  61.581          }
  61.582 -
  61.583 -	if (fdp.hasMoreData()) {
  61.584 -	    /* Skip remaining function data. */
  61.585 -	    fdp.parseData(new Writer() {
  61.586 -		    public void close() {}
  61.587 -		    public void flush() {}
  61.588 -		    public void write(char[] cbuf, int off, int len) {}
  61.589 -		});
  61.590 -	}
  61.591 -	
  61.592 -	return r;
  61.593 +        
  61.594 +        return r;
  61.595      }
  61.596 -
  61.597 -    public Object getValue(String name) throws TemplateException {
  61.598 -	Object value = variables.get(name);
  61.599 -	if (value != null) return value;   
  61.600 -
  61.601 -	if (superParser != null) {
  61.602 -	    if (name.startsWith(SUPER_PREFIX))
  61.603 -		return superParser.getValue
  61.604 -                    (name.substring(SUPER_PREFIX.length()));
  61.605 -	    else
  61.606 -		return superParser.getValue(name);
  61.607 -	}
  61.608 -
  61.609 -	return null;
  61.610 +          
  61.611 +    public int invoke(String name, FunctionDataParser fdp, Writer out)
  61.612 +    throws IOException, TemplateException {
  61.613 +        Object value = context.get(name);
  61.614 +        
  61.615 +        if (value instanceof Function) {
  61.616 +            return ((Function) value).invoke(fdp, out);
  61.617 +        }
  61.618 +        
  61.619 +        if (value instanceof Context) {
  61.620 +            String code = fdp.getData();
  61.621 +            
  61.622 +            if (fdp.getLastReturnCode() == 0)
  61.623 +                return 0;
  61.624 +            
  61.625 +            TemplateParser parser = new TemplateParser((Context) value);
  61.626 +            return parser.parse(
  61.627 +                    new TemplateReader(new StringReader(code)), out);
  61.628 +        }
  61.629 +        
  61.630 +        return parseValue(value, out);
  61.631      }
  61.632 -
  61.633 -    public void setValue(String name, Object value) {
  61.634 -	variables.put(name, value);
  61.635 -    }
  61.636 -
  61.637 -    public void clearValues() {
  61.638 -	variables.clear();
  61.639 -        Functions.registerAllFunctions(this);
  61.640 -    }
  61.641 -
  61.642 -    // TEST
  61.643 -    public static void main(String[] args)
  61.644 -	throws IOException, TemplateException {
  61.645 -	
  61.646 -	TemplateParser p = new TemplateParser();
  61.647 -	
  61.648 -	TemplateReader in = 
  61.649 -            new TemplateReader
  61.650 -            (new LineNumberReader
  61.651 -             (new FileReader("parser.in")), "parser.in");
  61.652 -
  61.653 -	FileWriter out = new FileWriter("parser.out");
  61.654 -
  61.655 -	p.parse(in, out);
  61.656 -
  61.657 -	in.close();
  61.658 -	out.close();
  61.659 +    
  61.660 +    public Context getContext() {
  61.661 +        return context;
  61.662      }
  61.663  }
    62.1 --- a/src/kryshen/tema/TemplateReader.java	Thu Dec 14 23:22:05 2006 +0300
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,64 +0,0 @@
    62.4 -/*
    62.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    62.6 - *
    62.7 - *  This program is free software; you can redistribute it and/or modify
    62.8 - *  it under the terms of the GNU General Public License as published by
    62.9 - *  the Free Software Foundation; either version 2 of the License, or
   62.10 - *  (at your option) any later version.
   62.11 - *
   62.12 - *  This program is distributed in the hope that it will be useful,
   62.13 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   62.14 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   62.15 - *  GNU General Public License for more details.
   62.16 - *
   62.17 - *  You should have received a copy of the GNU General Public License
   62.18 - *  along with this program; if not, write to the Free Software
   62.19 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   62.20 - *
   62.21 - *  $Id: TemplateReader.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $
   62.22 - */
   62.23 -
   62.24 -package kryshen.tema;
   62.25 -
   62.26 -import java.io.Reader;
   62.27 -import java.io.LineNumberReader;
   62.28 -import java.io.FilterReader;
   62.29 -import java.io.IOException;
   62.30 -
   62.31 -/**
   62.32 - * Reader for TEMA templates. Stores data source name (commonly
   62.33 - * filename) and tracks line numbers for error reporting.
   62.34 - *
   62.35 - * @author Mikhail A. Kryshen
   62.36 - */
   62.37 -public class TemplateReader extends FilterReader {
   62.38 -    private String source = null;
   62.39 -
   62.40 -    private LineNumberReader lnReader = null;
   62.41 -    private TemplateReader parentReader = null;
   62.42 -
   62.43 -    public TemplateReader(LineNumberReader in, String source) {
   62.44 -        super(in);
   62.45 -        this.lnReader = in;
   62.46 -        this.source = source;
   62.47 -    }
   62.48 -
   62.49 -    public TemplateReader(Reader in, TemplateReader parent) {
   62.50 -        super(in);
   62.51 -        this.source = source;
   62.52 -    }
   62.53 -
   62.54 -    public String getSource() {
   62.55 -        if (source != null)
   62.56 -            return source;
   62.57 -        
   62.58 -        return parentReader.getSource();
   62.59 -    }
   62.60 -    
   62.61 -    public int getLineNumber() {
   62.62 -        if (lnReader != null)
   62.63 -            return lnReader.getLineNumber();
   62.64 -        
   62.65 -        return parentReader.getLineNumber();
   62.66 -    }
   62.67 -}
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/src/kryshen/tema/ant/TemaTask.java	Tue Feb 19 20:32:17 2008 +0300
    63.3 @@ -0,0 +1,145 @@
    63.4 +/*
    63.5 + *  Copyright 2006-2008 Mikhail Kryshen
    63.6 + *
    63.7 + *  This file is part of Tema.
    63.8 + *
    63.9 + *  Tema is free software: you can redistribute it and/or modify it
   63.10 + *  under the terms of the GNU Lesser General Public License as
   63.11 + *  published by the Free Software Foundation, either version 3 of the
   63.12 + *  License, or (at your option) any later version.
   63.13 + *
   63.14 + *  Tema is distributed in the hope that it will be useful,
   63.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   63.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   63.17 + *  GNU Lesser General Public License for more details.
   63.18 + *
   63.19 + *  You should have received a copy of the 
   63.20 + *  GNU Lesser General Public License along with Tema.  
   63.21 + *  If not, see <http://www.gnu.org/licenses/>.
   63.22 + *
   63.23 + *  $Id: TemaTask.java,v 1.17 2008/02/17 23:58:01 mikhail Exp $
   63.24 + */
   63.25 +
   63.26 +package kryshen.tema.ant;
   63.27 +
   63.28 +import java.io.BufferedReader;
   63.29 +import java.io.BufferedWriter;
   63.30 +import java.io.File;
   63.31 +import java.io.FileReader;
   63.32 +import java.io.FileWriter;
   63.33 +import java.io.IOException;
   63.34 +import java.io.Writer;
   63.35 +import java.util.ArrayList;
   63.36 +import java.util.Collection;
   63.37 +import kryshen.tema.TemplateException;
   63.38 +import kryshen.tema.TemplateParser;
   63.39 +import kryshen.tema.io.NullWriter;
   63.40 +import kryshen.tema.io.TemplateReader;
   63.41 +import org.apache.tools.ant.BuildException;
   63.42 +import org.apache.tools.ant.Task;
   63.43 +
   63.44 +/**
   63.45 + * Tema support for ant.
   63.46 + *
   63.47 + * @author Mikhail Kryshen
   63.48 + */
   63.49 +public class TemaTask extends Task {
   63.50 +    
   63.51 +    public static class Variable {
   63.52 +        private String name;
   63.53 +        private String value;
   63.54 +        
   63.55 +        public void setName(String name) {
   63.56 +            this.name = name;
   63.57 +        }
   63.58 +        
   63.59 +        public void setValue(String value) {
   63.60 +            this.value = value;
   63.61 +        }
   63.62 +        
   63.63 +        public void setPath(File file) {
   63.64 +            this.value = file.getAbsolutePath();
   63.65 +        }
   63.66 +    }
   63.67 +    
   63.68 +    private File basedir = null;
   63.69 +    
   63.70 +    private File infile = null;
   63.71 +    private File outfile = null;
   63.72 +    
   63.73 +    private Collection<Variable> variables = new ArrayList<Variable>();
   63.74 +    
   63.75 +    @Override
   63.76 +    public void execute() throws BuildException {
   63.77 +        if (basedir == null) {
   63.78 +            basedir = getProject().getBaseDir();
   63.79 +        }
   63.80 +        
   63.81 +        if (infile == null) {
   63.82 +            throw new BuildException("no infile specified", getLocation());
   63.83 +        }
   63.84 +        
   63.85 +        try {
   63.86 +            executeTema();
   63.87 +        } catch (IOException e) {
   63.88 +            throw new BuildException(e);
   63.89 +        } catch (TemplateException e) {
   63.90 +            throw new BuildException(e);
   63.91 +        }
   63.92 +    }
   63.93 +    
   63.94 +    private void executeTema() throws IOException, TemplateException {
   63.95 +        TemplateParser parser = new TemplateParser(basedir);
   63.96 +        
   63.97 +        for (Variable var : variables) {
   63.98 +            if (var.name == null) {
   63.99 +                throw new BuildException(
  63.100 +                        "no name specified for variable", getLocation());
  63.101 +            }
  63.102 +            
  63.103 +            if (var.value == null) {
  63.104 +                throw new BuildException(
  63.105 +                        "no value specified for variable", getLocation());
  63.106 +            }
  63.107 +            
  63.108 +            parser.getContext().set(var.name, var.value);
  63.109 +        }
  63.110 +        
  63.111 +        TemplateReader in = new TemplateReader(
  63.112 +                new BufferedReader(new FileReader(infile)),
  63.113 +                infile.getName());
  63.114 +        try {
  63.115 +            Writer out;
  63.116 +            
  63.117 +            if (outfile != null) {
  63.118 +                out = new BufferedWriter(new FileWriter(outfile));
  63.119 +            } else {
  63.120 +                out = NullWriter.INSTANCE;
  63.121 +            }
  63.122 +            
  63.123 +            try {
  63.124 +                parser.parse(in, out);
  63.125 +            } finally {
  63.126 +                out.close();
  63.127 +            }
  63.128 +        } finally {
  63.129 +            in.close();
  63.130 +        }
  63.131 +    }
  63.132 +    
  63.133 +    public void setBasedir(File basedir) {
  63.134 +        this.basedir = basedir;
  63.135 +    }
  63.136 +    
  63.137 +    public void setInfile(File infile) {
  63.138 +        this.infile = infile;
  63.139 +    }
  63.140 +    
  63.141 +    public void setOutfile(File outfile) {
  63.142 +        this.outfile = outfile;
  63.143 +    }
  63.144 +    
  63.145 +    public void addVariable(Variable variable) {
  63.146 +        variables.add(variable);
  63.147 +    }
  63.148 +}
    64.1 --- a/src/kryshen/tema/demo/DemoFrame.java	Thu Dec 14 23:22:05 2006 +0300
    64.2 +++ b/src/kryshen/tema/demo/DemoFrame.java	Tue Feb 19 20:32:17 2008 +0300
    64.3 @@ -1,181 +1,228 @@
    64.4  /*
    64.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    64.6 + *  Copyright 2006-2008 Mikhail Kryshen
    64.7   *
    64.8 - *  This program is free software; you can redistribute it and/or modify
    64.9 - *  it under the terms of the GNU General Public License as published by
   64.10 - *  the Free Software Foundation; either version 2 of the License, or
   64.11 - *  (at your option) any later version.
   64.12 + *  This file is part of Tema.
   64.13   *
   64.14 - *  This program is distributed in the hope that it will be useful,
   64.15 + *  Tema is free software: you can redistribute it and/or modify it
   64.16 + *  under the terms of the GNU Lesser General Public License as
   64.17 + *  published by the Free Software Foundation, either version 3 of the
   64.18 + *  License, or (at your option) any later version.
   64.19 + *
   64.20 + *  Tema is distributed in the hope that it will be useful,
   64.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   64.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   64.23 - *  GNU General Public License for more details.
   64.24 + *  GNU Lesser General Public License for more details.
   64.25   *
   64.26 - *  You should have received a copy of the GNU General Public License
   64.27 - *  along with this program; if not, write to the Free Software
   64.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   64.29 + *  You should have received a copy of the 
   64.30 + *  GNU Lesser General Public License along with Tema.  
   64.31 + *  If not, see <http://www.gnu.org/licenses/>.
   64.32   *
   64.33 - *  $Id: DemoFrame.java,v 1.3 2006/12/14 15:59:48 mikhail Exp $
   64.34 + *  $Id: DemoFrame.java,v 1.13 2008/02/16 17:38:03 mikhail Exp $
   64.35   */
   64.36  
   64.37  package kryshen.tema.demo;
   64.38  
   64.39 -import java.awt.*;
   64.40 -import java.awt.event.*;
   64.41 -import java.io.*;
   64.42 +import java.awt.Button;
   64.43 +import java.awt.FlowLayout;
   64.44 +import java.awt.Font;
   64.45 +import java.awt.Frame;
   64.46 +import java.awt.GridBagConstraints;
   64.47 +import java.awt.GridBagLayout;
   64.48 +import java.awt.Insets;
   64.49 +import java.awt.Label;
   64.50 +import java.awt.Panel;
   64.51 +import java.awt.TextArea;
   64.52 +import java.awt.event.ActionEvent;
   64.53 +import java.awt.event.ActionListener;
   64.54 +import java.awt.event.WindowAdapter;
   64.55 +import java.awt.event.WindowEvent;
   64.56 +import java.io.BufferedReader;
   64.57 +import java.io.IOException;
   64.58 +import java.io.InputStreamReader;
   64.59 +import java.io.Reader;
   64.60 +import java.io.StringReader;
   64.61 +import java.io.StringWriter;
   64.62  import java.net.URL;
   64.63 -
   64.64 -import kryshen.tema.*;
   64.65 +import kryshen.tema.TemplateParser;
   64.66 +import kryshen.tema.io.TemplateReader;
   64.67  
   64.68  /**
   64.69 - * TEMA demonstation console.
   64.70 + * Tema demonstation console.
   64.71   */
   64.72  public class DemoFrame extends Frame {
   64.73 +    private static final Font TEXT_FONT =
   64.74 +            new Font("monospaced", Font.PLAIN, 12);
   64.75 +    
   64.76      private TextArea input;
   64.77      private TextArea output;
   64.78      private TextArea error;
   64.79      
   64.80 +    private String sample;
   64.81 +    
   64.82      public DemoFrame() {
   64.83 -        super("TEMA demo console");
   64.84 -
   64.85 +        super("Tema demo console");
   64.86 +        
   64.87          GridBagLayout gbl = new GridBagLayout();
   64.88 -
   64.89 +        
   64.90          GridBagConstraints c = new GridBagConstraints();
   64.91 -
   64.92 +        
   64.93          setLayout(gbl);
   64.94 -
   64.95 -        input = new TextArea(25, 40);
   64.96 +        
   64.97 +        input = new TextArea(28, 50);
   64.98          input.setEditable(true);
   64.99 -
  64.100 -        output = new TextArea(25, 40);
  64.101 +        input.setFont(TEXT_FONT);
  64.102 +        
  64.103 +        output = new TextArea(28, 50);
  64.104          output.setEditable(false);
  64.105 -
  64.106 -        error = new TextArea(5, 80);
  64.107 +        output.setFont(TEXT_FONT);
  64.108 +        
  64.109 +        error = new TextArea(5, 90);
  64.110          error.setEditable(false);
  64.111 -
  64.112 +        error.setFont(TEXT_FONT);
  64.113 +        
  64.114          Label l;
  64.115 -
  64.116 +        
  64.117          c.insets = new Insets(3, 3, 3, 3);
  64.118          c.fill = GridBagConstraints.BOTH;
  64.119          c.gridwidth = GridBagConstraints.RELATIVE;
  64.120 -
  64.121 -        l = new Label("Enter your code and click \"Process\".");
  64.122 -
  64.123 +        
  64.124 +        l = new Label("Enter your code and press \"Process\".");
  64.125 +        
  64.126          gbl.setConstraints(l, c);
  64.127          add(l);
  64.128 -
  64.129 +        
  64.130          Panel buttons = new Panel();
  64.131          buttons.setLayout(new FlowLayout(FlowLayout.LEFT));
  64.132          
  64.133          Button process = new Button("Process");
  64.134          Button clear = new Button("Clear");
  64.135 +        Button reset = new Button("Reset");
  64.136          Button close = new Button("Close");
  64.137 -
  64.138 +        
  64.139          buttons.add(process);
  64.140          buttons.add(clear);
  64.141 +        buttons.add(reset);
  64.142          buttons.add(close);
  64.143 -
  64.144 -        c.gridwidth = GridBagConstraints.REMAINDER; 
  64.145 -
  64.146 +        
  64.147 +        c.gridwidth = GridBagConstraints.REMAINDER;
  64.148 +        
  64.149          gbl.setConstraints(buttons, c);
  64.150          add(buttons);
  64.151 -
  64.152 +        
  64.153          c.fill = GridBagConstraints.BOTH;
  64.154          c.anchor = GridBagConstraints.CENTER;
  64.155          c.gridwidth = GridBagConstraints.RELATIVE;
  64.156 -
  64.157 +        
  64.158          l = new Label("Input:");
  64.159 -
  64.160 +        
  64.161          gbl.setConstraints(l, c);
  64.162          add(l);
  64.163 -
  64.164 -        c.gridwidth = GridBagConstraints.REMAINDER; 
  64.165 -
  64.166 +        
  64.167 +        c.gridwidth = GridBagConstraints.REMAINDER;
  64.168 +        
  64.169          l = new Label("Output:");
  64.170 -
  64.171 +        
  64.172          gbl.setConstraints(l, c);
  64.173          add(l);
  64.174 -
  64.175 -        c.gridwidth = GridBagConstraints.RELATIVE; 
  64.176 -
  64.177 +        
  64.178 +        c.gridwidth = GridBagConstraints.RELATIVE;
  64.179 +        c.weightx = 1.0;
  64.180 +        c.weighty = 1.0;
  64.181 +        
  64.182          gbl.setConstraints(input, c);
  64.183          add(input);
  64.184 -       
  64.185 -        c.gridwidth = GridBagConstraints.REMAINDER; 
  64.186 -
  64.187 +        
  64.188 +        c.gridwidth = GridBagConstraints.REMAINDER;
  64.189 +        
  64.190          gbl.setConstraints(output, c);
  64.191          add(output);
  64.192 -
  64.193 +        
  64.194 +        c.weightx = 0.0;
  64.195 +        c.weighty = 0.0;
  64.196 +        
  64.197          l = new Label("Errors:");
  64.198 -
  64.199 +        
  64.200          gbl.setConstraints(l, c);
  64.201          add(l);
  64.202 -
  64.203 +        
  64.204 +        c.weightx = 1.0;
  64.205 +        c.weighty = 0.25;
  64.206 +        
  64.207          gbl.setConstraints(error, c);
  64.208 -        add(error);      
  64.209 -
  64.210 +        add(error);
  64.211 +        
  64.212          process.addActionListener(new ActionListener() {
  64.213 -                public void actionPerformed(ActionEvent e) {
  64.214 -                    process();
  64.215 -                }
  64.216 -            });
  64.217 -
  64.218 +            public void actionPerformed(ActionEvent e) {
  64.219 +                process();
  64.220 +            }
  64.221 +        });
  64.222 +        
  64.223          clear.addActionListener(new ActionListener() {
  64.224 -                public void actionPerformed(ActionEvent e) {
  64.225 -                    error.setText("");
  64.226 -                    output.setText("");
  64.227 -                    input.setText("");
  64.228 -                    
  64.229 -                }
  64.230 -            });
  64.231 -
  64.232 +            public void actionPerformed(ActionEvent e) {
  64.233 +                error.setText("");
  64.234 +                output.setText("");
  64.235 +                input.setText("");
  64.236 +                input.requestFocus();
  64.237 +            }
  64.238 +        });
  64.239 +        
  64.240 +        reset.addActionListener(new ActionListener() {
  64.241 +            public void actionPerformed(ActionEvent e) {
  64.242 +                error.setText("");
  64.243 +                output.setText("");
  64.244 +                input.setText(sample);
  64.245 +            }
  64.246 +        });
  64.247 +        
  64.248          close.addActionListener(new ActionListener() {
  64.249 -                public void actionPerformed(ActionEvent e) {
  64.250 -                    dispose();
  64.251 -                }
  64.252 -            });
  64.253 -
  64.254 +            public void actionPerformed(ActionEvent e) {
  64.255 +                dispose();
  64.256 +            }
  64.257 +        });
  64.258 +        
  64.259          addWindowListener(new WindowAdapter() {
  64.260 -                public void windowClosing(WindowEvent e) {
  64.261 -                    dispose();
  64.262 -                }
  64.263 -            });
  64.264 +            public void windowClosing(WindowEvent e) {
  64.265 +                dispose();
  64.266 +            }
  64.267 +        });
  64.268          
  64.269          URL source = getClass().getResource("demo.template");
  64.270          StringBuffer buffer = new StringBuffer();
  64.271 -
  64.272 +        
  64.273          try {
  64.274              Reader in = new BufferedReader
  64.275 -                (new InputStreamReader(source.openStream(), "UTF-8"));           
  64.276 +                    (new InputStreamReader(source.openStream(), "UTF-8"));
  64.277              
  64.278              for (int ch = in.read(); ch >= 0; ch = in.read()) {
  64.279                  buffer.append((char)ch);
  64.280              }
  64.281 -
  64.282 +            
  64.283              in.close();
  64.284          } catch (IOException e) {
  64.285              e.printStackTrace();
  64.286          }
  64.287          
  64.288 -        input.setText(buffer.toString());
  64.289 +        sample = buffer.toString();
  64.290 +        
  64.291 +        input.setText(sample);
  64.292      }
  64.293 -
  64.294 +    
  64.295      private void process() {
  64.296          String s = input.getText();
  64.297          
  64.298 -        TemplateReader tr = new TemplateReader
  64.299 -            (new LineNumberReader(new StringReader(s)), "input");
  64.300 +        TemplateReader tr = new TemplateReader(new StringReader(s), "input");
  64.301          TemplateParser tp = new TemplateParser();
  64.302          StringWriter sw = new StringWriter();
  64.303 -
  64.304 +        
  64.305          error.setText("");
  64.306 -
  64.307 +        
  64.308          try {
  64.309              tp.parse(tr, sw);
  64.310          } catch (Exception e) {
  64.311              error.setText(e.toString());
  64.312 +            e.printStackTrace();
  64.313          }
  64.314 -
  64.315 +        
  64.316          output.setText(sw.toString());
  64.317      }
  64.318  }
    65.1 --- a/src/kryshen/tema/demo/Hello.java	Thu Dec 14 23:22:05 2006 +0300
    65.2 +++ b/src/kryshen/tema/demo/Hello.java	Tue Feb 19 20:32:17 2008 +0300
    65.3 @@ -1,21 +1,23 @@
    65.4  /*
    65.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    65.6 + *  Copyright 2006-2008 Mikhail Kryshen
    65.7   *
    65.8 - *  This program is free software; you can redistribute it and/or modify
    65.9 - *  it under the terms of the GNU General Public License as published by
   65.10 - *  the Free Software Foundation; either version 2 of the License, or
   65.11 - *  (at your option) any later version.
   65.12 + *  This file is part of Tema.
   65.13   *
   65.14 - *  This program is distributed in the hope that it will be useful,
   65.15 + *  Tema is free software: you can redistribute it and/or modify it
   65.16 + *  under the terms of the GNU Lesser General Public License as
   65.17 + *  published by the Free Software Foundation, either version 3 of the
   65.18 + *  License, or (at your option) any later version.
   65.19 + *
   65.20 + *  Tema is distributed in the hope that it will be useful,
   65.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   65.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   65.23 - *  GNU General Public License for more details.
   65.24 + *  GNU Lesser General Public License for more details.
   65.25   *
   65.26 - *  You should have received a copy of the GNU General Public License
   65.27 - *  along with this program; if not, write to the Free Software
   65.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   65.29 + *  You should have received a copy of the 
   65.30 + *  GNU Lesser General Public License along with Tema.  
   65.31 + *  If not, see <http://www.gnu.org/licenses/>.
   65.32   *
   65.33 - *  $Id: Hello.java,v 1.2 2006/12/14 14:39:24 mikhail Exp $
   65.34 + *  $Id: Hello.java,v 1.9 2008/02/16 17:56:34 mikhail Exp $
   65.35   */
   65.36  
   65.37  package kryshen.tema.demo;
   65.38 @@ -27,7 +29,7 @@
   65.39  /**
   65.40   * Example function implementation.
   65.41   * 
   65.42 - * @author Mikhail A. Kryshen
   65.43 + * @author Mikhail Kryshen
   65.44   */
   65.45  public class Hello extends Function {
   65.46      public Hello() {}
   65.47 @@ -36,8 +38,6 @@
   65.48          throws IOException, TemplateException {
   65.49          
   65.50          out.write("Hello, ");
   65.51 -        fdp.parseData(out);
   65.52 -
   65.53 -        return 1;
   65.54 +        return fdp.parseData(out);
   65.55      }
   65.56  }
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/src/kryshen/tema/functions/Control.java	Tue Feb 19 20:32:17 2008 +0300
    66.3 @@ -0,0 +1,166 @@
    66.4 +/*
    66.5 + *  Copyright 2006-2008 Mikhail Kryshen
    66.6 + *
    66.7 + *  This file is part of Tema.
    66.8 + *
    66.9 + *  Tema is free software: you can redistribute it and/or modify it
   66.10 + *  under the terms of the GNU Lesser General Public License as
   66.11 + *  published by the Free Software Foundation, either version 3 of the
   66.12 + *  License, or (at your option) any later version.
   66.13 + *
   66.14 + *  Tema is distributed in the hope that it will be useful,
   66.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   66.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   66.17 + *  GNU Lesser General Public License for more details.
   66.18 + *
   66.19 + *  You should have received a copy of the 
   66.20 + *  GNU Lesser General Public License along with Tema.  
   66.21 + *  If not, see <http://www.gnu.org/licenses/>.
   66.22 + *
   66.23 + *  $Id: Control.java,v 1.18 2008/02/19 16:21:00 mikhail Exp $
   66.24 + */
   66.25 +
   66.26 +package kryshen.tema.functions;
   66.27 +
   66.28 +import java.io.IOException;
   66.29 +import java.io.StringReader;
   66.30 +import java.io.StringWriter;
   66.31 +import java.io.Writer;
   66.32 +import kryshen.tema.Function;
   66.33 +import kryshen.tema.FunctionDataParser;
   66.34 +import kryshen.tema.TemplateException;
   66.35 +import kryshen.tema.TemplateParser;
   66.36 +import kryshen.tema.io.NullWriter;
   66.37 +import kryshen.tema.io.TemplateReader;
   66.38 +
   66.39 +/**
   66.40 + * Logical and conditional functions.
   66.41 + *
   66.42 + * @author Mikhail Kryshen
   66.43 + */
   66.44 +public class Control {
   66.45 +    
   66.46 +    /**
   66.47 +     * Copy input to output and return zero value.
   66.48 +     */
   66.49 +    public static final Function FALSE =
   66.50 +            new Function() {
   66.51 +        public int invoke(FunctionDataParser fdp, Writer out)
   66.52 +        throws IOException, TemplateException {
   66.53 +            
   66.54 +            if (fdp.hasMoreData())
   66.55 +                fdp.parseData(out);
   66.56 +            
   66.57 +            return 0;
   66.58 +        }
   66.59 +    };
   66.60 +
   66.61 +    /**
   66.62 +     * Copy input to output and return non-zero value.
   66.63 +     */
   66.64 +    public static final Function TRUE =
   66.65 +            new Function() {
   66.66 +        public int invoke(FunctionDataParser fdp, Writer out)
   66.67 +        throws IOException, TemplateException {
   66.68 +            
   66.69 +            if (fdp.hasMoreData())
   66.70 +                fdp.parseData(out);
   66.71 +            
   66.72 +            return 1;
   66.73 +        }
   66.74 +    };
   66.75 +    
   66.76 +    /**
   66.77 +     * Outputs it's data if it has non-zero value.
   66.78 +     */
   66.79 +    public static final Function OPTIONAL = new Function() {
   66.80 +        public int invoke(FunctionDataParser fdp, Writer out)
   66.81 +        throws IOException, TemplateException {
   66.82 +            
   66.83 +            StringWriter sw = new StringWriter();
   66.84 +            int s = fdp.parseData(sw);
   66.85 +            sw.close();
   66.86 +            String data = sw.toString();
   66.87 +            
   66.88 +            if (s != 0) {
   66.89 +                out.write(data);
   66.90 +                return 1;
   66.91 +            } else {
   66.92 +                return 0;
   66.93 +            }
   66.94 +        }
   66.95 +    };
   66.96 +    
   66.97 +    /**
   66.98 +     * Logical negation (applied to the return value).
   66.99 +     */
  66.100 +    public static final Function NOT = new Function() {
  66.101 +        public int invoke(FunctionDataParser fdp, Writer out)
  66.102 +        throws IOException, TemplateException {
  66.103 +            
  66.104 +            return (fdp.parseData(out) == 0) ? 1 : 0;
  66.105 +        }
  66.106 +    };
  66.107 +    
  66.108 +    public static final Function IF = new Function() {
  66.109 +        public int invoke(FunctionDataParser fdp, Writer out)
  66.110 +        throws IOException, TemplateException {
  66.111 +            
  66.112 +            int value = fdp.parseNextArg(NullWriter.INSTANCE);
  66.113 +            
  66.114 +            if (value != 0) {
  66.115 +                return fdp.parseData(out);
  66.116 +            }
  66.117 +            
  66.118 +            return 0;
  66.119 +        }
  66.120 +    };
  66.121 +    
  66.122 +    public static final Function IF_ELSE = new Function() {
  66.123 +        public int invoke(FunctionDataParser fdp, Writer out)
  66.124 +        throws IOException, TemplateException {
  66.125 +            
  66.126 +            int value = fdp.parseNextArg(NullWriter.INSTANCE);
  66.127 +            
  66.128 +            if (value != 0) {
  66.129 +                return fdp.parseNextArg(out);
  66.130 +            } else {
  66.131 +                fdp.skipNextArg();
  66.132 +                return fdp.parseData(out);
  66.133 +            }
  66.134 +        }
  66.135 +    };
  66.136 +    
  66.137 +    /**
  66.138 +     * Outputs it's evaluated data while the evaluation result is non-zero.
  66.139 +     */
  66.140 +    public static final Function WHILE = new Function() {
  66.141 +        public int invoke(FunctionDataParser fdp, final Writer out)
  66.142 +        throws IOException, TemplateException {
  66.143 +            
  66.144 +            String data = fdp.getData();
  66.145 +            StringReader dataReader = new StringReader(data);
  66.146 +            
  66.147 +            TemplateParser parser = fdp.getTemplateParser();
  66.148 +            
  66.149 +            int r = 0; // summarized return value
  66.150 +            int e = 0; // evaluation value
  66.151 +            
  66.152 +            while (true) {
  66.153 +                StringWriter sw = new StringWriter();
  66.154 +                
  66.155 +                e = parser.parse(new TemplateReader(dataReader), sw);
  66.156 +                
  66.157 +                if (e == 0)
  66.158 +                    break;
  66.159 +                
  66.160 +                r += Math.abs(e);
  66.161 +                out.write(sw.toString());
  66.162 +                dataReader.reset();
  66.163 +            }
  66.164 +            
  66.165 +            dataReader.close();
  66.166 +            return r;
  66.167 +        }
  66.168 +    };
  66.169 +}
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/src/kryshen/tema/functions/Database.java	Tue Feb 19 20:32:17 2008 +0300
    67.3 @@ -0,0 +1,208 @@
    67.4 +/*
    67.5 + *  Copyright 2006-2008 Mikhail Kryshen
    67.6 + *
    67.7 + *  This file is part of Tema.
    67.8 + *
    67.9 + *  Tema is free software: you can redistribute it and/or modify it
   67.10 + *  under the terms of the GNU Lesser General Public License as
   67.11 + *  published by the Free Software Foundation, either version 3 of the
   67.12 + *  License, or (at your option) any later version.
   67.13 + *
   67.14 + *  Tema is distributed in the hope that it will be useful,
   67.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   67.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   67.17 + *  GNU Lesser General Public License for more details.
   67.18 + *
   67.19 + *  You should have received a copy of the 
   67.20 + *  GNU Lesser General Public License along with Tema.  
   67.21 + *  If not, see <http://www.gnu.org/licenses/>.
   67.22 + *
   67.23 + *  $Id: Database.java,v 1.12 2008/02/17 23:58:01 mikhail Exp $
   67.24 + */
   67.25 +
   67.26 +package kryshen.tema.functions;
   67.27 +
   67.28 +import java.io.IOException;
   67.29 +import java.io.Reader;
   67.30 +import java.io.StringReader;
   67.31 +import java.io.Writer;
   67.32 +import java.sql.Connection;
   67.33 +import java.sql.DriverManager;
   67.34 +import java.sql.PreparedStatement;
   67.35 +import java.sql.ResultSet;
   67.36 +import java.sql.ResultSetMetaData;
   67.37 +import java.sql.SQLException;
   67.38 +import java.util.HashMap;
   67.39 +import java.util.List;
   67.40 +import kryshen.tema.Context;
   67.41 +import kryshen.tema.Function;
   67.42 +import kryshen.tema.FunctionDataParser;
   67.43 +import kryshen.tema.TemplateException;
   67.44 +import kryshen.tema.TemplateParser;
   67.45 +import kryshen.tema.io.TemplateReader;
   67.46 +
   67.47 +/**
   67.48 + * Data access functions.
   67.49 + *
   67.50 + * @author Mikhail Kryshen
   67.51 + */
   67.52 +public class Database {   
   67.53 +    /* db_connect:connection_name resource */
   67.54 +    public static final Function CONNECT = new Function() {
   67.55 +        public int invoke(FunctionDataParser fdp, Writer out)
   67.56 +        throws IOException, TemplateException {
   67.57 +            
   67.58 +            String arg0 = fdp.getNextArg();
   67.59 +            String data = fdp.getData();
   67.60 +            
   67.61 +            Connection connection;
   67.62 +            
   67.63 +            try {
   67.64 +                connection = DriverManager.getConnection(data);
   67.65 +            } catch (SQLException e) {
   67.66 +                throw new TemplateException
   67.67 +                        (e.getMessage(), e, fdp.getTemplateReader());
   67.68 +            }
   67.69 +            
   67.70 +            fdp.getContext().set(arg0, connection);
   67.71 +            
   67.72 +            out.write(arg0);
   67.73 +            return 1;
   67.74 +        }
   67.75 +    };
   67.76 +    
   67.77 +    /* db_prepare:qury_name connection sql_statement */
   67.78 +    public static final Function PREPARE = new Function() {
   67.79 +        public int invoke(FunctionDataParser fdp, Writer out)
   67.80 +        throws IOException, TemplateException {
   67.81 +            
   67.82 +            String arg0 = fdp.getNextArg(); // resulting variable
   67.83 +            String arg1 = fdp.getNextArg(); // connection
   67.84 +            String data = fdp.getData();    // statement
   67.85 +            
   67.86 +            Connection connection;
   67.87 +            PreparedStatement statement;
   67.88 +            
   67.89 +            try {
   67.90 +                connection = (Connection) fdp.getContext().get(arg1);
   67.91 +                statement = connection.prepareStatement(data);
   67.92 +            } catch (ClassCastException e) {
   67.93 +                throw new TemplateException
   67.94 +                        (e.getMessage(), e, fdp.getTemplateReader());
   67.95 +            } catch (SQLException e) {
   67.96 +                throw new TemplateException
   67.97 +                        (e.getMessage(), e, fdp.getTemplateReader());
   67.98 +            }
   67.99 +            
  67.100 +            fdp.getContext().set(arg0, statement);
  67.101 +            
  67.102 +            out.write(arg0);
  67.103 +            return 1;
  67.104 +        }
  67.105 +    };
  67.106 +    
  67.107 +    /* db_query:sql_query template arg1 arg2 ... argN */
  67.108 +    public static final Function QUERY = new Function() {
  67.109 +        public int invoke(FunctionDataParser fdp, Writer out)
  67.110 +        throws IOException, TemplateException {
  67.111 +            
  67.112 +            String query = fdp.getNextArg();
  67.113 +            String template = fdp.getNextArg();
  67.114 +            List<String> args = fdp.getArgs();
  67.115 +            
  67.116 +            TemplateParser tp = fdp.getTemplateParser();
  67.117 +            Context context = fdp.getContext();
  67.118 +            
  67.119 +            try {
  67.120 +                PreparedStatement statement =
  67.121 +                        (PreparedStatement) context.get(query);
  67.122 +                return query(template, fdp.getTemplateReader(), 
  67.123 +                        statement, args, tp, out);
  67.124 +            } catch (ClassCastException e) {
  67.125 +                throw new TemplateException
  67.126 +                        (e.getMessage(), e, fdp.getTemplateReader());
  67.127 +            } catch (SQLException e) {
  67.128 +                throw new TemplateException
  67.129 +                        (e.getMessage(), e, fdp.getTemplateReader());
  67.130 +            }
  67.131 +        }
  67.132 +    };
  67.133 +    
  67.134 +    /**
  67.135 +     * Process database query.
  67.136 +     *
  67.137 +     * @param template template to fill with data.
  67.138 +     * @param parentReader parent TemplateReader.
  67.139 +     * @param ps query statement to execute.
  67.140 +     * @param args list of query parameters.
  67.141 +     * @param superParser invoking object.
  67.142 +     * @param out Writer to output processed data.
  67.143 +     *
  67.144 +     * @return number of processed rows in query result.
  67.145 +     */
  67.146 +    private static int query(String template,
  67.147 +            TemplateReader parentReader,
  67.148 +            PreparedStatement ps,
  67.149 +            List<String> args,
  67.150 +            TemplateParser superParser,
  67.151 +            Writer out)
  67.152 +            throws IOException, SQLException, TemplateException {
  67.153 +        
  67.154 +        int i = 1;
  67.155 +        
  67.156 +        for (String arg : args) {
  67.157 +            ps.setString(i++, arg);
  67.158 +        }
  67.159 +        
  67.160 +        ResultSet resultSet = ps.executeQuery();
  67.161 +        ResultSetMetaData metaData = resultSet.getMetaData();
  67.162 +        int columnCount = metaData.getColumnCount();
  67.163 +        
  67.164 +        String[] names = new String[columnCount];
  67.165 +        
  67.166 +        for (int j = 0; j < columnCount; j++) {
  67.167 +            names[j] = metaData.getColumnName(j + 1);
  67.168 +        }
  67.169 +        
  67.170 +        final TemplateParser p = new TemplateParser(superParser);
  67.171 +        final HashMap<String, Object> fields = new HashMap<String, Object>();
  67.172 +        
  67.173 +        p.getContext().set("db", new Function() {
  67.174 +            public int invoke(FunctionDataParser fdp,
  67.175 +                    final Writer out)
  67.176 +                    throws IOException, TemplateException {
  67.177 +                
  67.178 +                String name = fdp.getData();
  67.179 +                Object value = fields.get(name);
  67.180 +                
  67.181 +                return p.parseValue(value, out);
  67.182 +            }
  67.183 +        });
  67.184 +        
  67.185 +        Reader input = new StringReader(template);
  67.186 +        
  67.187 +        for (i = 1; resultSet.next(); i++) {
  67.188 +            
  67.189 +            for (int j = 0; j < columnCount; j++) {
  67.190 +                Object value = resultSet.getObject(j + 1);
  67.191 +                if (resultSet.wasNull()) value = null;
  67.192 +                
  67.193 +                fields.put(names[j], value);
  67.194 +            }
  67.195 +            
  67.196 +            p.getContext().set("db_row", i);
  67.197 +            
  67.198 +            TemplateReader tr = new TemplateReader(input, parentReader);
  67.199 +            
  67.200 +            p.parse(tr, out);
  67.201 +
  67.202 +            input.reset();            
  67.203 +            fields.clear();
  67.204 +        }
  67.205 +        
  67.206 +        resultSet.close();
  67.207 +        input.close();
  67.208 +        ps.clearParameters();
  67.209 +        return i - 1;
  67.210 +    }
  67.211 +}
    68.1 --- a/src/kryshen/tema/functions/Define.java	Thu Dec 14 23:22:05 2006 +0300
    68.2 +++ b/src/kryshen/tema/functions/Define.java	Tue Feb 19 20:32:17 2008 +0300
    68.3 @@ -1,84 +1,126 @@
    68.4  /*
    68.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    68.6 + *  Copyright 2006-2008 Mikhail Kryshen
    68.7   *
    68.8 - *  This program is free software; you can redistribute it and/or modify
    68.9 - *  it under the terms of the GNU General Public License as published by
   68.10 - *  the Free Software Foundation; either version 2 of the License, or
   68.11 - *  (at your option) any later version.
   68.12 + *  This file is part of Tema.
   68.13   *
   68.14 - *  This program is distributed in the hope that it will be useful,
   68.15 + *  Tema is free software: you can redistribute it and/or modify it
   68.16 + *  under the terms of the GNU Lesser General Public License as
   68.17 + *  published by the Free Software Foundation, either version 3 of the
   68.18 + *  License, or (at your option) any later version.
   68.19 + *
   68.20 + *  Tema is distributed in the hope that it will be useful,
   68.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   68.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   68.23 - *  GNU General Public License for more details.
   68.24 + *  GNU Lesser General Public License for more details.
   68.25   *
   68.26 - *  You should have received a copy of the GNU General Public License
   68.27 - *  along with this program; if not, write to the Free Software
   68.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   68.29 + *  You should have received a copy of the 
   68.30 + *  GNU Lesser General Public License along with Tema.  
   68.31 + *  If not, see <http://www.gnu.org/licenses/>.
   68.32   *
   68.33 - *  $Id: Define.java,v 1.7 2006/12/14 14:35:00 mikhail Exp $
   68.34 + *  $Id: Define.java,v 1.25 2008/02/17 23:58:01 mikhail Exp $
   68.35   */
   68.36  
   68.37  package kryshen.tema.functions;
   68.38  
   68.39 -import java.io.*;
   68.40 -import java.util.*;
   68.41 -
   68.42 -import kryshen.tema.*;
   68.43 +import java.io.IOException;
   68.44 +import java.io.StringReader;
   68.45 +import java.io.StringWriter;
   68.46 +import java.io.Writer;
   68.47 +import kryshen.tema.Context;
   68.48 +import kryshen.tema.Function;
   68.49 +import kryshen.tema.FunctionDataParser;
   68.50 +import kryshen.tema.TemplateException;
   68.51 +import kryshen.tema.TemplateParser;
   68.52 +import kryshen.tema.io.TemplateReader;
   68.53  
   68.54  /**
   68.55   * Define function implementation.
   68.56   *
   68.57 - * @author Mikhail A. Kryshen
   68.58 + * @author Mikhail Kryshen
   68.59   */
   68.60  public class Define extends Function {
   68.61      public static final Function DEFINE = new Define();
   68.62 -
   68.63 +    
   68.64      public Define() {
   68.65      }
   68.66 -
   68.67 +    
   68.68      public int invoke(FunctionDataParser fdp, Writer out)
   68.69 -        throws IOException, TemplateException {
   68.70 +    throws IOException, TemplateException {
   68.71          
   68.72 -        final String arg0 = fdp.getNextArg();
   68.73 -        final String data = fdp.getData();
   68.74 -
   68.75 +        StringWriter nameWriter = new StringWriter();
   68.76 +        int r = fdp.parseNextArg(nameWriter);
   68.77 +        
   68.78 +        if (r == 0)
   68.79 +            return 0;                
   68.80 +        
   68.81 +        StringWriter dataWriter = new StringWriter();
   68.82 +        r = fdp.parseData(dataWriter);
   68.83 +        
   68.84 +        if (r == 0)
   68.85 +            return 0;
   68.86 +               
   68.87 +        final String name = nameWriter.toString();
   68.88 +        final String data = dataWriter.toString();
   68.89 +        
   68.90          Function newFunction = new Function() {
   68.91 -                public int invoke(final FunctionDataParser fdp, final Writer out)
   68.92 -                    throws IOException, TemplateException {
   68.93 -		    
   68.94 -                    TemplateParser functionParser = 
   68.95 -                        new TemplateParser(fdp.getTemplateParser());
   68.96 -                    
   68.97 -                    functionParser.registerFunction
   68.98 -			("nextarg", new Function() {
   68.99 -				public int invoke(FunctionDataParser unusedFdp, 
  68.100 -						  final Writer out)
  68.101 -				    throws IOException, TemplateException {
  68.102 -				    
  68.103 -				    return fdp.parseNextArg(out);
  68.104 -				}
  68.105 -			    });
  68.106 -		    
  68.107 -                    functionParser.registerFunction
  68.108 -			("data",new Function() {
  68.109 -				public int invoke(FunctionDataParser unusedFdp, 
  68.110 -						  final Writer out)
  68.111 -				    throws IOException, TemplateException {
  68.112 -				    
  68.113 -				    return fdp.parseData(out);
  68.114 -				}
  68.115 -			    });
  68.116 -		    
  68.117 -                    TemplateReader dataReader = new TemplateReader
  68.118 -                        (new StringReader(data), fdp.getTemplateReader());
  68.119 -
  68.120 -                    return functionParser.parse(dataReader, out);
  68.121 -                }
  68.122 -            };
  68.123 -	
  68.124 -        fdp.getTemplateParser().registerFunction(arg0, newFunction);
  68.125 -	
  68.126 -        out.write(arg0);
  68.127 -        return 1;
  68.128 +            public int invoke(final FunctionDataParser fdp1, final Writer out)
  68.129 +            throws IOException, TemplateException {
  68.130 +                
  68.131 +                final TemplateParser functionParser =
  68.132 +                        new TemplateParser(fdp1.getTemplateParser());
  68.133 +                
  68.134 +                final Context functionContext = 
  68.135 +                        functionParser.getContext();                
  68.136 +                
  68.137 +                functionContext.set
  68.138 +                        ("next_arg", new Function() {
  68.139 +                    public int invoke(FunctionDataParser unusedFdp,
  68.140 +                            final Writer out)
  68.141 +                            throws IOException, TemplateException {
  68.142 +                        
  68.143 +                        if (fdp1.hasMoreData())
  68.144 +                            return fdp1.parseNextArg(out);
  68.145 +                        
  68.146 +                        return 0;
  68.147 +                    }
  68.148 +                });
  68.149 +                
  68.150 +                functionContext.set
  68.151 +                        ("data", new Function() {
  68.152 +                    public int invoke(FunctionDataParser unusedFdp,
  68.153 +                            final Writer out)
  68.154 +                            throws IOException, TemplateException {
  68.155 +                        
  68.156 +                        return fdp1.parseData(out);
  68.157 +                    }
  68.158 +                });
  68.159 +                
  68.160 +                functionContext.set
  68.161 +                        ("has_more_data", new Function() {
  68.162 +                    public int invoke(FunctionDataParser unusedFdp,
  68.163 +                            final Writer out)
  68.164 +                            throws IOException, TemplateException {
  68.165 +                        
  68.166 +                        if (fdp1.hasMoreData()) {
  68.167 +                            out.write("true");
  68.168 +                            return 1;
  68.169 +                        }
  68.170 +                        
  68.171 +                        out.write("false");
  68.172 +                        return 0;
  68.173 +                    }
  68.174 +                });
  68.175 +                
  68.176 +                TemplateReader dataReader = new TemplateReader
  68.177 +                        (new StringReader(data), fdp1.getTemplateReader());
  68.178 +                
  68.179 +                return functionParser.parse(dataReader, out);
  68.180 +            }
  68.181 +        };
  68.182 +        
  68.183 +        fdp.getContext().set(name, newFunction);
  68.184 +        
  68.185 +        out.write(name);
  68.186 +        return r;
  68.187      }
  68.188  }
    69.1 --- a/src/kryshen/tema/functions/IO.java	Thu Dec 14 23:22:05 2006 +0300
    69.2 +++ b/src/kryshen/tema/functions/IO.java	Tue Feb 19 20:32:17 2008 +0300
    69.3 @@ -1,133 +1,168 @@
    69.4  /*
    69.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    69.6 + *  Copyright 2006-2008 Mikhail Kryshen
    69.7   *
    69.8 - *  This program is free software; you can redistribute it and/or modify
    69.9 - *  it under the terms of the GNU General Public License as published by
   69.10 - *  the Free Software Foundation; either version 2 of the License, or
   69.11 - *  (at your option) any later version.
   69.12 + *  This file is part of Tema.
   69.13   *
   69.14 - *  This program is distributed in the hope that it will be useful,
   69.15 + *  Tema is free software: you can redistribute it and/or modify it
   69.16 + *  under the terms of the GNU Lesser General Public License as
   69.17 + *  published by the Free Software Foundation, either version 3 of the
   69.18 + *  License, or (at your option) any later version.
   69.19 + *
   69.20 + *  Tema is distributed in the hope that it will be useful,
   69.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   69.23 - *  GNU General Public License for more details.
   69.24 + *  GNU Lesser General Public License for more details.
   69.25   *
   69.26 - *  You should have received a copy of the GNU General Public License
   69.27 - *  along with this program; if not, write to the Free Software
   69.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   69.29 + *  You should have received a copy of the 
   69.30 + *  GNU Lesser General Public License along with Tema.  
   69.31 + *  If not, see <http://www.gnu.org/licenses/>.
   69.32   *
   69.33 - *  $Id: IO.java,v 1.4 2006/12/14 15:59:49 mikhail Exp $
   69.34 + *  $Id: IO.java,v 1.19 2008/02/19 16:21:00 mikhail Exp $
   69.35   */
   69.36  
   69.37  package kryshen.tema.functions;
   69.38  
   69.39 -import java.io.*;
   69.40 -import java.util.*;
   69.41 -
   69.42 -import kryshen.tema.*;
   69.43 +import java.io.File;
   69.44 +import java.io.FileInputStream;
   69.45 +import java.io.FileOutputStream;
   69.46 +import java.io.IOException;
   69.47 +import java.io.InputStream;
   69.48 +import java.io.OutputStream;
   69.49 +import java.io.Reader;
   69.50 +import java.io.Writer;
   69.51 +import kryshen.tema.Function;
   69.52 +import kryshen.tema.FunctionDataParser;
   69.53 +import kryshen.tema.Tema;
   69.54 +import kryshen.tema.TemplateException;
   69.55 +import kryshen.tema.io.TemplateReader;
   69.56  
   69.57  /**
   69.58   * I/O functions.
   69.59   */
   69.60  public class IO {
   69.61 -    public static final Function COPY =
   69.62 -        new Function() {
   69.63 -           public int invoke(FunctionDataParser fdp, Writer out)
   69.64 -                throws IOException, TemplateException {
   69.65 -
   69.66 -                String arg0 = fdp.getNextArg();
   69.67 -                String arg1 = fdp.getNextArg();
   69.68 -
   69.69 -                File source = new File
   69.70 -                    (Tema.getProperty("resource_base"), arg0);
   69.71 -                File dest = new File(arg1);
   69.72 -                
   69.73 -                try {
   69.74 -                    copyFile(source, dest);
   69.75 -                } catch (IOException e) {
   69.76 -                    System.err.println(e);
   69.77 -                    return 0;
   69.78 -                }
   69.79 -                out.write(arg1);
   69.80 -                return 1;
   69.81 +    /**
   69.82 +     * Copy files.
   69.83 +     */
   69.84 +    public static final Function COPY = new Function() {
   69.85 +        public int invoke(FunctionDataParser fdp, Writer out)
   69.86 +        throws IOException, TemplateException {
   69.87 +            
   69.88 +            String arg0 = fdp.getNextArg();
   69.89 +            String arg1 = fdp.getNextArg();
   69.90 +            
   69.91 +            File source = fdp.createFile(arg0);
   69.92 +            File dest = fdp.createFile(arg1);
   69.93 +            
   69.94 +            try {
   69.95 +                copyFile(source, dest);
   69.96 +            } catch (IOException e) {
   69.97 +                System.err.println(e);
   69.98 +                return 0;
   69.99              }
  69.100 -        };
  69.101 -
  69.102 -    public static final Function WRITE =
  69.103 -        new Function() {
  69.104 -           public int invoke(FunctionDataParser fdp, Writer out)
  69.105 -                throws IOException, TemplateException {
  69.106 -
  69.107 -                String arg0 = fdp.getNextArg();
  69.108 -
  69.109 -		System.err.println("Writing " + arg0 + "...");
  69.110 -
  69.111 -                Writer fw;
  69.112 -
  69.113 -                try {
  69.114 -		    fw = Tema.createFileWriter(arg0);
  69.115 -                } catch (IOException e) {
  69.116 -                    System.err.println(e);
  69.117 -                    //throw new TemplateException(e.getMessage(), e, in);
  69.118 -                    return 0;
  69.119 -                }
  69.120 -
  69.121 -                try {
  69.122 -		    fdp.parseData(fw);
  69.123 -                } finally {
  69.124 -                    fw.close();
  69.125 -                }
  69.126 -
  69.127 -                out.write(arg0);
  69.128 -
  69.129 -		System.err.println("Saved " + arg0 + ".");
  69.130 -                return 1;
  69.131 +            out.write(arg1);
  69.132 +            return 1;
  69.133 +        }
  69.134 +    };
  69.135 +    
  69.136 +    /**
  69.137 +     * Write data to file.
  69.138 +     */
  69.139 +    public static final Function WRITE = new Function() {
  69.140 +        public int invoke(FunctionDataParser fdp, Writer out)
  69.141 +        throws IOException, TemplateException {
  69.142 +            
  69.143 +            String arg0 = fdp.getNextArg();
  69.144 +            
  69.145 +            System.err.println("Writing " + arg0 + "...");
  69.146 +            
  69.147 +            Writer fw;
  69.148 +            
  69.149 +            try {
  69.150 +                fw = Tema.createFileWriter(fdp.createFile(arg0));
  69.151 +            } catch (IOException e) {
  69.152 +                System.err.println(e);
  69.153 +                //throw new TemplateException(e.getMessage(), e, in);
  69.154 +                return 0;
  69.155              }
  69.156 -        };
  69.157 -
  69.158 -    public static final Function READ =
  69.159 -        new Function() {
  69.160 -           public int invoke(FunctionDataParser fdp, Writer out)
  69.161 -                throws IOException, TemplateException {
  69.162 -
  69.163 -	       String filename = fdp.getData();
  69.164 -	       String file;
  69.165 -	       
  69.166 -                try {
  69.167 -                    file = Tema.readFile(new File(filename));
  69.168 -                } catch (IOException e) {
  69.169 -                    System.err.println(e);
  69.170 -                    //throw new TemplateException(e.getMessage(), e, in);
  69.171 -                    return 0;
  69.172 -                }
  69.173 -		
  69.174 -                out.write(file);
  69.175 -                return 1;
  69.176 +            
  69.177 +            try {
  69.178 +                fdp.parseData(fw);
  69.179 +            } finally {
  69.180 +                fw.close();
  69.181              }
  69.182 -        };
  69.183 -
  69.184 -    public static final Function INCLUDE =
  69.185 -        new Function() {
  69.186 -           public int invoke(FunctionDataParser fdp, Writer out)
  69.187 -                throws IOException, TemplateException {
  69.188 -                
  69.189 -                String filename = fdp.getData();
  69.190 -                
  69.191 -                TemplateReader fin;
  69.192 -
  69.193 -                try {
  69.194 -                    fin = Tema.createTemplateReader(new File(filename));
  69.195 -                } catch (IOException e) {
  69.196 -                    throw new TemplateException(e.getMessage(), e,
  69.197 -                                                fdp.getTemplateReader());
  69.198 -                }
  69.199 -
  69.200 -                int r = fdp.getTemplateParser().parse(fin, out);
  69.201 -
  69.202 -                fin.close();
  69.203 -                return r;
  69.204 +            
  69.205 +            out.write(arg0);
  69.206 +            
  69.207 +            return 1;
  69.208 +        }
  69.209 +    };
  69.210 +    
  69.211 +    /**
  69.212 +     * Read from file.
  69.213 +     */
  69.214 +    public static final Function READ = new Function() {
  69.215 +        public int invoke(FunctionDataParser fdp, Writer out)
  69.216 +        throws IOException, TemplateException {
  69.217 +            
  69.218 +            String filename = fdp.getData();
  69.219 +            String file;
  69.220 +            
  69.221 +            try {
  69.222 +                readFile(fdp.createFile(filename), out);
  69.223 +            } catch (IOException e) {
  69.224 +                System.err.println(e);
  69.225 +                //throw new TemplateException(e.getMessage(), e, in);
  69.226 +                return 0;
  69.227              }
  69.228 -        };
  69.229 -
  69.230 +            
  69.231 +            return 1;
  69.232 +        }
  69.233 +    };
  69.234 +    
  69.235 +    /**
  69.236 +     * Evaluate the code read from file.
  69.237 +     */
  69.238 +    public static final Function INCLUDE = new Function() {
  69.239 +        public int invoke(FunctionDataParser fdp, Writer out)
  69.240 +        throws IOException, TemplateException {
  69.241 +            
  69.242 +            String filename = fdp.getData();
  69.243 +            
  69.244 +            TemplateReader fin;
  69.245 +            
  69.246 +            try {
  69.247 +                fin = Tema.createTemplateReader(fdp.createFile(filename));
  69.248 +            } catch (IOException e) {
  69.249 +                throw new TemplateException(e.getMessage(), e,
  69.250 +                        fdp.getTemplateReader());
  69.251 +            }
  69.252 +            
  69.253 +            int r = fdp.getTemplateParser().parse(fin, out);
  69.254 +            
  69.255 +            fin.close();
  69.256 +            return r;
  69.257 +        }
  69.258 +    };
  69.259 +    
  69.260 +    /**
  69.261 +     * Create path from base path and file name.
  69.262 +     */
  69.263 +    public static final Function FILE = new Function() {
  69.264 +        public int invoke(FunctionDataParser fdp, Writer out)
  69.265 +        throws IOException, TemplateException {
  69.266 +            
  69.267 +            String base = fdp.getNextArg();
  69.268 +            String name = fdp.getNextArg();                        
  69.269 +            
  69.270 +            if (fdp.getLastReturnCode() == 0)
  69.271 +                return 0;                        
  69.272 +                       
  69.273 +            out.write((new File(fdp.createFile(base), name)).getPath());
  69.274 +            
  69.275 +            return fdp.getLastReturnCode();
  69.276 +        }
  69.277 +    };
  69.278 +    
  69.279      /**
  69.280       * Update file (copy if newer).
  69.281       *
  69.282 @@ -137,27 +172,51 @@
  69.283       * @trows IOException on copying error.
  69.284       */
  69.285      private static void copyFile(File src, File dest) throws IOException {
  69.286 -	System.err.print("Copying " + src + "... ");
  69.287 -	
  69.288 -	if (src.lastModified() < dest.lastModified()) {
  69.289 -	    System.err.println(dest + " is up to date.");
  69.290 -	    return;
  69.291 -	}
  69.292 -
  69.293 -	File parent = dest.getParentFile();
  69.294 -	if (parent != null) parent.mkdirs();
  69.295 -
  69.296 +        System.err.print("Copying " + src + "... ");
  69.297 +        
  69.298 +        if (src.lastModified() < dest.lastModified()) {
  69.299 +            System.err.println(dest + " is up to date.");
  69.300 +            return;
  69.301 +        }
  69.302 +        
  69.303 +        File parent = dest.getParentFile();
  69.304 +        if (parent != null) parent.mkdirs();
  69.305 +        
  69.306          InputStream in = new FileInputStream(src);
  69.307          OutputStream out = new FileOutputStream(dest);
  69.308          
  69.309 +        copy(in, out);
  69.310 +        
  69.311 +        in.close();
  69.312 +        out.close();
  69.313 +    }
  69.314 +    
  69.315 +    private static void copy(InputStream in, OutputStream out)
  69.316 +    throws IOException {
  69.317 +        
  69.318          byte[] buffer = new byte[1024];
  69.319          int len;
  69.320 +        
  69.321          while ((len = in.read(buffer)) > 0) {
  69.322              out.write(buffer, 0, len);
  69.323          }
  69.324 -        in.close();
  69.325 -        out.close();
  69.326 -
  69.327 -	System.err.println("saved " + dest + ".");
  69.328 +    }
  69.329 +    
  69.330 +    private static void copy(Reader in, Writer out)
  69.331 +    throws IOException {
  69.332 +        
  69.333 +        char[] buffer = new char[1024];
  69.334 +        int len;
  69.335 +        
  69.336 +        while ((len = in.read(buffer)) > 0) {
  69.337 +            out.write(buffer, 0, len);
  69.338 +        }
  69.339 +    }
  69.340 +    
  69.341 +    private static void readFile(File src, Writer out)
  69.342 +    throws IOException {
  69.343 +        
  69.344 +        Reader in = Tema.createFileReader(src);
  69.345 +        copy(in, out);
  69.346      }
  69.347  }
    70.1 --- a/src/kryshen/tema/functions/ImageConverter.java	Thu Dec 14 23:22:05 2006 +0300
    70.2 +++ b/src/kryshen/tema/functions/ImageConverter.java	Tue Feb 19 20:32:17 2008 +0300
    70.3 @@ -1,21 +1,23 @@
    70.4  /*
    70.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    70.6 + *  Copyright 2006-2008 Mikhail Kryshen
    70.7   *
    70.8 - *  This program is free software; you can redistribute it and/or modify
    70.9 - *  it under the terms of the GNU General Public License as published by
   70.10 - *  the Free Software Foundation; either version 2 of the License, or
   70.11 - *  (at your option) any later version.
   70.12 + *  This file is part of Tema.
   70.13   *
   70.14 - *  This program is distributed in the hope that it will be useful,
   70.15 + *  Tema is free software: you can redistribute it and/or modify it
   70.16 + *  under the terms of the GNU Lesser General Public License as
   70.17 + *  published by the Free Software Foundation, either version 3 of the
   70.18 + *  License, or (at your option) any later version.
   70.19 + *
   70.20 + *  Tema is distributed in the hope that it will be useful,
   70.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   70.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   70.23 - *  GNU General Public License for more details.
   70.24 + *  GNU Lesser General Public License for more details.
   70.25   *
   70.26 - *  You should have received a copy of the GNU General Public License
   70.27 - *  along with this program; if not, write to the Free Software
   70.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   70.29 + *  You should have received a copy of the 
   70.30 + *  GNU Lesser General Public License along with Tema.  
   70.31 + *  If not, see <http://www.gnu.org/licenses/>.
   70.32   *
   70.33 - *  $Id: ImageConverter.java,v 1.4 2006/12/14 19:44:32 mikhail Exp $
   70.34 + *  $Id: ImageConverter.java,v 1.13 2008/02/16 17:56:34 mikhail Exp $
   70.35   */
   70.36  
   70.37  package kryshen.tema.functions;
   70.38 @@ -33,11 +35,11 @@
   70.39  /**
   70.40   * Convert images to specified format.
   70.41   *
   70.42 - * @author Mikhail A. Kryshen
   70.43 + * @author Mikhail Kryshen
   70.44   */
   70.45  public class ImageConverter extends Function {    
   70.46  
   70.47 -    public static final Function IMAGE = new ImageConverter();
   70.48 +    public static final Function CONVERT_IMAGE = new ImageConverter();
   70.49  
   70.50      public int invoke(FunctionDataParser fdp, Writer out)
   70.51          throws IOException, TemplateException {
   70.52 @@ -49,14 +51,11 @@
   70.53              Integer.parseInt(fdp.getNextArg()) : -1;
   70.54          int arg4 = fdp.hasMoreData() ? 
   70.55              Integer.parseInt(fdp.getNextArg()) : -1;
   70.56 -        
   70.57 -        File source = new File
   70.58 -            (Tema.getProperty("resource_base"), arg0);
   70.59 -        
   70.60 +
   70.61          try {
   70.62              convert
   70.63 -                (source,                  /* source file */
   70.64 -                 new File(arg1),          /* dest file */
   70.65 +                (fdp.createFile(arg0),    /* source file */
   70.66 +                 fdp.createFile(arg1),    /* dest file */
   70.67                   arg2,                    /* format */
   70.68                   arg3,                    /* max width */
   70.69                   arg4);                   /* max height */
    71.1 --- a/src/kryshen/tema/functions/Logics.java	Thu Dec 14 23:22:05 2006 +0300
    71.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.3 @@ -1,75 +0,0 @@
    71.4 -/*
    71.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    71.6 - *
    71.7 - *  This program is free software; you can redistribute it and/or modify
    71.8 - *  it under the terms of the GNU General Public License as published by
    71.9 - *  the Free Software Foundation; either version 2 of the License, or
   71.10 - *  (at your option) any later version.
   71.11 - *
   71.12 - *  This program is distributed in the hope that it will be useful,
   71.13 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   71.14 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   71.15 - *  GNU General Public License for more details.
   71.16 - *
   71.17 - *  You should have received a copy of the GNU General Public License
   71.18 - *  along with this program; if not, write to the Free Software
   71.19 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   71.20 - *
   71.21 - *  $Id: Logics.java,v 1.6 2006/12/14 14:39:26 mikhail Exp $
   71.22 - */
   71.23 -
   71.24 -package kryshen.tema.functions;
   71.25 -
   71.26 -import java.io.*;
   71.27 -import java.util.*;
   71.28 -
   71.29 -import kryshen.tema.*;
   71.30 -
   71.31 -/**
   71.32 - * Logical and conditional functions.
   71.33 - *
   71.34 - * @author Mikhail A. Kryshen
   71.35 - */
   71.36 -public class Logics {
   71.37 -    public static final Function FALSE =
   71.38 -        new Function() {
   71.39 -            public int invoke(FunctionDataParser fdp, Writer out)
   71.40 -                throws IOException, TemplateException {
   71.41 -		
   71.42 -		fdp.parseData(out);
   71.43 -                return 0;
   71.44 -            }
   71.45 -        };
   71.46 -
   71.47 -    public static final Function TRUE =
   71.48 -        new Function() {
   71.49 -            public int invoke(FunctionDataParser fdp, Writer out)
   71.50 -                throws IOException, TemplateException {
   71.51 -		
   71.52 -		fdp.parseData(out);
   71.53 -                return 1;
   71.54 -            }
   71.55 -        };
   71.56 -
   71.57 -    /**
   71.58 -     * Outputs it's data it has non-zero value.
   71.59 -     */
   71.60 -    public static final Function OPTIONAL =
   71.61 -        new Function() {
   71.62 -            public int invoke(FunctionDataParser fdp, Writer out)
   71.63 -                throws IOException, TemplateException {
   71.64 -
   71.65 -                StringWriter sw = new StringWriter();
   71.66 -                int s = fdp.parseData(sw);
   71.67 -                sw.close();
   71.68 -                String data = sw.toString();
   71.69 -
   71.70 -                if (s != 0) {
   71.71 -                    out.write(data);
   71.72 -                    return 1;
   71.73 -                } else {
   71.74 -                    return 0;
   71.75 -                }
   71.76 -            }
   71.77 -        };
   71.78 -}
    72.1 --- a/src/kryshen/tema/functions/ReplaceWriter.java	Thu Dec 14 23:22:05 2006 +0300
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,154 +0,0 @@
    72.4 -/*
    72.5 - *  Copyright (C) 2006 Mikhail A. Kryshen
    72.6 - *
    72.7 - *  This program is free software; you can redistribute it and/or modify
    72.8 - *  it under the terms of the GNU General Public License as published by
    72.9 - *  the Free Software Foundation; either version 2 of the License, or
   72.10 - *  (at your option) any later version.
   72.11 - *
   72.12 - *  This program is distributed in the hope that it will be useful,
   72.13 - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   72.14 - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   72.15 - *  GNU General Public License for more details.
   72.16 - *
   72.17 - *  You should have received a copy of the GNU General Public License
   72.18 - *  along with this program; if not, write to the Free Software
   72.19 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   72.20 - *
   72.21 - *  $Id: ReplaceWriter.java,v 1.2 2006/12/14 14:39:26 mikhail Exp $
   72.22 - */
   72.23 -
   72.24 -package kryshen.tema.functions;
   72.25 -
   72.26 -import java.io.Writer;
   72.27 -import java.io.FilterWriter;
   72.28 -import java.io.IOException;
   72.29 -
   72.30 -import java.util.LinkedList;
   72.31 -import java.util.Iterator;
   72.32 -
   72.33 -/**
   72.34 - * FilterWriter which replaces characters with escape strings.
   72.35 - *
   72.36 - * @author Mikhail A. Kryshen
   72.37 - */
   72.38 -class ReplaceWriter extends FilterWriter {
   72.39 -    private String[] patterns;
   72.40 -    private String[] replaces;
   72.41 -
   72.42 -    private String prefix;
   72.43 -    private String postfix;
   72.44 -
   72.45 -    private int maxPatternLength = 0;
   72.46 -
   72.47 -    /** Have this Writer processed any data? */
   72.48 -    private boolean processedData = false;
   72.49 -
   72.50 -    private StringBuffer buffer = new StringBuffer();
   72.51 -
   72.52 -    public ReplaceWriter(Writer w, String pattern, String replace) {
   72.53 -        this(w, new String[]{pattern}, new String[]{replace});
   72.54 -    }
   72.55 -
   72.56 -    public ReplaceWriter(Writer w, String pattern, String replace,
   72.57 -                         String prefix, String postfix) {
   72.58 -
   72.59 -        this(w, new String[]{pattern}, new String[]{replace}, 
   72.60 -             prefix, postfix);
   72.61 -    }
   72.62 -
   72.63 -    public ReplaceWriter(Writer w, String[] patterns, String[] replaces) {
   72.64 -        this(w, patterns, replaces, null, null);
   72.65 -    }
   72.66 -
   72.67 -    public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 
   72.68 -                         String prefix, String postfix) {
   72.69 -	super(w);
   72.70 -        
   72.71 -	this.patterns = patterns;
   72.72 -	this.replaces = replaces;
   72.73 -        
   72.74 -        this.prefix = prefix;
   72.75 -        this.postfix = postfix;
   72.76 -        
   72.77 -	for (int i = 0; i < patterns.length; i++) {
   72.78 -	    int length = patterns[i].length();
   72.79 -	    if (length > maxPatternLength)
   72.80 -		maxPatternLength = length;
   72.81 -	}
   72.82 -    }
   72.83 -
   72.84 -    private boolean processBuffer(int minLength) throws IOException {
   72.85 -        if (buffer.length() == 0) return false;
   72.86 -
   72.87 -        if (!processedData) {
   72.88 -            if (prefix != null)
   72.89 -                super.write(prefix, 0, prefix.length());
   72.90 -            processedData = true;
   72.91 -        }
   72.92 -
   72.93 -        int k;
   72.94 -	for (k = 0; minLength + k < buffer.length(); k++) {
   72.95 -	    for (int i = 0; i < patterns.length; i++) {
   72.96 -		String pattern = patterns[i];
   72.97 -		int length = pattern.length();
   72.98 -
   72.99 -                if (length + k > buffer.length())
  72.100 -                    continue;
  72.101 -
  72.102 -		boolean match = true;
  72.103 -
  72.104 -		for (int j = 0; j < length; j++) {
  72.105 -		    if (pattern.charAt(j) != buffer.charAt(j + k)) {
  72.106 -			match = false;
  72.107 -                        break;
  72.108 -		    }
  72.109 -		}
  72.110 -
  72.111 -		if (match) {
  72.112 -                    super.write(buffer.substring(0, k), 0, k);
  72.113 -                    buffer.delete(0, k + length);
  72.114 -                    super.write(replaces[i], 0, replaces[i].length());
  72.115 -		    return true;
  72.116 -		}
  72.117 -	    }
  72.118 -	}
  72.119 -
  72.120 -        super.write(buffer.substring(0, k), 0, k);
  72.121 -        buffer.delete(0, k);
  72.122 -
  72.123 -        return false;
  72.124 -    }
  72.125 -
  72.126 -    public void write(int c) throws IOException {
  72.127 -	buffer.append((char)c);
  72.128 -	processBuffer(maxPatternLength);
  72.129 -    }
  72.130 -
  72.131 -    public void write(char[] cbuf, int off, int len) throws IOException {
  72.132 -	for (int i = off; i < off + len; i++) {
  72.133 -	    buffer.append(cbuf[i]);
  72.134 -	}
  72.135 -	processBuffer(maxPatternLength);
  72.136 -    }
  72.137 -
  72.138 -    public void write(String str, int off, int len) throws IOException {
  72.139 -        buffer.append(str.substring(off, off + len));
  72.140 -	processBuffer(maxPatternLength);
  72.141 -    }
  72.142 -
  72.143 -    public void finish() throws IOException {
  72.144 -        while (processBuffer(0));
  72.145 -
  72.146 -//         super.write(buffer.toString(), 0, buffer.length());
  72.147 -//         buffer.delete(0, buffer.length());
  72.148 -
  72.149 -        if (processedData && postfix != null)
  72.150 -            super.write(postfix, 0, postfix.length());
  72.151 -    }
  72.152 -
  72.153 -    public void close() throws IOException {
  72.154 -        finish();
  72.155 -        super.close();
  72.156 -    }
  72.157 -}
    73.1 --- a/src/kryshen/tema/functions/Standard.java	Thu Dec 14 23:22:05 2006 +0300
    73.2 +++ b/src/kryshen/tema/functions/Standard.java	Tue Feb 19 20:32:17 2008 +0300
    73.3 @@ -1,258 +1,259 @@
    73.4  /*
    73.5 - *  Copyright (C) 2005, 2006 Mikhail A. Kryshen
    73.6 + *  Copyright 2006-2008 Mikhail Kryshen
    73.7   *
    73.8 - *  This program is free software; you can redistribute it and/or modify
    73.9 - *  it under the terms of the GNU General Public License as published by
   73.10 - *  the Free Software Foundation; either version 2 of the License, or
   73.11 - *  (at your option) any later version.
   73.12 + *  This file is part of Tema.
   73.13   *
   73.14 - *  This program is distributed in the hope that it will be useful,
   73.15 + *  Tema is free software: you can redistribute it and/or modify it
   73.16 + *  under the terms of the GNU Lesser General Public License as
   73.17 + *  published by the Free Software Foundation, either version 3 of the
   73.18 + *  License, or (at your option) any later version.
   73.19 + *
   73.20 + *  Tema is distributed in the hope that it will be useful,
   73.21   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   73.22   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   73.23 - *  GNU General Public License for more details.
   73.24 + *  GNU Lesser General Public License for more details.
   73.25   *
   73.26 - *  You should have received a copy of the GNU General Public License
   73.27 - *  along with this program; if not, write to the Free Software
   73.28 - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   73.29 + *  You should have received a copy of the 
   73.30 + *  GNU Lesser General Public License along with Tema.  
   73.31 + *  If not, see <http://www.gnu.org/licenses/>.
   73.32   *
   73.33 - *  $Id: Standard.java,v 1.5 2006/12/14 14:39:26 mikhail Exp $
   73.34 + *  $Id: Standard.java,v 1.34 2008/02/19 17:32:17 mikhail Exp $
   73.35   */
   73.36  
   73.37  package kryshen.tema.functions;
   73.38  
   73.39 -import java.io.*;
   73.40 -import java.util.*;
   73.41 -import java.net.*;
   73.42 -
   73.43 -import java.sql.SQLException;
   73.44 -import java.sql.PreparedStatement;
   73.45 -
   73.46 -import kryshen.tema.*;
   73.47 +import java.io.IOException;
   73.48 +import java.io.Writer;
   73.49 +import java.net.URL;
   73.50 +import java.net.URLClassLoader;
   73.51 +import java.util.ArrayList;
   73.52 +import java.util.List;
   73.53 +import kryshen.tema.Context;
   73.54 +import kryshen.tema.Function;
   73.55 +import kryshen.tema.FunctionDataParser;
   73.56 +import kryshen.tema.Tema;
   73.57 +import kryshen.tema.TemplateException;
   73.58 +import kryshen.tema.io.NullWriter;
   73.59  
   73.60  /**
   73.61   * Standard TEMA functions.
   73.62   */
   73.63  public class Standard {
   73.64 -    public static final Function SET =
   73.65 -        new Function() {
   73.66 -            public int invoke(FunctionDataParser fdp, Writer out)
   73.67 +    
   73.68 +    /**
   73.69 +     * Output Tema version.
   73.70 +     */
   73.71 +    public static final Function TEMA = new Function() {
   73.72 +        public int invoke(FunctionDataParser fdp, Writer out)
   73.73 +        throws IOException, TemplateException {
   73.74 +            out.write(Tema.TITLE + " " + Tema.VERSION
   73.75 +                    /*+ " by " + Tema.AUTHOR*/);
   73.76 +            return 1;
   73.77 +        }
   73.78 +    };
   73.79 +    
   73.80 +    /**
   73.81 +     * Define static variable.
   73.82 +     */
   73.83 +    public static final Function SET = new Function() {
   73.84 +        public int invoke(FunctionDataParser fdp, Writer out)
   73.85 +        throws IOException, TemplateException {
   73.86 +            
   73.87 +            String name = fdp.getNextArg();
   73.88 +            
   73.89 +            if (fdp.getLastReturnCode() == 0)
   73.90 +                return 0;
   73.91 +            
   73.92 +            String data = fdp.getData(out);
   73.93 +            fdp.getContext().set(name, data);
   73.94 +            
   73.95 +            return fdp.getLastReturnCode();
   73.96 +        }
   73.97 +    };
   73.98 +    
   73.99 +    /**
  73.100 +     * Recursively remove definition.
  73.101 +     */
  73.102 +    public static final Function UNSET = new Function() {
  73.103 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.104 +        throws IOException, TemplateException {
  73.105 +            
  73.106 +            int r = 0;
  73.107 +            
  73.108 +            while (fdp.hasMoreData()) {
  73.109 +                String name = fdp.getNextArg();
  73.110 +                
  73.111 +                if (fdp.getLastReturnCode() == 0)
  73.112 +                    continue;
  73.113 +                
  73.114 +                if (fdp.getContext().unset(name))
  73.115 +                    r++;
  73.116 +            }
  73.117 +            
  73.118 +            return r;
  73.119 +        }
  73.120 +    };
  73.121 +    
  73.122 +    /**
  73.123 +     * Export variable to the global (outermost) context.
  73.124 +     */
  73.125 +    public static final Function EXPORT = new Function() {
  73.126 +        public int invoke(FunctionDataParser fdp,
  73.127 +                final Writer out)
  73.128                  throws IOException, TemplateException {
  73.129 -
  73.130 -                String arg0 = fdp.getNextArg();
  73.131 -                String arg1 = fdp.getData();
  73.132 +            
  73.133 +            String name = fdp.getNextArg();
  73.134 +            
  73.135 +            if (fdp.getLastReturnCode() == 0)
  73.136 +                return 0;
  73.137 +            
  73.138 +            // Set and export.
  73.139 +            if (fdp.hasMoreData()) {
  73.140 +                Object value = fdp.getData(out);
  73.141                  
  73.142 -                fdp.getTemplateParser().setValue(arg0, arg1);
  73.143 -                
  73.144 -		out.write(arg0);
  73.145 -                return 1;
  73.146 +                fdp.getContext().export(name, value);
  73.147 +                return fdp.getLastReturnCode();
  73.148              }
  73.149 -        };
  73.150 -
  73.151 -    /* prepare:qury_name sql_statement */
  73.152 -    public static final Function PREPARE =
  73.153 -        new Function() {
  73.154 -            public int invoke(FunctionDataParser fdp, Writer out)
  73.155 -                throws IOException, TemplateException {
  73.156 -
  73.157 -                String arg0 = fdp.getNextArg();
  73.158 -                String data = fdp.getData();
  73.159 -
  73.160 -		PreparedStatement statement;
  73.161 -
  73.162 -		try {
  73.163 -		    statement = Tema.getDbConnection()
  73.164 -                        .prepareStatement(data);
  73.165 -		} catch (SQLException e) {
  73.166 -		    throw new TemplateException
  73.167 -                        (e.getMessage(), e, fdp.getTemplateReader());
  73.168 -		}
  73.169 -                
  73.170 -                fdp.getTemplateParser().setValue(arg0, statement);   
  73.171 -             
  73.172 -		out.write(arg0);
  73.173 -                return 1;
  73.174 -            }
  73.175 -        };
  73.176 -
  73.177 -    /* query:sql_query template arg1 arg2 ... argN */
  73.178 -    public static final Function QUERY =
  73.179 -        new Function() {
  73.180 -           public int invoke(FunctionDataParser fdp, Writer out)
  73.181 -                throws IOException, TemplateException {
  73.182 -                
  73.183 -                String arg0 = fdp.getNextArg();
  73.184 -                String arg1 = fdp.getNextArg();
  73.185 -		List<String> args = fdp.getArgs();				
  73.186 -
  73.187 -		TemplateParser tp = fdp.getTemplateParser();
  73.188 -
  73.189 -                TemplateReader tr = 
  73.190 -                    new TemplateReader(new StringReader(arg1),
  73.191 -                                       fdp.getTemplateReader());
  73.192 -
  73.193 -		try {
  73.194 -		    return Tema.query
  73.195 -			(tr, (PreparedStatement)tp.getValue(arg0),
  73.196 -			 args, tp, out);
  73.197 -		} catch (SQLException e) {
  73.198 -		    throw new TemplateException
  73.199 -                        (e.getMessage(), e, fdp.getTemplateReader());
  73.200 -		}
  73.201 -            }
  73.202 -        };
  73.203 -
  73.204 -    public static final Function REPLACE =
  73.205 -        new Function() {
  73.206 -	    public int invoke(FunctionDataParser fdp, Writer out)
  73.207 -		throws IOException, TemplateException {		
  73.208 -
  73.209 -                String arg0 = fdp.getNextArg();
  73.210 -                String arg1 = fdp.getNextArg();
  73.211 -
  73.212 -                ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1);
  73.213 -
  73.214 -                int ret = fdp.parseData(rw);
  73.215 -                rw.finish();
  73.216 -                return ret;
  73.217 -            }
  73.218 -        };
  73.219 -
  73.220 -    public static final Function LOAD =
  73.221 -
  73.222 -        new Function() {
  73.223 -            public int invoke(FunctionDataParser fdp, Writer out)
  73.224 -                throws IOException, TemplateException {
  73.225 -                
  73.226 -                final String name = fdp.getNextArg();
  73.227 -                final String className = fdp.getNextArg();
  73.228 -
  73.229 -                List<URL> urls = new ArrayList<URL>(1);
  73.230 -
  73.231 -                while (fdp.hasMoreData()) {
  73.232 -                    urls.add(new URL(fdp.getNextArg()));                    
  73.233 -                }
  73.234 -                
  73.235 -                ClassLoader loader = this.getClass().getClassLoader();
  73.236 -
  73.237 -                if (urls.size() > 0) {
  73.238 -                    loader = new URLClassLoader
  73.239 -                        (urls.toArray(new URL[0]), loader);
  73.240 -                }                
  73.241 -
  73.242 -                Class<Function> functionClass;
  73.243 -                Function function;
  73.244 -
  73.245 -                try {
  73.246 -                    functionClass = loadFunctionClass(loader, className);
  73.247 -                } catch (ClassNotFoundException e) {
  73.248 -                    throw new TemplateException
  73.249 -                        ("Class not found", e, fdp.getTemplateReader());
  73.250 -                } catch (ClassCastException e) {
  73.251 -                    throw new TemplateException
  73.252 -                        ("Not a function class", e, fdp.getTemplateReader());
  73.253 -                }
  73.254 -                
  73.255 -                try {
  73.256 -                    function = functionClass.newInstance();
  73.257 -                } catch (InstantiationException e) {
  73.258 -                    throw new TemplateException
  73.259 -                        ("Could not load class", e, fdp.getTemplateReader());
  73.260 -                } catch (IllegalAccessException e) {
  73.261 -                    throw new TemplateException
  73.262 -                        ("Could not load class", e, fdp.getTemplateReader());
  73.263 -                }
  73.264 -
  73.265 -                fdp.getTemplateParser().registerFunction(name, function);
  73.266 -                                
  73.267 -
  73.268 +            
  73.269 +            // Only export.
  73.270 +            if (fdp.getContext().export(name)) {
  73.271                  out.write(name);
  73.272                  return 1;
  73.273              }
  73.274 -        };
  73.275 +            
  73.276 +            return 0;
  73.277 +        }
  73.278 +    };
  73.279 +    
  73.280 +    /**
  73.281 +     * Copy macro definitions.
  73.282 +     */
  73.283 +    public static final Function ASSIGN = new Function() {
  73.284 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.285 +                throws IOException, TemplateException {
  73.286  
  73.287 -    public static final Function NULL_OUTPUT =
  73.288 -        new Function() {
  73.289 -	    public int invoke(FunctionDataParser fdp, Writer out)
  73.290 -		throws IOException, TemplateException {		
  73.291 +            String name1 = fdp.getNextArg();
  73.292  
  73.293 -		/* Write nothing. */
  73.294 -		return fdp.parseData(new Writer() {
  73.295 -                    public void close() {}
  73.296 -                    public void flush() {}
  73.297 -                    public void write(char[] cbuf, int off, int len) {}
  73.298 -                });
  73.299 +            if (fdp.getLastReturnCode() == 0)
  73.300 +                return 0;
  73.301 +            
  73.302 +            String name2 = fdp.getData();
  73.303 +            
  73.304 +            if (fdp.getLastReturnCode() == 0)
  73.305 +                return 0;
  73.306 +
  73.307 +            Context context = fdp.getContext();
  73.308 +            Object value = context.get(name2);
  73.309 +            
  73.310 +            if (value == null)
  73.311 +                return 0;
  73.312 +            
  73.313 +            context.set(name1, value);
  73.314 +            
  73.315 +            return 1;
  73.316 +        }
  73.317 +    };
  73.318 +    
  73.319 +    /**
  73.320 +     * Invoke function specified by name.
  73.321 +     */
  73.322 +    public static final Function INVOKE = new Function() {
  73.323 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.324 +        throws IOException, TemplateException {
  73.325 +            
  73.326 +            String name = fdp.getNextArg();
  73.327 +            
  73.328 +            if (fdp.getLastReturnCode() == 0)
  73.329 +                return 0;
  73.330 +            
  73.331 +            return fdp.getTemplateParser().invoke(name, fdp, out);            
  73.332 +        }
  73.333 +    };
  73.334 +    
  73.335 +    /**
  73.336 +     * Create definiton as a new Java object.
  73.337 +     */
  73.338 +    public static final Function LOAD = new Function() {
  73.339 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.340 +        throws IOException, TemplateException {
  73.341 +            
  73.342 +            final String name = fdp.getNextArg();
  73.343 +            final String className = fdp.getNextArg();
  73.344 +            
  73.345 +            List<URL> urls = new ArrayList<URL>(1);
  73.346 +            
  73.347 +            while (fdp.hasMoreData()) {
  73.348 +                urls.add(new URL(fdp.getNextArg()));
  73.349              }
  73.350 -        };
  73.351 -
  73.352 -    public static final Function XML_ESCAPE =
  73.353 -        new Function() {
  73.354 -	    public int invoke(FunctionDataParser fdp, Writer out)
  73.355 -		throws IOException, TemplateException {		
  73.356 -
  73.357 -                final String[] chars = {"&", "<", ">", "`", "\""};
  73.358 -                final String[] escape = {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"};
  73.359 -
  73.360 -                ReplaceWriter rw = new ReplaceWriter(out, chars, escape);
  73.361 -
  73.362 -                int ret = fdp.parseData(rw);
  73.363 -                rw.finish();
  73.364 -                return ret;
  73.365 +            
  73.366 +            ClassLoader loader = this.getClass().getClassLoader();
  73.367 +            
  73.368 +            if (urls.size() > 0) {
  73.369 +                loader = new URLClassLoader
  73.370 +                        (urls.toArray(new URL[0]), loader);
  73.371              }
  73.372 -        };
  73.373 -
  73.374 -    public static final Function XML_CDATA =
  73.375 -        new Function() {
  73.376 -	    public int invoke(FunctionDataParser fdp, Writer out)
  73.377 -		throws IOException, TemplateException {		
  73.378 -
  73.379 -                ReplaceWriter rw = new ReplaceWriter
  73.380 -                    (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>");
  73.381 -
  73.382 -                int ret = fdp.parseData(rw);
  73.383 -                rw.finish();
  73.384 -                return ret;
  73.385 +            
  73.386 +            Class<?> loadedClass;
  73.387 +            Object instance;
  73.388 +            
  73.389 +            try {
  73.390 +                loadedClass = loader.loadClass(className);
  73.391 +            } catch (ClassNotFoundException e) {
  73.392 +                throw new TemplateException
  73.393 +                        ("Class not found", e, fdp.getTemplateReader());
  73.394              }
  73.395 -        };
  73.396 -
  73.397 -
  73.398 -    @SuppressWarnings("unchecked")
  73.399 -    private static Class<Function> loadFunctionClass
  73.400 -        (ClassLoader loader, String className)
  73.401 -        throws ClassNotFoundException {
  73.402 -        
  73.403 -        return (Class<Function>)loader.loadClass(className);
  73.404 -    }
  73.405 -
  73.406 +            
  73.407 +            try {
  73.408 +                instance = loadedClass.newInstance();
  73.409 +            } catch (InstantiationException e) {
  73.410 +                throw new TemplateException
  73.411 +                        ("Could not load class", e, fdp.getTemplateReader());
  73.412 +            } catch (IllegalAccessException e) {
  73.413 +                throw new TemplateException
  73.414 +                        ("Could not load class", e, fdp.getTemplateReader());
  73.415 +            }
  73.416 +            
  73.417 +            fdp.getContext().set(name, instance);
  73.418 +                        
  73.419 +            out.write(name);
  73.420 +            return 1;
  73.421 +        }
  73.422 +    };
  73.423 +    
  73.424 +    public static final Function ECHO = new Function() {
  73.425 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.426 +        throws IOException, TemplateException {
  73.427 +            
  73.428 +            if (!fdp.hasMoreData())
  73.429 +                return 0;
  73.430 +            
  73.431 +            return fdp.parseData(out);
  73.432 +        }
  73.433 +    };
  73.434 +    
  73.435      /**
  73.436 -     * Update file (copy if newer).
  73.437 -     *
  73.438 -     * @param src source file.
  73.439 -     * @param dest destination file.
  73.440 -     *
  73.441 -     * @trows IOException on copying error.
  73.442 +     * Process arguments, but output nothing.
  73.443       */
  73.444 -    private static void copyFile(File src, File dest) throws IOException {
  73.445 -	System.err.print("Copying " + src + "... ");
  73.446 -	
  73.447 -	if (src.lastModified() < dest.lastModified()) {
  73.448 -	    System.err.println(dest + " is up to date.");
  73.449 -	    return;
  73.450 -	}
  73.451 -
  73.452 -	File parent = dest.getParentFile();
  73.453 -	if (parent != null) parent.mkdirs();
  73.454 -
  73.455 -        InputStream in = new FileInputStream(src);
  73.456 -        OutputStream out = new FileOutputStream(dest);
  73.457 -        
  73.458 -        byte[] buffer = new byte[1024];
  73.459 -        int len;
  73.460 -        while ((len = in.read(buffer)) > 0) {
  73.461 -            out.write(buffer, 0, len);
  73.462 +    public static final Function SILENT = new Function() {
  73.463 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.464 +        throws IOException, TemplateException {
  73.465 +            
  73.466 +            if (!fdp.hasMoreData())
  73.467 +                return 0;
  73.468 +            
  73.469 +            return fdp.parseData(NullWriter.INSTANCE);
  73.470          }
  73.471 -        in.close();
  73.472 -        out.close();
  73.473 -
  73.474 -	System.err.println("saved " + dest + ".");
  73.475 -    }
  73.476 +    };
  73.477 +    
  73.478 +    /**
  73.479 +     * Skip arguments.
  73.480 +     */
  73.481 +    public static final Function SKIP = new Function() {
  73.482 +        public int invoke(FunctionDataParser fdp, Writer out)
  73.483 +        throws IOException, TemplateException {
  73.484 +            
  73.485 +            // Ignore arguments.
  73.486 +            return 0;
  73.487 +        }
  73.488 +    };
  73.489  }
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/src/kryshen/tema/functions/Strings.java	Tue Feb 19 20:32:17 2008 +0300
    74.3 @@ -0,0 +1,225 @@
    74.4 +/*
    74.5 + *  Copyright 2006-2008 Mikhail Kryshen
    74.6 + *
    74.7 + *  This file is part of Tema.
    74.8 + *
    74.9 + *  Tema is free software: you can redistribute it and/or modify it
   74.10 + *  under the terms of the GNU Lesser General Public License as
   74.11 + *  published by the Free Software Foundation, either version 3 of the
   74.12 + *  License, or (at your option) any later version.
   74.13 + *
   74.14 + *  Tema is distributed in the hope that it will be useful,
   74.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   74.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   74.17 + *  GNU Lesser General Public License for more details.
   74.18 + *
   74.19 + *  You should have received a copy of the 
   74.20 + *  GNU Lesser General Public License along with Tema.  
   74.21 + *  If not, see <http://www.gnu.org/licenses/>.
   74.22 + *
   74.23 + *  $Id: Strings.java,v 1.13 2008/02/16 17:38:03 mikhail Exp $
   74.24 + */
   74.25 +
   74.26 +package kryshen.tema.functions;
   74.27 +
   74.28 +import java.io.IOException;
   74.29 +import java.io.Writer;
   74.30 +import kryshen.tema.Function;
   74.31 +import kryshen.tema.FunctionDataParser;
   74.32 +import kryshen.tema.TemplateException;
   74.33 +import kryshen.tema.io.ReplaceWriter;
   74.34 +
   74.35 +/**
   74.36 + * Functions for string manipulation.
   74.37 + */
   74.38 +public class Strings {
   74.39 +    public static final Function TO_UPPER = new Function() {
   74.40 +        public int invoke(FunctionDataParser fdp, Writer out)
   74.41 +        throws IOException, TemplateException {
   74.42 +            
   74.43 +            String data = fdp.getData();
   74.44 +            out.write(data.toUpperCase());
   74.45 +            return fdp.getLastReturnCode();
   74.46 +        }
   74.47 +    };
   74.48 +    
   74.49 +    public static final Function TO_LOWER = new Function() {
   74.50 +        public int invoke(FunctionDataParser fdp, Writer out)
   74.51 +        throws IOException, TemplateException {
   74.52 +            
   74.53 +            String data = fdp.getData();
   74.54 +            out.write(data.toLowerCase());
   74.55 +            return fdp.getLastReturnCode();
   74.56 +        }
   74.57 +    };
   74.58 +    
   74.59 +    public static final Function SUBSTRING = new Function() {
   74.60 +        public int invoke(FunctionDataParser fdp, Writer out)
   74.61 +        throws IOException, TemplateException {
   74.62 +            
   74.63 +            String is = fdp.getNextArg();
   74.64 +            String js = fdp.getNextArg();
   74.65 +            
   74.66 +            String data = fdp.getData();
   74.67 +            
   74.68 +            try {
   74.69 +                if (js.equals("$")) {
   74.70 +                    out.write(data.substring(Integer.parseInt(is)));
   74.71 +                } else {
   74.72 +                    out.write(data.substring(
   74.73 +                            Integer.parseInt(is),
   74.74 +                            Integer.parseInt(js)));
   74.75 +                }
   74.76 +            } catch (NumberFormatException e) {
   74.77 +                throw new TemplateException(
   74.78 +                        e.toString(), e, fdp.getTemplateReader());
   74.79 +            } catch (IndexOutOfBoundsException e) {
   74.80 +                throw new TemplateException(
   74.81 +                        e.toString(), e, fdp.getTemplateReader());
   74.82 +            }
   74.83 +            
   74.84 +            return fdp.getLastReturnCode();
   74.85 +        }
   74.86 +    };
   74.87 +    
   74.88 +    public static final Function REPLACE = new Function() {
   74.89 +        public int invoke(FunctionDataParser fdp, Writer out)
   74.90 +        throws IOException, TemplateException {
   74.91 +            
   74.92 +            String arg0 = fdp.getNextArg();
   74.93 +            String arg1 = fdp.getNextArg();
   74.94 +            
   74.95 +            ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1);
   74.96 +            
   74.97 +            int ret = fdp.parseData(rw);
   74.98 +            rw.finish();
   74.99 +            return ret;
  74.100 +        }
  74.101 +    };
  74.102 +    
  74.103 +    public static final Function XML_ESCAPE = new Function() {
  74.104 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.105 +        throws IOException, TemplateException {
  74.106 +            
  74.107 +            final String[] chars = {"&", "<", ">", "`", "\""};
  74.108 +            final String[] escape = {"&amp;", "&lt;", "&gt;", "&apos;", "&quot;"};
  74.109 +            
  74.110 +            ReplaceWriter rw = new ReplaceWriter(out, chars, escape);
  74.111 +            
  74.112 +            int ret = fdp.parseData(rw);
  74.113 +            rw.finish();
  74.114 +            return ret;
  74.115 +        }
  74.116 +    };
  74.117 +    
  74.118 +    public static final Function XML_CDATA = new Function() {
  74.119 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.120 +        throws IOException, TemplateException {
  74.121 +            
  74.122 +            ReplaceWriter rw = new ReplaceWriter
  74.123 +                    (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>");
  74.124 +            
  74.125 +            int ret = fdp.parseData(rw);
  74.126 +            rw.finish();
  74.127 +            return ret;
  74.128 +        }
  74.129 +    };
  74.130 +    
  74.131 +    public static final Function REGEX_MATCH = new Function() {
  74.132 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.133 +        throws IOException, TemplateException {
  74.134 +            
  74.135 +            String regex = fdp.getNextArg();            
  74.136 +            String data = fdp.getData(out);
  74.137 +            
  74.138 +            if (data.matches(regex)) {
  74.139 +                return 1;
  74.140 +            }
  74.141 +            
  74.142 +            return 0;
  74.143 +        }
  74.144 +    };
  74.145 +    
  74.146 +    public static final Function REGEX_REPLACE_FIRST = new Function() {
  74.147 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.148 +        throws IOException, TemplateException {
  74.149 +            
  74.150 +            String regex = fdp.getNextArg();
  74.151 +            String replacement = fdp.getNextArg();
  74.152 +            String data = fdp.getData();
  74.153 +            
  74.154 +            if (fdp.getLastReturnCode() == 0)
  74.155 +                return 0;
  74.156 +            
  74.157 +            out.write(data.replaceFirst(regex, replacement));
  74.158 +            
  74.159 +            return fdp.getLastReturnCode();
  74.160 +        }
  74.161 +    };
  74.162 +    
  74.163 +    public static final Function REGEX_REPLACE_ALL = new Function() {
  74.164 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.165 +        throws IOException, TemplateException {
  74.166 +            
  74.167 +            String regex = fdp.getNextArg();
  74.168 +            String replacement = fdp.getNextArg();
  74.169 +            String data = fdp.getData();
  74.170 +            
  74.171 +            if (fdp.getLastReturnCode() == 0)
  74.172 +                return 0;
  74.173 +            
  74.174 +            out.write(data.replaceAll(regex, replacement));
  74.175 +            
  74.176 +            return fdp.getLastReturnCode();
  74.177 +        }
  74.178 +    };
  74.179 +    
  74.180 +    public static final Function EQUAL = new Function() {
  74.181 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.182 +        throws IOException, TemplateException {
  74.183 +            
  74.184 +            String s1 = fdp.getNextArg();
  74.185 +            
  74.186 +            while (fdp.hasMoreData()) {
  74.187 +                String s2 = fdp.getNextArg();
  74.188 +                
  74.189 +                if (!s1.equals(s2)) {
  74.190 +                    return 0;
  74.191 +                }
  74.192 +                
  74.193 +                s1 = s2;
  74.194 +            }
  74.195 +
  74.196 +            return 1;
  74.197 +        }
  74.198 +    };
  74.199 +    
  74.200 +    public static final Function CHAR = new Function() {
  74.201 +        public int invoke(FunctionDataParser fdp, Writer out)
  74.202 +                throws IOException, TemplateException {           
  74.203 +
  74.204 +            if (!fdp.hasMoreData())
  74.205 +                return 0;
  74.206 +            
  74.207 +            do {
  74.208 +                String s = fdp.getNextArg();
  74.209 +                int code;
  74.210 +
  74.211 +                try {
  74.212 +                    if (s.startsWith("0x")) {
  74.213 +                        code = Integer.parseInt(s.substring(2), 16);
  74.214 +                    } else {
  74.215 +                        code = Integer.parseInt(s);
  74.216 +                    }
  74.217 +                } catch (NumberFormatException e) {
  74.218 +                    throw new TemplateException(e.getMessage(), e,
  74.219 +                            fdp.getTemplateReader());
  74.220 +                }
  74.221 +
  74.222 +                out.write(code);                
  74.223 +            } while (fdp.hasMoreData());
  74.224 +                
  74.225 +            return 1;
  74.226 +        }
  74.227 +    };
  74.228 +}
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/src/kryshen/tema/io/CopyWriter.java	Tue Feb 19 20:32:17 2008 +0300
    75.3 @@ -0,0 +1,69 @@
    75.4 +/*
    75.5 + *  Copyright 2006-2008 Mikhail Kryshen
    75.6 + *
    75.7 + *  This file is part of Tema.
    75.8 + *
    75.9 + *  Tema is free software: you can redistribute it and/or modify it
   75.10 + *  under the terms of the GNU Lesser General Public License as
   75.11 + *  published by the Free Software Foundation, either version 3 of the
   75.12 + *  License, or (at your option) any later version.
   75.13 + *
   75.14 + *  Tema is distributed in the hope that it will be useful,
   75.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   75.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   75.17 + *  GNU Lesser General Public License for more details.
   75.18 + *
   75.19 + *  You should have received a copy of the 
   75.20 + *  GNU Lesser General Public License along with Tema.  
   75.21 + *  If not, see <http://www.gnu.org/licenses/>.
   75.22 + *
   75.23 + *  $Id: CopyWriter.java,v 1.7 2008/02/16 17:56:34 mikhail Exp $
   75.24 + */
   75.25 +
   75.26 +package kryshen.tema.io;
   75.27 +
   75.28 +import java.io.IOException;
   75.29 +import java.io.Writer;
   75.30 +
   75.31 +/**
   75.32 + * Copies it's output to several writers.
   75.33 + *
   75.34 + * @author Mikhail Kryshen
   75.35 + */
   75.36 +public class CopyWriter extends Writer {
   75.37 +    private final Writer[] writers;
   75.38 +    
   75.39 +    public CopyWriter(Writer... writers) {
   75.40 +        this.writers = writers;
   75.41 +    }
   75.42 +    
   75.43 +    public void write(char[] cbuf, int off, int len) throws IOException {
   75.44 +        for (Writer w : writers) {
   75.45 +            w.write(cbuf, off, len);
   75.46 +        }
   75.47 +    }
   75.48 +    
   75.49 +    public void write(int c) throws IOException {
   75.50 +        for (Writer w : writers) {
   75.51 +            w.write(c);
   75.52 +        }
   75.53 +    }
   75.54 +    
   75.55 +    public void write(String str, int off, int len) throws IOException {
   75.56 +        for (Writer w : writers) {
   75.57 +            w.write(str, off, len);
   75.58 +        }
   75.59 +    }
   75.60 +    
   75.61 +    public void flush() throws IOException {
   75.62 +        for (Writer w : writers) {
   75.63 +            w.flush();
   75.64 +        }
   75.65 +    }
   75.66 +    
   75.67 +    public void close() throws IOException {
   75.68 +        for (Writer w : writers) {
   75.69 +            w.close();
   75.70 +        }
   75.71 +    }
   75.72 +}
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/src/kryshen/tema/io/NullWriter.java	Tue Feb 19 20:32:17 2008 +0300
    76.3 @@ -0,0 +1,46 @@
    76.4 +/*
    76.5 + *  Copyright 2006-2008 Mikhail Kryshen
    76.6 + *
    76.7 + *  This file is part of Tema.
    76.8 + *
    76.9 + *  Tema is free software: you can redistribute it and/or modify it
   76.10 + *  under the terms of the GNU Lesser General Public License as
   76.11 + *  published by the Free Software Foundation, either version 3 of the
   76.12 + *  License, or (at your option) any later version.
   76.13 + *
   76.14 + *  Tema is distributed in the hope that it will be useful,
   76.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   76.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   76.17 + *  GNU Lesser General Public License for more details.
   76.18 + *
   76.19 + *  You should have received a copy of the 
   76.20 + *  GNU Lesser General Public License along with Tema.  
   76.21 + *  If not, see <http://www.gnu.org/licenses/>.
   76.22 + *
   76.23 + *  $Id: NullWriter.java,v 1.6 2008/02/16 17:38:03 mikhail Exp $
   76.24 + */
   76.25 +
   76.26 +package kryshen.tema.io;
   76.27 +
   76.28 +import java.io.Writer;
   76.29 +
   76.30 +/**
   76.31 + * No-op writer.
   76.32 + *
   76.33 + * @author Mikhail Kryshen
   76.34 + */
   76.35 +public class NullWriter extends Writer{
   76.36 +    public static final NullWriter INSTANCE = new NullWriter();
   76.37 +    
   76.38 +    private NullWriter() {        
   76.39 +    }
   76.40 +    
   76.41 +    public void close() {
   76.42 +    }
   76.43 +    
   76.44 +    public void flush() {
   76.45 +    }
   76.46 +    
   76.47 +    public void write(char[] cbuf, int off, int len) {
   76.48 +    }
   76.49 +}
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/src/kryshen/tema/io/ReplaceWriter.java	Tue Feb 19 20:32:17 2008 +0300
    77.3 @@ -0,0 +1,153 @@
    77.4 +/*
    77.5 + *  Copyright 2006-2008 Mikhail Kryshen
    77.6 + *
    77.7 + *  This file is part of Tema.
    77.8 + *
    77.9 + *  Tema is free software: you can redistribute it and/or modify it
   77.10 + *  under the terms of the GNU Lesser General Public License as
   77.11 + *  published by the Free Software Foundation, either version 3 of the
   77.12 + *  License, or (at your option) any later version.
   77.13 + *
   77.14 + *  Tema is distributed in the hope that it will be useful,
   77.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   77.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   77.17 + *  GNU Lesser General Public License for more details.
   77.18 + *
   77.19 + *  You should have received a copy of the 
   77.20 + *  GNU Lesser General Public License along with Tema.  
   77.21 + *  If not, see <http://www.gnu.org/licenses/>.
   77.22 + *
   77.23 + *  $Id: ReplaceWriter.java,v 1.8 2008/02/19 16:21:00 mikhail Exp $
   77.24 + */
   77.25 +
   77.26 +package kryshen.tema.io;
   77.27 +
   77.28 +import java.io.Writer;
   77.29 +import java.io.FilterWriter;
   77.30 +import java.io.IOException;
   77.31 +
   77.32 +/**
   77.33 + * FilterWriter which replaces characters with escape strings.
   77.34 + *
   77.35 + * @author Mikhail Kryshen
   77.36 + */
   77.37 +public class ReplaceWriter extends FilterWriter {
   77.38 +    private String[] patterns;
   77.39 +    private String[] replaces;
   77.40 +
   77.41 +    private String prefix;
   77.42 +    private String postfix;
   77.43 +
   77.44 +    private int maxPatternLength = 0;
   77.45 +
   77.46 +    /** Have this Writer processed any data? */
   77.47 +    private boolean processedData = false;
   77.48 +
   77.49 +    private StringBuffer buffer = new StringBuffer();
   77.50 +
   77.51 +    public ReplaceWriter(Writer w, String pattern, String replace) {
   77.52 +        this(w, new String[]{pattern}, new String[]{replace});
   77.53 +    }
   77.54 +
   77.55 +    public ReplaceWriter(Writer w, String pattern, String replace,
   77.56 +                         String prefix, String postfix) {
   77.57 +
   77.58 +        this(w, new String[]{pattern}, new String[]{replace}, 
   77.59 +             prefix, postfix);
   77.60 +    }
   77.61 +
   77.62 +    public ReplaceWriter(Writer w, String[] patterns, String[] replaces) {
   77.63 +        this(w, patterns, replaces, null, null);
   77.64 +    }
   77.65 +
   77.66 +    public ReplaceWriter(Writer w, String[] patterns, String[] replaces, 
   77.67 +                         String prefix, String postfix) {
   77.68 +	super(w);
   77.69 +        
   77.70 +	this.patterns = patterns;
   77.71 +	this.replaces = replaces;
   77.72 +        
   77.73 +        this.prefix = prefix;
   77.74 +        this.postfix = postfix;
   77.75 +        
   77.76 +	for (int i = 0; i < patterns.length; i++) {
   77.77 +	    int length = patterns[i].length();
   77.78 +	    if (length > maxPatternLength)
   77.79 +		maxPatternLength = length;
   77.80 +	}
   77.81 +    }
   77.82 +
   77.83 +    private boolean processBuffer(int minLength) throws IOException {
   77.84 +        if (buffer.length() == 0) return false;
   77.85 +
   77.86 +        if (!processedData) {
   77.87 +            if (prefix != null)
   77.88 +                super.write(prefix, 0, prefix.length());
   77.89 +            processedData = true;
   77.90 +        }
   77.91 +
   77.92 +        int k;
   77.93 +	for (k = 0; minLength + k < buffer.length(); k++) {
   77.94 +	    for (int i = 0; i < patterns.length; i++) {
   77.95 +		String pattern = patterns[i];
   77.96 +		int length = pattern.length();
   77.97 +
   77.98 +                if (length + k > buffer.length())
   77.99 +                    continue;
  77.100 +
  77.101 +		boolean match = true;
  77.102 +
  77.103 +		for (int j = 0; j < length; j++) {
  77.104 +		    if (pattern.charAt(j) != buffer.charAt(j + k)) {
  77.105 +			match = false;
  77.106 +                        break;
  77.107 +		    }
  77.108 +		}
  77.109 +
  77.110 +		if (match) {
  77.111 +                    super.write(buffer.substring(0, k), 0, k);
  77.112 +                    buffer.delete(0, k + length);
  77.113 +                    super.write(replaces[i], 0, replaces[i].length());
  77.114 +		    return true;
  77.115 +		}
  77.116 +	    }
  77.117 +	}
  77.118 +
  77.119 +        super.write(buffer.substring(0, k), 0, k);
  77.120 +        buffer.delete(0, k);
  77.121 +
  77.122 +        return false;
  77.123 +    }
  77.124 +
  77.125 +    public void write(int c) throws IOException {
  77.126 +	buffer.append((char)c);
  77.127 +	processBuffer(maxPatternLength);
  77.128 +    }
  77.129 +
  77.130 +    public void write(char[] cbuf, int off, int len) throws IOException {
  77.131 +	for (int i = off; i < off + len; i++) {
  77.132 +	    buffer.append(cbuf[i]);
  77.133 +	}
  77.134 +	processBuffer(maxPatternLength);
  77.135 +    }
  77.136 +
  77.137 +    public void write(String str, int off, int len) throws IOException {
  77.138 +        buffer.append(str.substring(off, off + len));
  77.139 +	processBuffer(maxPatternLength);
  77.140 +    }
  77.141 +
  77.142 +    public void finish() throws IOException {
  77.143 +        while (processBuffer(0));
  77.144 +
  77.145 +//         super.write(buffer.toString(), 0, buffer.length());
  77.146 +//         buffer.delete(0, buffer.length());
  77.147 +
  77.148 +        if (processedData && postfix != null)
  77.149 +            super.write(postfix, 0, postfix.length());
  77.150 +    }
  77.151 +
  77.152 +    public void close() throws IOException {
  77.153 +        finish();
  77.154 +        super.close();
  77.155 +    }
  77.156 +}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/src/kryshen/tema/io/TemplateReader.java	Tue Feb 19 20:32:17 2008 +0300
    78.3 @@ -0,0 +1,102 @@
    78.4 +/*
    78.5 + *  Copyright 2006-2008 Mikhail Kryshen
    78.6 + *
    78.7 + *  This file is part of Tema.
    78.8 + *
    78.9 + *  Tema is free software: you can redistribute it and/or modify it
   78.10 + *  under the terms of the GNU Lesser General Public License as
   78.11 + *  published by the Free Software Foundation, either version 3 of the
   78.12 + *  License, or (at your option) any later version.
   78.13 + *
   78.14 + *  Tema is distributed in the hope that it will be useful,
   78.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   78.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   78.17 + *  GNU Lesser General Public License for more details.
   78.18 + *
   78.19 + *  You should have received a copy of the 
   78.20 + *  GNU Lesser General Public License along with Tema.  
   78.21 + *  If not, see <http://www.gnu.org/licenses/>.
   78.22 + *
   78.23 + *  $Id: TemplateReader.java,v 1.8 2008/02/19 00:20:48 mikhail Exp $
   78.24 + */
   78.25 +
   78.26 +package kryshen.tema.io;
   78.27 +
   78.28 +import java.io.Reader;
   78.29 +import java.io.LineNumberReader;
   78.30 +import java.io.PushbackReader;
   78.31 +import kryshen.tema.TemplateParser;
   78.32 +
   78.33 +/**
   78.34 + * Reader for Tema templates. Stores data source name (commonly
   78.35 + * filename) and tracks line numbers for error reporting.
   78.36 + *
   78.37 + * @author Mikhail Kryshen
   78.38 + */
   78.39 +public class TemplateReader extends PushbackReader {
   78.40 +    static final int UNREAD_BUFFER_SIZE;
   78.41 +    
   78.42 +    /* Calculate UNREAD_BUFFER_SIZE value. */
   78.43 +    static {
   78.44 +        int max = 0;
   78.45 +        
   78.46 +        for (String s : TemplateParser.BRACKET_OPEN) {
   78.47 +            max = Math.max(max, s.length());
   78.48 +        }
   78.49 +        
   78.50 +        for (String s : TemplateParser.BRACKET_CLOSE) {
   78.51 +            max = Math.max(max, s.length());
   78.52 +        }
   78.53 +        
   78.54 +        max = Math.max(max, TemplateParser.ESCAPE_NEWLINE.length() + 2);
   78.55 +        max = Math.max(max, TemplateParser.ESCAPE_WHITESPACE.length());
   78.56 +        
   78.57 +        UNREAD_BUFFER_SIZE = max;
   78.58 +    }
   78.59 +    
   78.60 +    private final String source;
   78.61 +    private final LineNumberReader lnReader;
   78.62 +    private final TemplateReader parentReader;
   78.63 +    
   78.64 +    public TemplateReader(Reader in) {
   78.65 +        this(new LineNumberReader(in));
   78.66 +    }
   78.67 +    
   78.68 +    public TemplateReader(Reader in, String source) {
   78.69 +        this(new LineNumberReader(in), source);
   78.70 +    }
   78.71 +    
   78.72 +    public TemplateReader(LineNumberReader in) {
   78.73 +        this(in, "");
   78.74 +    }
   78.75 +    
   78.76 +    public TemplateReader(LineNumberReader in, String source) {
   78.77 +        super(in, UNREAD_BUFFER_SIZE);
   78.78 +        
   78.79 +        this.parentReader = null;
   78.80 +        this.lnReader = in;
   78.81 +        this.source = source;
   78.82 +    }
   78.83 +    
   78.84 +    public TemplateReader(Reader in, TemplateReader parent) {
   78.85 +        super(in, UNREAD_BUFFER_SIZE);
   78.86 +        
   78.87 +        this.parentReader = parent;
   78.88 +        this.lnReader = null;
   78.89 +        this.source = null;
   78.90 +    }
   78.91 +    
   78.92 +    public String getSource() {
   78.93 +        if (source != null)
   78.94 +            return source;
   78.95 +        
   78.96 +        return parentReader.getSource();
   78.97 +    }
   78.98 +    
   78.99 +    public int getLineNumber() {
  78.100 +        if (lnReader != null)
  78.101 +            return lnReader.getLineNumber();
  78.102 +        
  78.103 +        return parentReader.getLineNumber();
  78.104 +    }
  78.105 +}
    79.1 --- a/test/demo	Thu Dec 14 23:22:05 2006 +0300
    79.2 +++ b/test/demo	Tue Feb 19 20:32:17 2008 +0300
    79.3 @@ -1,4 +1,4 @@
    79.4  #!/bin/sh
    79.5  
    79.6  #java -jar ../dist/tema.jar
    79.7 -java -classpath .:../dist/tema.jar kryshen.tema.Tema
    79.8 +java -classpath .:../dist/tema.jar kryshen.tema.Tema main.template
    80.1 --- a/test/demo.bat	Thu Dec 14 23:22:05 2006 +0300
    80.2 +++ b/test/demo.bat	Tue Feb 19 20:32:17 2008 +0300
    80.3 @@ -1,1 +1,1 @@
    80.4 -java -classpath .:..\dist\tema.jar kryshen.tema.Tema
    80.5 +java -classpath .:..\dist\tema.jar kryshen.tema.Tema main.template
    81.1 --- a/test/include.template	Thu Dec 14 23:22:05 2006 +0300
    81.2 +++ b/test/include.template	Tue Feb 19 20:32:17 2008 +0300
    81.3 @@ -1,1 +1,1 @@
    81.4 -<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%>
    81.5 \ No newline at end of file
    81.6 +<%define#test test arg1:<%next_arg:%>, test arg2:<%next_arg:%>, test data:<%data:%>.%>
    81.7 \ No newline at end of file
    82.1 --- a/test/main.template	Thu Dec 14 23:22:05 2006 +0300
    82.2 +++ b/test/main.template	Tue Feb 19 20:32:17 2008 +0300
    82.3 @@ -1,4 +1,4 @@
    82.4 -[%!\ UTF-8 text %]
    82.5 +[%!\ UTF-8 text %]\
    82.6  
    82.7  Вывод текста:
    82.8  test text
    82.9 @@ -10,7 +10,7 @@
   82.10  <%include:include.template%>
   82.11  
   82.12  Вызов новой функции:
   82.13 -<%test:1 2 3%>
   82.14 +<%test:1 2 3 4 5%>
   82.15  
   82.16  Тестирование read:
   82.17  <%read\include.template%>
    83.1 --- a/test/tema.properties	Thu Dec 14 23:22:05 2006 +0300
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,22 +0,0 @@
    83.4 -# Data source configuration
    83.5 -# resource          : jdbc:odbc:database
    83.6 -# driver            : sun.jdbc.odbc.JdbcOdbcDriver
    83.7 -
    83.8 -# Base directory for images and files
    83.9 -# resource_base     : .
   83.10 -
   83.11 -# Template to start processing with
   83.12 -main_template     : main.template
   83.13 -
   83.14 -# File encodings
   83.15 -input_encoding    : UTF-8
   83.16 -output_encoding   : UTF-8
   83.17 -
   83.18 -# Cache templates
   83.19 -# cache_read        : true
   83.20 -
   83.21 -# Output main_template parsing result to stderr
   83.22 -# output            : stderr
   83.23 -
   83.24 -# File to output error messages (redirect stderr)
   83.25 -# log               : dbreader.log