Mercurial > hg > tema
changeset 2:6c41a0b43e58 release_0_3
Tema 0.3 (imported from CVS).
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.cvsignore Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,1 @@ +build
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING.LESSER Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING.apache Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NOTICE Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,13 @@ +Tema +Copyright 2006-2008 Mikhail Kryshen <mikhail@kryshen.pp.ru> + +This is free software. You may redistribute copies of it under the terms of +the GNU Lesser General Public License version 3 or later. + + + +Apache Commons CLI +Copyright 2001-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/).
--- a/TODO Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -if, <, >, =, +, -, *, /
--- a/build.xml Thu Dec 14 23:22:05 2006 +0300 +++ b/build.xml Tue Feb 19 20:32:17 2008 +0300 @@ -1,44 +1,113 @@ <?xml version="1.0"?> <project name="tema" default="dist" basedir="."> - + + <property name="version" value="0.3"/> + <property name="src" value="src"/> <property name="build" value="build"/> <property name="dist" value="dist"/> <property name="res" value="res"/> <property name="doc" value="doc"/> + <property name="lib" value="${dist}/lib"/> <property name="jar_file" value="tema.jar"/> - + + <property name="ant_jar" value="/usr/share/java/ant.jar"/> + + <path id="project.libs"> + <fileset dir="${lib}"> + <include name="**/*.jar"/> + </fileset> + </path> + <target name="init"> - <tstamp/> - <mkdir dir="${build}"/> + <tstamp/> + <mkdir dir="${build}"/> </target> - + <target name="compile" depends="init"> <javac srcdir="${src}" destdir="${build}" deprecation="on" optimize="on" debug="on"> - <!-- <compilerarg value="-Xlint:unchecked"/> --> + <compilerarg value="-Xlint:unchecked"/> + <classpath refid="project.libs"/> </javac> + + <copy todir="${build}"> + <fileset dir="${res}"/> + </copy> </target> - + <target name="dist" depends="compile"> - <jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf"> - <fileset dir="${build}" includes="**/*.class"/> - <fileset dir="${res}" includes="**/*"/> - </jar> + <jar jarfile="${dist}/${jar_file}" manifest="${src}/Manifest.mf"> + <fileset dir="${build}" includes="**/*.class"/> + <fileset dir="${build}" includes="**/*.template"/> + </jar> + </target> + + <target name="run" depends="compile"> + <java classname="kryshen.tema.Tema" fork="true"> + <classpath> + <pathelement location="${build}"/> + <path refid="project.libs"/> + </classpath> + </java> + </target> + + <target name="run.demo" depends="compile"> + <java classname="kryshen.tema.Tema" fork="true"> + <classpath> + <pathelement location="${build}"/> + <path refid="project.libs"/> + </classpath> + <arg value="-demo"/> + </java> + </target> + + <target name="doc.manual" depends="dist"> + <taskdef name="tema" + classname="kryshen.tema.ant.TemaTask" + classpath="${dist}/tema.jar"/> + + <tema infile="${doc}/manual/manual.tema" + outfile="${doc}/manual/manual.html" + basedir="${doc}/manual"/> </target> - <target name="javadoc" depends="init"> + <target name="doc.api" depends="init"> <javadoc destdir="${doc}/api" sourcepath="${src}" packagenames="kryshen.tema.*"> + <classpath> + <path refid="project.libs"/> + <pathelement location="${ant_jar}"/> + </classpath> </javadoc> </target> - - <target name="clean"> - <delete> - <fileset dir="${build}" includes="**/*.class"/> - </delete> - <delete file="${dist}/${jar_file}"/> - <delete dir="${doc}/api"/> + + <target name="package.tar" depends="dist,doc.manual,doc.api"> + <tar destfile="${dist}/${ant.project.name}-${version}.tar.gz" + compression="gzip"> + <tarfileset dir="${basedir}" + prefix="${ant.project.name}-${version}"> + <exclude name="${build}/**"/> + <exclude name="misc/**"/> + <exclude name="test/**"/> + <exclude name="nbproject/**"/> + <exclude name="${dist}/${ant.project.name}-*.tar.gz"/> + <exclude name="${dist}/tema"/> + </tarfileset> + <tarfileset dir="${basedir}" + prefix="${ant.project.name}-${version}" + mode="755"> + <include name="${dist}/tema"/> + </tarfileset> + </tar> + </target> + + <target name="clean" depends="init"> + <delete> + <fileset dir="${build}" includes="**/*.class"/> + </delete> + <delete file="${dist}/${jar_file}"/> + <delete dir="${doc}/api"/> </target> </project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/.cvsignore Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,2 @@ +tema.jar +tema-*.tar.gz
--- a/dist/biotopes/biotope-top.sql Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -SELECT t1.*, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND -Right(t2.rangcode, 8) = '00000000') AS class0, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND -Right(t2.rangcode, 6) = '000000') AS class1, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND -Right(t2.rangcode, 4) = '0000') AS class2, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND -Right(t2.rangcode, 2) = '00') AS class3 - -FROM biotopelist AS t1 -WHERE Right(t1.rangcode, 2) <> '00' AND rusname
--- a/dist/biotopes/biotope.sql Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -SELECT t1.*, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) -AND Right(t2.rangcode, 8) = '00000000' -AND Right(t1.rangcode, 8) <> '00000000') AS class0, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) -AND Right(t2.rangcode, 6) = '000000' -AND Right(t1.rangcode, 6) <> '000000') AS class1, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) -AND Right(t2.rangcode, 4) = '0000' -AND Right(t1.rangcode, 4) <> '0000') AS class2, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) -AND Right(t2.rangcode, 2) = '00' -AND Right(t1.rangcode, 2) <> '00') AS class3 - -FROM biotopelist AS t1 -WHERE rusname
--- a/dist/biotopes/biotope.template Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-5"?> -<!DOCTYPE _ SYSTEM "brief.dtd"> -<!-- rangcode: <%xml_escape db\rangcode%> --> -<_ show="0"> - < display="0"> - <%optional:<_ ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\code%>.png png%>"/>%> -<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> - </> - <><%xml_escape db\rusname%></> - <><%xml_escape db\class0%></> - <1><%xml_escape db\class1%></1> - <2><%xml_escape db\class2%></2> - <3><%xml_escape db\class3%></3> - <_ rows="3"><%xml_cdata db\descript%></_> - <_ rows="3"><%xml_cdata db\geobotdescr%></_> - <_><%xml_escape db\contributors%></_> -</_>
--- a/dist/biotopes/brief.dtd Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -<?xml encoding="ISO-8859-5"?> -<!ELEMENT _ (?, , , 1, 2, 3, _, _, _)> -<!ELEMENT (|_)*> -<!ELEMENT EMPTY> -<!ELEMENT _ EMPTY> -<!ELEMENT (#PCDATA)> -<!ELEMENT (#PCDATA)> -<!ELEMENT 1 (#PCDATA)> -<!ELEMENT 2 (#PCDATA)> -<!ELEMENT 3 (#PCDATA)> -<!ELEMENT _ (#PCDATA)> -<!ELEMENT _ (#PCDATA)> -<!ELEMENT _ (#PCDATA)> -<!ATTLIST _ show (0|1) "1"> -<!ATTLIST - display CDATA #FIXED "0"> -<!ATTLIST - num ID #REQUIRED - file CDATA #REQUIRED - big CDATA #REQUIRED - text CDATA #IMPLIED - CDATA #IMPLIED> -<!ATTLIST _ - num ID #REQUIRED - file CDATA #REQUIRED> -<!ATTLIST _ rows CDATA #FIXED "3"> -<!ATTLIST _ rows CDATA #FIXED "3">
--- a/dist/biotopes/class.sql Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -SELECT t1.* -FROM biotopelist AS t1 -WHERE rusname AND Right(t1.rangcode, 8) = '00000000' - AND EXISTS - (SELECT NULL FROM biotopelist AS t2 - WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) - AND Right(t2.rangcode, 8) <> '00000000')
--- a/dist/biotopes/classes.template Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-5"?> -<><%query:class_sql [%\ - <!-- rangcode: <%xml_escape get\rangcode%> --> - < id="<%get\NUMBER%>"><%xml_escape db\rusname%></>%]%> -</>
--- a/dist/biotopes/doc/article.txt Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,391 +0,0 @@ -* XML- . - - " -" Microsoft Access XML- - DbReader. - - DbReader - . - - . - SQL-, -. - - -* : - - <%<_>{:|\}<>%> - - -<_> - , . - . -<> - , . - - -* : - - [<_>][<>] - - -<_> - , . - . -<> - , . - . , - , . - - , - : -: - , -\ - . - - , , - , - . - - - . - - . , - - -. - - '<', '>' '[', ']'. - - -* : - -: set -: <> -: <> -: <> -: <> - : 1 - -: get -: <> -: <>. - : 1, , 0 - . - -: prepare -: <> -: <> -: SQL- <> , - <>. -: <> - : 1 - -: query -: <_> <> <1> ... <N> -: , - prepare. - '?'. - , <>. - <> NUMBER, - . , - , - <> SUPER.<_>. - -: <> - . - : . - -: optional -: <> -: <>, - 0, - . - : 1, - , 0 - . - -: image -: <_> <_> <> [<_> [<_>]] -: <_> ( - "resource_base") - , - <_>. , - . -: <_> , - . - : 1 , 0 - . - -: copy -: <_> <_> -: <_> <_> - ( <_> - "resource_base"). -: <_> , - . - : 1 , 0 - . - -: write -: <_> -: <> -: <> <_>. -: <_> , - . - : 1 , 0 - . - -: read -: <_> -: <_>. -: , - - . - : 1 , 0 - . - -: include -: <_> -: <_>. -: . - : , . - -: ! -: <> -: . -: . - : , . - -: replace -: <1> <2> -: <> -: , <1> - <2>. - : , . - -: xml_escape -: <> -: <>, - '&', '<', '>', '`', '\' - XML. - : , . - -: xml_cdata -: <> -: XML CDATA. - : , . - - DbReader : -, Java. - - -* DbReader - " " Microsoft Access - XML- - - " - " ( ): - -biotopelist (code, rangcode, rusname, engname, descript, geobotdescr, - contributors, descrdate) - - code - , ; - rangcode - ABBCCDDEE, , BB, CC, DD, - - , ; - rusname, engname, descript, geobotdescr - ; - descrdate - . - -photos (biotope, photo, authphoto) - - biotope - , code biotopelist; - photo - ; - authphoto - . - - xml- biotopelist, - , , - . - - xml- - DbReader ( biotope.template): - ----------------------------------------------------------------------- -<?xml version="1.0" encoding="ISO-8859-5"?> -<!DOCTYPE _ SYSTEM "brief.dtd"> -<!-- rangcode: <%xml_escape get\rangcode%> --> -<_ show="0"> - < display="0"> - <%optional:<_ ="1" - file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> -<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> - </> - <><%xml_escape get\rusname%></> - <><%xml_escape get\class0%></> - <1><%xml_escape get\class1%></1> - <2><%xml_escape get\class2%></2> - <3><%xml_escape get\class3%></3> - <_ rows="3"><%xml_cdata get\descript%></_> - <_ rows="3"><%xml_cdata get\geobotdescr%></_> - <_><%xml_escape get\contributors%></_> -</_> ----------------------------------------------------------------------- - - SQL-, - rangcode, rusname, class0, class1, class2, -class3, descript, geobotdescr contributors ( biotope.sql): - ----------------------------------------------------------------------- -SELECT t1.*, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) -AND Right(t2.rangcode, 8) = '00000000' -AND Right(t1.rangcode, 8) <> '00000000') AS class0, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) -AND Right(t2.rangcode, 6) = '000000' -AND Right(t1.rangcode, 6) <> '000000') AS class1, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) -AND Right(t2.rangcode, 4) = '0000' -AND Right(t1.rangcode, 4) <> '0000') AS class2, - -(SELECT t2.rusname FROM biotopelist AS t2 -WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) -AND Right(t2.rangcode, 2) = '00' -AND Right(t1.rangcode, 2) <> '00') AS class3 - -FROM biotopelist AS t1 -WHERE rusname ----------------------------------------------------------------------- - - biotope.template <%include\photo.template%>, - ( photo.template): - ----------------------------------------------------------------------- - < num="<%xml_escape get\NUMBER%>" - <%optional:="<%xml_escape get\authphoto%>" %>text="" - file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" - big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/> ----------------------------------------------------------------------- - - SQL- -(photo.sql): - ----------------------------------------------------------------------- -SELECT * from photos WHERE biotope = ? ----------------------------------------------------------------------- - -, ( classes.template): - ----------------------------------------------------------------------- -<?xml version="1.0" encoding="ISO-8859-5"?> -<><%query:class_sql [%\ - <!-- rangcode: <%xml_escape get\rangcode%> --> - < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%> -</> ----------------------------------------------------------------------- - - SQL- (class.sql): - ----------------------------------------------------------------------- -SELECT t1.* -FROM biotopelist AS t1 -WHERE rusname AND Right(t1.rangcode, 8) = '00000000' - AND EXISTS - (SELECT NULL FROM biotopelist AS t2 - WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) - AND Right(t2.rangcode, 8) <> '00000000') ----------------------------------------------------------------------- - -, ( plants.template): - ----------------------------------------------------------------------- -<?xml version="1.0" encoding="ISO-8859-5"?> -<><%query:plant_sql [%\ - <!-- rangcode: <%xml_escape get\rangcode%> --> - <><%xml_escape get\rusname%></>%]%> -</> ----------------------------------------------------------------------- - - SQL- (plant.sql): - ----------------------------------------------------------------------- -SELECT t1.* -FROM biotopelist AS t1 -WHERE rusname AND Right(t1.rangcode, 2) <> '00' ----------------------------------------------------------------------- - - DbReader index.template, - SQL- -: - ----------------------------------------------------------------------- -<%!: - <%prepare:biotope_sql <%read\biotope.sql%>%> - <%prepare:photo_sql <%read\photo.sql%>%> - <%prepare:class_sql <%read\class.sql%>%> - <%prepare:plant_sql <%read\plant.sql%>%> - - <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> - - <%write:classes.xml <%include\classes.template%>%> - <%write:plants.xml <%include\plants.template%>%> -%> ----------------------------------------------------------------------- - - XML-: - ----------------------------------------------------------------------- -<?xml version="1.0" encoding="ISO-8859-5"?> -<!DOCTYPE _ SYSTEM "brief.dtd"> -<!-- rangcode: E04020302 --> -<_ show="0"> - < display="0"> - < num="1" =" .." text="" - file="images/3_1.jpg" - big="images/big/3_1.jpg"/> - < num="2" =" .." text="" - file="images/3_2.jpg" - big="images/big/3_2.jpg"/> - </> - <>Betula sp. - Avenella flexuosa - Polytrichum commune</> - <>E. </> - <1> </1> - <2></2> - <3></3> - <_ rows="3"><![CDATA[ . 5 - 7 , , , .]]></_> - <_ rows="3"></_> - <_></_> -</_> ----------------------------------------------------------------------- - - -* DbReader - - DbReader Java - : - -ru.karrc.dbreader.DbReader: c . -, - JDBC, . - -ru.karrc.dbreader.TemplateParser: , - . - -ru.karrc.dbreader.Function: . -DbReader . - -ru.karrc.dbreader.FunctionDataParser: -. , -. - TemplateParser. - -ru.karrc.dbreader.Functions: - , Function. - -ru.karrc.dbreader.TemplateParser: , - . - - , , - . - - -* . - - : 8, - Java- ( ): 27, - : 1311, - ( ): 812, - : 180. - - -* - - DbReader, - - . -DbReader " " - XML- .
--- a/dist/biotopes/doc/readme.html Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "DTD/xhtml1-transitional.dtd"> - -<html> - -<head> - <title>DbReader</title> - <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" /> -</head> - -<body> -<h1>DbReader</h1> - -<h2> </h2> -<ol> -<li> .</li> - -<li> :<br /> - Windows 2000: // (ODBC), biotopes-data.mdb.</li> - -<li> :<br /> - dbreader.properties , :<br /> - <code>resource: jdbc:odbc:<em></em></code><br /> - , ( biotopephotos maps):<br /> - <code>resource_base: C:\\biotopes</code><br /> -( '\' )</li> - -<li> :<br /> -<code>dbreader.bat</code> <br /> -<code>java -jar dbreader.jar</code>.<br /> - Java Runtime Environment (JRE) 5.0, <a href="http://java.sun.com/j2se/1.5.0/download.jsp">http://java.sun.com/j2se/1.5.0/download.jsp</a>. , JRE - . - - :<br /> - <code>java -Dru.karrc.dbreader.<em></em>=<em></em> -jar dbreader.jar</code><br /> -(: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li> -</ol> - -<h2> </h2> - -<p> biotope.sql ( , dbreader.properties), biotope.template, .</p> -<p> : <code><%<em>_</em>[:|\]<em></em>%></code>, <em> </em> - , . , .</p> - -<h3> </h3> - -<ul> - <li><code>:</code> - .</li> - <li><code>\</code> - . <code><%</code> <code>%></code> (<code><%\<%%></code> <code><%\%%>></code>).</li> -</ul> - -<h3></h3> - -<ul> - <li><code><%get:<em></em>%></code><br /> - .</li> - - <li><code><%optional:<em></em>%></code><br /> - <em></em>, , , .</li> - - <li><code><%escape:<em></em>%></code><br /> - "" ( ).</li> - - <li><code><%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%></code><br /> - <em></em>.sql <em></em>.template. '?'.</li> - - <li><code><%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%></code><br /> - <em>_</em> ( "resource_base") , <em>_</em>. , . - , <code><%image:...%></code> <em>_</em>, - .</li> - - <li><code><%copy:<em>_</em> <em>_</em>%></code><br /> - <em>_</em> ( "resource_base") <em>_</em>. , <code><%copy:...%></code> <em>_</em>, - .</li> -</ul> - -<h3> </h3> - -<p><code>NUMBER</code> - . - , invoke, <code>SUPER.</code> (: <code>SUPER.NUMBER</code>).</p> - -<h3></h3> - -<p> name :</p> -<p><code><%escape get:name%></code></p> - -<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru"> </a></i></p> - -</body> -</html>
--- a/dist/biotopes/doc/readme.txt Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -text/plain; charset=UTF-8 - -Установка программы -------------------- - -1. Распаковать архив. - -2. Установить источник данных: -в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes.mdb. - -3. Настроить программу: -В файле dbreader.properties указать имя, присвоенное источнику данных: - "resource: jdbc:odbc:<имя>" -и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps): - "resource_base: C:\\biotopes" -(символ '\' необходимо дублировать) - -4. Запуск программы: dbreader.bat или "java -jar dbreader.jar" -Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с http://java.sun.com/j2se/1.5.0/download.jsp. Возможно, будет работать и со старыми версиями JRE - не проверял. - -Все значения файла конфигурации можно переопределять при запуске программы: - команда "java -Dru.karrc.dbreader.<ключ>=<значение> -jar dbreader.jar" -(например: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar") - - -Работа программы ----------------- - -Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения. - -Формат инструкций: "<%список_функций[:|\]данные%>", список функций - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней. - -Разделители между списком функций и данными: -':' - данные будут обрабатываться рекурсивно. -'\' - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов "<%" и "%>" ("<%\<%%>" и "<%\%%>>"). - -Функции: -<%get:<имя>%> - заменяется на значение встроенной переменной или колонки запроса. - -<%optional:<текст>%> -Заменяется на <текст>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку. - -<%escape:<текст>%> -Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации). - -<%invoke:<имя> <парам1> <парам2> ... <парамN>%> -Выполняет запрос с параметрами <имя>.sql и заменяется на результаты обработки шаблона <имя>.template. Значения параметров подставляются в запрос вместо символа '?'. - -<%image:<исх_файл> <кон_файл> <формат> [<макс_ширина>] [<макс_высота>]%> -Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. -При успешном выполнении, инструкция "<%!image ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. - -<%copy:<исх_файл> <кон_файл>%> -Копирует файл <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base"). -При успешном выполнении, инструкция "<%!copy ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. - -Встроенные переменные: -NUMBER - порядковый номер строки результата выполнения запроса. -Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить "SUPER." (например: "SUPER.NUMBER"). - -Пример: -Следующая инструкция получит значение из столбца name и заменит в нем специальные символы: -<%escape get:name%>
--- a/dist/biotopes/main.template Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -<%!: - <%prepare:biotope_sql <%read\biotope.sql%>%> - <%prepare:photo_sql <%read\photo.sql%>%> - <%prepare:class_sql <%read\class.sql%>%> - <%prepare:plant_sql <%read\plant.sql%>%> - - <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%> - - <%write:classes.xml <%include\classes.template%>%> - <%write:plants.xml <%include\plants.template%>%> -%>
--- a/dist/biotopes/photo.sql Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -SELECT * from photos WHERE biotope = ?
--- a/dist/biotopes/photo.template Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - < num="<%number\%>" <%optional:="<%xml_escape db\authphoto%>" %>text="" - file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" - big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
--- a/dist/biotopes/plant.sql Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -SELECT t1.* -FROM biotopelist AS t1 -WHERE rusname AND Right(t1.rangcode, 2) <> '00'
--- a/dist/biotopes/plants.template Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-5"?> -<><%query:plant_sql [%\ - <!-- rangcode: <%xml_escape db\rangcode%> --> - <><%xml_escape db\rusname%></>%]%> -</>
--- a/dist/biotopes/tema.properties Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -# Data source configuration -resource : jdbc:odbc:biotopes-data -driver : sun.jdbc.odbc.JdbcOdbcDriver - -# Base directory for images and files -resource_base : C:\\biotopes\\db - -# Template to start processing with -main_template : main.template - -# File encodings -input_encoding : ISO-8859-5 -output_encoding : ISO-8859-5 - -# Cache templates -cache_read : true - -# Output main_template parsing result to stderr -#output : stderr - -# File to output error messages (redirect stderr) -#log : tema.log
--- a/dist/tema.properties Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -# Data source configuration -# resource : jdbc:odbc:biotopes-data -# driver : sun.jdbc.odbc.JdbcOdbcDriver - -# Base directory for images and files -# resource_base : C:\\biotopes\\db - -# Template to start processing with -main_template : main.template - -# File encodings -# input_encoding : UTF-8 -# output_encoding : UTF-8 - -# Cache templates -# cache_read : true - -# Output main_template parsing result to stderr -# output : stderr - -# File to output error messages (redirect stderr) -# log : tema.log
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/.cvsignore Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,1 @@ +api
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/manual/.cvsignore Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,1 @@ +manual.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/manual/document.tema Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,107 @@ +[%\ + Macro definitions used in manual.tema to generate HTML document. +%] + +[%!\ + Create HTML document. + Arguments are read in pairs (name value) until "content" name is found. + Then follows the document content. + + TODO: generate TOC. +%] +<%define#document + <%silent while# + <%if:<%not equal:<%set:arg <%next_arg:%>%> content%> + <%export:<%arg:%> <%next_arg:%>%> + %> + %>\\ +<%if:<%not embedded:%> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + +<head> + <title><%html_escape title:%></title> + <meta http-equiv="Content-Type" content="text/html; charset=<%charset:%>" /> + <meta name="generator" content="<%tema:%>" /> +</head> + +<body> +<h1><%html_escape title:%><%optional:<br /><%html_escape subtitle:%>%></h1> +%>\ +<%html_escape data:%> +<%if:<%not embedded:%> +</body> +</html> +%>\ +%> + +<%set:charset iso-8859-1%> +<%set:escape <%char:0%>%> + +[%!\ + Create HTML tag. +%] +<%define#tag <%false:<%escape:%><<%data:%><%escape:%>>%>%> + +[%!\ + Escape special HTML characters (except those preceded with <%escape:%>). +%] +<%define#html_escape + <%replace:<%escape:%> <%:%> + <%regex_replace_all:(?<!<%escape:%>)-- – + <%regex_replace_all:(?<!<%escape:%>)--- — + <%regex_replace_all:(?<!<%escape:%>)< < + <%regex_replace_all:(?<!<%escape:%>)> > + <%regex_replace_all:(?<!<%escape:%>)& & + <%data:%>\\ + %>%>%>%>%>%>\ +%> + +<%define#section + <%tag:h2<%if:<%first_section:%> <%: class="first"%>%>%><%data:%><%tag:/h2%>\\ + <%unset:first_section%>\\ +%> + +<%define#subsection <%tag:h3%><%data:%><%tag:/h3%>%> + +<%define#par <%tag:p%><%data:%><%tag:/p%>%> + +<%define#itemize +<%tag:ul%> +<%while#\ + <%tag:li%><%next_arg:%><%tag:/li%> +%>\ +<%tag:/ul%> +%> + +<%define#code <%tag:code%><%replace:-- <%escape:%>-- <%data:%>%><%tag:/code%>%> + +<%define#emph <%tag:i%><%data:%><%tag:/i%>%> + +<%define#link + <%silent set:url <%next_arg:%>%>\\ + <%tag:a href="<%url:%>"%>\\ + <%if_else:<%has_more_data:%> + <%data:%> + <%url:%>%>\\ + <%tag:/a%>\\ +%> + +<%define#function + <%silent set:name <%next_arg:%>%>\\ + <%silent while# + <%set:<%next_arg:%> <%next_arg:%>%> + %>\\ + <%tag:div%> + <%tag:b%><%name:%><%tag:/b%><%tag:br /%> + <%tag:/div%> + <%optional:<%tag:div style="padding-left:1em; margin-bottom: 0.5em;"%> + <%description:%> + <%tag:/div%>%> + <%tag:div style="padding-left:1em; margin-bottom: 1em;"%> + <%optional:<%tag:b%>Arguments:<%tag:/b%> <%arguments:%><%tag:br /%>%> + <%optional:<%tag:b%>Data:<%tag:/b%> <%input_data:%><%tag:br /%>%> + <%optional:<%tag:b%>Output:<%tag:/b%> <%output:%><%tag:br /%>%> + <%tag:/div%> +%>
--- a/doc/manual/index.html Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,358 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "DTD/xhtml1-transitional.dtd"> - -<html> - -<head> - <title>Макропроцессор TEMA</title> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -</head> - -<body> -<h1>Макропроцессор TEMA</h1> - -Макропроцессор TEMA обрабатывает заданные шаблоны текстовых файлов и -заменяет найденные в них инструкции на результаты их выполнения. - -<p><b>Формат инструкций</b></p> - -<blockquote> - <code><%<i>список_функций</i>{:|\|`}<i>данные</i>%></code> -</blockquote> -<p> -где<br /> - -<code><i>список_функций</i></code> - список имен функций, разделенных - пробелами. Может быть пустым.<br /> -<code><i>данные</i></code> - данные, передаваемые функции. -</p> - -<p><b>Формат данных</b></p> - -<blockquote> - <code> - [<i>список_аргументов</i>][<i>текст</i>] - </code> -</blockquote> -<p> -где<br /> - -<code><i>список_аргументов</i></code> - список аргументов функции, разделенных пробелами. - Может быть пустым.<br /> -<code><i>текст</i></code> - текст, передаваемый функции без разбиения на аргументы. - Может быть пустым. Количество аргументов, после которого следует - текст, зависит от функции. -</p><p> -Разделитель между списком функций и данными определяет, как должны -обрабатываться данные функции: -</p><p> -<code>:</code> - рекурсивная обработка,<br /> -<code>\</code> или <code>`</code> - передать без обработки. -</p><p> -Если в списке функций задано две и более функции, они выполняются, -начиная с последней, так что каждая функция получает в качестве данных -результат выполнения следующей функции. -</p><p> -Каждая функция имеет код возврата - целое число. Код возврата -инструкции - код возврата первой в списке функции. Код возврата, -получаемый при обработке текста - сумма кодов возврата обработанных -инструкций (как правило, смысл этого значения - количество инструкций, -замененных на непустой текст). -</p><p> -Кроме скобок '<', '>', можно использовать скобки '[', ']'. -</p> - - -<h2>Функции</h2> - -<p><code><b>set</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>имя</i></td></tr> - -<tr><td>Текст:</td> -<td><i>значение</i></td></tr> - -<tr><td>Действие:</td> -<td>Устанавливает значение переменной <i>имя</i>.</td></tr> - -<tr><td>Результат:</td> -<td><i>имя</i></td></tr> - -<tr><td>Код возврата:</td> -<td>1</td></tr> -</table> - -<p><code><b>define</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>имя</i></td></tr> - -<tr><td>Текст:</td> -<td><i>шаблон</i></td></tr> - -<tr><td>Действие:</td><td>Определяет новую функцию <i>имя</i>, при -вызове которой обрабатывается <i>шаблон</i>. При обработке доступны -функции <code>nextarg</code> для получения очередного аргумента -вызываемой функции и <code>data</code> для получения текста.</td></tr> - -<tr><td>Результат:</td> -<td><i>имя</i></td></tr> - -<tr><td>Код возврата:</td> -<td>1</td></tr> -</table> - -<p><code><b>load</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>имя</i> <i>имя_класса</i></td></tr> - -<tr><td>Действие:</td> - -<td>Определяет новую функцию <i>имя</i>. Реализация функции определена -Java-классом <i>имя_класса</i>, наследующим класс -<code>kryshen.tema.Function</code>.</td></tr> - -<tr><td>Результат:</td> -<td><i>имя</i></td></tr> - -<tr><td>Код возврата:</td> -<td>1</td></tr> -</table> - -<p><code><b>prepare</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>имя</i></td></tr> - -<tr><td>Текст:</td> -<td><i>запрос</i></td></tr> - -<tr><td>Действие:</td> -<td>Подготавливает SQL-запрос <i>запрос</i> для выполнения, записывает -подготовленный запрос в переменную <i>имя</i>.</td></tr> - -<tr><td>Результат:</td> -<td><i>имя</i></td></tr> - -<tr><td>Код возврата:</td> -<td>1</td></tr> -</table> - -<p><code><b>query</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>имя_запроса</i> <i>шаблон</i> <i>парам1</i> ... <i>парамN</i></td></tr> - -<tr><td>Действие:</td> -<td>Выполняет запрос с параметрами, подготовленный с помощью функции -prepare. Значения параметров подставляются в запрос вместо символа -'?'. Значения полей ответа доступны с помощью функции <code>db</code>, -как переменные шаблона <i>шаблон</i>. При обработки шаблона также -определяется переменная <code>number</code>, содержащая номер текущей -строки ответа.</td></tr> - -<tr><td>Результат:</td> -<td>результат обработки шаблона <i>шаблон</i> для каждой строки -ответа.</td></tr> - -<tr><td>Код возврата:</td> -<td>Количество полученных строк ответа.</td></tr> -</table> - -<p><code><b>optional</b></code></p> - -<table> -<tr><td>Текст:</td> -<td><i>данные</i></td></tr> - -<tr><td>Результат:</td><td><i>данные</i>, если при обработке данных -был получен код возврата отличный от 0, иначе - пустая -строка.</td></tr> - -<tr><td>Код возврата:</td> -<td>1, если результат - пустая строка, 0 - иначе.</td></tr> -</table> - -<p><code><b>image</b></code></p> - -<table> -<tr><td>Аргументы:</td> -<td><i>исх_файл</i> <i>кон_файл</i> <i>формат</i> [<i>макс_ширина</i> -[<i>макс_высота</i>]]</td></tr> - -<tr><td>Действие:</td> -<td>Загружает изображение из файла <i>исх_файл</i> (путь определяется -относительно конфигурационного параметра "resource_base") и -преобразует его в указанный формат, сохраняя результат в -<i>кон_файл</i>. Если заданы максимальная высота и ширина, большие -изображения будут уменьшены.</td></tr> - -<tr><td>Результат:</td> -<td><i>кон_файл</i> при успешном выполнении, пустая строка - иначе.</td></tr> - -<tr><td>Код возврата:</td> -<td>1 при успешном выполнении, 0 - иначе.</td></tr> -</table> - - -<p><code><b>copy</b></code></p> - -<table> -<tr><td>Аргументы:</td><td><i>исх_файл</i> <i>кон_файл</i></td></tr> - -<tr><td>Действие:</td><td>Копирует файл <i>исх_файл</i> в файл -<i>кон_файл</i> (путь <i>исх_файл</i> определяется относительно -конфигурационного параметра "resource_base").</td></tr> - -<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении, -пустая строка - иначе.</td></tr> - -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - -иначе.</td></tr> -</table> - -<p><code><b>write</b></code></p> - -<table> -<tr><td>Аргументы:</td><td><i>имя_файла</i></td></tr> - -<tr><td>Текст:</td><td><i>данные</i></td></tr> - -<tr><td>Действие:</td><td>Записывает <i>данные</i> в файл -<i>исх_файл</i>.</td></tr> - -<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении, -пустая строка - иначе.</td></tr> - -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - -иначе.</td></tr> -</table> - -<p><code><b>read</b></code></p> - -<table> -<tr><td>Текст:</td><td><i>имя_файла</i></td></tr> -<tr><td>Действие:</td><td>Читает файл <i>имя_файла</i>.</td></tr> -<tr><td>Результат:</td><td>прочитанные данные при успешном выполнении, - пустая строка - иначе.</td></tr> -<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - -иначе.</td></tr> -</table> - -<p><code><b>include</b></code></p> - -<table> -<tr><td>Текст:</td><td><i>имя_файла</i></td></tr> -<tr><td>Действие:</td><td>включает шаблон из файла -<i>имя_файла</i>.</td></tr> -<tr><td>Результат:</td><td>результат обработки шаблона.</td></tr> -<tr><td>Код возврата:</td><td>код возврата, полученный при обработке -шаблона.</td></tr> -</table> - -<p><code><b>!</b></code></p> - -<table> -<tr><td>Текст:</td><td><i>данные</i></td></tr> - -<tr><td>Действие:</td><td>нет.</td></tr> - -<tr><td>Результат:</td><td>нет.</td></tr> - -<tr><td>Код возврата:</td><td>код возврата, полученный при обработке -текста данных.</td></tr> -</table> - -<p><code><b>replace</b></code></p> - -<table> -<tr><td>Аргументы:</td><td><i>стр1</i> <i>стр2</i></td></tr> - -<tr><td>Текст:</td><td><i>данные</i></td></tr> - -<tr><td>Результат:</td><td>данные, с замененными вхождениями подстроки -<i>стр1</i> на <i>стр2</i>.</td></tr> - -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке -текста данных.</td></tr> -</table> - -<p><code><b>xml_escape</b></code></p> - -<table> -<tr><td>Текст:</td><td><i>данные</i></td></tr> -<tr><td>Результат:</td><td>текст <i>данные</i>, в котором символы -'&', '<', '>', '`', '\' заменены на соответствующие сущности -XML.</td></tr> - -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке -текста данных.</td></tr> -</table> - -<p><code><b>xml_cdata</b></code></p> - -<table> -<tr><td>Текст:</td><td><i>данные</i></td></tr> - -<tr><td>Результат:</td><td>данные в виде блока XML CDATA.</td></tr> - -<tr><td>Код возврата:</td><td> код возврата, полученный при обработке -текста данных. </td></tr> -</table> - -<p> -Макропроцессор TEMA расширяем: возможно добавление в систему новых -функций, реализованных в виде классов на языке Java. -</p> - -<h2>Запуск</h2> - -<p>java -jar tema.jar [<i>опции</i>] -</p><p> -Опции: -</p> -<table> -<tr><td>-d[emo]</td><td>Демонстрационный режим</td></tr> -<tr><td>-v[ersion]</td><td>Вывод версии</td></tr> -<tr><td>-h[help] -u[sage]</td><td>Вывод справки</td></tr> -</table> - -<p> -При запуске читается файл "tema.properties" из текущего каталога.<br /> -Пример файла "tema.properties": -</p> - -<pre> -# Настройка источника данных -# resource : jdbc:odbc:database -# driver : sun.jdbc.odbc.JdbcOdbcDriver - -# Базовый каталог ресурсов -# resource_base : . - -# Шаблон, с которого начинается обработка -main_template : main.template - -# Кодировки файлов -# input_encoding : UTF-8 -# output_encoding : UTF-8 - -# Кэширование шаблонов -# cache_read : true - -# Вывод результата разбора шаблона main.template в stderr -# output : stderr - -# Вывод сообщений об ошибках в файл -# log : dbreader.log -</pre> - -</body> -</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/manual/manual.tema Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,253 @@ +[%!\ + Tema User Manual. +%]\\ + +<%silent include:document.tema%>\\ + +<%document: + title <%:Tema -- template macro processor%> + author <%:Mikhail Kryshen%> + content + +<%section:Introduction%> + +<%par:Tema is a macro processor and template engine. It reads the input file +recursively expanding any macro found in the text.%> + +<%par:Distinctive features:%> +<%itemize: + <%:Extensible: implement new functions as Java classes.%> + <%:Database access.%> + <%:Processes and outputs data as early as possible (function could start + to output data before all it's arguments are read and parsed).%> + <%:Apache Ant integration.%> +%> + +<%par:Tema macro has the following syntax:%> + +<%par:[%code\<%function_list{:|#|\|`}[escape]text%>[escape]%]%> + +<%par:<%code:function_list%> is the list of text-processing functions. +Functions will be applied to text in reverse order.%> + +<%par:<%code:text%> could contain space-separated list of arguments +followed by arbitrary data. Number of arguments is determined by the last +function in the <%code:function_list%>.%> + +<%par:<%code\[arg1 arg2...] [data]%>%> + +<%par:The text is separated from the list of functions by one of the +following characters:%> + +<%itemize: + <%\':' -- process text recursively.%> + <%\'#' -- parse text but do not replace any embedded macro.%> + <%\'\', '`' -- do not parse text (ignore any '<%' sequences).%> +%> + +<%par:<%code:escape%> is either '\' or '\\':%> + +<%itemize: + <%:<%:\%> -- the following newline symbol will be removed;%> + <%:<%:\\%> -- the following sequence of the whitespace characters will be removed.%> +%> + +<%par:You could use <%\'[%' and '%]'%> character sequences to denote macro +as an alternative to [%\'<%' and '%>'%].%> + +<%par:Every function returns integer value. The general convention is to +return non-zero for successful operation. The value of the macro substitution +is the return value of the first function in the function list. The value of +any Tema text is the sum value of all macro in the text, except the value of +the text without any macro equals -1.%> + +<%par:Internally, Tema function could be represented by any Java object. +Instances of kryshen.tema.Function and kryshen.tema.Context are handled +specially. For any other type of object, function output would be the value +returned by the method <%code:toString()%>.%> + +<%section:Built-in functions%> + +<%par emph:Notice: some functions are not yet described in this manual. +For the complete list of built-in functions refer to the API documentation +and source code.%> + +<%function:tema + output <%:Tema version%> +%> + +<%function:echo + output <%:function data%> +%> + +<%function:! + output nothing + description <%:Ignores the input text (':' separator works as '#'). + Use for commenting (e.g. <%code\[%!\ comment %]%>).%> +%> + +<%function:silent + output nothing +%> + +<%function:set + arguments <%:definition name%> + input_data <%:variable value%> + output <%:function data%> + description <%:Defines new function as a static variable.%> +%> + +<%function:define + arguments <%:name, code%> + description <%:\\ + Defines new function. + Use <%code:next_arg%>, <%code:data%>, and <%code:has_more_data%> + functions to access function arguments.%> + output <%:name%> +%> + +[%!\ TODO: next_arg, data, has_more_data %]\\ + +<%function:export + arguments <%:definition name%> + input_data <%:static variable value (optional)%> + output <%:function data%> + description <%:Exports the definition to the global (outermost) context.%> +%> + +<%function:unset + arguments <%:def1, def2, ...%> + output <%:nothing%> + description <%:Unsets the definitions.%> +%> + +<%function:invoke + arguments <%:function, arg1, arg2, ..., data%> + output <%:function output%> + description <%:Invokes function.%> +%> + +<%function:load + arguments <%:name, class, url1, url2, ...%> + output <%:name%> + description <%:Instantiate specified class as a Tema function definition. + URL arguments are optional.%> +%> + +<%function:super + input_data <%:code%> + output <%:output generated by the code%> + description <%:Evaluates the specified template code in the super-context + (i.e. context of the calling function or context executing + the database query).%> +%> + +<%function:replace + arguments <%:s1, s2, data%> + description <%:\\ + Replaces all occurrences of <%code:s1%> with <%code:s2%> in data.%> +%> + +[%!\ TODO: all functions defined in Strings.java %]\\ + +<%subsection:Input / output%> + +<%function:copy + arguments <%:src, dest%> + description <%:Copies file <%code:src%> to <%code:dest%>.%> + output <%:dest%> +%> + +<%function:write + arguments <%:name%> + input_data <%:text%> + description <%:Writes text to file.%> + output <%:name%> +%> + +<%function:read + arguments <%:name%> + description <%:Reads file.%> + output <%:File contents.%> +%> + +<%function:include + arguments <%:name%> + description <%:Includes template.%> + output <%:Result of processing the template.%> +%> + +<%function:file + arguments <%:base, name%> + output <%:Path constructed from the base directory and file name.%> +%> + +<%subsection:Conditionals%> + +<%function:optional + input_data <%:text%> + output <%:Function data if it's value is non-zero or empty text.%> +%> + +<%function:while + input_data <%:code%> + description <%:Repeatedly outputs it's evaluated data while it has non-zero value.%> +%> + +[%!\ TODO: all functions defined in Control.java %]\\ + +<%subsection:Database%> + +<%function:db_connect + arguments <%:connection name%> + input_data <%:resource%> + description <%:Establishes connection with the database. + Load the appropriate database driver using the <%code:load%> function + before using <%code:db_connect%> + (e.g. [%code\<%load:driver sun.jdbc.odbc.JdbcOdbcDriver%>%]).%> +%> + +<%function:db_prepare + arguments <%:query name, connection name%> + input_data <%:SQL statement%> +%> + +<%function:db_query + arguments <%:query, template, arg1, arg2, ...%> + description <%:Executes query, evaluating the template for each result row.%> +%> + +<%function:db + input_data <%:column name%> + output <%:value from the query result.%> + description <%:Available in the template for the <%code:db_query%> function.%> +%> + +<%function:db_row + output <%:current row number in the result set.%> + description <%:Available in the template for the <%code:db_query%> function.%> +%> + +[%!\ TODO: all functions defined in ImageConverter.java %]\\ + +<%section:Running Tema%> + +<%par:Change to the dist subdirectory in the distribution package and +issue the following command:%> + +<%par:<%code:java -jar tema.jar [options] [files]%>%> + +<%par:The following options are recognized:%> +<%itemize: + <%:<%code:--demo%> --- run demo console with a code example;%> + <%:<%code:-h, --help%> --- print help message;%> + <%:<%code:--input-encoding <arg>%> --- set the input encoding;%> + <%:<%code:--log <arg>%> --- log all error messages to the specified file;%> + <%:<%code:-o, --output <arg>%> --- set the output file;%> + <%:<%code:--output-encoding <arg>%> --- set the output encoding;%> + <%:<%code:-v, --version%> --- print the version information and exit.%> +%> + +<%section:Homepage%> + +<%par link:http://kryshen.pp.ru/tema/%>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/biotope-top.sql Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,20 @@ +SELECT t1.*, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) AND +Right(t2.rangcode, 8) = '00000000') AS class0, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) AND +Right(t2.rangcode, 6) = '000000') AS class1, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) AND +Right(t2.rangcode, 4) = '0000') AS class2, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) AND +Right(t2.rangcode, 2) = '00') AS class3 + +FROM biotopelist AS t1 +WHERE Right(t1.rangcode, 2) <> '00' AND rusname
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/biotope.sql Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,24 @@ +SELECT t1.*, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) +AND Right(t2.rangcode, 8) = '00000000' +AND Right(t1.rangcode, 8) <> '00000000') AS class0, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) +AND Right(t2.rangcode, 6) = '000000' +AND Right(t1.rangcode, 6) <> '000000') AS class1, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) +AND Right(t2.rangcode, 4) = '0000' +AND Right(t1.rangcode, 4) <> '0000') AS class2, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) +AND Right(t2.rangcode, 2) = '00' +AND Right(t1.rangcode, 2) <> '00') AS class3 + +FROM biotopelist AS t1 +WHERE rusname
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/biotope.template Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="ISO-8859-5"?> +<!DOCTYPE _ SYSTEM "brief.dtd"> +<!-- rangcode: <%xml_escape db\rangcode%> --> +<_ show="0"> + < display="0"> + <%optional:<_ ="1" file="<%xml_escape image:maps/<%db\rangcode%>.gif maps/<%db\code%>.png png%>"/>%> +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> + </> + <><%xml_escape db\rusname%></> + <><%xml_escape db\class0%></> + <1><%xml_escape db\class1%></1> + <2><%xml_escape db\class2%></2> + <3><%xml_escape db\class3%></3> + <_ rows="3"><%xml_cdata db\descript%></_> + <_ rows="3"><%xml_cdata db\geobotdescr%></_> + <_><%xml_escape db\contributors%></_> +</_>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/brief.dtd Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,27 @@ +<?xml encoding="ISO-8859-5"?> +<!ELEMENT _ (?, , , 1, 2, 3, _, _, _)> +<!ELEMENT (|_)*> +<!ELEMENT EMPTY> +<!ELEMENT _ EMPTY> +<!ELEMENT (#PCDATA)> +<!ELEMENT (#PCDATA)> +<!ELEMENT 1 (#PCDATA)> +<!ELEMENT 2 (#PCDATA)> +<!ELEMENT 3 (#PCDATA)> +<!ELEMENT _ (#PCDATA)> +<!ELEMENT _ (#PCDATA)> +<!ELEMENT _ (#PCDATA)> +<!ATTLIST _ show (0|1) "1"> +<!ATTLIST + display CDATA #FIXED "0"> +<!ATTLIST + num ID #REQUIRED + file CDATA #REQUIRED + big CDATA #REQUIRED + text CDATA #IMPLIED + CDATA #IMPLIED> +<!ATTLIST _ + num ID #REQUIRED + file CDATA #REQUIRED> +<!ATTLIST _ rows CDATA #FIXED "3"> +<!ATTLIST _ rows CDATA #FIXED "3">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/class.sql Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,7 @@ +SELECT t1.* +FROM biotopelist AS t1 +WHERE rusname AND Right(t1.rangcode, 8) = '00000000' + AND EXISTS + (SELECT NULL FROM biotopelist AS t2 + WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) + AND Right(t2.rangcode, 8) <> '00000000')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/classes.template Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="ISO-8859-5"?> +<><%query:class_sql [%\ + <!-- rangcode: <%xml_escape get\rangcode%> --> + < id="<%get\NUMBER%>"><%xml_escape db\rusname%></>%]%> +</>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/doc/article.txt Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,391 @@ +* XML- . + + " +" Microsoft Access XML- + DbReader. + + DbReader + . + + . + SQL-, +. + + +* : + + <%<_>{:|\}<>%> + + +<_> - , . + . +<> - , . + + +* : + + [<_>][<>] + + +<_> - , . + . +<> - , . + . , + , . + + , + : +: - , +\ - . + + , , + , + . + + - . + - . , + - +. + + '<', '>' '[', ']'. + + +* : + +: set +: <> +: <> +: <> +: <> + : 1 + +: get +: <> +: <>. + : 1, , 0 - . + +: prepare +: <> +: <> +: SQL- <> , + <>. +: <> + : 1 + +: query +: <_> <> <1> ... <N> +: , + prepare. + '?'. + , <>. + <> NUMBER, + . , + , + <> SUPER.<_>. + +: <> + . + : . + +: optional +: <> +: <>, + 0, - . + : 1, - , 0 - . + +: image +: <_> <_> <> [<_> [<_>]] +: <_> ( + "resource_base") + , + <_>. , + . +: <_> , - . + : 1 , 0 - . + +: copy +: <_> <_> +: <_> <_> + ( <_> + "resource_base"). +: <_> , - . + : 1 , 0 - . + +: write +: <_> +: <> +: <> <_>. +: <_> , - . + : 1 , 0 - . + +: read +: <_> +: <_>. +: , + - . + : 1 , 0 - . + +: include +: <_> +: <_>. +: . + : , . + +: ! +: <> +: . +: . + : , . + +: replace +: <1> <2> +: <> +: , <1> + <2>. + : , . + +: xml_escape +: <> +: <>, + '&', '<', '>', '`', '\' + XML. + : , . + +: xml_cdata +: <> +: XML CDATA. + : , . + + DbReader : +, Java. + + +* DbReader + " " Microsoft Access + XML- + + " + " ( ): + +biotopelist (code, rangcode, rusname, engname, descript, geobotdescr, + contributors, descrdate) + + code - , ; + rangcode - ABBCCDDEE, , BB, CC, DD, - + , ; + rusname, engname, descript, geobotdescr - ; + descrdate - . + +photos (biotope, photo, authphoto) + + biotope - , code biotopelist; + photo - ; + authphoto - . + + xml- biotopelist, + , , + . + + xml- + DbReader ( biotope.template): + +---------------------------------------------------------------------- +<?xml version="1.0" encoding="ISO-8859-5"?> +<!DOCTYPE _ SYSTEM "brief.dtd"> +<!-- rangcode: <%xml_escape get\rangcode%> --> +<_ show="0"> + < display="0"> + <%optional:<_ ="1" + file="<%xml_escape image:maps/<%get\rangcode%>.gif maps/<%get\code%>.png png%>"/>%> +<%query:photo_sql [%\<%include\photo.template%>%] <%get\code%>%> + </> + <><%xml_escape get\rusname%></> + <><%xml_escape get\class0%></> + <1><%xml_escape get\class1%></1> + <2><%xml_escape get\class2%></2> + <3><%xml_escape get\class3%></3> + <_ rows="3"><%xml_cdata get\descript%></_> + <_ rows="3"><%xml_cdata get\geobotdescr%></_> + <_><%xml_escape get\contributors%></_> +</_> +---------------------------------------------------------------------- + + SQL-, + rangcode, rusname, class0, class1, class2, +class3, descript, geobotdescr contributors ( biotope.sql): + +---------------------------------------------------------------------- +SELECT t1.*, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) +AND Right(t2.rangcode, 8) = '00000000' +AND Right(t1.rangcode, 8) <> '00000000') AS class0, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 3) = Left(t1.rangcode, 3) +AND Right(t2.rangcode, 6) = '000000' +AND Right(t1.rangcode, 6) <> '000000') AS class1, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 5) = Left(t1.rangcode, 5) +AND Right(t2.rangcode, 4) = '0000' +AND Right(t1.rangcode, 4) <> '0000') AS class2, + +(SELECT t2.rusname FROM biotopelist AS t2 +WHERE Left(t2.rangcode, 7) = Left(t1.rangcode, 7) +AND Right(t2.rangcode, 2) = '00' +AND Right(t1.rangcode, 2) <> '00') AS class3 + +FROM biotopelist AS t1 +WHERE rusname +---------------------------------------------------------------------- + + biotope.template <%include\photo.template%>, + ( photo.template): + +---------------------------------------------------------------------- + < num="<%xml_escape get\NUMBER%>" + <%optional:="<%xml_escape get\authphoto%>" %>text="" + file="<%xml_escape image:biotopephotos/<%get\photo%> images/<%get\SUPER.code%>_<%get\NUMBER%>.jpg jpg 300 300%>" + big="<%xml_escape copy:biotopephotos/<%get\photo%> images/big/<%get\SUPER.code%>_<%get\NUMBER%>.jpg%>"/> +---------------------------------------------------------------------- + + SQL- +(photo.sql): + +---------------------------------------------------------------------- +SELECT * from photos WHERE biotope = ? +---------------------------------------------------------------------- + +, ( classes.template): + +---------------------------------------------------------------------- +<?xml version="1.0" encoding="ISO-8859-5"?> +<><%query:class_sql [%\ + <!-- rangcode: <%xml_escape get\rangcode%> --> + < id="<%get\NUMBER%>"><%xml_escape get\rusname%></>%]%> +</> +---------------------------------------------------------------------- + + SQL- (class.sql): + +---------------------------------------------------------------------- +SELECT t1.* +FROM biotopelist AS t1 +WHERE rusname AND Right(t1.rangcode, 8) = '00000000' + AND EXISTS + (SELECT NULL FROM biotopelist AS t2 + WHERE Left(t2.rangcode, 1) = Left(t1.rangcode, 1) + AND Right(t2.rangcode, 8) <> '00000000') +---------------------------------------------------------------------- + +, ( plants.template): + +---------------------------------------------------------------------- +<?xml version="1.0" encoding="ISO-8859-5"?> +<><%query:plant_sql [%\ + <!-- rangcode: <%xml_escape get\rangcode%> --> + <><%xml_escape get\rusname%></>%]%> +</> +---------------------------------------------------------------------- + + SQL- (plant.sql): + +---------------------------------------------------------------------- +SELECT t1.* +FROM biotopelist AS t1 +WHERE rusname AND Right(t1.rangcode, 2) <> '00' +---------------------------------------------------------------------- + + DbReader index.template, + SQL- +: + +---------------------------------------------------------------------- +<%!: + <%prepare:biotope_sql <%read\biotope.sql%>%> + <%prepare:photo_sql <%read\photo.sql%>%> + <%prepare:class_sql <%read\class.sql%>%> + <%prepare:plant_sql <%read\plant.sql%>%> + + <%query:biotope_sql [%\<%write:<%get\code%>.xml <%include\biotope.template%>%> %]%> + + <%write:classes.xml <%include\classes.template%>%> + <%write:plants.xml <%include\plants.template%>%> +%> +---------------------------------------------------------------------- + + XML-: + +---------------------------------------------------------------------- +<?xml version="1.0" encoding="ISO-8859-5"?> +<!DOCTYPE _ SYSTEM "brief.dtd"> +<!-- rangcode: E04020302 --> +<_ show="0"> + < display="0"> + < num="1" =" .." text="" + file="images/3_1.jpg" + big="images/big/3_1.jpg"/> + < num="2" =" .." text="" + file="images/3_2.jpg" + big="images/big/3_2.jpg"/> + </> + <>Betula sp. - Avenella flexuosa - Polytrichum commune</> + <>E. </> + <1> </1> + <2></2> + <3></3> + <_ rows="3"><![CDATA[ . 5 - 7 , , , .]]></_> + <_ rows="3"></_> + <_></_> +</_> +---------------------------------------------------------------------- + + +* DbReader + + DbReader Java + : + +ru.karrc.dbreader.DbReader: c . +, + JDBC, . + +ru.karrc.dbreader.TemplateParser: , + . + +ru.karrc.dbreader.Function: . +DbReader . + +ru.karrc.dbreader.FunctionDataParser: +. , +. + TemplateParser. + +ru.karrc.dbreader.Functions: + , Function. + +ru.karrc.dbreader.TemplateParser: , + . + + , , + . + + +* . + + : 8, + Java- ( ): 27, + : 1311, + ( ): 812, + : 180. + + +* + + DbReader, + + . +DbReader " " + XML- .
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/doc/readme.html Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,86 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <title>DbReader</title> + <meta http-equiv="Content-Type" content="text/html; charset=koi8-r" /> +</head> + +<body> +<h1>DbReader</h1> + +<h2> </h2> +<ol> +<li> .</li> + +<li> :<br /> + Windows 2000: // (ODBC), biotopes-data.mdb.</li> + +<li> :<br /> + dbreader.properties , :<br /> + <code>resource: jdbc:odbc:<em></em></code><br /> + , ( biotopephotos maps):<br /> + <code>resource_base: C:\\biotopes</code><br /> +( '\' )</li> + +<li> :<br /> +<code>dbreader.bat</code> <br /> +<code>java -jar dbreader.jar</code>.<br /> + Java Runtime Environment (JRE) 5.0, <a href="http://java.sun.com/j2se/1.5.0/download.jsp">http://java.sun.com/j2se/1.5.0/download.jsp</a>. , JRE - . + + :<br /> + <code>java -Dru.karrc.dbreader.<em></em>=<em></em> -jar dbreader.jar</code><br /> +(: <code>java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar</code>)</li> +</ol> + +<h2> </h2> + +<p> biotope.sql ( , dbreader.properties), biotope.template, .</p> +<p> : <code><%<em>_</em>[:|\]<em></em>%></code>, <em> </em> - , . , .</p> + +<h3> </h3> + +<ul> + <li><code>:</code> - .</li> + <li><code>\</code> - . <code><%</code> <code>%></code> (<code><%\<%%></code> <code><%\%%>></code>).</li> +</ul> + +<h3></h3> + +<ul> + <li><code><%get:<em></em>%></code><br /> + .</li> + + <li><code><%optional:<em></em>%></code><br /> + <em></em>, , , .</li> + + <li><code><%escape:<em></em>%></code><br /> + "" ( ).</li> + + <li><code><%invoke:<em></em>; <em>1</em> <em>2</em> ... <em>N</em>%></code><br /> + <em></em>.sql <em></em>.template. '?'.</li> + + <li><code><%image:<em>_</em> <em>_</em> <em></em> [<em>_</em>] [<em>_</em>]%></code><br /> + <em>_</em> ( "resource_base") , <em>_</em>. , . + , <code><%image:...%></code> <em>_</em>, - .</li> + + <li><code><%copy:<em>_</em> <em>_</em>%></code><br /> + <em>_</em> ( "resource_base") <em>_</em>. , <code><%copy:...%></code> <em>_</em>, - .</li> +</ul> + +<h3> </h3> + +<p><code>NUMBER</code> - . + , invoke, <code>SUPER.</code> (: <code>SUPER.NUMBER</code>).</p> + +<h3></h3> + +<p> name :</p> +<p><code><%escape get:name%></code></p> + +<p align="right"><i><a href="mailto:kryshen@cs.karelia.ru"> </a></i></p> + +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/doc/readme.txt Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,63 @@ +text/plain; charset=UTF-8 + +Установка программы +------------------- + +1. Распаковать архив. + +2. Установить источник данных: +в Windows 2000: Панель управления/Администрирование/Источники данных (ODBC), добавить biotopes.mdb. + +3. Настроить программу: +В файле dbreader.properties указать имя, присвоенное источнику данных: + "resource: jdbc:odbc:<имя>" +и путь к каталогу, относительно которого программа будет искать изображения (содержащий biotopephotos и maps): + "resource_base: C:\\biotopes" +(символ '\' необходимо дублировать) + +4. Запуск программы: dbreader.bat или "java -jar dbreader.jar" +Для запуска необходима Java Runtime Environment (JRE) 5.0, можно скачать с http://java.sun.com/j2se/1.5.0/download.jsp. Возможно, будет работать и со старыми версиями JRE - не проверял. + +Все значения файла конфигурации можно переопределять при запуске программы: + команда "java -Dru.karrc.dbreader.<ключ>=<значение> -jar dbreader.jar" +(например: "java -Dru.karrc.dbreader.log=dbreader.log -jar dbreader.jar") + + +Работа программы +---------------- + +Программа выполняет запрос biotope.sql (или другой, указанный в dbreader.properties), после чего обрабатывает файл biotope.template, заменяя найденные в нем инструкции на результаты их выполнения. + +Формат инструкций: "<%список_функций[:|\]данные%>", список функций - имена функций разделенные пробелом, список может быть пустым. Если указано несколько функций, они выполняются начиная с последней. + +Разделители между списком функций и данными: +':' - данные будут обрабатываться рекурсивно. +'\' - данные будут переданы функции без обработки. Можно использовать для экранирования комбинаций символов "<%" и "%>" ("<%\<%%>" и "<%\%%>>"). + +Функции: +<%get:<имя>%> - заменяется на значение встроенной переменной или колонки запроса. + +<%optional:<текст>%> +Заменяется на <текст>, если в нем найдены инструкции, заменившиеся на непустые строки, иначе заменяется на пустую строку. + +<%escape:<текст>%> +Заменяет в тексте "опасные" символы (таблица замен задается в файле конфигурации). + +<%invoke:<имя> <парам1> <парам2> ... <парамN>%> +Выполняет запрос с параметрами <имя>.sql и заменяется на результаты обработки шаблона <имя>.template. Значения параметров подставляются в запрос вместо символа '?'. + +<%image:<исх_файл> <кон_файл> <формат> [<макс_ширина>] [<макс_высота>]%> +Загружает изображение из файла <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base") и преобразует его в указанный формат, сохраняя результат в <кон_файл>. Если заданы максимальная высота и ширина, большие изображения будут уменьшены. +При успешном выполнении, инструкция "<%!image ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. + +<%copy:<исх_файл> <кон_файл>%> +Копирует файл <исх_файл> (путь определяется относительно конфигурационного параметра "resource_base"). +При успешном выполнении, инструкция "<%!copy ...%>" будет заменена на значение <кон_файл>, иначе - на пустую строку. + +Встроенные переменные: +NUMBER - порядковый номер строки результата выполнения запроса. +Чтобы обратиться к переменной запроса, из которого обрабатываемый шаблон был вызван с помощью функции invoke, перед именем переменной нужно добавить "SUPER." (например: "SUPER.NUMBER"). + +Пример: +Следующая инструкция получит значение из столбца name и заменит в нем специальные символы: +<%escape get:name%>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/main.template Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,11 @@ +<%!: + <%prepare:biotope_sql <%read\biotope.sql%>%> + <%prepare:photo_sql <%read\photo.sql%>%> + <%prepare:class_sql <%read\class.sql%>%> + <%prepare:plant_sql <%read\plant.sql%>%> + + <%query:biotope_sql [%\<%write:<%db\code%>.xml <%include\biotope.template%>%> %]%> + + <%write:classes.xml <%include\classes.template%>%> + <%write:plants.xml <%include\plants.template%>%> +%>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/photo.sql Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,1 @@ +SELECT * from photos WHERE biotope = ?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/photo.template Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,3 @@ + < num="<%number\%>" <%optional:="<%xml_escape db\authphoto%>" %>text="" + file="<%xml_escape image:biotopephotos/<%db\photo%> images/<%super.db\code%>_<%number\%>.jpg jpg 300 300%>" + big="<%xml_escape copy:biotopephotos/<%db\photo%> images/big/<%super.db\code%>_<%number\%>.jpg%>"/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/plant.sql Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,3 @@ +SELECT t1.* +FROM biotopelist AS t1 +WHERE rusname AND Right(t1.rangcode, 2) <> '00'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/plants.template Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="ISO-8859-5"?> +<><%query:plant_sql [%\ + <!-- rangcode: <%xml_escape db\rangcode%> --> + <><%xml_escape db\rusname%></>%]%> +</>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/biotopes/tema.properties Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,22 @@ +# Data source configuration +resource : jdbc:odbc:biotopes-data +driver : sun.jdbc.odbc.JdbcOdbcDriver + +# Base directory for images and files +resource_base : C:\\biotopes\\db + +# Template to start processing with +main_template : main.template + +# File encodings +input_encoding : ISO-8859-5 +output_encoding : ISO-8859-5 + +# Cache templates +cache_read : true + +# Output main_template parsing result to stderr +#output : stderr + +# File to output error messages (redirect stderr) +#log : tema.log
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/manual-ru-old/index.html Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,370 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "DTD/xhtml1-transitional.dtd"> + +<html> + +<head> + <title>Макропроцессор TEMA</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +</head> + +<body> +<h1>Макропроцессор TEMA</h1> + +<p>Макропроцессор TEMA обрабатывает заданные шаблоны текстовых файлов и +заменяет найденные в них инструкции на результаты их выполнения. +</p><p> +Особенности: +</p> +<ul> + <li>Расширяемость: возможно динамически подключать новые функии, + реализованные в виде классов на Java.</li> + <li>Работа с базами данных: использование SQL-запросов для получения + данных.</li> + <li>Поточная обработка данных: инструкции обрабатываются по мере + чтения текста без необходимости загрузки файла в оперативную память + и выполнения полного синтаксического разбора.</li> +</ul> + +<p><b>Формат инструкций</b></p> + +<blockquote> + <code><%<i>список_функций</i>{:|\|`}<i>данные</i>%></code> +</blockquote> +<p> +где<br /> + +<code><i>список_функций</i></code> - список имен функций, разделенных + пробелами. Может быть пустым.<br /> +<code><i>данные</i></code> - данные, передаваемые функции. +</p> + +<p><b>Формат данных</b></p> + +<blockquote> + <code> + [<i>список_аргументов</i>][<i>текст</i>] + </code> +</blockquote> +<p> +где<br /> + +<code><i>список_аргументов</i></code> - список аргументов функции, разделенных пробелами. + Может быть пустым.<br /> +<code><i>текст</i></code> - текст, передаваемый функции без разбиения на аргументы. + Может быть пустым. Количество аргументов, после которого следует + текст, зависит от функции. +</p><p> +Разделитель между списком функций и данными определяет, как должны +обрабатываться данные функции: +</p><p> +<code>:</code> - рекурсивная обработка,<br /> +<code>\</code> или <code>`</code> - передать без обработки. +</p><p> +Если в списке функций задано две и более функции, они выполняются, +начиная с последней, так что каждая функция получает в качестве данных +результат выполнения следующей функции. +</p><p> +Каждая функция имеет код возврата - целое число. Код возврата +инструкции - код возврата первой в списке функции. Код возврата, +получаемый при обработке текста - сумма кодов возврата обработанных +инструкций (как правило, смысл этого значения - количество инструкций, +замененных на непустой текст). +</p><p> +Кроме скобок '<', '>', можно использовать скобки '[', ']'. +</p> + + +<h2>Функции</h2> + +<p><code><b>set</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>имя</i></td></tr> + +<tr><td>Текст:</td> +<td><i>значение</i></td></tr> + +<tr><td>Действие:</td> +<td>Устанавливает значение переменной <i>имя</i>.</td></tr> + +<tr><td>Результат:</td> +<td><i>имя</i></td></tr> + +<tr><td>Код возврата:</td> +<td>1</td></tr> +</table> + +<p><code><b>define</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>имя</i></td></tr> + +<tr><td>Текст:</td> +<td><i>шаблон</i></td></tr> + +<tr><td>Действие:</td><td>Определяет новую функцию <i>имя</i>, при +вызове которой обрабатывается <i>шаблон</i>. При обработке доступны +функции <code>nextarg</code> для получения очередного аргумента +вызываемой функции и <code>data</code> для получения текста.</td></tr> + +<tr><td>Результат:</td> +<td><i>имя</i></td></tr> + +<tr><td>Код возврата:</td> +<td>1</td></tr> +</table> + +<p><code><b>load</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>имя</i> <i>имя_класса</i></td></tr> + +<tr><td>Действие:</td> + +<td>Определяет новую функцию <i>имя</i>. Реализация функции определена +Java-классом <i>имя_класса</i>, наследующим класс +<code>kryshen.tema.Function</code>.</td></tr> + +<tr><td>Результат:</td> +<td><i>имя</i></td></tr> + +<tr><td>Код возврата:</td> +<td>1</td></tr> +</table> + +<p><code><b>prepare</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>имя</i></td></tr> + +<tr><td>Текст:</td> +<td><i>запрос</i></td></tr> + +<tr><td>Действие:</td> +<td>Подготавливает SQL-запрос <i>запрос</i> для выполнения, записывает +подготовленный запрос в переменную <i>имя</i>.</td></tr> + +<tr><td>Результат:</td> +<td><i>имя</i></td></tr> + +<tr><td>Код возврата:</td> +<td>1</td></tr> +</table> + +<p><code><b>query</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>имя_запроса</i> <i>шаблон</i> <i>парам1</i> ... <i>парамN</i></td></tr> + +<tr><td>Действие:</td> +<td>Выполняет запрос с параметрами, подготовленный с помощью функции +prepare. Значения параметров подставляются в запрос вместо символа +'?'. Значения полей ответа доступны с помощью функции <code>db</code>, +как переменные шаблона <i>шаблон</i>. При обработки шаблона также +определяется переменная <code>number</code>, содержащая номер текущей +строки ответа.</td></tr> + +<tr><td>Результат:</td> +<td>результат обработки шаблона <i>шаблон</i> для каждой строки +ответа.</td></tr> + +<tr><td>Код возврата:</td> +<td>Количество полученных строк ответа.</td></tr> +</table> + +<p><code><b>optional</b></code></p> + +<table> +<tr><td>Текст:</td> +<td><i>данные</i></td></tr> + +<tr><td>Результат:</td><td><i>данные</i>, если при обработке данных +был получен код возврата отличный от 0, иначе - пустая +строка.</td></tr> + +<tr><td>Код возврата:</td> +<td>1, если результат - пустая строка, 0 - иначе.</td></tr> +</table> + +<p><code><b>image</b></code></p> + +<table> +<tr><td>Аргументы:</td> +<td><i>исх_файл</i> <i>кон_файл</i> <i>формат</i> [<i>макс_ширина</i> +[<i>макс_высота</i>]]</td></tr> + +<tr><td>Действие:</td> +<td>Загружает изображение из файла <i>исх_файл</i> (путь определяется +относительно конфигурационного параметра "resource_base") и +преобразует его в указанный формат, сохраняя результат в +<i>кон_файл</i>. Если заданы максимальная высота и ширина, большие +изображения будут уменьшены.</td></tr> + +<tr><td>Результат:</td> +<td><i>кон_файл</i> при успешном выполнении, пустая строка - иначе.</td></tr> + +<tr><td>Код возврата:</td> +<td>1 при успешном выполнении, 0 - иначе.</td></tr> +</table> + + +<p><code><b>copy</b></code></p> + +<table> +<tr><td>Аргументы:</td><td><i>исх_файл</i> <i>кон_файл</i></td></tr> + +<tr><td>Действие:</td><td>Копирует файл <i>исх_файл</i> в файл +<i>кон_файл</i> (путь <i>исх_файл</i> определяется относительно +конфигурационного параметра "resource_base").</td></tr> + +<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении, +пустая строка - иначе.</td></tr> + +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - +иначе.</td></tr> +</table> + +<p><code><b>write</b></code></p> + +<table> +<tr><td>Аргументы:</td><td><i>имя_файла</i></td></tr> + +<tr><td>Текст:</td><td><i>данные</i></td></tr> + +<tr><td>Действие:</td><td>Записывает <i>данные</i> в файл +<i>исх_файл</i>.</td></tr> + +<tr><td>Результат:</td><td><i>кон_файл</i> при успешном выполнении, +пустая строка - иначе.</td></tr> + +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - +иначе.</td></tr> +</table> + +<p><code><b>read</b></code></p> + +<table> +<tr><td>Текст:</td><td><i>имя_файла</i></td></tr> +<tr><td>Действие:</td><td>Читает файл <i>имя_файла</i>.</td></tr> +<tr><td>Результат:</td><td>прочитанные данные при успешном выполнении, + пустая строка - иначе.</td></tr> +<tr><td>Код возврата:</td><td>1 при успешном выполнении, 0 - +иначе.</td></tr> +</table> + +<p><code><b>include</b></code></p> + +<table> +<tr><td>Текст:</td><td><i>имя_файла</i></td></tr> +<tr><td>Действие:</td><td>включает шаблон из файла +<i>имя_файла</i>.</td></tr> +<tr><td>Результат:</td><td>результат обработки шаблона.</td></tr> +<tr><td>Код возврата:</td><td>код возврата, полученный при обработке +шаблона.</td></tr> +</table> + +<p><code><b>!</b></code></p> + +<table> +<tr><td>Текст:</td><td><i>данные</i></td></tr> + +<tr><td>Действие:</td><td>нет.</td></tr> + +<tr><td>Результат:</td><td>нет.</td></tr> + +<tr><td>Код возврата:</td><td>код возврата, полученный при обработке +текста данных.</td></tr> +</table> + +<p><code><b>replace</b></code></p> + +<table> +<tr><td>Аргументы:</td><td><i>стр1</i> <i>стр2</i></td></tr> + +<tr><td>Текст:</td><td><i>данные</i></td></tr> + +<tr><td>Результат:</td><td>данные, с замененными вхождениями подстроки +<i>стр1</i> на <i>стр2</i>.</td></tr> + +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке +текста данных.</td></tr> +</table> + +<p><code><b>xml_escape</b></code></p> + +<table> +<tr><td>Текст:</td><td><i>данные</i></td></tr> +<tr><td>Результат:</td><td>текст <i>данные</i>, в котором символы +'&', '<', '>', '`', '\' заменены на соответствующие сущности +XML.</td></tr> + +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке +текста данных.</td></tr> +</table> + +<p><code><b>xml_cdata</b></code></p> + +<table> +<tr><td>Текст:</td><td><i>данные</i></td></tr> + +<tr><td>Результат:</td><td>данные в виде блока XML CDATA.</td></tr> + +<tr><td>Код возврата:</td><td> код возврата, полученный при обработке +текста данных. </td></tr> +</table> + +<p> +Макропроцессор TEMA расширяем: возможно добавление в систему новых +функций, реализованных в виде классов на языке Java. +</p> + +<h2>Запуск</h2> + +<p>java -jar tema.jar [<i>опции</i>] +</p><p> +Опции: +</p> +<table> +<tr><td>-d[emo]</td><td>Демонстрационный режим</td></tr> +<tr><td>-v[ersion]</td><td>Вывод версии</td></tr> +<tr><td>-h[help] -u[sage]</td><td>Вывод справки</td></tr> +</table> + +<p> +При запуске читается файл "tema.properties" из текущего каталога.<br /> +Пример файла "tema.properties": +</p> + +<pre> +# Настройка источника данных +# resource : jdbc:odbc:database +# driver : sun.jdbc.odbc.JdbcOdbcDriver + +# Базовый каталог ресурсов +# resource_base : . + +# Шаблон, с которого начинается обработка +main_template : main.template + +# Кодировки файлов +# input_encoding : UTF-8 +# output_encoding : UTF-8 + +# Кэширование шаблонов +# cache_read : true + +# Вывод результата разбора шаблона main.template в stderr +# output : stderr + +# Вывод сообщений об ошибках в файл +# log : dbreader.log +</pre> + +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/util/header Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,21 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: $ + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/util/header.gpl Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006, 2007, 2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tema. If not, see <http://www.gnu.org/licenses/>. + * + * $Id: header.gpl,v 1.1 2008/02/16 16:56:34 mikhail Exp $ + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/util/update_headers.pl Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use File::Find; + +undef $/; + +my $src = "../../src"; +my $header_file = "header"; + +open (FILE, "$header_file"); +my $header = <FILE>; +close(FILE); + +find (\&update_header, $src); + +sub update_header +{ + my $code; + + if ( $File::Find::name !~ /^.*\.java$/ ) + { + return; + } + + print $File::Find::name."\n"; + open(FILE, "$_") or die "error opening file"; + + $code = <FILE>; + $code =~ s|(^[[:space:]]*/\*.*?\*/[[:space:]]*?\n\|^)|$header|s; + + close(FILE); + + open(FILE, ">$_") or die "error opening file"; + print FILE $code; + close(FILE); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nbproject/.cvsignore Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,1 @@ +private
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nbproject/project.xml Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.ant.freeform</type> + <configuration> + <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1"> + <!-- Do not use Project Properties customizer when editing this file manually. --> + <name>TEMA</name> + <properties/> + <folders> + <source-folder> + <label>src</label> + <type>java</type> + <location>src</location> + </source-folder> + <source-folder> + <label>test</label> + <type>java</type> + <location>test</location> + </source-folder> + </folders> + <ide-actions> + <action name="build"> + <target>compile</target> + </action> + <action name="clean"> + <target>clean</target> + </action> + <action name="javadoc"> + <target>doc.api</target> + </action> + <action name="rebuild"> + <target>clean</target> + <target>compile</target> + </action> + <action name="run"> + <target>run.demo</target> + </action> + </ide-actions> + <view> + <items> + <source-folder style="packages"> + <label>src</label> + <location>src</location> + </source-folder> + <source-folder style="packages"> + <label>test</label> + <location>test</location> + </source-folder> + <source-file> + <location>build.xml</location> + </source-file> + </items> + <context-menu> + <ide-action name="build"/> + <ide-action name="rebuild"/> + <ide-action name="clean"/> + <ide-action name="javadoc"/> + <ide-action name="run"/> + <action> + <label>Compile manual</label> + <target>doc.manual</target> + </action> + </context-menu> + </view> + <subprojects/> + </general-data> + <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/2"> + <compilation-unit> + <package-root>src</package-root> + <classpath mode="compile">build:dist/lib/commons-cli-1.1.jar:../../../../../usr/share/java/ant.jar</classpath> + <source-level>1.5</source-level> + </compilation-unit> + <compilation-unit> + <package-root>test</package-root> + <unit-tests/> + <classpath mode="compile">build</classpath> + <source-level>1.5</source-level> + </compilation-unit> + </java-data> + </configuration> +</project>
--- a/res/kryshen/tema/demo/demo.template Thu Dec 14 23:22:05 2006 +0300 +++ b/res/kryshen/tema/demo/demo.template Tue Feb 19 20:32:17 2008 +0300 @@ -1,25 +1,34 @@ -[%!\ TEMA demo template %] +[%!\ + Tema demo template +%]\\ -Вывод текста: -test text +<%tema:%> -Вывод специальных символов: -[%\<%test%>%] +Escaping special character sequences: +[%\<%test:%>%] -Объявление функции: -<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%> +Macro definition: +<%define#test + arg1:<%next_arg:%>, arg2:<%next_arg:%>, data:<%data:%>.%> -Вызов новой функции: -<%test:1 2 3%> +Invoke defined macro: +<%test:1 2 3 4 5%> -Загрузка функции из класса: +Define macro implemented as a Java class: <%load\hello kryshen.tema.demo.Hello%> -Выполенение загруженной функции: -<%hello\TEMA%> +Invoke defined macro: +<%hello\Tema%> + +Conditional output: +<%optional:<%true:%>True%>\ +<%optional:<%false:%>False%> -Условное выполнение: -<%optional:<%true:%>True%> <%optional:<%false:%>False%> +Cycle: +<%silent define#cycle_test + Arguments list: <%while#"<%next_arg:%>" %>\ +%>\ +<%cycle_test:1 2 3 <%:4 5%>%> -Тестирование xml_escape: +Escaping special characters in XML: <%xml_escape\x < a & b%>
--- a/src/Manifest.mf Thu Dec 14 23:22:05 2006 +0300 +++ b/src/Manifest.mf Tue Feb 19 20:32:17 2008 +0300 @@ -1,2 +1,3 @@ Manifest-Version: 1.0 Main-Class: kryshen.tema.Tema +Class-Path: lib/commons-cli-1.1.jar
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/Context.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,130 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: Context.java,v 1.11 2008/02/19 16:21:00 mikhail Exp $ + */ + +package kryshen.tema; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * Tema template context. + * + * @author Mikhail Kryshen + */ +public class Context { + private Map<String, Object> definitions = new HashMap<String, Object>(); + private Context superContext; + private File baseDir; + + public Context() { + this(null, null); + } + + public Context(Context superContext) { + this(superContext, null); + } + + public Context(File baseDir) { + this(null, baseDir); + } + + public Context(Context superContext, File baseDir) { + this.superContext = superContext; + this.baseDir = baseDir; + + definitions.put("this", this); + + if (superContext != null) + definitions.put("super", superContext); + } + + public void clear() { + definitions.clear(); + } + + public boolean export(String name) { + Object value = definitions.get(name); + + if (value == null) + return false; + + export(name, value); + return true; + } + + public void export(String name, Object value) { + if (superContext == null) { + set(name, value); + return; + } + + definitions.remove(name); + superContext.export(name, value); + } + + public Object get(String name) throws TemplateException { + Object value = definitions.get(name); + + if (value == null && superContext != null) + return superContext.get(name); + + return value; + } + + /** + * Set the definition value. + * + * @param name Variable name. + * @param value New variable value. + */ + public void set(String name, Object value) { + definitions.put(name, value); + } + + /** + * Remove the definition recursively. + * + * @param name Definition name. + * @return true if the definition was found and removed. + */ + public boolean unset(String name) { + if (definitions.remove(name) != null) + return true; + + if (superContext != null) + return superContext.unset(name); + + return false; + } + + /** + * Returns base directory which should be used to resolve + * relative path names in template. + */ + public File getBaseDirectory() { + if (baseDir == null && superContext != null) + return superContext.getBaseDirectory(); + + return baseDir; + } +}
--- a/src/kryshen/tema/Function.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/Function.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,33 +1,34 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: Function.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ + * $Id: Function.java,v 1.13 2008/02/19 16:21:00 mikhail Exp $ */ package kryshen.tema; -import java.io.*; -import java.util.*; -import java.sql.ResultSet; +import java.io.IOException; +import java.io.Writer; /** - * Abstact class for TEMA functions. + * Abstact class for Tema functions. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public abstract class Function {
--- a/src/kryshen/tema/FunctionDataParser.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/FunctionDataParser.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,140 +1,204 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: FunctionDataParser.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ + * $Id: FunctionDataParser.java,v 1.27 2008/02/16 17:56:34 mikhail Exp $ */ package kryshen.tema; -import java.io.*; -import java.util.*; - +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; import static kryshen.tema.TemplateParser.Result; -import static kryshen.tema.TemplateParser.FunctionData; +import static kryshen.tema.TemplateParser.DataFormat; +import kryshen.tema.TemplateParser.DataFormat; import static kryshen.tema.TemplateParser.Terminator; +import kryshen.tema.io.CopyWriter; +import kryshen.tema.io.NullWriter; +import kryshen.tema.io.TemplateReader; /** * Parser for a function data. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class FunctionDataParser { static final char[] ARG_SEPARATORS = TemplateParser.LIST_SEPARATORS; - + private TemplateParser tp; - private FunctionData fd; + private DataFormat fd; private TemplateReader in; - + private boolean available = true; - private boolean first = true; - - FunctionDataParser(TemplateParser tp, FunctionData fd, - TemplateReader in) { + + private int lastReturnCode = 0; + + FunctionDataParser(TemplateParser tp, DataFormat fd, TemplateReader in) + throws IOException, TemplateException { this.tp = tp; this.fd = fd; this.in = in; + + // Check for empty function data. + checkAvailable(); } - - private TemplateParser.Result parseData(Writer out, boolean argument) - throws IOException, TemplateException { + + private void checkAvailable() throws IOException, TemplateException { + if (tp.checkCloseBracket(in)) { + // Complete parsing the instruction. + skipData(); + } + } + + private int parseData(Writer out, boolean argument, boolean skip) + throws IOException, TemplateException { if (!available) throw new TemplateException - ("Unexpected end of instruction data.", in); - + ("Unexpected end of instruction data.", in); + + DataFormat fd = skip ? this.fd.noCall() : this.fd; + TemplateParser.Result r; - - if (fd == FunctionData.RECURSIVE) { - r = tp.parse(in, out, true, - argument ? ARG_SEPARATORS : null, - (argument || !first) ? ARG_SEPARATORS : null); - } else if (fd == FunctionData.NONRECURSIVE) { - r = tp.parse(in, out, false, - argument ? ARG_SEPARATORS : null, - (argument || !first) ? ARG_SEPARATORS : null); - } else if (fd == FunctionData.SUBFUNCTION && argument) { - // Subfunction can pass a list of arguments - StringWriter sw = new StringWriter(); - tp.parseFunction(in, sw); - sw.close(); - in = new TemplateReader(new StringReader(sw.toString()), in); - fd = FunctionData.NONRECURSIVE; - r = parseData(out, true); - } else if (fd == FunctionData.SUBFUNCTION) { - r = new Result(null, tp.parseFunction(in, out), false); + +// if (fd.subfunction && argument) { +// // Allow subfunction to pass a list of arguments +// StringWriter sw = new StringWriter(); +// tp.parse(in, sw, fd); +// sw.close(); +// in = new TemplateReader(new StringReader(sw.toString()), in); +// this.fd = DataFormat.VERBATIM; +// r = parseData(out, true, false); +// } else + if (fd.subfunction) { + r = tp.parse(in, out, fd); + } else if (argument) { + // Skip duplicate separators before argument. + tp.skip(in, ARG_SEPARATORS); + + r = tp.parse(in, out, fd, ARG_SEPARATORS); + + // Skip duplicate separators after argument. + if (r.terminator == Terminator.SEPARATOR) { + tp.skip(in, ARG_SEPARATORS); + checkAvailable(); + } } else { - throw new IllegalArgumentException("Invalid FunctiodData: " + fd); + r = tp.parse(in, out, fd, null); } - - if (r.terminator != TemplateParser.Terminator.SEPARATOR) + + if (r.terminator != Terminator.SEPARATOR) available = false; // No more function data available. - - first = false; - return r; + + lastReturnCode = r.retCode; + return r.retCode; + } + + /** + * Parse function data. + */ + public int parseData(Writer out) throws IOException, TemplateException { + return parseData(out, false, false); } - - public int parseData(Writer out) throws IOException, TemplateException { - return parseData(out, false).retCode; + + /** + * Skip function data (do not call any functions). + */ + public void skipData() throws IOException, TemplateException { + parseData(NullWriter.INSTANCE, false, true); } - - public String getData() throws IOException, TemplateException { + + /** + * Get function data as string. + */ + public String getData() throws IOException, TemplateException { StringWriter sw = new StringWriter(); parseData(sw); sw.close(); return sw.toString(); } - + + /** + * Parse function data into specified <code>Writer</code>. + * Returns copy of the parsed data as string. + */ + public String getData(Writer out) throws IOException, TemplateException { + StringWriter sw = new StringWriter(); + parseData(new CopyWriter(sw, out)); + sw.close(); + return sw.toString(); + } + public int parseNextArg(Writer out) throws IOException, TemplateException { - TemplateParser.Result r = parseData(out, true); - - // Ignore empty arguments. - while (r.empty && available) { - r = parseData(out, true); - } - - return r.retCode; + return parseData(out, true, false); } - - public String getNextArg() throws IOException, TemplateException { + + public void skipNextArg() throws IOException, TemplateException { + parseData(NullWriter.INSTANCE, true, true); + } + + public String getNextArg() throws IOException, TemplateException { StringWriter sw = new StringWriter(); parseNextArg(sw); sw.close(); return sw.toString(); } - + public List<String> getArgs() throws IOException, TemplateException { - List<String> l = new ArrayList<String>(); - - while (available) { - l.add(getNextArg()); - } - - return l; + List<String> l = new ArrayList<String>(); + + while (available) { + l.add(getNextArg()); + } + + return l; } - + public boolean hasMoreData() { return available; } - + + public int getLastReturnCode() { + return lastReturnCode; + } + public TemplateParser getTemplateParser() { return tp; } + public Context getContext() { + return tp.getContext(); + } + public TemplateReader getTemplateReader() { return in; } + + public File createFile(String path) { + File file = new File(path); + + if (file.isAbsolute()) + return file; + + return new File(tp.getContext().getBaseDirectory(), path); + } }
--- a/src/kryshen/tema/Functions.java Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: Functions.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $ - */ - -package kryshen.tema; - -import java.io.*; -import java.util.*; - -import kryshen.tema.functions.*; - -/** - * Standard TEMA functions. - * - * @author Mikhail A. Kryshen - */ -public class Functions { - // TODO: arithmetics, conditions - - /** - * Register all standard functions. - * - * @param p TemplateParser to register functions in. - */ - static void registerAllFunctions(TemplateParser p) { - p.registerFunction("!", Standard.NULL_OUTPUT); - p.registerFunction("set", Standard.SET); - p.registerFunction("load", Standard.LOAD); - p.registerFunction("query", Standard.QUERY); - p.registerFunction("prepare", Standard.PREPARE); - p.registerFunction("replace", Standard.REPLACE); - p.registerFunction("xml_escape", Standard.XML_ESCAPE); - p.registerFunction("xml_cdata", Standard.XML_CDATA); - - p.registerFunction("define", Define.DEFINE); - - p.registerFunction("write", IO.WRITE); - p.registerFunction("read", IO.READ); - p.registerFunction("include", IO.INCLUDE); - p.registerFunction("copy", IO.COPY); - - p.registerFunction("false", Logics.FALSE); - p.registerFunction("true", Logics.TRUE); - p.registerFunction("optional", Logics.OPTIONAL); - - p.registerFunction("image", ImageConverter.IMAGE); - - /* - Other functuons: - db - defined in Tema.query(). - nextarg, data - defined in Define.invoke(). - */ - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/GlobalContext.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,95 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: GlobalContext.java,v 1.16 2008/02/19 16:21:00 mikhail Exp $ + */ + +package kryshen.tema; + +import java.io.File; +import kryshen.tema.functions.Database; +import kryshen.tema.functions.Define; +import kryshen.tema.functions.IO; +import kryshen.tema.functions.ImageConverter; +import kryshen.tema.functions.Control; +import kryshen.tema.functions.Standard; +import kryshen.tema.functions.Strings; + +/** + * Context to hold exported variables and standard Tema definitions. + * + * @author Mikhail Kryshen + */ +class GlobalContext extends Context { + + GlobalContext() { + super(new File(System.getProperty("user.dir"))); + + // Register all standard functions. + // TODO: arithmetics + + set("tema", Standard.TEMA); + set("echo", Standard.ECHO); + set("", Standard.ECHO); + set("!", Standard.SKIP); + set("silent", Standard.SILENT); + set("set", Standard.SET); + set("unset", Standard.UNSET); + set("export", Standard.EXPORT); + set("assign", Standard.ASSIGN); + set("invoke", Standard.INVOKE); + set("load", Standard.LOAD); + + set("to_upper", Strings.TO_UPPER); + set("to_lower", Strings.TO_LOWER); + set("substring", Strings.SUBSTRING); + set("equal", Strings.EQUAL); + set("xml_escape", Strings.XML_ESCAPE); + set("xml_cdata", Strings.XML_CDATA); + set("char", Strings.CHAR); + set("replace", Strings.REPLACE); + set("regex_match", Strings.REGEX_MATCH); + set("regex_replace_first", Strings.REGEX_REPLACE_FIRST); + set("regex_replace_all", Strings.REGEX_REPLACE_ALL); + + set("define", Define.DEFINE); + + set("write", IO.WRITE); + set("read", IO.READ); + set("include", IO.INCLUDE); + set("copy", IO.COPY); + set("file", IO.FILE); + + set("false", Control.FALSE); + set("true", Control.TRUE); + set("not", Control.NOT); + set("optional", Control.OPTIONAL); + set("if", Control.IF); + set("if_else", Control.IF_ELSE); + set("while", Control.WHILE); + + set("db_connect", Database.CONNECT); + set("db_prepare", Database.PREPARE); + set("db_query", Database.QUERY); + + set("convert_image", ImageConverter.CONVERT_IMAGE); + + // Other functions are defined in classes Database and Define. + } +}
--- a/src/kryshen/tema/Tema.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/Tema.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,364 +1,248 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: Tema.java,v 1.17 2006/12/14 19:44:31 mikhail Exp $ + * $Id: Tema.java,v 1.42 2008/02/19 17:14:34 mikhail Exp $ */ package kryshen.tema; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.Connection; -import java.sql.Statement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.Writer; +import java.nio.charset.Charset; import java.sql.SQLException; - -import java.util.Map; -import java.util.HashMap; -import java.util.Properties; -import java.util.List; -import java.util.Collections; - -import java.io.*; - import kryshen.tema.demo.DemoFrame; +import kryshen.tema.io.TemplateReader; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; /** * Tema main class. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class Tema { - public static final String TITLE = "TEMA"; - public static final String VERSION = "0.1"; - public static final String AUTHOR = "Mikhail A. Kryshen"; - - private static final String CONFIG_FILE = "tema.properties"; - private static final String ENV_PREFIX = "kryshen.tema."; - - private static Properties config = new Properties(); - private static Connection connection = null; - - private static String inputEncoding; - private static String outputEncoding; - - private static Map<File, String> fileCache = null; - - public static void main(String[] args) - throws IOException, SQLException, - ClassNotFoundException, InstantiationException, - IllegalAccessException { - + public static final String TITLE = "Tema"; + public static final String VERSION = "0.3"; + public static final String AUTHOR = "Mikhail Kryshen"; + public static final String COPYRIGHT = + "Copyright 2008 Mikhail Kryshen <mikhail@kryshen.pp.ru>"; + public static final String LICENSE = + "This is free software. " + + "You may redistribute copies of it under the terms of" + + System.getProperty("line.separator") + + "the GNU Lesser General Public License version 3 or later" + + System.getProperty("line.separator") + + "<http://gnu.org/licenses/lgpl.html>."; + + private static final String DEFAULT_CHARSET = + Charset.defaultCharset().name(); + + private static String inputEncoding = DEFAULT_CHARSET; + private static String outputEncoding = DEFAULT_CHARSET; + + public static void main(String[] args) + throws IOException, SQLException, + ClassNotFoundException, InstantiationException, + IllegalAccessException { + boolean demo = false; boolean version = false; boolean help = false; - - // Parse arguments. - for (int i = 0; i < args.length; i++) { - if ("-demo".equals(args[i]) || - "-d".equals(args[i])) { - demo = true; - } else if ("-version".equals(args[i]) || - "-v".equals(args[i])) { - version = true; - } else if ("-help".equals(args[i]) || - "-h".equals(args[i]) || - "-usage".equals(args[i]) || - "-u".equals(args[i])) { - help = true; - } else { - System.err.println("Invalid option: " + args[i]); - return; - } + + Options options = new Options(); + + options.addOption(null, "demo", false, "demo mode"); + options.addOption("v", "version", false, + "print the version information and exit"); + options.addOption("h", "help", false, + "print this help message"); + options.addOption("o", "output", true, + "output file"); + options.addOption(null, "log", true, + "log all error messages to file"); + options.addOption(null, "input-encoding", true, + "input encoding"); + options.addOption(null, "output-encoding", true, + "output encoding"); + + CommandLineParser parser = new GnuParser(); + CommandLine line; + + try { + line = parser.parse(options, args ); + } catch (ParseException ex) { + System.err.println(ex.getMessage()); + System.exit(1); + return; // to avoid "not initialized" compile-time errors. } - - if (version || help) { - System.err.println(TITLE + " " + VERSION + " by " + AUTHOR); - - if (help) { - PrintStream err = System.err; - - err.println(); - err.println("Usage: tema [OPTIONS]"); - err.println(); - err.println("Options:"); - err.println(" -d[emo] Demo mode"); - err.println(" -v[ersion] Print version"); - err.println(" -h[help] -u[sage] Print this help message"); - } + + if (line.hasOption("version")) { + System.err.println(TITLE + " " + VERSION); + System.err.println(COPYRIGHT); + System.err.println(LICENSE); return; } - - if (demo) { - // Run in demo mode. + + if (line.hasOption("help")) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("tema [options] [files]", options); + return; + } + + if (line.hasOption("input-encoding")) { + inputEncoding = line.getOptionValue("input-encoding"); + } + + if (line.hasOption("output-encoding")) { + outputEncoding = line.getOptionValue("output-encoding"); + } + + if (line.hasOption("log")) { + System.setErr(new PrintStream + (new FileOutputStream(line.getOptionValue("log")))); + } + + if (line.hasOption("demo")) { + // Open the demo console. DemoFrame df = new DemoFrame(); df.pack(); df.setVisible(true); return; } - - process(); - } - - /** - * Standard execution. - */ - private static void process() - throws IOException, SQLException, - ClassNotFoundException, InstantiationException, - IllegalAccessException { - - InputStream configIn = new FileInputStream(CONFIG_FILE); - config.load(configIn); - configIn.close(); + + Writer out; - configure(); - - String main = getProperty("main_template"); - String output = getProperty("output"); - - Writer out; - - if ("stderr".equals(output)) - out = new OutputStreamWriter(System.err); - else - out = new OutputStreamWriter(System.out); - - TemplateReader in = createTemplateReader(new File(main)); - TemplateParser p = new TemplateParser(); - TemplateException te = null; - - try { - p.parse(in, out); - } catch (TemplateException e) { - te = e; - } finally { - in.close(); - out.flush(); - } - - if (te != null) { - System.err.println(te.getMessage()); - if (te.getCause() != null) { - System.err.println("Caused by " + te.getCause()); - } + if (line.hasOption("output")) { + File outfile = new File(line.getOptionValue("output")); + out = createFileWriter(outfile); } else { - System.err.println("Done"); + out = new OutputStreamWriter(System.out, outputEncoding) { + @Override + public void write(int c) throws IOException { + super.write(c); + if (c == '\r' || c == '\n') + flush(); + } + + @Override + public void write(char cbuf[], int off, int len) + throws IOException { + super.write(cbuf, off, len); + flush(); + } + + @Override + public void write(String str, int off, int len) + throws IOException { + super.write(str, off, len); + flush(); + } + }; } - } - - private static void configure() - throws IOException, SQLException, IllegalAccessException, - ClassNotFoundException, InstantiationException { - - String logFile = getProperty("log"); - if (logFile != null && logFile.length() > 0) - System.setErr(new PrintStream(new FileOutputStream(logFile))); - - if (Boolean.parseBoolean(getProperty("cache_read")) == true) - fileCache = new HashMap<File, String>(); - - inputEncoding = getProperty("input_encoding", "iso-8859-1"); - outputEncoding = getProperty("output_encoding", "iso-8859-1"); - - String resourceProperty = getProperty("resource"); - - if (resourceProperty != null) { - String driverProperty = getProperty("driver"); - if (driverProperty != null) { - // Register driver. - Driver d = (Driver)Class.forName(driverProperty).newInstance(); - } - - // Open connection. - connection = DriverManager.getConnection(resourceProperty); - } - } - - - - /** - * Get configuration property. - */ - public static String getProperty(String name) { - String value = System.getProperty(ENV_PREFIX + name); - if (value != null) return value; - return config.getProperty(name); - } - - /** - * Get configuration property. - */ - public static String getProperty(String name, String fallback) { - String value = getProperty(name); - if (value != null) return value; - return fallback; + + String[] files = line.getArgs(); + + if (files.length == 0) { + TemplateReader in = createTemplateReader(System.in); + if (!process(in, out)) { + System.exit(1); + } + } + + for (String file: files) { + TemplateReader in = createTemplateReader(new File(file)); + if (!process(in, out)) { + System.exit(1); + } + } + + out.close(); } - - /** - * Process database query. - * - * @param templateReader reader for the template - * to fill with data. - * @param ps query statement to execute. - * @param args list of query parameters. - * @param superParser invoking object. - * @param out Writer to output processed data. - * - * @return number of processed rows in query result. - */ - public static int query(TemplateReader templateReader, - PreparedStatement ps, - List<String> args, - TemplateParser superParser, - Writer out) - throws IOException, SQLException, TemplateException { - - int i = 1; - - for (String arg : args) { - ps.setString(i++, arg); - } - - ResultSet r = ps.executeQuery(); - ResultSetMetaData rm = r.getMetaData(); - int columnCount = rm.getColumnCount(); - - String[] names = new String[columnCount]; - - for (int j = 0; j < columnCount; j++) { - names[j] = rm.getColumnName(j + 1); - } - - final TemplateParser p = new TemplateParser(superParser); - final HashMap<String, Object> fields = new HashMap<String, Object>(); - - p.registerFunction("db", new Function() { - public int invoke(FunctionDataParser fdp, - final Writer out) - throws IOException, TemplateException { - - String name = fdp.getData(); - Object value = fields.get(name); - - return p.parseValue(value, out); - } - }); - - for (i = 1; r.next(); i++) { - - for (int j = 0; j < columnCount; j++) { - Object value = r.getObject(j + 1); - if (r.wasNull()) value = null; - - fields.put(names[j], value); - } - - p.setValue("number", i); - p.parse(templateReader, out); - templateReader.reset(); - fields.clear(); - } - - r.close(); - ps.clearParameters(); - return i - 1; + + private static boolean process(TemplateReader in, Writer out) + throws IOException { + + TemplateParser p = new TemplateParser(); + TemplateException ex = null; + + p.getContext().set("input_encoding", inputEncoding); + p.getContext().set("output_encoding", outputEncoding); + + try { + p.parse(in, out); + } catch (TemplateException e) { + ex = e; + } finally { + in.close(); + } + + if (ex != null) { + System.err.println(ex.getMessage()); + if (ex.getCause() != null) { + System.err.println("Caused by " + ex.getCause()); + } + return false; + } + + return true; } - - public static BufferedWriter createFileWriter(String filename) - throws IOException { - - OutputStream os = new FileOutputStream(filename); - return new BufferedWriter - (new OutputStreamWriter(os, Tema.outputEncoding)); - } - - public static BufferedReader createFileReader(File file) - throws IOException { - - InputStream is = new FileInputStream(file); - return new BufferedReader - (new InputStreamReader(is, Tema.inputEncoding)); - } - - public static TemplateReader createTemplateReader(File file) - throws IOException { - - return new TemplateReader - (new LineNumberReader(createCachedFileReader(file)), file.getPath()); - } - - /** - * Creates StringReader for a cached file if caching is enabled or - * a BufferedReader. - * - * @param file File to read. - * @return Reader for a file. - */ - public static Reader createCachedFileReader(File file) - throws IOException { + + public static BufferedWriter createFileWriter(File file) + throws IOException { - if (fileCache != null) return new StringReader(readFile(file)); - else return createFileReader(file); + OutputStream os = new FileOutputStream(file); + return new BufferedWriter + (new OutputStreamWriter(os, Tema.outputEncoding)); } - - /** - * Read text file. - * - * @return file contents. - */ - public static String readFile(File file) throws IOException { - String data; - - if (fileCache != null) { - data = fileCache.get(file); - if (data != null) return data; - } + + public static BufferedReader createFileReader(File file) + throws IOException { - Reader r = new BufferedReader(createFileReader(file)); - - // FIXME: possible overflow (long -> int). - StringBuffer sb = new StringBuffer((int)file.length()); - - try { - for (int c = r.read(); c >= 0; c = r.read()) { - sb.append((char)c); - } - } finally { - r.close(); - } - - data = sb.toString(); - - if (fileCache != null) { - fileCache.put(file, data); - } - - return data; + InputStream is = new FileInputStream(file); + return new BufferedReader + (new InputStreamReader(is, Tema.inputEncoding)); } - - /** - * Get database connection. - * - * @return database connection if any was configured. - */ - public static Connection getDbConnection() { - return connection; + + public static TemplateReader createTemplateReader(File file) + throws IOException { + + return new TemplateReader(createFileReader(file), file.getPath()); + } + + public static TemplateReader createTemplateReader(InputStream in) + throws IOException { + + return new TemplateReader( + new InputStreamReader(in, Tema.inputEncoding)); } }
--- a/src/kryshen/tema/TemplateException.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/TemplateException.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,29 +1,33 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: TemplateException.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ + * $Id: TemplateException.java,v 1.12 2008/02/16 17:56:34 mikhail Exp $ */ package kryshen.tema; +import kryshen.tema.io.TemplateReader; + /** * Signals that template parsing fails. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class TemplateException extends Exception { //private String source;
--- a/src/kryshen/tema/TemplateParser.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/TemplateParser.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,296 +1,445 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: TemplateParser.java,v 1.11 2006/12/14 19:44:31 mikhail Exp $ + * $Id: TemplateParser.java,v 1.58 2008/02/19 00:20:48 mikhail Exp $ */ package kryshen.tema; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.io.Writer; +import kryshen.tema.io.TemplateReader; /** - * Parser for TEMA templates. + * Parser for Tema templates. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class TemplateParser { - // TODO: report non-critical errors and warnings. - - static final String SUPER_PREFIX = "super."; - /* Brackets. */ - static final char[] BR_LEFT = {'<', '['}; - static final char[] BR_RIGHT = {'>', ']'}; - - static final char BR_IN = '%'; + public static final String[] BRACKET_OPEN = {"<%", "[%"}; + public static final String[] BRACKET_CLOSE = {"%>", "%]"}; + + public static final String ESCAPE_NEWLINE = "\\"; + public static final String ESCAPE_WHITESPACE = "\\\\"; /* Separators. */ - static final char[] REC_DATA_SEPARATORS = {':'}; - static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; - static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'}; - + public static final char[] REC_DATA_SEPARATORS = {':'}; + public static final char[] VERBATIM_DATA_SEPARATORS = {'\\', '`'}; + public static final char[] NOCALL_DATA_SEPARATORS = {'#'}; + public static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'}; + /** - * Methods of parsing function arguments and data. + * Specifies how to parse function arguments and data. */ - static enum FunctionData { - SUBFUNCTION, RECURSIVE, NONRECURSIVE; + static enum DataFormat { + RECURSIVE(true, false), + VERBATIM(false, false), + NOCALL(false, false), + SUBFUNCTION(true, true), + SUBFUNCTION_NOCALL(false, true); + + public final boolean call; + public final boolean subfunction; + + DataFormat(boolean call, boolean subfunction) { + this.call = call; + this.subfunction = subfunction; + } + + /** + * Returns no-call equivalent to this format. + */ + public DataFormat noCall() { + if (this == RECURSIVE) + return NOCALL; + + if (this == SUBFUNCTION) + return SUBFUNCTION_NOCALL; + + return this; + } }; - + + /** + * Specifies how the template instruction was terminated. + */ static enum Terminator { - EOF, BRACKET, SEPARATOR; + EOF, BRACKET, SEPARATOR; }; - + + /** + * The result of evaluating template instruction. + */ static class Result { - Terminator terminator; - int retCode; - + Terminator terminator; + int retCode; + /** No text had been parsed. */ - boolean empty; - - Result(Terminator terminator, int retCode, boolean empty) { + boolean empty; + + Result(Terminator terminator, int retCode, boolean empty) { this.terminator = terminator; this.retCode = retCode; this.empty = empty; } - + Result() { this(null, -1, true); - } - }; - - private Map<String, Object> variables = new HashMap<String, Object>(); - private TemplateParser superParser; - + } + }; + + protected final Context context; + private int termBracket = -1; - + public TemplateParser() { - this(null); + this.context = new Context(new GlobalContext()); } - + + public TemplateParser(File baseDir) { + this.context = new Context(new GlobalContext(), baseDir); + } + public TemplateParser(TemplateParser superParser) { - this.superParser = superParser; - - Functions.registerAllFunctions(this); + this.context = new Context(superParser.context); } - - public void registerFunction(String name, Function f) { - variables.put(name, f); + + public TemplateParser(TemplateParser superParser, File baseDir) { + this.context = new Context(superParser.context, baseDir); + } + + public TemplateParser(Context context) { + this.context = context; } - - public int parse(TemplateReader in, Writer out) - throws IOException, TemplateException { - - return parse(in, out, true, null, null).retCode; + + /** + * Parse template + * + * @param in TemplateReader to read template data. + * @param out Writer for the processed data. + * @throws IOException if case of I/O error. + * @throws TemplateException in case of parsing error (syntax + * error or invalid arguments in template instructions). + */ + public int parse(TemplateReader in, Writer out) + throws IOException, TemplateException { + return parse(in, out, DataFormat.RECURSIVE, null).retCode; } - + + Result parse(TemplateReader in, Writer out, DataFormat format) + throws IOException, TemplateException { + return parse(in, out, format, null); + } + /** - * Parse template. + * Parse template. * * @param in TemplateReader to read template data. * @param out Writer to write processed data. - * @param recursive enables recursive processing. - * @param separators characters which terminate parsing block. - * @param leading characters to ignore at the beginning of the block. + * @param DataFormat specifies parsing mode. */ - Result parse(TemplateReader in, Writer out, boolean recursive, - char[] separators, char[] leading) - throws IOException, TemplateException { - - Result result = new Result(); - int lc = -1; - - while (true) { - int c = in.read(); + Result parse(TemplateReader in, Writer out, DataFormat format, + char[] separators) + throws IOException, TemplateException { + + Result result = new Result(); + + if (format == DataFormat.SUBFUNCTION || + format == DataFormat.SUBFUNCTION_NOCALL) { - if (leading != null && isSeparator(c, leading)) - continue; - else - leading = null; - - boolean leftBracket = false; - int index; - - for (index = 0; index < BR_LEFT.length; index++) { - if (lc == BR_LEFT[index]) { - leftBracket = true; - break; + result.retCode = parseFunction(in, out, format); + result.empty = false; + return result; + } + + while (true) { + if (format != DataFormat.VERBATIM) { + int openBracket = matchInput(in, BRACKET_OPEN); + + if (openBracket >= 0) { + if (result.retCode < 0) + result.retCode = 0; + + if (!format.call) { + out.write(BRACKET_OPEN[openBracket]); + } + + int tb = termBracket; + termBracket = openBracket; + result.retCode += Math.abs(parseFunction(in, out, format)); + result.empty = false; + termBracket = tb; + + if (!format.call) { + out.write(BRACKET_CLOSE[openBracket]); + } + + continue; } } - - if (recursive && leftBracket && c == BR_IN) { - - if (result.retCode < 0) - result.retCode = 0; - - lc = -1; - int tb = termBracket; - termBracket = BR_RIGHT[index]; - result.retCode += parseFunction(in, out); - termBracket = tb; - - } else if (lc == BR_IN && c == termBracket) { - - lc = -1; - result.terminator = Terminator.BRACKET; - break; - - } else { - - if (lc >= 0) - out.write(lc); - - lc = c; - } - - if (c < 0) { - result.terminator = Terminator.EOF; - break; - } else if (separators != null && isSeparator(c, separators)) { + + if (matchCloseBracket(in)) { + result.terminator = Terminator.BRACKET; + skipEscaped(in); + break; + } + + int c = in.read(); + + if (c < 0) { +// if (termBracket >= 0) { +// throw new TemplateException("Unexpected end of file", in); +// } + + result.terminator = Terminator.EOF; + break; + } + + if (separators != null && isSeparator(c, separators)) { result.terminator = Terminator.SEPARATOR; break; } - + + out.write(c); result.empty = false; - } - - return result; + } + + return result; + } + + /** + * Check if the closing bracket sequence follows in the reader. + */ + boolean checkCloseBracket(TemplateReader in) throws IOException { + boolean match = matchCloseBracket(in); + + if (!match) + return false; + + // Put the matched characters back to the stream + in.unread(BRACKET_CLOSE[termBracket].toCharArray()); + + return true; + } + + private boolean matchCloseBracket(TemplateReader in) + throws IOException { + + if (termBracket < 0) + return false; + + return matchInput(in, BRACKET_CLOSE[termBracket]); + } + + private int matchInput(TemplateReader in, String[] s) + throws IOException { + for (int i = 0; i < s.length; i++) { + if (matchInput(in, s[i])) + return i; + } + + return -1; } - + + private boolean matchInput(TemplateReader in, String s) + throws IOException { + int n = s.length(); + for (int k = 0; k < n; k++) { + int c = in.read(); + + if (c != s.charAt(k)) { + if (c >= 0) { + in.unread(c); + } + + for (int j = k - 1; j >= 0; j--) { + in.unread(s.charAt(j)); + } + + return false; + } + } + + return true; + } + + void skip(TemplateReader in, char[] chars) throws IOException { + readLoop: + while (true) { + int c = in.read(); + + if (c < 0) + break; + + for (int i = 0; i < chars.length; i++) { + if (c == chars[i]) + continue readLoop; + } + + in.unread(c); + break; + } + } + + private void skipEscaped(TemplateReader in) throws IOException { + if (matchInput(in, ESCAPE_WHITESPACE)) { + int c = in.read(); + + if (c < 0) + return; + + if (!Character.isWhitespace(c)) { + in.unread(c); + in.unread(ESCAPE_WHITESPACE.toCharArray()); + return; + } + + do { + c = in.read(); + } while (Character.isWhitespace(c)); + + if (c >= 0) + in.unread(c); + + return; + } + + matchInput(in, + new String[] { + ESCAPE_NEWLINE + "\r\n", + ESCAPE_NEWLINE + "\r", + ESCAPE_NEWLINE + "\n"}); + } + boolean isSeparator(int c, char[] separators) { for (char p : separators) { if (c == p) return true; } - + return false; } - - int parseFunction(TemplateReader in, Writer out) - throws IOException, TemplateException { + + private int parseFunction(TemplateReader in, Writer out, DataFormat fd) + throws IOException, TemplateException { + + StringBuffer sb = new StringBuffer(); - StringBuffer sb = new StringBuffer(); - - while (true) { - int c = in.read(); + while (true) { + if (termBracket >= 0 && + matchInput(in, BRACKET_CLOSE[termBracket])) { + throw new TemplateException( + "Unexpected end of instruction", in); + } + + int c = in.read(); + + if (c < 0) + throw new TemplateException("Unexpected end of file.", in); + + if (!fd.call) + out.write(c); if (isSeparator(c, LIST_SEPARATORS)) { - return invokeFunction(sb.toString(), - FunctionData.SUBFUNCTION, - in, out); + return invoke( + fd.call ? sb.toString() : "true", + fd.call ? + DataFormat.SUBFUNCTION : + DataFormat.SUBFUNCTION_NOCALL, + in, out); } else if (isSeparator(c, REC_DATA_SEPARATORS)) { - return invokeFunction(sb.toString(), - FunctionData.RECURSIVE, - in, out); - } else if (isSeparator(c, NONREC_DATA_SEPARATORS)) { - return invokeFunction(sb.toString(), - FunctionData.NONRECURSIVE, - in, out); - } else if (c < 0) { - throw new TemplateException("Unexpected end of file.", in); + skipEscaped(in); + return invoke( + fd.call ? sb.toString() : "true", + fd.call ? + DataFormat.RECURSIVE : + DataFormat.NOCALL, + in, out); + } else if (isSeparator(c, VERBATIM_DATA_SEPARATORS)) { + return invoke( + fd.call ? sb.toString() : "true", + DataFormat.VERBATIM, in, out); + } else if (isSeparator(c, NOCALL_DATA_SEPARATORS)) { + skipEscaped(in); + return invoke( + fd.call ? sb.toString() : "true", + DataFormat.NOCALL, in, out); } else { - sb.append((char)c); - } - } + sb.append((char)c); + } + } } - - int parseValue(Object value, Writer out) throws IOException { + + public int parseValue(Object value, Writer out) throws IOException { if (value == null) return 0; - + String svalue = value.toString(); if (svalue == null || svalue.length() == 0) return 0; - + out.write(svalue); return 1; } - - private int invokeFunction(String name, FunctionData fd, - TemplateReader in, Writer out) - throws IOException, TemplateException { - - FunctionDataParser fdp = new FunctionDataParser(this, fd, in); - - if ("".equals(name)) { - return fdp.parseData(out); - } + + private int invoke(String name, DataFormat fd, + TemplateReader in, Writer out) + throws IOException, TemplateException { - Object value = getValue(name); - int r; - - if (value instanceof Function) { - r = ((Function) value).invoke(fdp, out); - } else { - r = parseValue(value, out); + FunctionDataParser fdp = new FunctionDataParser(this, fd, in); + + int r = invoke(name, fdp, out); + + if (fdp.hasMoreData()) { + /* Skip remaining function data. */ + fdp.skipData(); } - - if (fdp.hasMoreData()) { - /* Skip remaining function data. */ - fdp.parseData(new Writer() { - public void close() {} - public void flush() {} - public void write(char[] cbuf, int off, int len) {} - }); - } - - return r; + + return r; } - - public Object getValue(String name) throws TemplateException { - Object value = variables.get(name); - if (value != null) return value; - - if (superParser != null) { - if (name.startsWith(SUPER_PREFIX)) - return superParser.getValue - (name.substring(SUPER_PREFIX.length())); - else - return superParser.getValue(name); - } - - return null; - } - - public void setValue(String name, Object value) { - variables.put(name, value); + + public int invoke(String name, FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + Object value = context.get(name); + + if (value instanceof Function) { + return ((Function) value).invoke(fdp, out); + } + + if (value instanceof Context) { + String code = fdp.getData(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + TemplateParser parser = new TemplateParser((Context) value); + return parser.parse( + new TemplateReader(new StringReader(code)), out); + } + + return parseValue(value, out); } - - public void clearValues() { - variables.clear(); - Functions.registerAllFunctions(this); - } - - // TEST - public static void main(String[] args) - throws IOException, TemplateException { - - TemplateParser p = new TemplateParser(); - - TemplateReader in = - new TemplateReader - (new LineNumberReader - (new FileReader("parser.in")), "parser.in"); - - FileWriter out = new FileWriter("parser.out"); - - p.parse(in, out); - - in.close(); - out.close(); + + public Context getContext() { + return context; } }
--- a/src/kryshen/tema/TemplateReader.java Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2006 Mikhail A. Kryshen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: TemplateReader.java,v 1.5 2006/12/14 14:39:22 mikhail Exp $ - */ - -package kryshen.tema; - -import java.io.Reader; -import java.io.LineNumberReader; -import java.io.FilterReader; -import java.io.IOException; - -/** - * Reader for TEMA templates. Stores data source name (commonly - * filename) and tracks line numbers for error reporting. - * - * @author Mikhail A. Kryshen - */ -public class TemplateReader extends FilterReader { - private String source = null; - - private LineNumberReader lnReader = null; - private TemplateReader parentReader = null; - - public TemplateReader(LineNumberReader in, String source) { - super(in); - this.lnReader = in; - this.source = source; - } - - public TemplateReader(Reader in, TemplateReader parent) { - super(in); - this.source = source; - } - - public String getSource() { - if (source != null) - return source; - - return parentReader.getSource(); - } - - public int getLineNumber() { - if (lnReader != null) - return lnReader.getLineNumber(); - - return parentReader.getLineNumber(); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/ant/TemaTask.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,145 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: TemaTask.java,v 1.17 2008/02/17 23:58:01 mikhail Exp $ + */ + +package kryshen.tema.ant; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import kryshen.tema.TemplateException; +import kryshen.tema.TemplateParser; +import kryshen.tema.io.NullWriter; +import kryshen.tema.io.TemplateReader; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + * Tema support for ant. + * + * @author Mikhail Kryshen + */ +public class TemaTask extends Task { + + public static class Variable { + private String name; + private String value; + + public void setName(String name) { + this.name = name; + } + + public void setValue(String value) { + this.value = value; + } + + public void setPath(File file) { + this.value = file.getAbsolutePath(); + } + } + + private File basedir = null; + + private File infile = null; + private File outfile = null; + + private Collection<Variable> variables = new ArrayList<Variable>(); + + @Override + public void execute() throws BuildException { + if (basedir == null) { + basedir = getProject().getBaseDir(); + } + + if (infile == null) { + throw new BuildException("no infile specified", getLocation()); + } + + try { + executeTema(); + } catch (IOException e) { + throw new BuildException(e); + } catch (TemplateException e) { + throw new BuildException(e); + } + } + + private void executeTema() throws IOException, TemplateException { + TemplateParser parser = new TemplateParser(basedir); + + for (Variable var : variables) { + if (var.name == null) { + throw new BuildException( + "no name specified for variable", getLocation()); + } + + if (var.value == null) { + throw new BuildException( + "no value specified for variable", getLocation()); + } + + parser.getContext().set(var.name, var.value); + } + + TemplateReader in = new TemplateReader( + new BufferedReader(new FileReader(infile)), + infile.getName()); + try { + Writer out; + + if (outfile != null) { + out = new BufferedWriter(new FileWriter(outfile)); + } else { + out = NullWriter.INSTANCE; + } + + try { + parser.parse(in, out); + } finally { + out.close(); + } + } finally { + in.close(); + } + } + + public void setBasedir(File basedir) { + this.basedir = basedir; + } + + public void setInfile(File infile) { + this.infile = infile; + } + + public void setOutfile(File outfile) { + this.outfile = outfile; + } + + public void addVariable(Variable variable) { + variables.add(variable); + } +}
--- a/src/kryshen/tema/demo/DemoFrame.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/demo/DemoFrame.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,181 +1,228 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: DemoFrame.java,v 1.3 2006/12/14 15:59:48 mikhail Exp $ + * $Id: DemoFrame.java,v 1.13 2008/02/16 17:38:03 mikhail Exp $ */ package kryshen.tema.demo; -import java.awt.*; -import java.awt.event.*; -import java.io.*; +import java.awt.Button; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; import java.net.URL; - -import kryshen.tema.*; +import kryshen.tema.TemplateParser; +import kryshen.tema.io.TemplateReader; /** - * TEMA demonstation console. + * Tema demonstation console. */ public class DemoFrame extends Frame { + private static final Font TEXT_FONT = + new Font("monospaced", Font.PLAIN, 12); + private TextArea input; private TextArea output; private TextArea error; + private String sample; + public DemoFrame() { - super("TEMA demo console"); - + super("Tema demo console"); + GridBagLayout gbl = new GridBagLayout(); - + GridBagConstraints c = new GridBagConstraints(); - + setLayout(gbl); - - input = new TextArea(25, 40); + + input = new TextArea(28, 50); input.setEditable(true); - - output = new TextArea(25, 40); + input.setFont(TEXT_FONT); + + output = new TextArea(28, 50); output.setEditable(false); - - error = new TextArea(5, 80); + output.setFont(TEXT_FONT); + + error = new TextArea(5, 90); error.setEditable(false); - + error.setFont(TEXT_FONT); + Label l; - + c.insets = new Insets(3, 3, 3, 3); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.RELATIVE; - - l = new Label("Enter your code and click \"Process\"."); - + + l = new Label("Enter your code and press \"Process\"."); + gbl.setConstraints(l, c); add(l); - + Panel buttons = new Panel(); buttons.setLayout(new FlowLayout(FlowLayout.LEFT)); Button process = new Button("Process"); Button clear = new Button("Clear"); + Button reset = new Button("Reset"); Button close = new Button("Close"); - + buttons.add(process); buttons.add(clear); + buttons.add(reset); buttons.add(close); - - c.gridwidth = GridBagConstraints.REMAINDER; - + + c.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(buttons, c); add(buttons); - + c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.gridwidth = GridBagConstraints.RELATIVE; - + l = new Label("Input:"); - + gbl.setConstraints(l, c); add(l); - - c.gridwidth = GridBagConstraints.REMAINDER; - + + c.gridwidth = GridBagConstraints.REMAINDER; + l = new Label("Output:"); - + gbl.setConstraints(l, c); add(l); - - c.gridwidth = GridBagConstraints.RELATIVE; - + + c.gridwidth = GridBagConstraints.RELATIVE; + c.weightx = 1.0; + c.weighty = 1.0; + gbl.setConstraints(input, c); add(input); - - c.gridwidth = GridBagConstraints.REMAINDER; - + + c.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(output, c); add(output); - + + c.weightx = 0.0; + c.weighty = 0.0; + l = new Label("Errors:"); - + gbl.setConstraints(l, c); add(l); - + + c.weightx = 1.0; + c.weighty = 0.25; + gbl.setConstraints(error, c); - add(error); - + add(error); + process.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - process(); - } - }); - + public void actionPerformed(ActionEvent e) { + process(); + } + }); + clear.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - error.setText(""); - output.setText(""); - input.setText(""); - - } - }); - + public void actionPerformed(ActionEvent e) { + error.setText(""); + output.setText(""); + input.setText(""); + input.requestFocus(); + } + }); + + reset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + error.setText(""); + output.setText(""); + input.setText(sample); + } + }); + close.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - dispose(); - } - }); - + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - dispose(); - } - }); + public void windowClosing(WindowEvent e) { + dispose(); + } + }); URL source = getClass().getResource("demo.template"); StringBuffer buffer = new StringBuffer(); - + try { Reader in = new BufferedReader - (new InputStreamReader(source.openStream(), "UTF-8")); + (new InputStreamReader(source.openStream(), "UTF-8")); for (int ch = in.read(); ch >= 0; ch = in.read()) { buffer.append((char)ch); } - + in.close(); } catch (IOException e) { e.printStackTrace(); } - input.setText(buffer.toString()); + sample = buffer.toString(); + + input.setText(sample); } - + private void process() { String s = input.getText(); - TemplateReader tr = new TemplateReader - (new LineNumberReader(new StringReader(s)), "input"); + TemplateReader tr = new TemplateReader(new StringReader(s), "input"); TemplateParser tp = new TemplateParser(); StringWriter sw = new StringWriter(); - + error.setText(""); - + try { tp.parse(tr, sw); } catch (Exception e) { error.setText(e.toString()); + e.printStackTrace(); } - + output.setText(sw.toString()); } }
--- a/src/kryshen/tema/demo/Hello.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/demo/Hello.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,21 +1,23 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: Hello.java,v 1.2 2006/12/14 14:39:24 mikhail Exp $ + * $Id: Hello.java,v 1.9 2008/02/16 17:56:34 mikhail Exp $ */ package kryshen.tema.demo; @@ -27,7 +29,7 @@ /** * Example function implementation. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class Hello extends Function { public Hello() {} @@ -36,8 +38,6 @@ throws IOException, TemplateException { out.write("Hello, "); - fdp.parseData(out); - - return 1; + return fdp.parseData(out); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/Control.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,166 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: Control.java,v 1.18 2008/02/19 16:21:00 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.TemplateException; +import kryshen.tema.TemplateParser; +import kryshen.tema.io.NullWriter; +import kryshen.tema.io.TemplateReader; + +/** + * Logical and conditional functions. + * + * @author Mikhail Kryshen + */ +public class Control { + + /** + * Copy input to output and return zero value. + */ + public static final Function FALSE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + if (fdp.hasMoreData()) + fdp.parseData(out); + + return 0; + } + }; + + /** + * Copy input to output and return non-zero value. + */ + public static final Function TRUE = + new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + if (fdp.hasMoreData()) + fdp.parseData(out); + + return 1; + } + }; + + /** + * Outputs it's data if it has non-zero value. + */ + public static final Function OPTIONAL = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + StringWriter sw = new StringWriter(); + int s = fdp.parseData(sw); + sw.close(); + String data = sw.toString(); + + if (s != 0) { + out.write(data); + return 1; + } else { + return 0; + } + } + }; + + /** + * Logical negation (applied to the return value). + */ + public static final Function NOT = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + return (fdp.parseData(out) == 0) ? 1 : 0; + } + }; + + public static final Function IF = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + int value = fdp.parseNextArg(NullWriter.INSTANCE); + + if (value != 0) { + return fdp.parseData(out); + } + + return 0; + } + }; + + public static final Function IF_ELSE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + int value = fdp.parseNextArg(NullWriter.INSTANCE); + + if (value != 0) { + return fdp.parseNextArg(out); + } else { + fdp.skipNextArg(); + return fdp.parseData(out); + } + } + }; + + /** + * Outputs it's evaluated data while the evaluation result is non-zero. + */ + public static final Function WHILE = new Function() { + public int invoke(FunctionDataParser fdp, final Writer out) + throws IOException, TemplateException { + + String data = fdp.getData(); + StringReader dataReader = new StringReader(data); + + TemplateParser parser = fdp.getTemplateParser(); + + int r = 0; // summarized return value + int e = 0; // evaluation value + + while (true) { + StringWriter sw = new StringWriter(); + + e = parser.parse(new TemplateReader(dataReader), sw); + + if (e == 0) + break; + + r += Math.abs(e); + out.write(sw.toString()); + dataReader.reset(); + } + + dataReader.close(); + return r; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/Database.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,208 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: Database.java,v 1.12 2008/02/17 23:58:01 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import kryshen.tema.Context; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.TemplateException; +import kryshen.tema.TemplateParser; +import kryshen.tema.io.TemplateReader; + +/** + * Data access functions. + * + * @author Mikhail Kryshen + */ +public class Database { + /* db_connect:connection_name resource */ + public static final Function CONNECT = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String data = fdp.getData(); + + Connection connection; + + try { + connection = DriverManager.getConnection(data); + } catch (SQLException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } + + fdp.getContext().set(arg0, connection); + + out.write(arg0); + return 1; + } + }; + + /* db_prepare:qury_name connection sql_statement */ + public static final Function PREPARE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); // resulting variable + String arg1 = fdp.getNextArg(); // connection + String data = fdp.getData(); // statement + + Connection connection; + PreparedStatement statement; + + try { + connection = (Connection) fdp.getContext().get(arg1); + statement = connection.prepareStatement(data); + } catch (ClassCastException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } catch (SQLException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } + + fdp.getContext().set(arg0, statement); + + out.write(arg0); + return 1; + } + }; + + /* db_query:sql_query template arg1 arg2 ... argN */ + public static final Function QUERY = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String query = fdp.getNextArg(); + String template = fdp.getNextArg(); + List<String> args = fdp.getArgs(); + + TemplateParser tp = fdp.getTemplateParser(); + Context context = fdp.getContext(); + + try { + PreparedStatement statement = + (PreparedStatement) context.get(query); + return query(template, fdp.getTemplateReader(), + statement, args, tp, out); + } catch (ClassCastException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } catch (SQLException e) { + throw new TemplateException + (e.getMessage(), e, fdp.getTemplateReader()); + } + } + }; + + /** + * Process database query. + * + * @param template template to fill with data. + * @param parentReader parent TemplateReader. + * @param ps query statement to execute. + * @param args list of query parameters. + * @param superParser invoking object. + * @param out Writer to output processed data. + * + * @return number of processed rows in query result. + */ + private static int query(String template, + TemplateReader parentReader, + PreparedStatement ps, + List<String> args, + TemplateParser superParser, + Writer out) + throws IOException, SQLException, TemplateException { + + int i = 1; + + for (String arg : args) { + ps.setString(i++, arg); + } + + ResultSet resultSet = ps.executeQuery(); + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + + String[] names = new String[columnCount]; + + for (int j = 0; j < columnCount; j++) { + names[j] = metaData.getColumnName(j + 1); + } + + final TemplateParser p = new TemplateParser(superParser); + final HashMap<String, Object> fields = new HashMap<String, Object>(); + + p.getContext().set("db", new Function() { + public int invoke(FunctionDataParser fdp, + final Writer out) + throws IOException, TemplateException { + + String name = fdp.getData(); + Object value = fields.get(name); + + return p.parseValue(value, out); + } + }); + + Reader input = new StringReader(template); + + for (i = 1; resultSet.next(); i++) { + + for (int j = 0; j < columnCount; j++) { + Object value = resultSet.getObject(j + 1); + if (resultSet.wasNull()) value = null; + + fields.put(names[j], value); + } + + p.getContext().set("db_row", i); + + TemplateReader tr = new TemplateReader(input, parentReader); + + p.parse(tr, out); + + input.reset(); + fields.clear(); + } + + resultSet.close(); + input.close(); + ps.clearParameters(); + return i - 1; + } +}
--- a/src/kryshen/tema/functions/Define.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/functions/Define.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,84 +1,126 @@ /* - * Copyright (C) 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: Define.java,v 1.7 2006/12/14 14:35:00 mikhail Exp $ + * $Id: Define.java,v 1.25 2008/02/17 23:58:01 mikhail Exp $ */ package kryshen.tema.functions; -import java.io.*; -import java.util.*; - -import kryshen.tema.*; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import kryshen.tema.Context; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.TemplateException; +import kryshen.tema.TemplateParser; +import kryshen.tema.io.TemplateReader; /** * Define function implementation. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class Define extends Function { public static final Function DEFINE = new Define(); - + public Define() { } - + public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { + throws IOException, TemplateException { + + StringWriter nameWriter = new StringWriter(); + int r = fdp.parseNextArg(nameWriter); + + if (r == 0) + return 0; - final String arg0 = fdp.getNextArg(); - final String data = fdp.getData(); - + StringWriter dataWriter = new StringWriter(); + r = fdp.parseData(dataWriter); + + if (r == 0) + return 0; + + final String name = nameWriter.toString(); + final String data = dataWriter.toString(); + Function newFunction = new Function() { - public int invoke(final FunctionDataParser fdp, final Writer out) - throws IOException, TemplateException { - - TemplateParser functionParser = - new TemplateParser(fdp.getTemplateParser()); - - functionParser.registerFunction - ("nextarg", new Function() { - public int invoke(FunctionDataParser unusedFdp, - final Writer out) - throws IOException, TemplateException { - - return fdp.parseNextArg(out); - } - }); - - functionParser.registerFunction - ("data",new Function() { - public int invoke(FunctionDataParser unusedFdp, - final Writer out) - throws IOException, TemplateException { - - return fdp.parseData(out); - } - }); - - TemplateReader dataReader = new TemplateReader - (new StringReader(data), fdp.getTemplateReader()); - - return functionParser.parse(dataReader, out); - } - }; - - fdp.getTemplateParser().registerFunction(arg0, newFunction); - - out.write(arg0); - return 1; + public int invoke(final FunctionDataParser fdp1, final Writer out) + throws IOException, TemplateException { + + final TemplateParser functionParser = + new TemplateParser(fdp1.getTemplateParser()); + + final Context functionContext = + functionParser.getContext(); + + functionContext.set + ("next_arg", new Function() { + public int invoke(FunctionDataParser unusedFdp, + final Writer out) + throws IOException, TemplateException { + + if (fdp1.hasMoreData()) + return fdp1.parseNextArg(out); + + return 0; + } + }); + + functionContext.set + ("data", new Function() { + public int invoke(FunctionDataParser unusedFdp, + final Writer out) + throws IOException, TemplateException { + + return fdp1.parseData(out); + } + }); + + functionContext.set + ("has_more_data", new Function() { + public int invoke(FunctionDataParser unusedFdp, + final Writer out) + throws IOException, TemplateException { + + if (fdp1.hasMoreData()) { + out.write("true"); + return 1; + } + + out.write("false"); + return 0; + } + }); + + TemplateReader dataReader = new TemplateReader + (new StringReader(data), fdp1.getTemplateReader()); + + return functionParser.parse(dataReader, out); + } + }; + + fdp.getContext().set(name, newFunction); + + out.write(name); + return r; } }
--- a/src/kryshen/tema/functions/IO.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/functions/IO.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,133 +1,168 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: IO.java,v 1.4 2006/12/14 15:59:49 mikhail Exp $ + * $Id: IO.java,v 1.19 2008/02/19 16:21:00 mikhail Exp $ */ package kryshen.tema.functions; -import java.io.*; -import java.util.*; - -import kryshen.tema.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.Tema; +import kryshen.tema.TemplateException; +import kryshen.tema.io.TemplateReader; /** * I/O functions. */ public class IO { - public static final Function COPY = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - - File source = new File - (Tema.getProperty("resource_base"), arg0); - File dest = new File(arg1); - - try { - copyFile(source, dest); - } catch (IOException e) { - System.err.println(e); - return 0; - } - out.write(arg1); - return 1; + /** + * Copy files. + */ + public static final Function COPY = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + + File source = fdp.createFile(arg0); + File dest = fdp.createFile(arg1); + + try { + copyFile(source, dest); + } catch (IOException e) { + System.err.println(e); + return 0; + } + out.write(arg1); + return 1; + } + }; + + /** + * Write data to file. + */ + public static final Function WRITE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + + System.err.println("Writing " + arg0 + "..."); + + Writer fw; + + try { + fw = Tema.createFileWriter(fdp.createFile(arg0)); + } catch (IOException e) { + System.err.println(e); + //throw new TemplateException(e.getMessage(), e, in); + return 0; + } + + try { + fdp.parseData(fw); + } finally { + fw.close(); } - }; - - public static final Function WRITE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - - System.err.println("Writing " + arg0 + "..."); - - Writer fw; - - try { - fw = Tema.createFileWriter(arg0); - } catch (IOException e) { - System.err.println(e); - //throw new TemplateException(e.getMessage(), e, in); - return 0; - } - - try { - fdp.parseData(fw); - } finally { - fw.close(); - } - - out.write(arg0); - - System.err.println("Saved " + arg0 + "."); - return 1; + + out.write(arg0); + + return 1; + } + }; + + /** + * Read from file. + */ + public static final Function READ = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String filename = fdp.getData(); + String file; + + try { + readFile(fdp.createFile(filename), out); + } catch (IOException e) { + System.err.println(e); + //throw new TemplateException(e.getMessage(), e, in); + return 0; } - }; - - public static final Function READ = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String filename = fdp.getData(); - String file; - - try { - file = Tema.readFile(new File(filename)); - } catch (IOException e) { - System.err.println(e); - //throw new TemplateException(e.getMessage(), e, in); - return 0; - } - - out.write(file); - return 1; + + return 1; + } + }; + + /** + * Evaluate the code read from file. + */ + public static final Function INCLUDE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String filename = fdp.getData(); + + TemplateReader fin; + + try { + fin = Tema.createTemplateReader(fdp.createFile(filename)); + } catch (IOException e) { + throw new TemplateException(e.getMessage(), e, + fdp.getTemplateReader()); } - }; - - public static final Function INCLUDE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String filename = fdp.getData(); - - TemplateReader fin; - - try { - fin = Tema.createTemplateReader(new File(filename)); - } catch (IOException e) { - throw new TemplateException(e.getMessage(), e, - fdp.getTemplateReader()); - } - - int r = fdp.getTemplateParser().parse(fin, out); - - fin.close(); - return r; - } - }; - + + int r = fdp.getTemplateParser().parse(fin, out); + + fin.close(); + return r; + } + }; + + /** + * Create path from base path and file name. + */ + public static final Function FILE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String base = fdp.getNextArg(); + String name = fdp.getNextArg(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + out.write((new File(fdp.createFile(base), name)).getPath()); + + return fdp.getLastReturnCode(); + } + }; + /** * Update file (copy if newer). * @@ -137,27 +172,51 @@ * @trows IOException on copying error. */ private static void copyFile(File src, File dest) throws IOException { - System.err.print("Copying " + src + "... "); - - if (src.lastModified() < dest.lastModified()) { - System.err.println(dest + " is up to date."); - return; - } - - File parent = dest.getParentFile(); - if (parent != null) parent.mkdirs(); - + System.err.print("Copying " + src + "... "); + + if (src.lastModified() < dest.lastModified()) { + System.err.println(dest + " is up to date."); + return; + } + + File parent = dest.getParentFile(); + if (parent != null) parent.mkdirs(); + InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); + copy(in, out); + + in.close(); + out.close(); + } + + private static void copy(InputStream in, OutputStream out) + throws IOException { + byte[] buffer = new byte[1024]; int len; + while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } - in.close(); - out.close(); - - System.err.println("saved " + dest + "."); + } + + private static void copy(Reader in, Writer out) + throws IOException { + + char[] buffer = new char[1024]; + int len; + + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + } + + private static void readFile(File src, Writer out) + throws IOException { + + Reader in = Tema.createFileReader(src); + copy(in, out); } }
--- a/src/kryshen/tema/functions/ImageConverter.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/functions/ImageConverter.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,21 +1,23 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: ImageConverter.java,v 1.4 2006/12/14 19:44:32 mikhail Exp $ + * $Id: ImageConverter.java,v 1.13 2008/02/16 17:56:34 mikhail Exp $ */ package kryshen.tema.functions; @@ -33,11 +35,11 @@ /** * Convert images to specified format. * - * @author Mikhail A. Kryshen + * @author Mikhail Kryshen */ public class ImageConverter extends Function { - public static final Function IMAGE = new ImageConverter(); + public static final Function CONVERT_IMAGE = new ImageConverter(); public int invoke(FunctionDataParser fdp, Writer out) throws IOException, TemplateException { @@ -49,14 +51,11 @@ Integer.parseInt(fdp.getNextArg()) : -1; int arg4 = fdp.hasMoreData() ? Integer.parseInt(fdp.getNextArg()) : -1; - - File source = new File - (Tema.getProperty("resource_base"), arg0); - + try { convert - (source, /* source file */ - new File(arg1), /* dest file */ + (fdp.createFile(arg0), /* source file */ + fdp.createFile(arg1), /* dest file */ arg2, /* format */ arg3, /* max width */ arg4); /* max height */
--- a/src/kryshen/tema/functions/Logics.java Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2006 Mikhail A. Kryshen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: Logics.java,v 1.6 2006/12/14 14:39:26 mikhail Exp $ - */ - -package kryshen.tema.functions; - -import java.io.*; -import java.util.*; - -import kryshen.tema.*; - -/** - * Logical and conditional functions. - * - * @author Mikhail A. Kryshen - */ -public class Logics { - public static final Function FALSE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - fdp.parseData(out); - return 0; - } - }; - - public static final Function TRUE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - fdp.parseData(out); - return 1; - } - }; - - /** - * Outputs it's data it has non-zero value. - */ - public static final Function OPTIONAL = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - StringWriter sw = new StringWriter(); - int s = fdp.parseData(sw); - sw.close(); - String data = sw.toString(); - - if (s != 0) { - out.write(data); - return 1; - } else { - return 0; - } - } - }; -}
--- a/src/kryshen/tema/functions/ReplaceWriter.java Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2006 Mikhail A. Kryshen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: ReplaceWriter.java,v 1.2 2006/12/14 14:39:26 mikhail Exp $ - */ - -package kryshen.tema.functions; - -import java.io.Writer; -import java.io.FilterWriter; -import java.io.IOException; - -import java.util.LinkedList; -import java.util.Iterator; - -/** - * FilterWriter which replaces characters with escape strings. - * - * @author Mikhail A. Kryshen - */ -class ReplaceWriter extends FilterWriter { - private String[] patterns; - private String[] replaces; - - private String prefix; - private String postfix; - - private int maxPatternLength = 0; - - /** Have this Writer processed any data? */ - private boolean processedData = false; - - private StringBuffer buffer = new StringBuffer(); - - public ReplaceWriter(Writer w, String pattern, String replace) { - this(w, new String[]{pattern}, new String[]{replace}); - } - - public ReplaceWriter(Writer w, String pattern, String replace, - String prefix, String postfix) { - - this(w, new String[]{pattern}, new String[]{replace}, - prefix, postfix); - } - - public ReplaceWriter(Writer w, String[] patterns, String[] replaces) { - this(w, patterns, replaces, null, null); - } - - public ReplaceWriter(Writer w, String[] patterns, String[] replaces, - String prefix, String postfix) { - super(w); - - this.patterns = patterns; - this.replaces = replaces; - - this.prefix = prefix; - this.postfix = postfix; - - for (int i = 0; i < patterns.length; i++) { - int length = patterns[i].length(); - if (length > maxPatternLength) - maxPatternLength = length; - } - } - - private boolean processBuffer(int minLength) throws IOException { - if (buffer.length() == 0) return false; - - if (!processedData) { - if (prefix != null) - super.write(prefix, 0, prefix.length()); - processedData = true; - } - - int k; - for (k = 0; minLength + k < buffer.length(); k++) { - for (int i = 0; i < patterns.length; i++) { - String pattern = patterns[i]; - int length = pattern.length(); - - if (length + k > buffer.length()) - continue; - - boolean match = true; - - for (int j = 0; j < length; j++) { - if (pattern.charAt(j) != buffer.charAt(j + k)) { - match = false; - break; - } - } - - if (match) { - super.write(buffer.substring(0, k), 0, k); - buffer.delete(0, k + length); - super.write(replaces[i], 0, replaces[i].length()); - return true; - } - } - } - - super.write(buffer.substring(0, k), 0, k); - buffer.delete(0, k); - - return false; - } - - public void write(int c) throws IOException { - buffer.append((char)c); - processBuffer(maxPatternLength); - } - - public void write(char[] cbuf, int off, int len) throws IOException { - for (int i = off; i < off + len; i++) { - buffer.append(cbuf[i]); - } - processBuffer(maxPatternLength); - } - - public void write(String str, int off, int len) throws IOException { - buffer.append(str.substring(off, off + len)); - processBuffer(maxPatternLength); - } - - public void finish() throws IOException { - while (processBuffer(0)); - -// super.write(buffer.toString(), 0, buffer.length()); -// buffer.delete(0, buffer.length()); - - if (processedData && postfix != null) - super.write(postfix, 0, postfix.length()); - } - - public void close() throws IOException { - finish(); - super.close(); - } -}
--- a/src/kryshen/tema/functions/Standard.java Thu Dec 14 23:22:05 2006 +0300 +++ b/src/kryshen/tema/functions/Standard.java Tue Feb 19 20:32:17 2008 +0300 @@ -1,258 +1,259 @@ /* - * Copyright (C) 2005, 2006 Mikhail A. Kryshen + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * Tema is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. * - * $Id: Standard.java,v 1.5 2006/12/14 14:39:26 mikhail Exp $ + * $Id: Standard.java,v 1.34 2008/02/19 17:32:17 mikhail Exp $ */ package kryshen.tema.functions; -import java.io.*; -import java.util.*; -import java.net.*; - -import java.sql.SQLException; -import java.sql.PreparedStatement; - -import kryshen.tema.*; +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import kryshen.tema.Context; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.Tema; +import kryshen.tema.TemplateException; +import kryshen.tema.io.NullWriter; /** * Standard TEMA functions. */ public class Standard { - public static final Function SET = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getData(); - - fdp.getTemplateParser().setValue(arg0, arg1); + + /** + * Output Tema version. + */ + public static final Function TEMA = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + out.write(Tema.TITLE + " " + Tema.VERSION + /*+ " by " + Tema.AUTHOR*/); + return 1; + } + }; + + /** + * Define static variable. + */ + public static final Function SET = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String name = fdp.getNextArg(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + String data = fdp.getData(out); + fdp.getContext().set(name, data); + + return fdp.getLastReturnCode(); + } + }; + + /** + * Recursively remove definition. + */ + public static final Function UNSET = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + int r = 0; + + while (fdp.hasMoreData()) { + String name = fdp.getNextArg(); - out.write(arg0); - return 1; - } - }; - - /* prepare:qury_name sql_statement */ - public static final Function PREPARE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String data = fdp.getData(); - - PreparedStatement statement; - - try { - statement = Tema.getDbConnection() - .prepareStatement(data); - } catch (SQLException e) { - throw new TemplateException - (e.getMessage(), e, fdp.getTemplateReader()); - } + if (fdp.getLastReturnCode() == 0) + continue; - fdp.getTemplateParser().setValue(arg0, statement); - - out.write(arg0); - return 1; - } - }; - - /* query:sql_query template arg1 arg2 ... argN */ - public static final Function QUERY = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - List<String> args = fdp.getArgs(); - - TemplateParser tp = fdp.getTemplateParser(); - - TemplateReader tr = - new TemplateReader(new StringReader(arg1), - fdp.getTemplateReader()); - - try { - return Tema.query - (tr, (PreparedStatement)tp.getValue(arg0), - args, tp, out); - } catch (SQLException e) { - throw new TemplateException - (e.getMessage(), e, fdp.getTemplateReader()); - } + if (fdp.getContext().unset(name)) + r++; } - }; - - public static final Function REPLACE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - String arg0 = fdp.getNextArg(); - String arg1 = fdp.getNextArg(); - - ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; - } - }; - - public static final Function LOAD = - - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) + + return r; + } + }; + + /** + * Export variable to the global (outermost) context. + */ + public static final Function EXPORT = new Function() { + public int invoke(FunctionDataParser fdp, + final Writer out) throws IOException, TemplateException { - - final String name = fdp.getNextArg(); - final String className = fdp.getNextArg(); - - List<URL> urls = new ArrayList<URL>(1); - - while (fdp.hasMoreData()) { - urls.add(new URL(fdp.getNextArg())); - } + + String name = fdp.getNextArg(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + // Set and export. + if (fdp.hasMoreData()) { + Object value = fdp.getData(out); - ClassLoader loader = this.getClass().getClassLoader(); - - if (urls.size() > 0) { - loader = new URLClassLoader - (urls.toArray(new URL[0]), loader); - } - - Class<Function> functionClass; - Function function; - - try { - functionClass = loadFunctionClass(loader, className); - } catch (ClassNotFoundException e) { - throw new TemplateException - ("Class not found", e, fdp.getTemplateReader()); - } catch (ClassCastException e) { - throw new TemplateException - ("Not a function class", e, fdp.getTemplateReader()); - } - - try { - function = functionClass.newInstance(); - } catch (InstantiationException e) { - throw new TemplateException - ("Could not load class", e, fdp.getTemplateReader()); - } catch (IllegalAccessException e) { - throw new TemplateException - ("Could not load class", e, fdp.getTemplateReader()); - } - - fdp.getTemplateParser().registerFunction(name, function); - - + fdp.getContext().export(name, value); + return fdp.getLastReturnCode(); + } + + // Only export. + if (fdp.getContext().export(name)) { out.write(name); return 1; } - }; - - public static final Function NULL_OUTPUT = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { + + return 0; + } + }; + + /** + * Copy macro definitions. + */ + public static final Function ASSIGN = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { - /* Write nothing. */ - return fdp.parseData(new Writer() { - public void close() {} - public void flush() {} - public void write(char[] cbuf, int off, int len) {} - }); - } - }; + String name1 = fdp.getNextArg(); - public static final Function XML_ESCAPE = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { + if (fdp.getLastReturnCode() == 0) + return 0; + + String name2 = fdp.getData(); + + if (fdp.getLastReturnCode() == 0) + return 0; - final String[] chars = {"&", "<", ">", "`", "\""}; - final String[] escape = {"&", "<", ">", "'", """}; - - ReplaceWriter rw = new ReplaceWriter(out, chars, escape); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; - } - }; - - public static final Function XML_CDATA = - new Function() { - public int invoke(FunctionDataParser fdp, Writer out) - throws IOException, TemplateException { - - ReplaceWriter rw = new ReplaceWriter - (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>"); - - int ret = fdp.parseData(rw); - rw.finish(); - return ret; + Context context = fdp.getContext(); + Object value = context.get(name2); + + if (value == null) + return 0; + + context.set(name1, value); + + return 1; + } + }; + + /** + * Invoke function specified by name. + */ + public static final Function INVOKE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String name = fdp.getNextArg(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + return fdp.getTemplateParser().invoke(name, fdp, out); + } + }; + + /** + * Create definiton as a new Java object. + */ + public static final Function LOAD = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + final String name = fdp.getNextArg(); + final String className = fdp.getNextArg(); + + List<URL> urls = new ArrayList<URL>(1); + + while (fdp.hasMoreData()) { + urls.add(new URL(fdp.getNextArg())); } - }; - - - @SuppressWarnings("unchecked") - private static Class<Function> loadFunctionClass - (ClassLoader loader, String className) - throws ClassNotFoundException { - - return (Class<Function>)loader.loadClass(className); - } - + + ClassLoader loader = this.getClass().getClassLoader(); + + if (urls.size() > 0) { + loader = new URLClassLoader + (urls.toArray(new URL[0]), loader); + } + + Class<?> loadedClass; + Object instance; + + try { + loadedClass = loader.loadClass(className); + } catch (ClassNotFoundException e) { + throw new TemplateException + ("Class not found", e, fdp.getTemplateReader()); + } + + try { + instance = loadedClass.newInstance(); + } catch (InstantiationException e) { + throw new TemplateException + ("Could not load class", e, fdp.getTemplateReader()); + } catch (IllegalAccessException e) { + throw new TemplateException + ("Could not load class", e, fdp.getTemplateReader()); + } + + fdp.getContext().set(name, instance); + + out.write(name); + return 1; + } + }; + + public static final Function ECHO = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + if (!fdp.hasMoreData()) + return 0; + + return fdp.parseData(out); + } + }; + /** - * Update file (copy if newer). - * - * @param src source file. - * @param dest destination file. - * - * @trows IOException on copying error. + * Process arguments, but output nothing. */ - private static void copyFile(File src, File dest) throws IOException { - System.err.print("Copying " + src + "... "); - - if (src.lastModified() < dest.lastModified()) { - System.err.println(dest + " is up to date."); - return; - } - - File parent = dest.getParentFile(); - if (parent != null) parent.mkdirs(); - - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dest); - - byte[] buffer = new byte[1024]; - int len; - while ((len = in.read(buffer)) > 0) { - out.write(buffer, 0, len); + public static final Function SILENT = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + if (!fdp.hasMoreData()) + return 0; + + return fdp.parseData(NullWriter.INSTANCE); } - in.close(); - out.close(); - - System.err.println("saved " + dest + "."); - } + }; + + /** + * Skip arguments. + */ + public static final Function SKIP = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + // Ignore arguments. + return 0; + } + }; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/functions/Strings.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,225 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: Strings.java,v 1.13 2008/02/16 17:38:03 mikhail Exp $ + */ + +package kryshen.tema.functions; + +import java.io.IOException; +import java.io.Writer; +import kryshen.tema.Function; +import kryshen.tema.FunctionDataParser; +import kryshen.tema.TemplateException; +import kryshen.tema.io.ReplaceWriter; + +/** + * Functions for string manipulation. + */ +public class Strings { + public static final Function TO_UPPER = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String data = fdp.getData(); + out.write(data.toUpperCase()); + return fdp.getLastReturnCode(); + } + }; + + public static final Function TO_LOWER = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String data = fdp.getData(); + out.write(data.toLowerCase()); + return fdp.getLastReturnCode(); + } + }; + + public static final Function SUBSTRING = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String is = fdp.getNextArg(); + String js = fdp.getNextArg(); + + String data = fdp.getData(); + + try { + if (js.equals("$")) { + out.write(data.substring(Integer.parseInt(is))); + } else { + out.write(data.substring( + Integer.parseInt(is), + Integer.parseInt(js))); + } + } catch (NumberFormatException e) { + throw new TemplateException( + e.toString(), e, fdp.getTemplateReader()); + } catch (IndexOutOfBoundsException e) { + throw new TemplateException( + e.toString(), e, fdp.getTemplateReader()); + } + + return fdp.getLastReturnCode(); + } + }; + + public static final Function REPLACE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String arg0 = fdp.getNextArg(); + String arg1 = fdp.getNextArg(); + + ReplaceWriter rw = new ReplaceWriter(out, arg0, arg1); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + public static final Function XML_ESCAPE = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + final String[] chars = {"&", "<", ">", "`", "\""}; + final String[] escape = {"&", "<", ">", "'", """}; + + ReplaceWriter rw = new ReplaceWriter(out, chars, escape); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + public static final Function XML_CDATA = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + ReplaceWriter rw = new ReplaceWriter + (out, "]]>", "]]]><![CDATA[]>", "<![CDATA[", "]]>"); + + int ret = fdp.parseData(rw); + rw.finish(); + return ret; + } + }; + + public static final Function REGEX_MATCH = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String regex = fdp.getNextArg(); + String data = fdp.getData(out); + + if (data.matches(regex)) { + return 1; + } + + return 0; + } + }; + + public static final Function REGEX_REPLACE_FIRST = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String regex = fdp.getNextArg(); + String replacement = fdp.getNextArg(); + String data = fdp.getData(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + out.write(data.replaceFirst(regex, replacement)); + + return fdp.getLastReturnCode(); + } + }; + + public static final Function REGEX_REPLACE_ALL = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String regex = fdp.getNextArg(); + String replacement = fdp.getNextArg(); + String data = fdp.getData(); + + if (fdp.getLastReturnCode() == 0) + return 0; + + out.write(data.replaceAll(regex, replacement)); + + return fdp.getLastReturnCode(); + } + }; + + public static final Function EQUAL = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + String s1 = fdp.getNextArg(); + + while (fdp.hasMoreData()) { + String s2 = fdp.getNextArg(); + + if (!s1.equals(s2)) { + return 0; + } + + s1 = s2; + } + + return 1; + } + }; + + public static final Function CHAR = new Function() { + public int invoke(FunctionDataParser fdp, Writer out) + throws IOException, TemplateException { + + if (!fdp.hasMoreData()) + return 0; + + do { + String s = fdp.getNextArg(); + int code; + + try { + if (s.startsWith("0x")) { + code = Integer.parseInt(s.substring(2), 16); + } else { + code = Integer.parseInt(s); + } + } catch (NumberFormatException e) { + throw new TemplateException(e.getMessage(), e, + fdp.getTemplateReader()); + } + + out.write(code); + } while (fdp.hasMoreData()); + + return 1; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/io/CopyWriter.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,69 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: CopyWriter.java,v 1.7 2008/02/16 17:56:34 mikhail Exp $ + */ + +package kryshen.tema.io; + +import java.io.IOException; +import java.io.Writer; + +/** + * Copies it's output to several writers. + * + * @author Mikhail Kryshen + */ +public class CopyWriter extends Writer { + private final Writer[] writers; + + public CopyWriter(Writer... writers) { + this.writers = writers; + } + + public void write(char[] cbuf, int off, int len) throws IOException { + for (Writer w : writers) { + w.write(cbuf, off, len); + } + } + + public void write(int c) throws IOException { + for (Writer w : writers) { + w.write(c); + } + } + + public void write(String str, int off, int len) throws IOException { + for (Writer w : writers) { + w.write(str, off, len); + } + } + + public void flush() throws IOException { + for (Writer w : writers) { + w.flush(); + } + } + + public void close() throws IOException { + for (Writer w : writers) { + w.close(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/io/NullWriter.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,46 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: NullWriter.java,v 1.6 2008/02/16 17:38:03 mikhail Exp $ + */ + +package kryshen.tema.io; + +import java.io.Writer; + +/** + * No-op writer. + * + * @author Mikhail Kryshen + */ +public class NullWriter extends Writer{ + public static final NullWriter INSTANCE = new NullWriter(); + + private NullWriter() { + } + + public void close() { + } + + public void flush() { + } + + public void write(char[] cbuf, int off, int len) { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/io/ReplaceWriter.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,153 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: ReplaceWriter.java,v 1.8 2008/02/19 16:21:00 mikhail Exp $ + */ + +package kryshen.tema.io; + +import java.io.Writer; +import java.io.FilterWriter; +import java.io.IOException; + +/** + * FilterWriter which replaces characters with escape strings. + * + * @author Mikhail Kryshen + */ +public class ReplaceWriter extends FilterWriter { + private String[] patterns; + private String[] replaces; + + private String prefix; + private String postfix; + + private int maxPatternLength = 0; + + /** Have this Writer processed any data? */ + private boolean processedData = false; + + private StringBuffer buffer = new StringBuffer(); + + public ReplaceWriter(Writer w, String pattern, String replace) { + this(w, new String[]{pattern}, new String[]{replace}); + } + + public ReplaceWriter(Writer w, String pattern, String replace, + String prefix, String postfix) { + + this(w, new String[]{pattern}, new String[]{replace}, + prefix, postfix); + } + + public ReplaceWriter(Writer w, String[] patterns, String[] replaces) { + this(w, patterns, replaces, null, null); + } + + public ReplaceWriter(Writer w, String[] patterns, String[] replaces, + String prefix, String postfix) { + super(w); + + this.patterns = patterns; + this.replaces = replaces; + + this.prefix = prefix; + this.postfix = postfix; + + for (int i = 0; i < patterns.length; i++) { + int length = patterns[i].length(); + if (length > maxPatternLength) + maxPatternLength = length; + } + } + + private boolean processBuffer(int minLength) throws IOException { + if (buffer.length() == 0) return false; + + if (!processedData) { + if (prefix != null) + super.write(prefix, 0, prefix.length()); + processedData = true; + } + + int k; + for (k = 0; minLength + k < buffer.length(); k++) { + for (int i = 0; i < patterns.length; i++) { + String pattern = patterns[i]; + int length = pattern.length(); + + if (length + k > buffer.length()) + continue; + + boolean match = true; + + for (int j = 0; j < length; j++) { + if (pattern.charAt(j) != buffer.charAt(j + k)) { + match = false; + break; + } + } + + if (match) { + super.write(buffer.substring(0, k), 0, k); + buffer.delete(0, k + length); + super.write(replaces[i], 0, replaces[i].length()); + return true; + } + } + } + + super.write(buffer.substring(0, k), 0, k); + buffer.delete(0, k); + + return false; + } + + public void write(int c) throws IOException { + buffer.append((char)c); + processBuffer(maxPatternLength); + } + + public void write(char[] cbuf, int off, int len) throws IOException { + for (int i = off; i < off + len; i++) { + buffer.append(cbuf[i]); + } + processBuffer(maxPatternLength); + } + + public void write(String str, int off, int len) throws IOException { + buffer.append(str.substring(off, off + len)); + processBuffer(maxPatternLength); + } + + public void finish() throws IOException { + while (processBuffer(0)); + +// super.write(buffer.toString(), 0, buffer.length()); +// buffer.delete(0, buffer.length()); + + if (processedData && postfix != null) + super.write(postfix, 0, postfix.length()); + } + + public void close() throws IOException { + finish(); + super.close(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kryshen/tema/io/TemplateReader.java Tue Feb 19 20:32:17 2008 +0300 @@ -0,0 +1,102 @@ +/* + * Copyright 2006-2008 Mikhail Kryshen + * + * This file is part of Tema. + * + * Tema is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Tema is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the + * GNU Lesser General Public License along with Tema. + * If not, see <http://www.gnu.org/licenses/>. + * + * $Id: TemplateReader.java,v 1.8 2008/02/19 00:20:48 mikhail Exp $ + */ + +package kryshen.tema.io; + +import java.io.Reader; +import java.io.LineNumberReader; +import java.io.PushbackReader; +import kryshen.tema.TemplateParser; + +/** + * Reader for Tema templates. Stores data source name (commonly + * filename) and tracks line numbers for error reporting. + * + * @author Mikhail Kryshen + */ +public class TemplateReader extends PushbackReader { + static final int UNREAD_BUFFER_SIZE; + + /* Calculate UNREAD_BUFFER_SIZE value. */ + static { + int max = 0; + + for (String s : TemplateParser.BRACKET_OPEN) { + max = Math.max(max, s.length()); + } + + for (String s : TemplateParser.BRACKET_CLOSE) { + max = Math.max(max, s.length()); + } + + max = Math.max(max, TemplateParser.ESCAPE_NEWLINE.length() + 2); + max = Math.max(max, TemplateParser.ESCAPE_WHITESPACE.length()); + + UNREAD_BUFFER_SIZE = max; + } + + private final String source; + private final LineNumberReader lnReader; + private final TemplateReader parentReader; + + public TemplateReader(Reader in) { + this(new LineNumberReader(in)); + } + + public TemplateReader(Reader in, String source) { + this(new LineNumberReader(in), source); + } + + public TemplateReader(LineNumberReader in) { + this(in, ""); + } + + public TemplateReader(LineNumberReader in, String source) { + super(in, UNREAD_BUFFER_SIZE); + + this.parentReader = null; + this.lnReader = in; + this.source = source; + } + + public TemplateReader(Reader in, TemplateReader parent) { + super(in, UNREAD_BUFFER_SIZE); + + this.parentReader = parent; + this.lnReader = null; + this.source = null; + } + + public String getSource() { + if (source != null) + return source; + + return parentReader.getSource(); + } + + public int getLineNumber() { + if (lnReader != null) + return lnReader.getLineNumber(); + + return parentReader.getLineNumber(); + } +}
--- a/test/demo Thu Dec 14 23:22:05 2006 +0300 +++ b/test/demo Tue Feb 19 20:32:17 2008 +0300 @@ -1,4 +1,4 @@ #!/bin/sh #java -jar ../dist/tema.jar -java -classpath .:../dist/tema.jar kryshen.tema.Tema +java -classpath .:../dist/tema.jar kryshen.tema.Tema main.template
--- a/test/demo.bat Thu Dec 14 23:22:05 2006 +0300 +++ b/test/demo.bat Tue Feb 19 20:32:17 2008 +0300 @@ -1,1 +1,1 @@ -java -classpath .:..\dist\tema.jar kryshen.tema.Tema +java -classpath .:..\dist\tema.jar kryshen.tema.Tema main.template
--- a/test/include.template Thu Dec 14 23:22:05 2006 +0300 +++ b/test/include.template Tue Feb 19 20:32:17 2008 +0300 @@ -1,1 +1,1 @@ -<%define\test test arg1:[%nextarg:%], test arg2:[%nextarg:%], test data:[%data:%].%> \ No newline at end of file +<%define#test test arg1:<%next_arg:%>, test arg2:<%next_arg:%>, test data:<%data:%>.%> \ No newline at end of file
--- a/test/main.template Thu Dec 14 23:22:05 2006 +0300 +++ b/test/main.template Tue Feb 19 20:32:17 2008 +0300 @@ -1,4 +1,4 @@ -[%!\ UTF-8 text %] +[%!\ UTF-8 text %]\ Вывод текста: test text @@ -10,7 +10,7 @@ <%include:include.template%> Вызов новой функции: -<%test:1 2 3%> +<%test:1 2 3 4 5%> Тестирование read: <%read\include.template%>
--- a/test/tema.properties Thu Dec 14 23:22:05 2006 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -# Data source configuration -# resource : jdbc:odbc:database -# driver : sun.jdbc.odbc.JdbcOdbcDriver - -# Base directory for images and files -# resource_base : . - -# Template to start processing with -main_template : main.template - -# File encodings -input_encoding : UTF-8 -output_encoding : UTF-8 - -# Cache templates -# cache_read : true - -# Output main_template parsing result to stderr -# output : stderr - -# File to output error messages (redirect stderr) -# log : dbreader.log