001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.util.pagetemplate;
007
008import java.io.*;
009import java.util.*;
010import java.sql.*;
011
012import fc.util.*;
013import fc.io.*;
014
015/** 
016A superclass for generated template pages. All templates derive from this class. Runs
017outside the web environment (intended to be invoked from the command line)
018<p>
019Pages are always assumed to be written in UTF-8 (a superset of regular
020ascii/IS0-8859-1). If the template page is sent as HTML to a device (via some outside
021mechanism that uses the templates as part of its workflow), then the HTML contained in
022the page template should set the appropriate content type/encoding meta header to say
023UTF-8, <b>if</b> UTF-8 characters (such as emojis) are used in the page.
024<p>
025See {@link TemplateMgr}
026
027@author hursh jain
028*/
029public abstract class TemplatePage 
030{
031static private  final boolean internal_dbg = false;
032
033public static String  PACKAGE_NAME = "molly.pagetemplate";
034public static String  DEFAULT_ENCODING    = "UTF-8";
035
036/** 
037Controls whether debugging is on or off. For expensive debug statements,
038<code>if (dbg) bug(....)</code> type statements can be used in a page.
039*/
040protected volatile  boolean  dbg = false;
041
042public Log      log = Log.getDefault(); 
043public  Writer  out;
044
045public File templateFile;
046
047public Connection con;
048public Map context;
049
050public void setSourcePath(File templateFile) {
051  this.templateFile = templateFile;
052  }
053
054public String getSourcePath()
055  {
056  return templateFile.getAbsolutePath();
057  }
058
059/* set a connect that can later be used in render, if needed. code in render can also get
060   a connection directly from a connection mgr, etc as well, of course. The resposibility
061   to close the connection can be inside render() or by the caller, whatever makes sense
062   in a particular use case.
063   */
064public void setConnection(Connection con) {
065  this.con = con;
066  }
067  
068/* set various objects (via a map) that can be later used in render, if needed. */
069public void setContext(Map m) {
070  this.context = m;
071  }
072  
073public void render(Writer out) throws Exception
074  {
075  //writers should already have a charset specified if they are using an outputstreamwriter or
076  //some other output stream. toPrinteWriter() just wraps that
077
078  render(IOUtil.toPrintWriter(
079      IOUtil.bufferWriter(out)));
080  }
081
082public void render(File out) throws Exception
083  {
084  render(new PrintWriter(out, DEFAULT_ENCODING));
085  }
086
087public void render(OutputStream out) throws Exception
088  {
089  render(new PrintWriter(
090      new BufferedWriter(
091        new OutputStreamWriter(out, DEFAULT_ENCODING))));
092  }
093
094
095/* 
096This is the method that runs the templates and writes the generated contents to the
097specified output destination. Is implemented by generated classes. 
098*/
099public abstract void render(PrintWriter out) throws Exception;
100
101/*
102Starts/stop debugging with no dbg_prefix/dbg_suffix.
103
104@param  val   true to enable debugging, false to disable.
105*/
106public final void dbg(final boolean val)
107  {
108  this.dbg = val;
109  }
110
111
112/**
113Prints a debug statement if debugging is turned on for this page.
114
115<p>Typically the implicit page printwriter (the <code>out</code>
116variable) will be passed to this method and debug statements will be
117printed at the point where they are lexically invoked at the page.
118*/
119public final void bug(final Writer writer, final Object str1) throws IOException
120  {
121  if (! dbg)
122    return;
123  
124  writer.append(str1 != null ? str1.toString() : "null");
125  }
126    
127public final void bug(final Writer writer, final Object str1, final Object... args) 
128throws IOException
129  {
130  if (! dbg)
131    return;
132    
133  writer.append(str1 != null ? str1.toString() : "null");
134  final int len = args.length;
135  for (int i = 0; i < len; i++) {
136    writer.append(args[i] != null ? args[i].toString() : "null");
137    }
138  }
139
140}