From 1565d0be33cb4d83ee6fa63081bf09ae0a68693d Mon Sep 17 00:00:00 2001
From: "David A. Madore" <david+git@madore.org>
Date: Wed, 31 Aug 2011 17:23:45 +0200
Subject: RSS feed generator.

---
 org/madore/damlengine/DamlEngine.java              |   4 +
 .../damlengine/WeblogDatabaseConnection.java       |   1 +
 org/madore/damlengine/WeblogRSS.java               | 152 +++++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 org/madore/damlengine/WeblogRSS.java

diff --git a/org/madore/damlengine/DamlEngine.java b/org/madore/damlengine/DamlEngine.java
index 070cbab..e54ee86 100644
--- a/org/madore/damlengine/DamlEngine.java
+++ b/org/madore/damlengine/DamlEngine.java
@@ -19,6 +19,10 @@ public final class DamlEngine {
     public static final String XML_NS = XMLConstants.XML_NS_URI;
     public static final String XHTML_NS = "http://www.w3.org/1999/xhtml";
     public static final String DAML_NS = "http://www.madore.org/~david/NS/daml/";
+    public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+    public static final String RSS10_NS = "http://purl.org/rss/1.0/";
+    public static final String DUBLINCORE_NS = "http://purl.org/dc/elements/1.1/";
+    public static final String SYNDICATION_NS = "http://purl.org/rss/1.0/modules/syndication/";
 
     public static final class DamlNSMapping implements NamespaceContext {
 	// This is used for XPath resolution (_not_ for parsing the document).
diff --git a/org/madore/damlengine/WeblogDatabaseConnection.java b/org/madore/damlengine/WeblogDatabaseConnection.java
index a1dfc1f..c88f5a8 100644
--- a/org/madore/damlengine/WeblogDatabaseConnection.java
+++ b/org/madore/damlengine/WeblogDatabaseConnection.java
@@ -23,6 +23,7 @@ public final class WeblogDatabaseConnection {
 	    dbProps.setProperty("ssl", "true");
 	    dbProps.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory");
 	    conn = (new Driver()).connect(dbUrl, dbProps);
+	    conn.createStatement().execute("SET TIME ZONE 0");
 	}
 	return conn;
     }
diff --git a/org/madore/damlengine/WeblogRSS.java b/org/madore/damlengine/WeblogRSS.java
new file mode 100644
index 0000000..c08991c
--- /dev/null
+++ b/org/madore/damlengine/WeblogRSS.java
@@ -0,0 +1,152 @@
+package org.madore.damlengine;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.*;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSParser;
+import org.w3c.dom.ls.LSSerializer;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSOutput;
+
+public final class WeblogRSS {
+
+    private WeblogRSS() { // Forbid instantiation
+	throw new AssertionError("WeblogRSS cannot be instantiated");
+    }
+
+    public static void main(String[] args)
+	throws Exception {
+
+	final Connection conn = WeblogDatabaseConnection.getConnection();
+
+	final PreparedStatement selSt
+	    = conn.prepareStatement("SELECT id , edate , to_char(cdate,'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') , lang , title , content FROM entries ORDER BY id DESC LIMIT 15");
+
+	final ResultSet selRes = selSt.executeQuery();
+
+	final DocumentBuilder db = DamlEngine.GetDocumentBuilder.db;
+
+	final DOMImplementationLS domi
+	    = (DOMImplementationLS)(db.getDOMImplementation());
+	LSSerializer ser = domi.createLSSerializer();
+	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");
+
+	Document rssDoc = db.newDocument();
+	Element rssRoot = rssDoc.createElementNS(DamlEngine.RDF_NS, "rdf:RDF");
+	rssDoc.appendChild(rssRoot);
+	// rssDoc.appendChild(rssDoc.createTextNode("\n"));
+
+	rssRoot.setAttributeNS(DamlEngine.XMLNS_NS, "xmlns:rdf", DamlEngine.RDF_NS);
+	rssRoot.setAttributeNS(DamlEngine.XMLNS_NS, "xmlns", DamlEngine.RSS10_NS);
+	rssRoot.setAttributeNS(DamlEngine.XMLNS_NS, "xmlns:dc", DamlEngine.DUBLINCORE_NS);
+	rssRoot.setAttributeNS(DamlEngine.XMLNS_NS, "xmlns:sy", DamlEngine.SYNDICATION_NS);
+	rssRoot.setAttributeNS(DamlEngine.XML_NS, "xml:lang", "en");
+	rssRoot.appendChild(rssDoc.createTextNode("\n"));
+
+	Element channel = rssDoc.createElementNS(DamlEngine.RSS10_NS, "channel");
+	rssRoot.appendChild(channel);
+	rssRoot.appendChild(rssDoc.createTextNode("\n"));
+	channel.setAttributeNS(DamlEngine.RDF_NS, "rdf:about", "http://www.madore.org/~david/weblog/");
+	channel.appendChild(rssDoc.createTextNode("\n"));
+
+	Element chanTitle = rssDoc.createElementNS(DamlEngine.RSS10_NS, "title");
+	channel.appendChild(chanTitle);
+	channel.appendChild(rssDoc.createTextNode("\n"));
+	chanTitle.appendChild(rssDoc.createTextNode("David Madore's WebLog"));
+	Element syUpdatePeriod = rssDoc.createElementNS(DamlEngine.SYNDICATION_NS, "sy:updatePeriod");
+	channel.appendChild(syUpdatePeriod);
+	channel.appendChild(rssDoc.createTextNode("\n"));
+	syUpdatePeriod.appendChild(rssDoc.createTextNode("hourly"));
+	Element syUpdateFrequency = rssDoc.createElementNS(DamlEngine.SYNDICATION_NS, "sy:updateFrequency");
+	channel.appendChild(syUpdateFrequency);
+	channel.appendChild(rssDoc.createTextNode("\n"));
+	syUpdateFrequency.appendChild(rssDoc.createTextNode("3"));
+	Element syUpdateBase = rssDoc.createElementNS(DamlEngine.SYNDICATION_NS, "sy:updateBase");
+	channel.appendChild(syUpdateBase);
+	channel.appendChild(rssDoc.createTextNode("\n"));
+	syUpdateBase.appendChild(rssDoc.createTextNode("2003-05-01T10:00:00Z"));
+	Element chanItems = rssDoc.createElementNS(DamlEngine.RSS10_NS, "items");
+	channel.appendChild(chanItems);
+	channel.appendChild(rssDoc.createTextNode("\n"));
+	chanItems.appendChild(rssDoc.createTextNode("\n"));
+	Element itemsSeq = rssDoc.createElementNS(DamlEngine.RDF_NS, "rdf:Seq");
+	chanItems.appendChild(itemsSeq);
+	chanItems.appendChild(rssDoc.createTextNode("\n"));
+	itemsSeq.appendChild(rssDoc.createTextNode("\n"));
+
+	while ( selRes.next() ) {
+	    int id = selRes.getInt(1);
+	    String date = selRes.getString(2);
+	    String cdate = selRes.getString(3);
+	    String lang = selRes.getString(4);
+	    String title = selRes.getString(5);
+	    String contentXml = selRes.getString(6);
+	    Matcher matcher = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$").matcher(date);
+	    if ( ! matcher.matches() )
+		throw new IllegalArgumentException("entry "+id+" has badly formed date");
+	    String yearStr = matcher.group(1);
+	    String monthStr = matcher.group(2);
+	    // String dayStr = matcher.group(3);
+	    String numberStr = String.format("%04d",id);
+	    String aboutUri = "http://www.madore.org/~david/weblog/"
+		+ "#d." + date + "." + numberStr;
+	    String linkUri = "http://www.madore.org/~david/weblog/"
+		+ yearStr + "-" + monthStr + ".html"
+		+ "#d." + date + "." + numberStr;
+	    Element li = rssDoc.createElementNS(DamlEngine.RDF_NS, "rdf:li");
+	    itemsSeq.appendChild(li);
+	    itemsSeq.appendChild(rssDoc.createTextNode("\n"));
+	    li.setAttributeNS(DamlEngine.RDF_NS, "rdf:resource",
+			      aboutUri);
+	    Element item = rssDoc.createElementNS(DamlEngine.RSS10_NS, "item");
+	    rssRoot.appendChild(item);
+	    rssRoot.appendChild(rssDoc.createTextNode("\n"));
+	    item.setAttributeNS(DamlEngine.RDF_NS, "rdf:about",
+				aboutUri);
+	    item.setAttributeNS(DamlEngine.XML_NS, "xml:lang", lang);
+	    item.appendChild(rssDoc.createTextNode("\n"));
+	    Element itemTitle = rssDoc.createElementNS(DamlEngine.RSS10_NS, "title");
+	    item.appendChild(itemTitle);
+	    item.appendChild(rssDoc.createTextNode("\n"));
+	    itemTitle.appendChild(rssDoc.createTextNode(title));
+	    Element itemLink = rssDoc.createElementNS(DamlEngine.RSS10_NS, "link");
+	    item.appendChild(itemLink);
+	    item.appendChild(rssDoc.createTextNode("\n"));
+	    itemLink.appendChild(rssDoc.createTextNode(linkUri));
+	    Element itemDate = rssDoc.createElementNS(DamlEngine.DUBLINCORE_NS, "dc:date");
+	    item.appendChild(itemDate);
+	    item.appendChild(rssDoc.createTextNode("\n"));
+	    itemDate.appendChild(rssDoc.createTextNode(cdate));
+	    LSInput input = domi.createLSInput();
+	    input.setStringData(contentXml);
+	    Document temp = par.parse(input);
+	    String contentStr = temp.getDocumentElement().getTextContent();
+	    int bound;
+	    try {
+		bound = Character.offsetByCodePoints(contentStr, 0, 160);
+	    } catch (IndexOutOfBoundsException e) {
+		bound = contentStr.length();
+	    }
+	    String descrStr = contentStr.substring(0, bound).replace("\n"," ");
+	    Element itemDescr = rssDoc.createElementNS(DamlEngine.RSS10_NS, "description");
+	    item.appendChild(itemDescr);
+	    item.appendChild(rssDoc.createTextNode("\n"));
+	    itemDescr.appendChild(rssDoc.createTextNode(descrStr));
+	}
+
+	ser.write(rssDoc, out);
+	out.getByteStream().write("\n".getBytes("UTF-8"));
+
+    }
+
+}
-- 
cgit v1.2.3