package org.madore.damlengine; import java.util.ArrayList; import java.util.regex.Pattern; import java.util.regex.Matcher; import org.w3c.dom.*; public final class TodoEntryElement extends TodoDefaultElement { public static class Factory extends TodoElement.Factory { @Override public TodoEntryElement newItem(Element node, Context ctx, TodoItem caller) { return new TodoEntryElement(node, ctx, caller); } } public TodoEntryElement(Element node, Context ctx, TodoItem caller) { super(node, ctx, caller); } @Override public void handleNodeOnly() { if ( ! ( caller instanceof TodoWeblogElement || caller instanceof TodoWeblogSelectElement ) ) throw new IllegalArgumentException("entry node can only be child of weblog node"); // A container
that contains everything Element containerDiv = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "div"); node.getParentNode().replaceChild(containerDiv, node); Element beforeP = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "p"); Element afterP = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "p"); // The
element containing the entry itself Element article = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "article"); String lang = LangHelper.getLangRec(node); String explicitLang = LangHelper.getLangNorec(node); if ( explicitLang != null ) LangHelper.setLangNorec(article, explicitLang); containerDiv.appendChild(beforeP); containerDiv.appendChild(article); containerDiv.appendChild(afterP); final String entryNumberStr = node.getAttributeNS(null, "number"); if ( ! Pattern.matches("^\\d{4}$", entryNumberStr) ) throw new IllegalArgumentException("entry number attribute must be of the form NNNN"); final int entryNumber = Integer.parseInt(entryNumberStr); final String entryDateStr = node.getAttributeNS(null, "date"); final Matcher entryDateMatcher = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$").matcher(entryDateStr); if ( ! entryDateMatcher.matches() ) throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD"); final String entryYearStr = entryDateMatcher.group(1); final String entryMonthStr = entryDateMatcher.group(2); final String entryDayStr = entryDateMatcher.group(3); String entryDowStr = node.getAttributeNS(null, "day-of-week"); { final int entryYear = Integer.parseInt(entryYearStr); final int entryMonth = Integer.parseInt(entryMonthStr); final int entryDay = Integer.parseInt(entryDayStr); final String entryRefDowStr = Calendar.dateDowName(lang, entryYear, entryMonth, entryDay); if ( entryRefDowStr != null ) { if ( entryDowStr.equals("") ) { entryDowStr = entryRefDowStr; } else if ( ( ! entryDowStr.equals(entryRefDowStr) ) && node.getAttributeNS(null, "override-day-of-week").equals("") ) { System.err.println("warning: "+entryDateStr+" day of week given "+entryDowStr+" expected "+entryRefDowStr); } } } final String entryCatStr = node.getAttributeNS(null, "cat"); final String entrySpecialNameStr = node.hasAttributeNS(null, "special-name") ? node.getAttributeNS(null, "special-name") : null; final String entryCdateStr = node.getAttributeNS(null, "cdate"); final ArrayList entryCatList; if ( entryCatStr.equals("") ) { entryCatList = new ArrayList(0); } else { String[] temp = entryCatStr.split("\\s+"); entryCatList = new ArrayList(temp.length); for ( String cat : temp ) { if ( ! cat.equals("") ) entryCatList.add(cat); } } final WeblogLink lk = new WeblogLink(entryYearStr, entryMonthStr, entryDayStr, entryNumberStr, "", entrySpecialNameStr); lk.setTypeStandard(); String entryIdStr = lk.getFragment(); article.setAttributeNS(null, "id", entryIdStr); { String classAtt = node.getAttributeNS(null, "class"); if ( ! classAtt.equals("") ) article.setAttributeNS(null, "class", "weblog-entry hentry "+classAtt); else article.setAttributeNS(null, "class", "weblog-entry hentry"); } { String styleAtt = node.getAttributeNS(null, "style"); if ( ! styleAtt.equals("") ) article.setAttributeNS(null, "style", styleAtt); } article.appendChild(ctx.doc.createTextNode("\n")); Element header = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "header"); article.appendChild(header); article.appendChild(ctx.doc.createTextNode("\n")); Element headlink = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "p"); headlink.setAttributeNS(null, "class", "weblog-entry-headlink"); header.appendChild(headlink); header.appendChild(ctx.doc.createTextNode("\n")); Element permalink = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "a"); permalink.setAttributeNS(null, "href", lk.getTarget("")); permalink.setAttributeNS(null, "rel", "bookmark"); Element time = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "time"); permalink.appendChild(time); if ( Pattern.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}(?:\\:\\d{2})?(?:Z|[\\+\\-]\\d{2}\\:\\d{2})$", entryCdateStr) ) time.setAttributeNS(null, "datetime", entryCdateStr); else System.err.println("warning: cdate value "+entryCdateStr +" is not a valid HTML5 datetime"); time.setAttributeNS(null, "pubdate", "pubdate"); time.setAttributeNS(null, "class", "published"); time.appendChild(ctx.doc.createTextNode(entryDateStr)); headlink.appendChild(permalink); if ( ! entryDowStr.equals("") ) headlink.appendChild(ctx.doc.createTextNode(" ("+entryDowStr+")")); // The
that contains the entry's body (content) Element mainDiv = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "div"); article.appendChild(mainDiv); article.appendChild(ctx.doc.createTextNode("\n")); mainDiv.setAttributeNS(null, "class", "entry-content"); Context ctx2 = ctx.clone(); ctx2.ent = new Context.EntryContext(entryYearStr, entryMonthStr, entryDayStr, entryNumberStr, entryDowStr, entrySpecialNameStr, entryCatList); ctx2.ent.headerNode = header; ctx2.ent.headlinkNode = headlink; ctx2.ent.mainDivNode = mainDiv; ArrayList childList = getChildList(this.node); ArrayList toProcess = new ArrayList(childList.size()+8); toProcess.add(TodoElement.getTodoElement(beforeP, ctx2, this)); for ( Node child : childList ) { if ( child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE ) { if ( ! Pattern.matches("^\\s*$",((CharacterData)child).getData()) ) throw new IllegalArgumentException("entry element cannot contain text"); mainDiv.appendChild(ctx.doc.createTextNode("\n")); } else if ( child.getNodeType() == Node.ELEMENT_NODE ) { if ( child.getLocalName().equals("title") ) { article.appendChild(child); } else { mainDiv.appendChild(child); } TodoElement it = TodoElement.getTodoElement((Element)child, ctx2, this); toProcess.add(it); } } Element footer = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "footer"); article.appendChild(footer); article.appendChild(ctx.doc.createTextNode("\n")); footer.setAttributeNS(null, "class", "entry-footer cleared"); if ( entryCatList.size() > 0 ) { Element token = ctx.doc.createElementNS(DamlEngine.DAML_NS, "d:implicit-do-categories"); footer.appendChild(token); footer.appendChild(ctx.doc.createTextNode("\n")); toProcess.add(new TodoCategories(token, ctx2, this)); } if ( node.getAttributeNS(null, "nocomments").equals("") ) { Element token = ctx.doc.createElementNS(DamlEngine.DAML_NS, "d:implicit-do-comments"); footer.appendChild(token); footer.appendChild(ctx.doc.createTextNode("\n")); toProcess.add(new TodoComments(token, ctx2, this)); } toProcess.add(TodoElement.getTodoElement(afterP, ctx2, this)); // Before and after

