JDynamiTe.java :  » Template-Engine » JDynamiTe » cb » jdynamite » Java Open Source

Java Open Source » Template Engine » JDynamiTe 
JDynamiTe » cb » jdynamite » JDynamiTe.java
/*
 *  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>
 * &lt;!-- BEGIN DYNAMIC : dynElemName --&gt; </pre>
 * or <pre>
 * &lt;!-- BEGIN DYNAMIC BLOCK: dynElemName --&gt; </pre>
 * means the "dynElemName" Dynamic Element definition begins on the next line.
 * <br><br>
 * <b>3) "End Dynamic Element" tag:</b> <pre>
 * &lt;!-- END DYNAMIC : dynElemName --&gt; </pre>
 * or <pre>
 * &lt;!-- END DYNAMIC BLOCK: dynElemName --&gt; </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>
 * &lt;!-- BEGIN IGNORED : ignoredElemName --&gt; </pre>
 * means an ignored block (skipped during analysis and document output) begins on the next line.
 * <br><pre>
 * &lt;!-- END IGNORED : ignoredElemName --&gt; </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>
     * &lt;-- BEGIN DYNAMIC : myList --&gt;
     * </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>
     * &lt;-- BEGIN DYNAMIC : myList --&gt;
     * </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);
        
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.