/*
* JDynamiTe - Dynamic Template in Java
* Copyright (C) 2001 Christophe Bouleau
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package cb.jdynamite;
import java.util.*;
import java.io.*;
import cb.jdynamite.analyser.*;
/**
* JDynamiTe is the unique class you need to parse a template document.
* This implementation extends the DefaultDynamicElement class (from package analyser),
* so a JDynamiTe object is a "Dynamic Element".
* The use is very simple : <br>
* First define the input file or input stream (for example an HTML template document)
* with the "setInput" method.<br>
* Secondly fill and develop this document with a few methods such as "setVariable",
* and "parseDynElem".<br>
* Finally, after calling the "parse" method to finalize building your dynamic document,
* you simply obtain the result with the "toString" method.
* <br><br>
* See an example in the main method of this class.
* <br><br>
* <h3>JDynamiTe elements</h3>
* There are (only) two elements which make a document a "template" document.
* <br><br><b>1) "Variable Element"</b><br>
* A "Variable Element" is defined by an identifier in the template document.
* Its value can be changed with the JDynamiTe.setValue method.<br>
* Example of use: titles, values of cells in tables, etc.
* <br><br><b>2) "Dynamic Element"</b><br>
* A "Dynamic Element" is a "block" which can be dynamically developed.
* It has an identifier, a template definition, and a value.
* Its value can be set or developed with the JDynamiTe.parseDynElem and JDynamiTe.setDynElem methods.<br>
* Example of use: list, table, enumeration, etc.
* <br><br><br>
* <h3>Template document syntax</h3>
* There are only 3 tags to use JDynamiTe : "Variable" tag, "Begin Dynamic Element" tag, and
* "End Dynamic Element" tag. The tag syntax is defined by regular expressions, you can change it in the
* analyser.<br>
* By default JDynamiTe uses the "DefaultAnalyser" to parse the template documents.
* By default, this analyser uses HTML style tags.
* <br><br>
* <b>1) "Variable" tag:</b> <pre>
* {VARNAME} </pre>
* means you can use setVariable("VARNAME", aStringValue) in Java code.<br><br>
* <b>2) "Begin Dynamic Element" tag:</b> <pre>
* <!-- BEGIN DYNAMIC : dynElemName --> </pre>
* or <pre>
* <!-- BEGIN DYNAMIC BLOCK: dynElemName --> </pre>
* means the "dynElemName" Dynamic Element definition begins on the next line.
* <br><br>
* <b>3) "End Dynamic Element" tag:</b> <pre>
* <!-- END DYNAMIC : dynElemName --> </pre>
* or <pre>
* <!-- END DYNAMIC BLOCK: dynElemName --> </pre>
* means the "dynElemName" Dynamic Element definition ends on the previous line.
* <br><br>
* <b>Identifiers syntax (for Variables and Dynamic Elements):</b><br>
* By default, it is a word made up of alphanumeric characters and these four characters:
* '.', ':', '_' and '-'
*
* <br><br><br>
* <h3>New concept : "Ignored Element"</h3>
* Since JDynamiTe 1.1, this optional element can be used in template documents. An "Ignored Element" is
* a "block" which will be completly ignored (skipped during document analysis).<br>
* Example of use: it allows the HTML designer to build more realistic pages, with concrete data, giving a
* better idea of the possible dynamic page look and feel. An "Ignored Element" can be inserted anywhere in
* the template document, even inside "Dynamic Element".<br><br>
* <b>"Ignored Element" tags</b> <pre>
* <!-- BEGIN IGNORED : ignoredElemName --> </pre>
* means an ignored block (skipped during analysis and document output) begins on the next line.
* <br><pre>
* <!-- END IGNORED : ignoredElemName --> </pre>
* means this ignored block ends on the previous line.
*
* <br><br><br>
* <h3>JDynamiTe home page</h3>
* JDynamiTe latest versions, news, examples ... at <b>http://jdynamite.sourceforge.net</b>
* <br><br><br>
* @author Christophe Bouleau
*/
public class JDynamiTe extends DefaultDynamicElement implements ITemplateDocument, Serializable {
private Hashtable variables;
private Hashtable dynamics;
private ITemplateAnalyser analyser;
/**
* Constructs an empty "JDynamiTe" (Java Dynamic Template) document.
*/
public JDynamiTe() {
this("__topLevel__");
}
/**
* Constructs an empty "JDynamiTe" (Java Dynamic Template) document.
*
* @param name The name of this "JDynamiTe" document, used for debugging purposes by the
* "getTemplateDefinition" method.
*/
public JDynamiTe(String name) {
super(name);
variables = new Hashtable();
dynamics = new Hashtable();
recordDynElem(name, this);
}
/**
* Starts the analysis of the input template document.
* If no custom "ITemplateAnalyser" was defined, JDynamiTe uses the "DefaultAnalyser".
* After this step, all the Variables and Dynamic Elements are identified,
* so this JDynamiTe is ready to be developed.
* By default all Variables are set to an empty string value.
* In addition, Variable identifiers (keys) can be retreived by getVariablesKeys.
*
* @param reader A BufferedReader to read the input template document.
* @exception java.io.IOException If an I/O error occurs.
* @see setInput(java.io.InputStream)
* @see setInput(java.lang.String)
* @see cb.jdynamite.analyser.DefaultAnalyser
* @see setAnalyser(ITemplateAnalyser templateAnalyser)
* @since JDynamyTe 1.2
*/
public void setInput(BufferedReader reader) throws IOException {
if (analyser == null) {
analyser = new DefaultAnalyser();
}
analyser.analyse(this, this, reader);
}
/**
* Starts the analysis of the input template document.
* If no custom "ITemplateAnalyser" was defined, JDynamiTe uses the "DefaultAnalyser".
* After this step, all the Variables and Dynamic Elements are identified,
* so this JDynamiTe is ready to be developed.
* By default all Variables are set to an empty string value.
* In addition, Variable identifiers (keys) can be retreived by getVariablesKeys.
*
* @param istream A stream to read the input template document.
* @exception java.io.IOException If an I/O error occurs.
* @see setInput(java.io.BufferedReader)
* @see setInput(java.lang.String)
* @see cb.jdynamite.analyser.DefaultAnalyser
* @see setAnalyser(ITemplateAnalyser templateAnalyser)
*/
public void setInput(InputStream istream) throws IOException {
setInput(new BufferedReader(new InputStreamReader(istream)));
}
/**
* Starts the analysis of the input template document.
* If no custom "ITemplateAnalyser" was defined, JDynamiTe uses the "DefaultAnalyser".
* After this step, all the Variables and Dynamic Elements are identified,
* so this JDynamiTe is ready to be developed.
* By default all Variables are set to an empty string value.
* In addition, Variable identifiers (keys) can be retreived by getVariablesKeys.
*
* @param fileName The name of the file which contains the input template document.
* @exception java.io.IOException If an I/O error occurs.
* @exception java.io.FileNotFoundException Bad filename.
* @see setInput(java.io.BufferedReader)
* @see setInput(java.io.InputStream)
* @see cb.jdynamite.analyser.DefaultAnalyser
* @see setAnalyser(ITemplateAnalyser templateAnalyser)
*/
public void setInput(String fileName) throws IOException, FileNotFoundException {
FileReader fileReader = new FileReader(fileName);
setInput(new BufferedReader(fileReader));
fileReader.close();
}
/**
* Returns the value of a variable that was set by setVariable.
* A "JDynamiTe" document maintains a list of key/value pairs, which is used when
* Dynamic Elements are parsed.
*
* @param key The key of the variable to retrieve.
* @return The value of the variable.
* @see setVariable(java.lang.String, java.lang.String)
*/
public String getVariable(String key) {
return (String)variables.get(key);
}
/**
* Set the value of a variable.
* Overrides its previous value if any.
* A "JDynamiTe" document maintains a list of key/value pairs, which is used when
* Dynamic Elements are parsed.
*
* @param key The key of the variable to set.
* @param value The new value of this variable.
* @see getVariable(java.lang.String)
*/
public void setVariable(String key, String value) {
variables.put(key, value);
}
/**
* Returns an enumeration of the template Variable keys in this JDynamiTe document.
* A "JDynamiTe" document maintains a list of key/value pairs, which is used when
* Dynamic Elements are parsed.
* The setInput method build this list (with an empty string as default value)
* during the template document analysis. After this step, the setVariable method
* is used to set a value to a Variable.
* Example of use :
* <pre>
* Enumeration keys = myJDynamiTeDoc.getVariableKeys();
* while (keys.hasMoreElements()) {
* String key = keys.nextElement();
* System.err.println(keys);
* String value = myDatabase.selectValue(key); // get the current value somewhere...
* myJDynamiTeDoc.setVariable(key, value); // set the template Variable.
* }
* </pre>
*
* @return The value of the variable.
* @see setVariable(java.lang.String, java.lang.String)
* @see setInput(InputStream istream)
* @see setInput(String fileName)
* @since JDynamiTe 1.2
*/
public Enumeration getVariableKeys() {
return variables.keys();
}
/**
* Returns the "Dynamic Element" identified by a string
* (Note: You do not need to directly call this method to use JDynamiTe).
* A "JDynamiTe" document maintains a list of "Dynamic Elements".
*
* @param key The "Dynamic Element" identifier. This is the string defined in the
* template document in the "BEGIN DYNAMIC" tag. For example:<pre>
* <-- BEGIN DYNAMIC : myList -->
* </pre>
* Here "myList" identifies the Dynamic Element which begins.
* @return The interface of the Dynamic Element.
*/
public IDynamicElement getDynElem(String key) {
return (IDynamicElement)dynamics.get(key);
}
/**
* Records a "Dynamic Element" in this "JDynamiTe" Document
* (Note: You do not need to directly call this method to use JDynamiTe).
* A "JDynamiTe" document maintains a list of "Dynamic Elements".
* It is called by the analyser.
*
* @param key The "Dynamic Element" identifier.
* @param value An object that implements the IDynamicElement interface.
*/
public void recordDynElem(String key, IDynamicElement value) {
dynamics.put(key, value);
}
/**
* Returns the analyser that parses template documents
* (Note: You do not need to directly call this method to use JDynamiTe).
*
* @return The current analyser.
* @see setAnalyser(cb.jdynamite.analyser.ITemplateAnalyser)
*/
public ITemplateAnalyser getAnalyser() {
return analyser;
}
/**
* Set the analyser that parses template documents
* (Note: You do not need to directly call this method to use JDynamiTe).
*
* @param templateAnalyser The new analyser.
* @see getAnalyser()
*/
public void setAnalyser(ITemplateAnalyser templateAnalyser) {
analyser = templateAnalyser;
}
///////// utils
/**
* This is a "key" method you call to append elements to the current value of a Dynamic Element.
* These elements are built from the template definition of this Dynamic Element and the current value
* of variables (and possibly nested Dynamic Elements). See examples.
*
* @param elementName The "Dynamic Element" identifier. This is the string defined
* in the template document in the "BEGIN DYNAMIC" tag. For example:<pre>
* <-- BEGIN DYNAMIC : myList -->
* </pre>
* Here "myList" identifies the Dynamic Element that begins.
*/
public void parseDynElem(String elementName) {
IDynamicElement dynElem = getDynElem(elementName);
if (dynElem != null) {
dynElem.parse(this);
}
}
/**
* Set an arbitrary value to a Dynamic Element. For example, enables emptying a
* Dynamic Element if you give an empty string as argument.
*
* @param elementName The Dynamic Element identifier.
* @param value New value for The Dynamic Element
*/
public void setDynElemValue(String elementName, String value) {
IDynamicElement dynElem = getDynElem(elementName);
if (dynElem != null) {
dynElem.setValue(value);
}
}
/**
* Calls the parse method inherited from DefaultDynamicElement. As this object is the "top level"
* dynamic element, this method enables obtaining the "final" value of this document.
* You can use the "toString" method to get this value.
*
* @see toString()
*/
public void parse() {
parse(this);
}
/**
* Returns the value (after parsing) of this JDynamiTe document.
* @return Value (after parsing) of this JDynamiTe document
*/
public String toString() {
return getValue(this);
}
/**
* For debugging purposes : get the result (structure of the template document) of the analyser parsing.
* @return Result (structure of the template document) of the analyser parsing.
*/
public String getTemplateDefinition() {
return getDefinition(0);
}
/**
* Reset all Variables and all Dynamic Element values.
*/
public void clearAll() {
clearAllVariables();
clearAllDynElemValues();
}
/**
* Reset all Variables.
*/
public void clearAllVariables() {
variables.clear();
}
/**
* Reset all Dynamic Element values.
*/
public void clearAllDynElemValues() {
Collection dynElems = dynamics.values();
Iterator iter = dynElems.iterator();
while (iter.hasNext()) {
IDynamicElement dynElem = (IDynamicElement)iter.next();
dynElem.setValue(null);
}
}
/////////////
/**
* Provides a simple (but sufficient) example of use.
* Needs "testTemplate.html" in current directory as a template file.
* Writes the result on standard output.
*/
public static void main(String args[]) {
JDynamiTe dynamiTe = new JDynamiTe("MyTemplateTest");
// 1) Use "setInput" method to define (and analyse) the input template file.
try {
dynamiTe.setInput("example/testTemplateV1_2.html");
}
catch (Exception e) {
System.err.println(e.getMessage());
}
// possibly see the template document structure (for debug)
String totalDef = dynamiTe.getDefinition(0);
System.err.println("\n----- definition -----\n\n" + totalDef + "\n-----\n");
System.err.println("\n===== keys =====\n");
Enumeration keys = dynamiTe.getVariableKeys();
while (keys.hasMoreElements()) {
System.err.println("[" + keys.nextElement() + "]");
}
System.err.println("\n=====\n");
//
// 2) Use "setVariable" method to give a value to variables.
dynamiTe.setVariable("THE_TITLE", "\"Java Dynamic Template\" test");
// First table
for (int i = 0; i < 6; i++) {
dynamiTe.setVariable("COL1", "line_" + i + ",col_1");
dynamiTe.setVariable("COL2", "line_" + i + ",col_2");
// 3) Use "parseDynElem" to build a Dynamic Element
dynamiTe.parseDynElem("mySimpleRow"); // add a row
// "parseDynElem" appends the Dynamic Element definition to its current value
}
// A message
java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("EEEEEE hh'h'mm'm'ss's'");
String dateString = formatter.format(new java.util.Date());
dynamiTe.setVariable("A_MESSAGE", "Hello Duke, " + dateString);
// An image list
for (int px = 0; px < 3; px++) {
dynamiTe.setVariable("PICTURE", "images/duke" + px + ".gif");
dynamiTe.parseDynElem("somePictures");
}
// Second table with nested Dynamic Element
for (int row = 0; row < 5; row++) {
// first group of columns
// 4) Use "setDynElemValue" to set or reset the value of a Dynamic Element
dynamiTe.setDynElemValue("colX", ""); // reset for each row
for (int col = 0; col < 3; col++) {
dynamiTe.setVariable("VALUE_X", "line_" + row + ",col_" + col);
dynamiTe.parseDynElem("colX"); // add a column
}
// second group of columns
dynamiTe.setDynElemValue("colY", ""); // reset for each row
for (int col = 3; col < 5; col++) {
dynamiTe.setVariable("VALUE_Y", "line_" + row + ",col(BIS)_" + col);
dynamiTe.parseDynElem("colY"); // add a column
}
dynamiTe.parseDynElem("myBigRow"); // add a row
}
// 5) Use "parse" to finaly get the value of your Dynamic Template Document
dynamiTe.parse();
System.out.println(dynamiTe.toString());
}
////////////////
private static void justForInternalTest(String args[]) {
JDynamiTe jDoc = new JDynamiTe("MonDocTemplate");
try {
jDoc.setInput("body1.html");
}
catch (Exception e) {
System.err.println(e.getMessage());
}
String totalDef = jDoc.getDefinition(0);
System.out.println("\nANALYSE :\n\n" + totalDef + "\n\nFIN ANALYSE\n\n");
///////////// Remplissage
jDoc.setVariable("TITRE", "Test de JDynamiTe");
for (int i = 0; i < 10; i++) {
jDoc.setVariable("PART1", "ligne_" + i + ",col_1");
jDoc.setVariable("PART2", "ligne_" + i + ",col_2");
jDoc.parseDynElem("elem");
}
jDoc.setVariable("PICTURE", "images/myPhoto.gif");
String option = "classic";
if (option.equals("classic")) {
jDoc.parseDynElem("pict");
}
else if (option.equals("arbitraire")) {
jDoc.setDynElemValue("pict", "\nVALEUR ARBITRAIRE !!!\n");
}
else if (option.equals("les deux !")) {
jDoc.setDynElemValue("pict", "\nVALEUR ARBITRAIRE !!!\n");
jDoc.parseDynElem("pict");
}
for (int row = 0; row < 5; row++) {
jDoc.setDynElemValue("col", "");
for (int col = 0; col < 3; col++) {
jDoc.setVariable("PARTX", "ligne_" + row + ",col_" + col);
jDoc.parseDynElem("col");
}
jDoc.setDynElemValue("xcl1", "");
for (int col = 3; col < 5; col++) {
jDoc.setVariable("XPART1", "ligne_" + row + ",col(y)_" + col);
jDoc.parseDynElem("xcl1");
}
jDoc.parseDynElem("row");
}
jDoc.parse();
System.out.println("\njDoc :\n" + jDoc);
jDoc.clearAllDynElemValues();
jDoc.parse();
System.out.println("\njDoc apres clearAllDynElemValues() ET parse() :\n" + jDoc);
jDoc.clearAllDynElemValues();
jDoc.clearAllVariables();
jDoc.parse();
System.out.println("\njDoc apres clearAllDynElemValues ET clearAllVariables() ET parse() :\n" + jDoc);
///////////// Remplissage DEUZE
jDoc.clearAll();
jDoc.setVariable("TITRE", "DEUZE Test de JDynamiTe");
for (int i = 0; i < 10; i++) {
jDoc.setVariable("PART1", "DEUZE ligne_" + i + ",col_1");
jDoc.setVariable("PART2", "DEUZE ligne_" + i + ",col_2");
jDoc.parseDynElem("elem");
}
jDoc.setVariable("PICTURE", "DEUZE images/myPhoto.gif");
option = "classic";
if (option.equals("classic")) {
jDoc.parseDynElem("pict");
}
else if (option.equals("arbitraire")) {
jDoc.setDynElemValue("pict", "DEUZE \nVALEUR ARBITRAIRE !!!\n");
}
else if (option.equals("les deux !")) {
jDoc.setDynElemValue("pict", "DEUZE \nVALEUR ARBITRAIRE !!!\n");
jDoc.parseDynElem("pict");
}
for (int row = 0; row < 5; row++) {
jDoc.setDynElemValue("col", "");
for (int col = 0; col < 3; col++) {
jDoc.setVariable("PARTX", "DEUZE ligne_" + row + ",col_" + col);
jDoc.parseDynElem("col");
}
jDoc.setDynElemValue("xcl1", "");
for (int col = 3; col < 5; col++) {
jDoc.setVariable("XPART1", "DEUZE ligne_" + row + ",col(y)_" + col);
jDoc.parseDynElem("xcl1");
}
jDoc.parseDynElem("row");
}
jDoc.parse();
System.out.println("\njDoc REUTILISE :\n" + jDoc);
}
}
|