diff options
-rw-r--r-- | org/madore/damlengine/Context.java | 3 | ||||
-rw-r--r-- | org/madore/damlengine/DamlEngine.java | 24 | ||||
-rw-r--r-- | org/madore/damlengine/TodoElement.java | 1 | ||||
-rw-r--r-- | org/madore/damlengine/TodoEntryElement.java | 7 | ||||
-rw-r--r-- | org/madore/damlengine/TodoWeblogSelectElement.java | 54 | ||||
-rw-r--r-- | org/madore/damlengine/TodoWrefAttr.java | 21 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogDatabaseConnection.java | 30 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogPopulate.java | 26 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogSelect.java | 43 | ||||
-rw-r--r-- | org/madore/damlengine/WeblogSummary.java | 53 |
10 files changed, 227 insertions, 35 deletions
diff --git a/org/madore/damlengine/Context.java b/org/madore/damlengine/Context.java index d001389..8b62b6b 100644 --- a/org/madore/damlengine/Context.java +++ b/org/madore/damlengine/Context.java @@ -1,6 +1,7 @@ package org.madore.damlengine; import java.util.ArrayList; +import java.util.Set; import org.w3c.dom.*; public class Context implements Cloneable { @@ -26,6 +27,8 @@ public class Context implements Cloneable { public GeneralContext gc; public static abstract class WeblogSelectionContext { + public Set<Integer> sel; + public ArrayList<String> xmlData; } public static class WeblogMonthSelectionContext diff --git a/org/madore/damlengine/DamlEngine.java b/org/madore/damlengine/DamlEngine.java index bf2049d..da49aeb 100644 --- a/org/madore/damlengine/DamlEngine.java +++ b/org/madore/damlengine/DamlEngine.java @@ -6,6 +6,7 @@ import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; // import org.xml.sax.EntityResolver; import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; @@ -40,6 +41,22 @@ public final class DamlEngine { } } + public static final class GetDocumentBuilder { + static final DocumentBuilder db; + static { + final Resolver resolver = new Resolver(); + final DocumentBuilderFactory dbf = new DocumentBuilderFactoryImpl(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + try { + db = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } + db.setEntityResolver(resolver); + } + } + private DamlEngine() { // Forbid instantiation throw new AssertionError("DamlEngine cannot be instantiated"); } @@ -73,12 +90,7 @@ public final class DamlEngine { Context.WeblogSelectionContext wsc) throws Exception { - final Resolver resolver = new Resolver(); - final DocumentBuilderFactory dbf = new DocumentBuilderFactoryImpl(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - final DocumentBuilder db = dbf.newDocumentBuilder(); - db.setEntityResolver(resolver); + final DocumentBuilder db = GetDocumentBuilder.db; Document doc = db.parse(fname); processDocument(doc, wsc); diff --git a/org/madore/damlengine/TodoElement.java b/org/madore/damlengine/TodoElement.java index 94867cc..320724c 100644 --- a/org/madore/damlengine/TodoElement.java +++ b/org/madore/damlengine/TodoElement.java @@ -61,6 +61,7 @@ public abstract class TodoElement extends TodoItem { damlFactories.put("smiley-cry", new TodoSmileyElement.Factory(TodoSmileyElement.Type.CRY)); damlFactories.put("smiley-evil", new TodoSmileyElement.Factory(TodoSmileyElement.Type.EVIL)); damlFactories.put("img-a", new TodoImgAElement.Factory()); + damlFactories.put("weblog-select", new TodoWeblogSelectElement.Factory()); } protected final Element node; diff --git a/org/madore/damlengine/TodoEntryElement.java b/org/madore/damlengine/TodoEntryElement.java index 8b38881..78bffd1 100644 --- a/org/madore/damlengine/TodoEntryElement.java +++ b/org/madore/damlengine/TodoEntryElement.java @@ -24,7 +24,8 @@ public final class TodoEntryElement extends TodoDefaultElement { @Override public void handleNodeOnly() { - if ( ! ( caller instanceof TodoWeblogElement ) ) + if ( ! ( caller instanceof TodoWeblogElement + || caller instanceof TodoWeblogSelectElement ) ) throw new IllegalArgumentException("entry node can only be child of weblog node"); Element div = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "div"); @@ -35,11 +36,11 @@ public final class TodoEntryElement extends TodoDefaultElement { String entryNumberStr = node.getAttributeNS(null, "number"); if ( ! Pattern.matches("^\\d{4}$", entryNumberStr) ) - throw new IllegalArgumentException("title number attribute must be of the form NNNN"); + throw new IllegalArgumentException("entry number attribute must be of the form NNNN"); String entryDateStr = node.getAttributeNS(null, "date"); Matcher entryDateMatcher = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$").matcher(entryDateStr); if ( ! entryDateMatcher.matches() ) - throw new IllegalArgumentException("title date attribute must be of the form YYYY-MM-DD"); + throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD"); String entryYearStr = entryDateMatcher.group(1); String entryMonthStr = entryDateMatcher.group(2); String entryDayStr = entryDateMatcher.group(3); diff --git a/org/madore/damlengine/TodoWeblogSelectElement.java b/org/madore/damlengine/TodoWeblogSelectElement.java new file mode 100644 index 0000000..145b938 --- /dev/null +++ b/org/madore/damlengine/TodoWeblogSelectElement.java @@ -0,0 +1,54 @@ +package org.madore.damlengine; + +import java.util.ArrayList; +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 TodoWeblogSelectElement extends TodoDefaultElement { + + public static class Factory extends TodoElement.Factory { + @Override + public TodoWeblogSelectElement newItem(Element node, + Context ctx, + TodoItem caller) { + return new TodoWeblogSelectElement(node, ctx, caller); + } + } + + public TodoWeblogSelectElement(Element node, + Context ctx, + TodoItem caller) { + super(node, ctx, caller); + } + + @Override + public void handleNodeOnly() { + if ( ctx.wsc == null ) { + throw new IllegalStateException("weblog-select element encountered with no weblog selection state"); + } + final DOMImplementationLS domi + = (DOMImplementationLS)ctx.doc.getImplementation(); + LSParser par = domi.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); + ArrayList<TodoElement> toProcess + = new ArrayList<TodoElement>(ctx.wsc.xmlData.size()); + for ( String str : ctx.wsc.xmlData ) { + LSInput input = domi.createLSInput(); + input.setStringData(str); + // Xerces2 does not implement parseWithContext() :-( + // Node newNode = par.parseWithContext(input, node, + // LSParser.ACTION_INSERT_BEFORE); + Document temp = par.parse(input); + Node newNode = ctx.doc.adoptNode(temp.getDocumentElement()); + node.getParentNode().insertBefore(newNode, node); + TodoElement it + = TodoElement.getTodoElement((Element)newNode, + this.ctx, this); + toProcess.add(it); + } + node.getParentNode().removeChild(node); + this.ownerDeque.registerAtStart(toProcess); + } + +} diff --git a/org/madore/damlengine/TodoWrefAttr.java b/org/madore/damlengine/TodoWrefAttr.java index 60fec1d..df30d99 100644 --- a/org/madore/damlengine/TodoWrefAttr.java +++ b/org/madore/damlengine/TodoWrefAttr.java @@ -33,10 +33,8 @@ public class TodoWrefAttr extends TodoAttr { String wrefNumberStr = wrefMatcher.group(4); String wrefSupplementStr = wrefMatcher.group(5); String targetFile = ""; - if ( ctx.wsc != null - && ctx.wsc instanceof Context.WeblogMonthSelectionContext - && wrefYearStr.equals(((Context.WeblogMonthSelectionContext)ctx.wsc).year) - && wrefMonthStr.equals(((Context.WeblogMonthSelectionContext)ctx.wsc).month) ) + if ( ctx.wsc != null && ctx.wsc.sel != null + && ctx.wsc.sel.contains(new Integer(wrefNumberStr)) ) targetFile = ""; else targetFile = ((ctx.gc.uriToTop==null)?"":(ctx.gc.uriToTop+"weblog/")) @@ -48,6 +46,21 @@ public class TodoWrefAttr extends TodoAttr { this.owner.setAttributeNS(null, "href", target); if ( ! this.owner.hasAttributeNS(null, "class") ) this.owner.setAttributeNS(null, "class", "weblog-internal-link"); + if ( wrefSupplementStr.equals("") + && ! this.owner.hasAttributeNS(null, "title") ) { + WeblogSummary wsum = WeblogSummary.getSummary(); + if ( wsum != null && wsum.entries != null ) { + WeblogSummary.EntrySummary esum + = wsum.entries.get(new Integer(wrefNumberStr)); + if ( esum != null ) { + if ( ! ((wrefYearStr+"-"+wrefMonthStr+"-"+wrefDayStr) + .equals(esum.date)) ) + System.err.println("warning: date mismatch for reference to entry "+wrefNumberStr); + if ( esum.title != null ) + this.owner.setAttributeNS(null, "title", esum.title); + } + } + } } } diff --git a/org/madore/damlengine/WeblogDatabaseConnection.java b/org/madore/damlengine/WeblogDatabaseConnection.java new file mode 100644 index 0000000..a1dfc1f --- /dev/null +++ b/org/madore/damlengine/WeblogDatabaseConnection.java @@ -0,0 +1,30 @@ +package org.madore.damlengine; + +import java.util.Properties; +import java.sql.Connection; +import java.sql.SQLException; +import org.postgresql.Driver; + +public final class WeblogDatabaseConnection { + + private WeblogDatabaseConnection() { // Forbid instantiation + throw new AssertionError("WeblogDatabaseConnection cannot be instantiated"); + } + + public static Connection conn; + + public static Connection getConnection() + throws SQLException { + if ( conn == null ) { + final String dbUrl = "jdbc:postgresql://localhost/weblog"; + final Properties dbProps = new Properties(); + dbProps.setProperty("user", "david"); + dbProps.setProperty("password", "IHATETHISWHYCANTIUSEUNIXDOMAINSOCKETS"); + dbProps.setProperty("ssl", "true"); + dbProps.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); + conn = (new Driver()).connect(dbUrl, dbProps); + } + return conn; + } + +} diff --git a/org/madore/damlengine/WeblogPopulate.java b/org/madore/damlengine/WeblogPopulate.java index 18e46c3..24c61dc 100644 --- a/org/madore/damlengine/WeblogPopulate.java +++ b/org/madore/damlengine/WeblogPopulate.java @@ -1,21 +1,16 @@ package org.madore.damlengine; -import java.util.Properties; import java.util.regex.Pattern; import java.security.MessageDigest; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.xpath.*; import org.w3c.dom.*; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; // import org.xml.sax.EntityResolver; -import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; -import org.apache.xerces.dom.DOMImplementationSourceImpl; -import org.postgresql.Driver; public final class WeblogPopulate { @@ -33,33 +28,20 @@ public final class WeblogPopulate { public static void main(String[] args) throws Exception { - final Resolver resolver = new Resolver(); - final DocumentBuilderFactory dbf = new DocumentBuilderFactoryImpl(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - final DocumentBuilder db = dbf.newDocumentBuilder(); - db.setEntityResolver(resolver); + final DocumentBuilder db = DamlEngine.GetDocumentBuilder.db; if ( args.length == 0 ) { System.err.println("expecting filename as argument"); } - final DOMImplementationSource domisrc - = new DOMImplementationSourceImpl(); final DOMImplementationLS domi - = (DOMImplementationLS)(domisrc.getDOMImplementation("LS")); + = (DOMImplementationLS)(db.getDOMImplementation()); LSSerializer ser = domi.createLSSerializer(); ser.getDomConfig().setParameter("xml-declaration", false); MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); - final String dbUrl = "jdbc:postgresql://localhost/weblog"; - final Properties dbProps = new Properties(); - dbProps.setProperty("user", "david"); - dbProps.setProperty("password", "IHATETHISWHYCANTIUSEUNIXDOMAINSOCKETS"); - dbProps.setProperty("ssl", "true"); - dbProps.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); - final Connection conn = (new Driver()).connect(dbUrl, dbProps); + final Connection conn = WeblogDatabaseConnection.getConnection(); final PreparedStatement checkSt = conn.prepareStatement("SELECT sha1 FROM entries WHERE id=?"); @@ -103,7 +85,7 @@ public final class WeblogPopulate { continue; Node titleNode = (Node)(texpr.evaluate(ent, XPathConstants.NODE)); String titleTxt = (titleNode != null) ? titleNode.getTextContent() : null; - String titleXml = ser.writeToString(titleNode); + String titleXml = (titleNode != null) ? ser.writeToString(titleNode) : null; conn.setAutoCommit(false); if ( exists ) { System.err.println("Updating entry "+id); diff --git a/org/madore/damlengine/WeblogSelect.java b/org/madore/damlengine/WeblogSelect.java new file mode 100644 index 0000000..ad61cbc --- /dev/null +++ b/org/madore/damlengine/WeblogSelect.java @@ -0,0 +1,43 @@ +package org.madore.damlengine; + +import java.util.HashSet; +import java.util.ArrayList; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public final class WeblogSelect { + + private WeblogSelect() { // Forbid instantiation + throw new AssertionError("WeblogSelect cannot be instantiated"); + } + + public static void main(String[] args) + 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+"-__"); + + 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() ) { + int id = selRes.getInt(1); + String content = selRes.getString(2); + wsc.sel.add(new Integer(id)); + wsc.xmlData.add(content); + } + + DamlEngine.fullProcess("weblog-month-template.daml", System.out, wsc); + + } + +} diff --git a/org/madore/damlengine/WeblogSummary.java b/org/madore/damlengine/WeblogSummary.java new file mode 100644 index 0000000..ceaf28e --- /dev/null +++ b/org/madore/damlengine/WeblogSummary.java @@ -0,0 +1,53 @@ +package org.madore.damlengine; + +import java.util.HashMap; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public final class WeblogSummary { + + public static final class EntrySummary { + int id; + String date; + String title; + public EntrySummary(int id, String date, String title) { + this.id = id; + this.date = date; + this.title = title; + } + } + + public HashMap<Integer,EntrySummary> entries; + + private static WeblogSummary singleton; + + private WeblogSummary() { + this.entries = new HashMap<Integer,EntrySummary>(); + } + + public static WeblogSummary getSummary() { + if ( singleton != null ) + return singleton; + singleton = new WeblogSummary(); + try { + final Connection conn = WeblogDatabaseConnection.getConnection(); + final PreparedStatement selSt + = conn.prepareStatement("SELECT id , edate , title 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)); + } + } catch (SQLException e) { + throw new RuntimeException(e); + // Well, we'll have no summary. Too bad, but better than abort. + // singleton = null; + } + return singleton; + } + +} |