From 1710554809835a82415a1f8789bed3016c58fc96 Mon Sep 17 00:00:00 2001
From: "David A. Madore" <david+git@madore.org>
Date: Sun, 28 Aug 2011 22:35:34 +0200
Subject: Handling of weblog index (including killing nested a elements).

---
 org/madore/damlengine/Context.java                 |   3 +
 org/madore/damlengine/TodoElement.java             |   7 ++
 org/madore/damlengine/TodoKillAElement.java        |  32 +++++++
 .../damlengine/TodoWeblogIndexSelectElement.java   | 100 +++++++++++++++++++++
 org/madore/damlengine/WeblogIndexSelect.java       |  16 ++++
 org/madore/damlengine/WeblogSummary.java           |  19 ++--
 6 files changed, 170 insertions(+), 7 deletions(-)
 create mode 100644 org/madore/damlengine/TodoKillAElement.java
 create mode 100644 org/madore/damlengine/TodoWeblogIndexSelectElement.java
 create mode 100644 org/madore/damlengine/WeblogIndexSelect.java

diff --git a/org/madore/damlengine/Context.java b/org/madore/damlengine/Context.java
index 8b62b6b..388a076 100644
--- a/org/madore/damlengine/Context.java
+++ b/org/madore/damlengine/Context.java
@@ -71,9 +71,12 @@ public class Context implements Cloneable {
 
     public EntryContext ent;
 
+    public boolean killA;
+
     public Context(Document doc) {
 	this.doc = doc;
 	this.gc = new GeneralContext();
+	this.killA = false;
     }
 
     public Context clone() {
diff --git a/org/madore/damlengine/TodoElement.java b/org/madore/damlengine/TodoElement.java
index 320724c..5c90366 100644
--- a/org/madore/damlengine/TodoElement.java
+++ b/org/madore/damlengine/TodoElement.java
@@ -62,8 +62,12 @@ public abstract class TodoElement extends TodoItem {
 	damlFactories.put("smiley-evil", new TodoSmileyElement.Factory(TodoSmileyElement.Type.EVIL));
 	damlFactories.put("img-a", new TodoImgAElement.Factory());
 	damlFactories.put("weblog-select", new TodoWeblogSelectElement.Factory());
+	damlFactories.put("weblog-index-select", new TodoWeblogIndexSelectElement.Factory());
     }
 
+    protected final static Factory killAFactory
+	= new TodoKillAElement.Factory();
+
     protected final Element node;
 
     public TodoElement(Element node,
@@ -80,6 +84,9 @@ public abstract class TodoElement extends TodoItem {
 	String nsuri = node.getNamespaceURI();
 	if ( nsuri != null && nsuri.equals(DamlEngine.DAML_NS) )
 	    factory = damlFactories.get(node.getLocalName());
+	else if ( nsuri != null && nsuri.equals(DamlEngine.XHTML_NS)
+		  && ctx.killA && node.getLocalName().equals("a") )
+	    factory = killAFactory;
 	if ( factory == null )
 	    factory = damlDefaultFactory;
 	return factory.newItem(node, ctx, caller);
diff --git a/org/madore/damlengine/TodoKillAElement.java b/org/madore/damlengine/TodoKillAElement.java
new file mode 100644
index 0000000..ea63a05
--- /dev/null
+++ b/org/madore/damlengine/TodoKillAElement.java
@@ -0,0 +1,32 @@
+package org.madore.damlengine;
+
+import java.util.ArrayList;
+import org.w3c.dom.*;
+
+public final class TodoKillAElement extends TodoDefaultElement {
+
+    public static class Factory extends TodoElement.Factory {
+	@Override
+	public TodoKillAElement newItem(Element node,
+					Context ctx,
+					TodoItem caller) {
+	    return new TodoKillAElement(node, ctx, caller);
+	}
+    }
+
+    public TodoKillAElement(Element node,
+			    Context ctx,
+			    TodoItem caller) {
+	super(node, ctx, caller);
+    }
+
+    @Override
+    public void handleNodeOnly() {
+	ArrayList<Node> childList = getChildList(node);
+	for ( Node child : childList ) {
+	    node.getParentNode().insertBefore(child, node);
+	}
+	node.getParentNode().removeChild(node);
+    }
+
+}
diff --git a/org/madore/damlengine/TodoWeblogIndexSelectElement.java b/org/madore/damlengine/TodoWeblogIndexSelectElement.java
new file mode 100644
index 0000000..b82953a
--- /dev/null
+++ b/org/madore/damlengine/TodoWeblogIndexSelectElement.java
@@ -0,0 +1,100 @@
+package org.madore.damlengine;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import org.w3c.dom.*;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSParser;
+import org.w3c.dom.ls.LSInput;
+
+public final class TodoWeblogIndexSelectElement extends TodoDefaultElement {
+
+    public static class Factory extends TodoElement.Factory {
+	@Override
+	public TodoWeblogIndexSelectElement newItem(Element node,
+						    Context ctx,
+						    TodoItem caller) {
+	    return new TodoWeblogIndexSelectElement(node, ctx, caller);
+	}
+    }
+
+    public TodoWeblogIndexSelectElement(Element node,
+					Context ctx,
+					TodoItem caller) {
+	super(node, ctx, caller);
+    }
+
+    @Override
+    public void handleNodeOnly() {
+	WeblogSummary wsum = WeblogSummary.getSummary();
+	if ( wsum == null || wsum.entries == null ) {
+	    throw new IllegalStateException("weblog-index-select element encountered with no weblog summary available");
+	}
+	TreeSet<Integer> entlist = new TreeSet<Integer>(wsum.entries.keySet());
+	Element ul = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "ul");
+	ul.setAttributeNS(null, "id", "index");
+	ul.appendChild(ctx.doc.createTextNode("\n"));
+	node.getParentNode().replaceChild(ul, node);
+	final DOMImplementationLS domi
+	    = (DOMImplementationLS)ctx.doc.getImplementation();
+	LSParser par = domi.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
+	ArrayList<TodoElement> toProcess
+	    = new ArrayList<TodoElement>(entlist.size()*2);
+	Context ctx2 = ctx.clone();  ctx2.killA = true;
+	for ( Iterator<Integer> iter=entlist.descendingIterator() ; iter.hasNext() ; ) {
+	    WeblogSummary.EntrySummary ent = wsum.entries.get(iter.next());
+	    Matcher matcher = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$").matcher(ent.date);
+	    if ( ! matcher.matches() )
+		throw new IllegalArgumentException("entry "+ent.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",ent.id);
+	    String targetFile = "";
+	    targetFile = ((ctx.gc.uriToTop==null)?"":(ctx.gc.uriToTop+"weblog/"))
+		+ yearStr + "-" + monthStr + ".html";
+	    String targetFragment = "d." + yearStr + "-" + monthStr
+		+ "-" + dayStr + "." + numberStr;
+	    String target = targetFile + "#" + targetFragment;
+	    Element li = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "li");
+	    ul.appendChild(li);
+	    ul.appendChild(ctx.doc.createTextNode("\n"));
+	    li.setAttributeNS(null, "id", targetFragment);
+	    li.setAttributeNS(null, "class", "weblog-index-entry");
+	    LangHelper.setLangRec(li, ent.lang);
+	    Element link;
+	    if ( ent.titleXml == null ) {
+		link = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "a");
+		li.appendChild(link);
+		link.appendChild(ctx.doc.createTextNode(ent.date));
+	    } else {
+		li.appendChild(ctx.doc.createTextNode(ent.date+": "));
+		link = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "a");
+		li.appendChild(link);
+		LSInput input = domi.createLSInput();
+		input.setStringData(ent.titleXml);
+		Document temp = par.parse(input);
+		Node newNode = ctx.doc.adoptNode(temp.getDocumentElement());
+		String explicitLang = LangHelper.getLangNorec(newNode);
+		if ( explicitLang != null )
+		    LangHelper.setLangNorec(link, explicitLang);
+		ArrayList<Node> childList = getChildList(newNode);
+		for ( Node child : childList ) {
+		    link.appendChild(child);
+		    if ( child instanceof Element ) {
+			TodoElement it
+			    = TodoElement.getTodoElement((Element)child,
+							 ctx2, this);
+			toProcess.add(it);
+		    }
+		}
+	    }
+	    link.setAttributeNS(null, "href", target);
+	}
+	this.ownerDeque.registerAtStart(toProcess);
+    }
+
+}
diff --git a/org/madore/damlengine/WeblogIndexSelect.java b/org/madore/damlengine/WeblogIndexSelect.java
new file mode 100644
index 0000000..5d6bc53
--- /dev/null
+++ b/org/madore/damlengine/WeblogIndexSelect.java
@@ -0,0 +1,16 @@
+package org.madore.damlengine;
+
+public final class WeblogIndexSelect {
+
+    private WeblogIndexSelect() { // Forbid instantiation
+	throw new AssertionError("WeblogIndexSelect cannot be instantiated");
+    }
+
+    public static void main(String[] args)
+	throws Exception {
+
+	DamlEngine.fullProcess("weblog-index-template.daml", System.out, null);
+
+    }
+
+}
diff --git a/org/madore/damlengine/WeblogSummary.java b/org/madore/damlengine/WeblogSummary.java
index ceaf28e..babfcf5 100644
--- a/org/madore/damlengine/WeblogSummary.java
+++ b/org/madore/damlengine/WeblogSummary.java
@@ -11,11 +11,15 @@ public final class WeblogSummary {
     public static final class EntrySummary {
 	int id;
 	String date;
-	String title;
-	public EntrySummary(int id, String date, String title) {
+	String lang;
+	String title;  String titleXml;
+	public EntrySummary(int id, String date, String lang,
+			    String title, String titleXml) {
 	    this.id = id;
 	    this.date = date;
+	    this.lang = lang;
 	    this.title = title;
+	    this.titleXml = titleXml;
 	}
     }
 
@@ -34,18 +38,19 @@ public final class WeblogSummary {
 	try {
 	    final Connection conn = WeblogDatabaseConnection.getConnection();
 	    final PreparedStatement selSt
-		= conn.prepareStatement("SELECT id , edate , title FROM entries");
+		= conn.prepareStatement("SELECT id , edate , lang , title , title_xml FROM entries");
 	    final ResultSet selRes = selSt.executeQuery();
 	    while ( selRes.next() ) {
 		int id = selRes.getInt(1);
 		String date = selRes.getString(2);
-		String title = selRes.getString(3);
-		singleton.entries.put(new Integer(id), new EntrySummary(id, date, title));
+		String lang = selRes.getString(3);
+		String title = selRes.getString(4);
+		String titleXml = selRes.getString(5);
+		singleton.entries.put(new Integer(id), new EntrySummary(id, date, lang, title, titleXml));
 	    }
 	} catch (SQLException e) {
-	    throw new RuntimeException(e);
 	    // Well, we'll have no summary.  Too bad, but better than abort.
-	    // singleton = null;
+	    singleton = null;
 	}
 	return singleton;
     }
-- 
cgit v1.2.3