's { final WeblogSummary wsum = WeblogSummary.getSummary(ctx.dc); final class DoLink { Element parent; int num; String text; boolean permalink; public DoLink(Element parent, int num, String text) { this.parent = parent; this.num = num; this.text = text; this.permalink = false; } public DoLink(Element parent, int num, String text, boolean permalink) { this.parent = parent; this.num = num; this.text = text; this.permalink = permalink; } public Element doit() { final WeblogSummary.EntrySummary esum; if ( wsum != null && wsum.entries != null ) esum = wsum.entries.get(num); else esum = null; Element a; if ( esum != null ) { a = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "a"); a.setAttributeNS(DamlEngine.DAML_NS, "d:wref", "#d." + esum.date + "." + String.format("%04d", esum.id)); if ( permalink ) // TodoWrefAttr handles this attribute: a.setAttributeNS(DamlEngine.DAML_NS, "d:wrefcat", "@force-single"); } else { a = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "del"); } a.appendChild(ctx.doc.createTextNode(text)); parent.appendChild(a); return a; } } Element span, tmp; span = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "span"); beforeP.appendChild(span); LangHelper.setLangRec(span, "en"); span.appendChild(ctx.doc.createTextNode("\u2193Entry #"+entryNumberStr)); span.appendChild(ctx.doc.createTextNode(" [")); new DoLink(span, entryNumber-1, "older").doit(); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber, "\u203b").doit(); tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode(" ")); new DoLink(span, entryNumber, "permalink", true).doit(); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber+1, "newer").doit(); if ( ctx.wsc != null && ctx.wsc.sel != null && ctx.wsc.sel.contains(entryNumber+1) ) tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode("]")); beforeP.appendChild(ctx.doc.createTextNode(" / ")); span = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "span"); beforeP.appendChild(span); LangHelper.setLangRec(span, "fr"); span.appendChild(ctx.doc.createTextNode("\u2193Entr\u00e9e #"+entryNumberStr)); span.appendChild(ctx.doc.createTextNode(" [")); new DoLink(span, entryNumber-1, "pr\u00e9c\u00e9dente").doit(); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber, "\u203b").doit(); tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode(" ")); new DoLink(span, entryNumber, "permalien", true).doit(); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber+1, "suivante").doit(); if ( ctx.wsc != null && ctx.wsc.sel != null && ctx.wsc.sel.contains(entryNumber+1) ) tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode("]")); beforeP.appendChild(ctx.doc.createTextNode("\u2001\u2193")); span = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "span"); afterP.appendChild(span); LangHelper.setLangRec(span, "en"); span.appendChild(ctx.doc.createTextNode("\u2191Entry #"+entryNumberStr)); span.appendChild(ctx.doc.createTextNode(" [")); tmp = new DoLink(span, entryNumber-1, "older").doit(); if ( ctx.wsc != null && ctx.wsc.sel != null && ctx.wsc.sel.contains(entryNumber-1) ) tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber, "\u203b").doit(); tmp.setAttributeNS(null, "title", "(Jump to top of entry)"); span.appendChild(ctx.doc.createTextNode(" ")); new DoLink(span, entryNumber, "permalink", true).doit(); span.appendChild(ctx.doc.createTextNode("|")); new DoLink(span, entryNumber+1, "newer").doit(); span.appendChild(ctx.doc.createTextNode("]")); afterP.appendChild(ctx.doc.createTextNode(" / ")); span = ctx.doc.createElementNS(DamlEngine.XHTML_NS, "span"); afterP.appendChild(span); LangHelper.setLangRec(span, "fr"); span.appendChild(ctx.doc.createTextNode("\u2191Entr\u00e9e #"+entryNumberStr)); span.appendChild(ctx.doc.createTextNode(" [")); tmp = new DoLink(span, entryNumber-1, "pr\u00e9c\u00e9dente").doit(); if ( ctx.wsc != null && ctx.wsc.sel != null && ctx.wsc.sel.contains(entryNumber-1) ) tmp.setAttributeNS(null, "style", "opacity: 0.1"); span.appendChild(ctx.doc.createTextNode("|")); tmp = new DoLink(span, entryNumber, "\u203b").doit(); tmp.setAttributeNS(null, "title", "(Retourner du d\u00e9but de l'entr\u00e9e)"); span.appendChild(ctx.doc.createTextNode(" ")); new DoLink(span, entryNumber, "permalien", true).doit(); span.appendChild(ctx.doc.createTextNode("|")); new DoLink(span, entryNumber+1, "suivante").doit(); span.appendChild(ctx.doc.createTextNode("]")); afterP.appendChild(ctx.doc.createTextNode("\u2001\u2191")); } this.ownerDeque.registerAtStart(toProcess); } }