From 057a46982292c765e664f886097fdaf33ed22a62 Mon Sep 17 00:00:00 2001
From: "David A. Madore" <david+git@madore.org>
Date: Wed, 31 Aug 2011 22:26:55 +0200
Subject: Wrap it all in a single command handler.

---
 org/madore/damlengine/Context.java                |   8 +
 org/madore/damlengine/DamlEngine.java             |  70 ++++++++-
 org/madore/damlengine/WeblogIndexSelect.java      |   6 +-
 org/madore/damlengine/WeblogPopulate.java         | 154 +++++++++----------
 org/madore/damlengine/WeblogRSS.java              |  13 +-
 org/madore/damlengine/WeblogSelect.java           |  32 ++--
 org/madore/damlengine/weblog-cat-template.daml    |  60 ++++++++
 org/madore/damlengine/weblog-index-template.daml  |  60 ++++++++
 org/madore/damlengine/weblog-month-template.daml  | 178 ++++++++++++++++++++++
 org/madore/damlengine/weblog-recent-template.daml |  60 ++++++++
 10 files changed, 536 insertions(+), 105 deletions(-)
 create mode 100644 org/madore/damlengine/weblog-cat-template.daml
 create mode 100644 org/madore/damlengine/weblog-index-template.daml
 create mode 100644 org/madore/damlengine/weblog-month-template.daml
 create mode 100644 org/madore/damlengine/weblog-recent-template.daml

(limited to 'org/madore/damlengine')

diff --git a/org/madore/damlengine/Context.java b/org/madore/damlengine/Context.java
index 388a076..12e2f1b 100644
--- a/org/madore/damlengine/Context.java
+++ b/org/madore/damlengine/Context.java
@@ -49,6 +49,14 @@ public class Context implements Cloneable {
 	}
     }
 
