/*
 * $Id: TemplateParser.java,v 1.15 2006/04/07 09:39:34 korowa Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: TemplateParser.java,v $
 * Revision 1.15  2006/04/07 09:39:34  korowa
 * Felehrhafte Datenbankzugrif wurde entfernt -->Logfile wird nicht mehr geführt
 *
 * Revision 1.14  2006/03/22 13:14:08  marbobo
 * + Bugfix
 *
 * Revision 1.13  2006/03/17 19:24:58  marbobo
 * + Als Übergangslösung habe ich den Pfad der velocity.log
 *     nach InfoLogFile-Pfad umgeleitet. Dies sollte keine Probleme mehr bereiten
 *
 * Revision 1.12  2006/03/17 17:05:34  jonyp
 * added some comments for velocity
 *
 * Revision 1.11  2005/07/28 19:57:26  marbobo
 * + Template-Pfade angepasst
 *
 * Revision 1.10  2005/04/12 12:56:07  korowa
 * Neuer path für Velocity Engine gesetzt, Head.txt enthält jetzt die gemeinsame Eigenschaften
 * (header,css-Teil und importiertes Bild)die früher in jeder Mail- HTML-Datei  standen.
 *
 * Revision 1.9  2005/03/15 12:27:30  lawern
 * Statische Methoden und Variablen entfernt.
 *
 * Revision 1.8  2004/11/10 15:02:46  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.7  2004/08/20 12:51:32  koppy
 * Leicht erweitert...
 *
 * Revision 1.6  2004/07/20 08:33:14  jonyp
 * added copyright info + cvs log
 *
 * Revision 1.5  2004/04/26 17:50:57  teng
 * new method getTemplateLoaderpath()
 */
package vkc.misc;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;

import vkc.db.serializer.VKCSysParameterSerializer;
import vkc.util.StringUtils;
import vkc.view.WebShare;

import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;

public class TemplateParser {
    private String templatepath = null;

    /**
     * Velocity sollte nur einmal initialisiert werden
     */
    private boolean inited = false;

    /**
     * Enthaelt die Daten, die in die Template-Datei hinein geschrieben werden sollen
     */
    private VelocityContext context = new VelocityContext();

    private TemplateParser() {
    }

    /**
     * Erzeugt ein neues Templateparser. Falls Velocity nicht initialisiert ist, wird Velocity initialisiert.
     * @throws Exception
     */
    public static TemplateParser getTemplateParser() throws Exception {
        TemplateParser instance = new TemplateParser();
        instance.init();

        return instance;
    }

    /**
     * Nur fuer die Benutzung ohne VKC-Server. Nicht innerhalb VKC diese Methode aufrufen!!!
     * @param loadPath
     * @return
     * @throws Exception
     */
    public static TemplateParser getTemplateParserStandalone(String loadPath) throws Exception {
        TemplateParser instance = new TemplateParser();
        instance.initStandalone(loadPath);

        return instance;
    }

    public static synchronized TemplateParser getTemplateParser(Properties props) throws Exception {
        if (props == null) {
            throw new IllegalArgumentException("No properties specified!");
        }

        TemplateParser instance = new TemplateParser();
        String log = VKCSysParameterSerializer.retrieveValue("LOGGING", "InfoLogFile", "");
        
        if (!StringUtils.isEmpty(log)) {
        	log = log.substring(0, log.lastIndexOf("/")) + "/velocity.log";
        } else {
        	log = StringUtils.replaceToken(WebShare.VKC_ROOT_PATH, "\\", "/") + "velocity.log";
        }
        
        props.setProperty(RuntimeConstants.RUNTIME_LOG, log);
        Velocity.init(props);
        instance.inited = true;
        System.out.println("Velocity initialized!");

        return instance;
    }

