Jörn Nettingsmeier wrote:
hi thorsten, hi everyone!
ok, here's my first attempt.
the first patch changes all private methods in LenyaMetaDataGenerator to
"protected".
the second file is a new subclass, LenyaSaneMetaDataGenerator (NOI
thorsten ;), that attempts to parse the messy metadata into something
more xmlish, which can then be handled more gracefully with xslts.
if you want to try it, just drop it into
src/java/org/apache/lenya/cms/cocoon/generation.
the third patch activates the new generator in the default sitemap.
after rebuilding, browse default/authoring/meta&docid=index&lang=en and
check out the output. for maximum enjoyment, it is advisable to submit
the current document, otherwise there will be no workflow metadata to view.
if you wonder why bother at all: i'm doing a "last changed on ... by
..." footer with it:
<div id="fusszeile">
© <i18n:text key="name_uni"/>, <i18n:text key="name_dept"/>.
<xsl:variable name="date">
<xsl:value-of
select="//lenya:meta/lenya:internal/lenya:workflow/lenya:version[last()]/lenya:timestamp/lenya:date"/>
</xsl:variable>
<xsl:variable name="time">
<xsl:value-of
select="//lenya:meta/lenya:internal/lenya:workflow/lenya:version[last()]/lenya:timestamp/lenya/time"/>
</xsl:variable>
<!-- avoid i18n "unparseable date" exception -->
<xsl:if test="$date and $time">
<i18n:translate>
<i18n:text i18n:key="last_change"/>
<i18n:param name="last_change_date">
<i18n:date src-pattern="yyyy-mm-dd" locale="{$language}"
value="{$date}"/>
<xsl:text>, </xsl:text>
<i18n:time src-pattern="hh:mm:ss" locale="{$language}"
value="{$time}"/>
</i18n:param>
<i18n:param name="last_change_by">
<xsl:value-of select="//lenya:meta/lenya:internal/
lenya:workflow/lenya:version[lenya:event =
'edit'][last()]/lenya:user"/>
</i18n:param>
</i18n:translate>
</xsl:if>
</div>
caveat: i don't know zilch about java, and this thing hasn't seen much
testing yet. i would welcome suggestions re style and implementation.
regards,
jörn
--
"Open source takes the bullshit out of software."
- Charles Ferguson on TechnologyReview.com
--
Jörn Nettingsmeier, EDV-Administrator
Institut für Politikwissenschaft
Universität Duisburg-Essen, Standort Duisburg
Mail: [EMAIL PROTECTED], Telefon: 0203/379-2736
Index: src/java/org/apache/lenya/cms/cocoon/generation/LenyaMetaDataGenerator.java
===================================================================
--- src/java/org/apache/lenya/cms/cocoon/generation/LenyaMetaDataGenerator.java (revision 411441)
+++ src/java/org/apache/lenya/cms/cocoon/generation/LenyaMetaDataGenerator.java (working copy)
@@ -222,7 +222,7 @@
endNodeRoot(ROOT_META_NODE_NAME);
}
- private void performIncludesMeta() throws SAXException, ProcessingException {
+ protected void performIncludesMeta() throws SAXException, ProcessingException {
// custom metadata
startNodeMeta(ROOT_CUSTOM_META_NODE_NAME);
parseMetaData("custom");
@@ -237,7 +237,7 @@
endNodeMeta(ROOT_DC_META_NODE_NAME);
}
- private void parseMetaData(String type) throws ProcessingException, SAXException {
+ protected void parseMetaData(String type) throws ProcessingException, SAXException {
MetaData metaData = getMetaData(type);
HashMap elementMap;
elementMap = metaData.getAvailableKey2Value();
@@ -266,37 +266,37 @@
}
}
- private void endNodeRoot(String nodeName) throws SAXException {
+ protected void endNodeRoot(String nodeName) throws SAXException {
endNodeMeta(nodeName);
this.contentHandler.endPrefixMapping(PREFIX_META);
this.contentHandler.endDocument();
}
- private void startNodeRoot(String nodeName) throws SAXException {
+ protected void startNodeRoot(String nodeName) throws SAXException {
this.contentHandler.startDocument();
this.contentHandler.startPrefixMapping(PREFIX_META, URI_META);
startNodeMeta(nodeName);
}
- private void startNodeMeta(String nodeName) throws SAXException {
+ protected void startNodeMeta(String nodeName) throws SAXException {
this.contentHandler.startElement(URI_META,
nodeName,
PREFIX_META + ":" + nodeName,
attributes);
}
- private void endNodeMeta(String nodeName) throws SAXException {
+ protected void endNodeMeta(String nodeName) throws SAXException {
this.contentHandler.endElement(URI_META, nodeName, PREFIX_META + ":" + nodeName);
}
- private void startNodeMetaDC(String nodeName) throws SAXException {
+ protected void startNodeMetaDC(String nodeName) throws SAXException {
this.contentHandler.startElement(URI_META_DC,
nodeName,
PREFIX_META_DC + ":" + nodeName,
attributes);
}
- private void endNodeMetaDC(String nodeName) throws SAXException {
+ protected void endNodeMetaDC(String nodeName) throws SAXException {
this.contentHandler.endElement(URI_META_DC, nodeName, PREFIX_META_DC + ":" + nodeName);
}
/*
* Copyright 1999-20045 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lenya.cms.cocoon.generation;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.cocoon.ProcessingException;
import org.apache.lenya.cms.metadata.MetaData;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* Meta data generator with sane XML output of the internal workflowVersion data.
*/
public class LenyaSaneMetaDataGenerator extends LenyaMetaDataGenerator {
protected void parseMetaData(String type) throws ProcessingException, SAXException {
MetaData metaData = getMetaData(type);
HashMap elementMap;
Iterator iteratorMap;
Map.Entry entry;
String key;
String value;
char[] textNode;
elementMap = metaData.getAvailableKey2Value();
if ("dc".equals(type)) {
iteratorMap = elementMap.entrySet().iterator();
while (iteratorMap.hasNext()) {
entry = (Map.Entry) iteratorMap.next();
key = (String) entry.getKey();
value = (String) entry.getValue();
this.contentHandler.startPrefixMapping(PREFIX_META_DC, URI_META_DC);
startNodeMetaDC(key);
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMetaDC(key);
this.contentHandler.endPrefixMapping(PREFIX_META_DC);
}
} else if ("custom".equals(type) | "internal".equals(type)) {
iteratorMap = elementMap.entrySet().iterator();
while (iteratorMap.hasNext()) {
entry = (Map.Entry) iteratorMap.next();
key = (String) entry.getKey();
value = (String) entry.getValue();
if (key.equals("workflowVersion")) {
parseRawWorkflowData(value);
} else {
startNodeMeta(key);
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta(key);
}
}
}
}
/**
* hack and slash the messy workflowVersion data into decent xml.
* assumptions:
* 1. the "event" data snippet is the first in each record.
* 2. every workflow version record starts with a single number,
* which is unfortunately not separated by whitespace from the previous record (this is probably a bug).
* it is represented by the xml element <index/>
* 3. the string "-REALLY_HACKISH_SEPARATOR-" never occurs in the data.
* (FIXME: is there a string that's "officially" illegal ?)
* 4. every other data snippet except for the version number at the beginning is
* of the form $key:$value, where $key can contain only lowercase characters.
* data snippets are represented in xml as <name>value</name>.
* 5. data snippets are separated by whitespace. thus, $value cannot
* contain whitespace.
*
* for later processing in xslts, i think it is also safe to assume that
* a. the single number (<index>n</index>) is unique and will be incremented without gaps;
* b. the <version> elements will be ordered oldest-to-latest.
*/
private void parseRawWorkflowData(String rawWorkflowData)
throws SAXException {
String[] workflowVersions;
String[] workflowVersionSnippets;
String key;
String value;
char[] textNode;
int colonIndex = 0;
startNodeMeta("workflow");
String workflowData = rawWorkflowData.replaceAll(
"(.*?)([0-9]+\\s+event)", //assumptions 1 and 2
"$1-REALLY_HACKISH_SEPARATOR-$2"); // assumption 3
workflowVersions = workflowData.split("-REALLY_HACKISH_SEPARATOR-"); // this is so ugly that it does not even deserve a proper string constant.
int i=1; // ignore empty first element caused by replace+split
while (i < workflowVersions.length) {
startNodeMeta("version");
workflowVersionSnippets = workflowVersions[i].split("\\s+"); //assumption 5
startNodeMeta("index"); //assumption 2
value = workflowVersionSnippets[0];
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta("index");
int k=1; // element 0 has been handled already
while (k < workflowVersionSnippets.length) {
colonIndex = workflowVersionSnippets[k].indexOf(":"); //assumption 4
try { // behave if a snippet does not follow the $key:$value format
key = workflowVersionSnippets[k].substring(0, colonIndex);
value = workflowVersionSnippets[k].substring(colonIndex + 1);
} catch (StringIndexOutOfBoundsException e) {
key = workflowVersionSnippets[k];
value = "";
}
if (key.equals("date"))
parseRawTimestamp(value);
else if (key.equals("var"))
parseRawVar(value);
else {
startNodeMeta(key);
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta(key);
}
++k;
}
endNodeMeta("version");
++i;
}
endNodeMeta("workflow");
}
/**
* parse timestamp
* assumption: the format is YYYY-MM-DD_HH:MM:SS
*
*/
private void parseRawTimestamp(String rawTimestamp)
throws SAXException {
String key;
String value;
char[] textNode;
startNodeMeta("timestamp");
assert(rawTimestamp.matches("[0-9]{4}-[01][0-9]-[0-3][0-9]_[0-2][0-9](:[0-6][0-9]){2}"));
value = rawTimestamp.substring(0,10);
startNodeMeta("date");
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta("date");
value = rawTimestamp.substring(11);
startNodeMeta("time");
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta("time");
endNodeMeta("timestamp");
}
/**
* parse var
* assumption: the format is $key=$value
*
*/
private void parseRawVar(String rawVar)
throws SAXException {
String key;
String value;
String[] var;
char[] textNode;
AttributesImpl attributes = new AttributesImpl();
assert(rawVar.matches("[a-zA-z][a-zA-Z0-9_-]*=[a-zA-Z0-9]"));
var = rawVar.split("=");
key = var[0];
try {
value = var[1];
} catch (ArrayIndexOutOfBoundsException e) {
value = new String("");
}
attributes.addAttribute(
"",
"name",
"name",
"NMTOKEN",
key
);
startNodeMeta("var", attributes);
textNode = value.toCharArray();
this.contentHandler.characters(textNode, 0, textNode.length);
endNodeMeta("var");
}
/**
* override to allow adding of attributes
*
*/
private void startNodeMeta(String nodeName, AttributesImpl attributes) throws SAXException {
this.contentHandler.startElement(
URI_META,
nodeName,
PREFIX_META + ":" + nodeName,
attributes
);
}
}
Index: src/pubs/default/sitemap.xmap
===================================================================
--- src/pubs/default/sitemap.xmap (revision 411441)
+++ src/pubs/default/sitemap.xmap (working copy)
@@ -23,7 +23,7 @@
<map:generators default="file">
<map:generator label="content" logger="sitemap.generator.directory"
name="lenyaMetaData" pool-max="16"
- src="org.apache.lenya.cms.cocoon.generation.LenyaMetaDataGenerator"/>
+ src="org.apache.lenya.cms.cocoon.generation.LenyaSaneMetaDataGenerator"/>
</map:generators>
<map:serializers default="xhtml">
<map:serializer logger="sitemap.serializer.links" name="links" src="org.apache.lenya.cms.cocoon.serialization.LinkSerializer"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]