+    public static class WeblogRecentSelectionContext
+	extends WeblogSelectionContext {
+	public int count;
+	public WeblogRecentSelectionContext(int count) {
+	    this.count = count;
+	}
+    }
+
     public WeblogSelectionContext wsc;
 
     public static class EntryContext {
diff --git a/org/madore/damlengine/DamlEngine.java b/org/madore/damlengine/DamlEngine.java
index e54ee86..874a220 100644
--- a/org/madore/damlengine/DamlEngine.java
+++ b/org/madore/damlengine/DamlEngine.java
@@ -1,9 +1,14 @@
 package org.madore.damlengine;
 
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 import java.io.InputStream;
 import java.io.FileInputStream;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.FileOutputStream;
 import java.io.OutputStreamWriter;
+import java.io.BufferedReader;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -117,12 +122,65 @@ public final class DamlEngine {
     public static void main(String[] args)
 	throws Exception {
 
-	if ( args.length == 0 ) {
-	    System.err.println("expecting filename as argument");
-	}
-
-	for (String fname : args) {
-	    fullProcess (new FileInputStream(fname), System.out);
+	BufferedReader buf = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+	String line;
+	Matcher matcher;
+
+	while ( ( line = buf.readLine() ) != null ) {
+	    if ( Pattern.matches("^\\s+$", line) )
+		continue;
+	    else if ( (matcher=Pattern.compile("process\\s+(\\S+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		String inf = matcher.group(1);
+		String outf = matcher.group(2);
+		InputStream in = new FileInputStream(inf);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		fullProcess(in, out);
+	    } else if ( (matcher=Pattern.compile("process-weblog-month\\s+(\\d{4})\\-(\\d{2})(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		String year = matcher.group(1);
+		String month = matcher.group(2);
+		String outf = matcher.group(3);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		WeblogSelect.fullProcess(new Context.WeblogMonthSelectionContext(year,month),
+					 out);
+	    } else if ( (matcher=Pattern.compile("process-weblog-cat\\s+([a-z0-9\\-]+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		String code = matcher.group(1);
+		String outf = matcher.group(2);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		WeblogSelect.fullProcess(new Context.WeblogCategorySelectionContext(code),
+					 out);
+	    } else if ( (matcher=Pattern.compile("process-weblog-recent\\s+(\\d+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		int count = Integer.parseInt(matcher.group(1));
+		String outf = matcher.group(2);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		WeblogSelect.fullProcess(new Context.WeblogRecentSelectionContext(count),
+					 out);
+	    } else if ( (matcher=Pattern.compile("process-weblog-index(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		String outf = matcher.group(1);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		WeblogIndexSelect.fullProcess(out);
+	    } else if ( (matcher=Pattern.compile("process-weblog-rss(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+		String outf = matcher.group(1);
+		OutputStream out = (outf != null)
+		    ? new FileOutputStream(outf)
+		    : System.out;
+		WeblogRSS.fullProcess(out);
+	    } else if ( (matcher=Pattern.compile("populate-weblog\\s+(\\S+)\\s*").matcher(line)).matches() ) {
+		String inf = matcher.group(1);
+		InputStream in = new FileInputStream(inf);
+		WeblogPopulate.populate(in);
+	    } else {
+		throw new IllegalArgumentException("couldn't understand command");
+	    }
 	}
 
     }
diff --git a/org/madore/damlengine/WeblogIndexSelect.java b/org/madore/damlengine/WeblogIndexSelect.java
index c9bf617..83c5461 100644
--- a/org/madore/damlengine/WeblogIndexSelect.java
+++ b/org/madore/damlengine/WeblogIndexSelect.java
@@ -1,16 +1,18 @@
 package org.madore.damlengine;
 
+import java.io.OutputStream;
+
 public final class WeblogIndexSelect {
 
     private WeblogIndexSelect() { // Forbid instantiation
 	throw new AssertionError("WeblogIndexSelect cannot be instantiated");
     }
 
-    public static void main(String[] args)
+    public static void fullProcess(OutputStream out)
 	throws Exception {
 
 	DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream("weblog-index-template.daml"),
-			       System.out, null);
+			       out, null);
 
     }
 
diff --git a/org/madore/damlengine/WeblogPopulate.java b/org/madore/damlengine/WeblogPopulate.java
index 0d28d92..56e51ac 100644
--- a/org/madore/damlengine/WeblogPopulate.java
+++ b/org/madore/damlengine/WeblogPopulate.java
@@ -1,6 +1,7 @@
 package org.madore.damlengine;
 
 import java.util.regex.Pattern;
+import java.io.InputStream;
 import java.security.MessageDigest;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -25,15 +26,11 @@ public final class WeblogPopulate {
 	return sb.toString();
     }
 
-    public static void main(String[] args)
+    public static void populate(InputStream in)
 	throws Exception {
 
 	final DocumentBuilder db = DamlEngine.GetDocumentBuilder.db;
 
-	if ( args.length == 0 ) {
-	    System.err.println("expecting filename as argument");
-	}
-
 	final DOMImplementationLS domi
 	    = (DOMImplementationLS)(db.getDOMImplementation());
 	LSSerializer ser = domi.createLSSerializer();
@@ -56,83 +53,81 @@ public final class WeblogPopulate {
 	final PreparedStatement setCatSt
 	    = conn.prepareStatement("INSERT INTO incat(id,code) VALUES (?,?)");
 
-	for (String fname : args) {
-	    Document doc = db.parse(fname);
-	    XPathFactory xpf = XPathFactory.newInstance();
-	    XPath xp = xpf.newXPath();
-	    xp.setNamespaceContext(new DamlEngine.DamlNSMapping());
-	    XPathExpression expr = xp.compile("//d:weblog/d:entry");
-	    XPathExpression texpr = xp.compile("d:title");
-	    NodeList entries = (NodeList)(expr.evaluate(doc, XPathConstants.NODESET));
-	    for ( int i=0 ; i<entries.getLength() ; i++ ) {
-		Element ent = (Element)(entries.item(i));
-		String idStr = ent.getAttributeNS(null, "number");
-		if ( ! Pattern.matches("^\\d{4}$", idStr) )
-		    throw new IllegalArgumentException("entry number attribute must be of the form NNNN");
-		int id = Integer.parseInt(idStr);
-		String date = ent.getAttributeNS(null, "date");
-		if ( ! Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", date) )
-		    throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD");
-		String cdate;
-		if ( ent.hasAttributeNS(null, "cdate") )
-		    cdate = ent.getAttributeNS(null, "cdate");
+	Document doc = db.parse(in);
+	XPathFactory xpf = XPathFactory.newInstance();
+	XPath xp = xpf.newXPath();
+	xp.setNamespaceContext(new DamlEngine.DamlNSMapping());
+	XPathExpression expr = xp.compile("//d:weblog/d:entry");
+	XPathExpression texpr = xp.compile("d:title");
+	NodeList entries = (NodeList)(expr.evaluate(doc, XPathConstants.NODESET));
+	for ( int i=0 ; i<entries.getLength() ; i++ ) {
+	    Element ent = (Element)(entries.item(i));
+	    String idStr = ent.getAttributeNS(null, "number");
+	    if ( ! Pattern.matches("^\\d{4}$", idStr) )
+		throw new IllegalArgumentException("entry number attribute must be of the form NNNN");
+	    int id = Integer.parseInt(idStr);
+	    String date = ent.getAttributeNS(null, "date");
+	    if ( ! Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", date) )
+		throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD");
+	    String cdate;
+	    if ( ent.hasAttributeNS(null, "cdate") )
+		cdate = ent.getAttributeNS(null, "cdate");
+	    else
+		cdate = null;
+	    String catStr = ent.getAttributeNS(null, "cat");
+	    String[] catList = catStr.split("\\s+");
+	    String lang = LangHelper.getLangRec(ent);
+	    String content = ser.writeToString(ent);
+	    sha1.reset();
+	    String digest = toHex(sha1.digest(content.getBytes("UTF-8")));
+
+	    checkSt.setInt(1, id);
+	    ResultSet checkRes = checkSt.executeQuery();
+	    boolean exists = checkRes.next();
+	    if ( exists && checkRes.getString(1).equals(digest) )
+		continue;
+	    Node titleNode = (Node)(texpr.evaluate(ent, XPathConstants.NODE));
+	    String titleTxt = (titleNode != null) ? titleNode.getTextContent() : null;
+	    String titleXml = (titleNode != null) ? ser.writeToString(titleNode) : null;
+	    conn.setAutoCommit(false);
+	    if ( exists ) {
+		System.err.println("Updating entry "+id);
+		updateSt.setString(1, date);
+		updateSt.setString(2, lang);
+		updateSt.setString(3, titleTxt);
+		updateSt.setString(4, titleXml);
+		updateSt.setString(5, content);
+		updateSt.setString(6, digest);
+		updateSt.setInt(7, id);
+		updateSt.executeUpdate();
+	    } else {
+		System.err.println("Registering entry "+id);
+		PreparedStatement insertSt;
+		if ( cdate == null )
+		    insertSt = insertNSt;
 		else
-		    cdate = null;
-		String catStr = ent.getAttributeNS(null, "cat");
-		String[] catList = catStr.split("\\s+");
-		String lang = LangHelper.getLangRec(ent);
-		String content = ser.writeToString(ent);
-		sha1.reset();
-		String digest = toHex(sha1.digest(content.getBytes("UTF-8")));
-		
-		checkSt.setInt(1, id);
-		ResultSet checkRes = checkSt.executeQuery();
-		boolean exists = checkRes.next();
-		if ( exists && checkRes.getString(1).equals(digest) )
-		    continue;
-		Node titleNode = (Node)(texpr.evaluate(ent, XPathConstants.NODE));
-		String titleTxt = (titleNode != null) ? titleNode.getTextContent() : null;
-		String titleXml = (titleNode != null) ? ser.writeToString(titleNode) : null;
-		conn.setAutoCommit(false);
-		if ( exists ) {
-		    System.err.println("Updating entry "+id);
-		    updateSt.setString(1, date);
-		    updateSt.setString(2, lang);
-		    updateSt.setString(3, titleTxt);
-		    updateSt.setString(4, titleXml);
-		    updateSt.setString(5, content);
-		    updateSt.setString(6, digest);
-		    updateSt.setInt(7, id);
-		    updateSt.executeUpdate();
-		} else {
-		    System.err.println("Registering entry "+id);
-		    PreparedStatement insertSt;
-		    if ( cdate == null )
-			insertSt = insertNSt;
-		    else
-			insertSt = insertCSt;
-		    insertSt.setInt(1, id);
-		    insertSt.setString(2, date);
-		    insertSt.setString(3, lang);
-		    insertSt.setString(4, titleTxt);
-		    insertSt.setString(5, titleXml);
-		    insertSt.setString(6, content);
-		    insertSt.setString(7, digest);
-		    if ( cdate != null )
-			insertSt.setString(8, cdate);
-		    insertSt.executeUpdate();
-		}
-		clearCatSt.setInt(1, id);
-		clearCatSt.executeUpdate();
-		for ( String cat : catList ) {
-		    if ( ! cat.equals("") ) {
-			setCatSt.setInt(1, id);
-			setCatSt.setString(2, cat);
-			setCatSt.executeUpdate();
-		    }
+		    insertSt = insertCSt;
+		insertSt.setInt(1, id);
+		insertSt.setString(2, date);
+		insertSt.setString(3, lang);
+		insertSt.setString(4, titleTxt);
+		insertSt.setString(5, titleXml);
+		insertSt.setString(6, content);
+		insertSt.setString(7, digest);
+		if ( cdate != null )
+		    insertSt.setString(8, cdate);
+		insertSt.executeUpdate();
+	    }
+	    clearCatSt.setInt(1, id);
+	    clearCatSt.executeUpdate();
+	    for ( String cat : catList ) {
+		if ( ! cat.equals("") ) {
+		    setCatSt.setInt(1, id);
+		    setCatSt.setString(2, cat);
+		    setCatSt.executeUpdate();
 		}
-		conn.commit();
 	    }
+	    conn.commit();
 	}
 
 	checkSt.close();
@@ -141,7 +136,6 @@ public final class WeblogPopulate {
 	updateSt.close();
 	clearCatSt.close();
 	setCatSt.close();
-	conn.close();
 
     }
 
diff --git a/org/madore/damlengine/WeblogRSS.java b/org/madore/damlengine/WeblogRSS.java
index c08991c..31744f5 100644
--- a/org/madore/damlengine/WeblogRSS.java
+++ b/org/madore/damlengine/WeblogRSS.java
@@ -2,6 +2,7 @@ package org.madore.damlengine;
 
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import java.io.OutputStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -19,7 +20,7 @@ public final class WeblogRSS {
 	throw new AssertionError("WeblogRSS cannot be instantiated");
     }
 
-    public static void main(String[] args)
+    public static void fullProcess(OutputStream out)
 	throws Exception {
 
 	final Connection conn = WeblogDatabaseConnection.getConnection();
@@ -37,9 +38,9 @@ public final class WeblogRSS {
 	ser.getDomConfig().setParameter("xml-declaration", true);
 	LSParser par = domi.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
 
-	final LSOutput out = domi.createLSOutput();
-	out.setByteStream(System.out);
-	out.setEncoding("UTF-8");
+	final LSOutput lsout = domi.createLSOutput();
+	lsout.setByteStream(out);
+	lsout.setEncoding("UTF-8");
 
 	Document rssDoc = db.newDocument();
 	Element rssRoot = rssDoc.createElementNS(DamlEngine.RDF_NS, "rdf:RDF");
@@ -144,8 +145,8 @@ public final class WeblogRSS {
 	    itemDescr.appendChild(rssDoc.createTextNode(descrStr));
 	}
 
-	ser.write(rssDoc, out);
-	out.getByteStream().write("\n".getBytes("UTF-8"));
+	ser.write(rssDoc, lsout);
+	out.write("\n".getBytes("UTF-8"));
 
     }
 
diff --git a/org/madore/damlengine/WeblogSelect.java b/org/madore/damlengine/WeblogSelect.java
index cb263e6..1593d72 100644
--- a/org/madore/damlengine/WeblogSelect.java
+++ b/org/madore/damlengine/WeblogSelect.java
@@ -2,6 +2,7 @@ package org.madore.damlengine;
 
 import java.util.HashSet;
 import java.util.ArrayList;
+import java.io.OutputStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -12,21 +13,30 @@ public final class WeblogSelect {
 	throw new AssertionError("WeblogSelect cannot be instantiated");
     }
 
-    public static void main(String[] args)
+    public static void fullProcess(Context.WeblogSelectionContext wsc,
+				   OutputStream out)
 	throws Exception {
 
-	String year = "2011";
-	String month = "08";
-
 	final Connection conn = WeblogDatabaseConnection.getConnection();
 
-	final PreparedStatement selSt
-	    = conn.prepareStatement("SELECT id , content FROM entries WHERE edate LIKE ? ORDER BY id DESC");
-	selSt.setString(1,year+"-"+month+"-__");
+	String templateResourceName;
+	final PreparedStatement selSt;
+	if ( wsc instanceof Context.WeblogMonthSelectionContext ) {
+	    templateResourceName = "weblog-month-template.daml";
+	    selSt = conn.prepareStatement("SELECT id , content FROM entries WHERE edate LIKE ? ORDER BY id DESC");
+	    selSt.setString(1,((Context.WeblogMonthSelectionContext)wsc).year+"-"+((Context.WeblogMonthSelectionContext)wsc).month+"-__");
+	} else if ( wsc instanceof Context.WeblogCategorySelectionContext ) {
+	    templateResourceName = "weblog-cat-template.daml";
+	    selSt = conn.prepareStatement("SELECT entries.id , entries.content FROM entries , incat WHERE entries.id=incat.id AND incat.code=? ORDER BY entries.id DESC");
+	    selSt.setString(1,((Context.WeblogCategorySelectionContext)wsc).code);
+	} else if ( wsc instanceof Context.WeblogRecentSelectionContext ) {
+	    templateResourceName = "weblog-recent-template.daml";
+	    selSt = conn.prepareStatement("SELECT id , content FROM entries ORDER BY id DESC LIMIT ?");
+	    selSt.setInt(1,((Context.WeblogRecentSelectionContext)wsc).count);
+	} else
+	    throw new IllegalArgumentException("don't know how to perform this selection");
 
 	final ResultSet selRes = selSt.executeQuery();
-	final Context.WeblogSelectionContext wsc
-	    = new Context.WeblogMonthSelectionContext(year,month);
 	wsc.sel = new HashSet<Integer>();
 	wsc.xmlData = new ArrayList<String>();
 	while ( selRes.next() ) {
@@ -36,8 +46,8 @@ public final class WeblogSelect {
 	    wsc.xmlData.add(content);
 	}
 
-	DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream("weblog-month-template.daml"),
-			       System.out, wsc);
+	DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream(templateResourceName),
+			       out, wsc);
 
     }
 
diff --git a/org/madore/damlengine/weblog-cat-template.daml b/org/madore/damlengine/weblog-cat-template.daml
new file mode 100644
index 0000000..261686f
--- /dev/null
+++ b/org/madore/damlengine/weblog-cat-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+  <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+  %HTMLlat1;
+  <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+  %HTMLspecial;
+  <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+  %HTMLsymbol;
+  <!ENTITY uri-to-top "../">
+  <!ENTITY file.language "en">
+  <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French.  A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa.  Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français.  Quelques-unes ont une version
+dans chaque langue.  À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>!  <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-index-template.daml b/org/madore/damlengine/weblog-index-template.daml
new file mode 100644
index 0000000..fb45477
--- /dev/null
+++ b/org/madore/damlengine/weblog-index-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+  <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+  %HTMLlat1;
+  <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+  %HTMLspecial;
+  <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+  %HTMLsymbol;
+  <!ENTITY uri-to-top "../">
+  <!ENTITY file.language "en">
+  <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French.  A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa.  Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français.  Quelques-unes ont une version
+dans chaque langue.  À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>!  <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-index-select />
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-month-template.daml b/org/madore/damlengine/weblog-month-template.daml
new file mode 100644
index 0000000..f0cf0b3
--- /dev/null
+++ b/org/madore/damlengine/weblog-month-template.daml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+  <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+  %HTMLlat1;
+  <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+  %HTMLspecial;
+  <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+  %HTMLsymbol;
+  <!ENTITY uri-to-top "../">
+  <!ENTITY file.language "en">
+  <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French.  A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa.  Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français.  Quelques-unes ont une version
+dans chaque langue.  À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>!  <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+<p>Entries by month / <span xml:lang="fr">Entrées par mois</span>:</p>
+
+<table border="1">
+
+<tr><th>2011</th><td><a href="2011-01.html">Jan</a></td><td><a
+href="2011-02.html">Feb</a></td><td><a
+href="2011-03.html">Mar</a></td><td><a
+href="2011-04.html">Apr</a></td><td><a
+href="2011-05.html">May</a></td><td><a
+href="2011-06.html">Jun</a></td><td><a
+href="2011-07.html">Jul</a></td><td><a
+href="2011-08.html">Aug</a></td><td><a
+href="2011-09.html">Sep</a></td><td colspan="3"
+/></tr>
+
+<tr><th>2010</th><td><a href="2010-01.html">Jan</a></td><td><a
+href="2010-02.html">Feb</a></td><td><a
+href="2010-03.html">Mar</a></td><td><a
+href="2010-04.html">Apr</a></td><td><a
+href="2010-05.html">May</a></td><td><a
+href="2010-06.html">Jun</a></td><td><a
+href="2010-07.html">Jul</a></td><td><a
+href="2010-08.html">Aug</a></td><td><a
+href="2010-09.html">Sep</a></td><td><a
+href="2010-10.html">Oct</a></td><td><a
+href="2010-11.html">Nov</a></td><td><a
+href="2010-12.html">Dec</a></td></tr>
+
+<tr><th>2009</th><td><a href="2009-01.html">Jan</a></td><td><a
+href="2009-02.html">Feb</a></td><td><a
+href="2009-03.html">Mar</a></td><td><a
+href="2009-04.html">Apr</a></td><td><a
+href="2009-05.html">May</a></td><td><a
+href="2009-06.html">Jun</a></td><td><a
+href="2009-07.html">Jul</a></td><td><a
+href="2009-08.html">Aug</a></td><td><a
+href="2009-09.html">Sep</a></td><td><a
+href="2009-10.html">Oct</a></td><td><a
+href="2009-11.html">Nov</a></td><td><a
+href="2009-12.html">Dec</a></td></tr>
+
+<tr><th>2008</th><td><a href="2008-01.html">Jan</a></td><td><a
+href="2008-02.html">Feb</a></td><td><a
+href="2008-03.html">Mar</a></td><td><a
+href="2008-04.html">Apr</a></td><td><a
+href="2008-05.html">May</a></td><td><a
+href="2008-06.html">Jun</a></td><td><a
+href="2008-07.html">Jul</a></td><td><a
+href="2008-08.html">Aug</a></td><td><a
+href="2008-09.html">Sep</a></td><td><a
+href="2008-10.html">Oct</a></td><td><a
+href="2008-11.html">Nov</a></td><td><a
+href="2008-12.html">Dec</a></td></tr>
+
+<tr><th>2007</th><td><a href="2007-01.html">Jan</a></td><td><a
+href="2007-02.html">Feb</a></td><td><a
+href="2007-03.html">Mar</a></td><td><a
+href="2007-04.html">Apr</a></td><td><a
+href="2007-05.html">May</a></td><td><a
+href="2007-06.html">Jun</a></td><td><a
+href="2007-07.html">Jul</a></td><td><a
+href="2007-08.html">Aug</a></td><td><a
+href="2007-09.html">Sep</a></td><td><a
+href="2007-10.html">Oct</a></td><td><a
+href="2007-11.html">Nov</a></td><td><a
+href="2007-12.html">Dec</a></td></tr>
+
+<tr><th>2006</th><td><a href="2006-01.html">Jan</a></td><td><a
+href="2006-02.html">Feb</a></td><td><a
+href="2006-03.html">Mar</a></td><td><a
+href="2006-04.html">Apr</a></td><td><a
+href="2006-05.html">May</a></td><td><a
+href="2006-06.html">Jun</a></td><td><a
+href="2006-07.html">Jul</a></td><td><a
+href="2006-08.html">Aug</a></td><td><a
+href="2006-09.html">Sep</a></td><td><a
+href="2006-10.html">Oct</a></td><td><a
+href="2006-11.html">Nov</a></td><td><a
+href="2006-12.html">Dec</a></td></tr>
+
+<tr><th>2005</th><td><a href="2005-01.html">Jan</a></td><td><a
+href="2005-02.html">Feb</a></td><td><a
+href="2005-03.html">Mar</a></td><td><a
+href="2005-04.html">Apr</a></td><td><a
+href="2005-05.html">May</a></td><td><a
+href="2005-06.html">Jun</a></td><td><a
+href="2005-07.html">Jul</a></td><td><a
+href="2005-08.html">Aug</a></td><td><a
+href="2005-09.html">Sep</a></td><td><a
+href="2005-10.html">Oct</a></td><td><a
+href="2005-11.html">Nov</a></td><td><a
+href="2005-12.html">Dec</a></td></tr>
+
+<tr><th>2004</th><td><a href="2004-01.html">Jan</a></td><td><a
+href="2004-02.html">Feb</a></td><td><a
+href="2004-03.html">Mar</a></td><td><a
+href="2004-04.html">Apr</a></td><td><a
+href="2004-05.html">May</a></td><td><a
+href="2004-06.html">Jun</a></td><td><a
+href="2004-07.html">Jul</a></td><td><a
+href="2004-08.html">Aug</a></td><td><a
+href="2004-09.html">Sep</a></td><td><a
+href="2004-10.html">Oct</a></td><td><a
+href="2004-11.html">Nov</a></td><td><a
+href="2004-12.html">Dec</a></td></tr>
+
+<tr><th>2003</th><td colspan="4" /><td><a
+href="2003-05.html">May</a></td><td><a
+href="2003-06.html">Jun</a></td><td><a
+href="2003-07.html">Jul</a></td><td><a
+href="2003-08.html">Aug</a></td><td><a
+href="2003-09.html">Sep</a></td><td><a
+href="2003-10.html">Oct</a></td><td><a
+href="2003-11.html">Nov</a></td><td><a
+href="2003-12.html">Dec</a></td></tr>
+
+</table>
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-recent-template.daml b/org/madore/damlengine/weblog-recent-template.daml
new file mode 100644
index 0000000..261686f
--- /dev/null
+++ b/org/madore/damlengine/weblog-recent-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+  <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+  %HTMLlat1;
+  <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+  %HTMLspecial;
+  <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+  %HTMLsymbol;
+  <!ENTITY uri-to-top "../">
+  <!ENTITY file.language "en">
+  <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French.  A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa.  Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français.  Quelques-unes ont une version
+dans chaque langue.  À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>!  <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+</d:body>
+
+</d:daml>
-- 
cgit v1.2.3