    private void init() throws Exception {
        if (!inited) {
/*
            PrintWriter writer = new PrintWriter(new FileOutputStream("velocity.properties"));
            writer.println("file.resource.loader.path = " + templatepath);
            writer.close();
            Velocity.init("velocity.properties");
*/
            String log = VKCSysParameterSerializer.retrieveValue("LOGGING", "InfoLogFile", "");
            
            if (!StringUtils.isEmpty(log)) {
            	log = log.substring(0, log.lastIndexOf("/")) + "/velocity.log";
            } else {
            	log = StringUtils.replaceToken(WebShare.VKC_ROOT_PATH, "\\", "/") + "velocity.log";
            }
            
            Velocity.setProperty(RuntimeConstants.RUNTIME_LOG, log);

            templatepath = WebShare.VKC_ROOT_PATH;
            templatepath = StringUtils.replaceToken(templatepath, "\\", "/");
            Velocity.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templatepath);
            
/*
            Velocity.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, insert default directory for your templates);
            Velocity.setProperty(RuntimeConstants.RUNTIME_LOG, insert the location of the log);
            Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
            					 DEBUG ? "org.apache.velocity.runtime.log.SimpleLog4JLogSystem"
            					 	   : "org.apache.velocity.runtime.log.NullLogSystem");          
            
            gefunden unter: http://www.almaer.com/blog/archives/000082.html            
*/
            
            Velocity.init();
            inited = true;
        }
    }

    /**
     * Init Velocity mit loadPath
     * @param loadPath
     * @throws Exception
     */
    private void initStandalone(String loadPath) throws Exception {
        if (!inited) {
        	//TODO Möglichkeit Logfile zu finden ohne auf Datenbank zuzugreifen
        	Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogSystem");
            templatepath = loadPath;
            Velocity.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, loadPath);
            Velocity.init();
            inited = true;
        }
    }

    /**
     * Basierend auf der Template-Datei eine neue Datei erzeugen
     * @param templateFile Dateiname. Sollte diese Datei unter einem Unterverzeichnis des Templatepath (Velocity Root) liegen,
     * dann muss dieser Name inklusive dieses Verzeichnis eingegeben werden z.B. "verzeichnis/dateiname".
     * @param newfile
     * @throws Exception
     */
    public void createFile(String templateFile, String newfile) throws Exception {
        Writer writer = null;

        try {
            writer = new PrintWriter(new FileOutputStream(newfile));

            Template template = Velocity.getTemplate(templateFile);
            template.merge(context, writer);
        } catch (Exception ex) {
            VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
            throw new Exception(ex.toString());
        } finally {
            if (writer != null) {
                try {
                    writer.flush();
                    writer.close();
                } catch (Exception ex) {
                    VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
                }
            }
        }
    }

    /**
     * Templatedatei wird bearbeitet und das Ergebnis als String zurueckgegeben. Falls die Datei templateFile nicht existiert, gibt null zurueck.
     * @param templateFile Dateiname. Sollte diese Datei unter einem Unterverzeichnis des Templatepath (Velocity Root) liegen,
     * dann muss dieser Name inklusive dieses Verzeichnis eingegeben werden z.B. "verzeichnis/dateiname".
     *
     * @return Falls die Datei <code>templateFile</code> nicht existiert, gibt null zurueck.
     */
    public String createString(String templateFile) {
        StringWriter writer = null;

        try {
            writer = new StringWriter();

            Template template = Velocity.getTemplate(templateFile);
            template.merge(context, writer);

            return writer.getBuffer().toString();
        } catch (Exception ex) {
            VKCLogManager.errorLog(this, "", ex.getMessage(), ex);

            return null;
        } finally {
            if (writer != null) {
                try {
                    writer.flush();
                    writer.close();
                } catch (Exception ex) {
                    VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
                }
            }
        }
    }

    /**
     * Ein Name/Value Paar in Context einzutragen
     * @param key Schluesselword, das als Variable in der Templatedatei verwendet wird
     * @param value
     */
    public void setContextData(String key, Object value) {
        context.put(key, value);
    }

    /**
     * Diese Methode kann benutzt werden, mehrere Name/Value Paare in Context einzutragen
     * @param map Key von Type <code>String</code>, Value von Type <code>Object</code>
     */
    public void setContextData(HashMap map) {
        String key;
        Iterator it = map.keySet().iterator();

        while (it.hasNext()) {
            key = (String) it.next();
            context.put(key, map.get(key));
        }
    }

    public String getTemplateLoaderpath() {
        return templatepath;
    }
}
