[Dive4elements-commits] [PATCH] Datacage: Introduced <dc:container-context>
Wald Commits
scm-commit at wald.intevation.org
Fri Jun 21 20:02:21 CEST 2013
# HG changeset patch
# User Sascha L. Teichmann <teichmann at intevation.de>
# Date 1371837735 -7200
# Node ID 10fe6758dfb053186452d0bb396860df0b19b209
# Parent 13ecaf6c0f207b2f074d160af4d6867da147a47c
Datacage: Introduced <dc:container-context>.
It is an analogon to <dc:context> to fetch the data from a collection.
Usage:
<dc:container-context container="myContainer">
<dc:properties>
<dc:property name="a"/>
<dc:property name="b" alias="c"/>
</dc:properties>
<dc:for-each><!-- as usual --></dc:for-each>
</dc:container-context>
Iterates over the collection stored on stack with the name 'myContainer'
and fetched for each item via getA() and getB() the values to be stored
under 'a' and 'c'. dc:has-result() & Co work as expected.
diff -r 13ecaf6c0f20 -r 10fe6758dfb0 artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Fri Jun 21 18:09:53 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Fri Jun 21 20:02:15 2013 +0200
@@ -12,6 +12,8 @@
import org.dive4elements.river.utils.Pair;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
@@ -164,6 +166,14 @@
* macros but not doing evaluation (e.g. of <dc:if>s).
*/
private Node findStatementNode(NodeList nodes) {
+ return findSelectNode(nodes, "statement");
+ }
+
+ private Node findPropertiesNode(NodeList nodes) {
+ return findSelectNode(nodes, "properties");
+ }
+
+ private Node findSelectNode(NodeList nodes, String selectName) {
int S = nodes.getLength();
// Check direct children and take special care of macros.
@@ -172,7 +182,7 @@
String ns;
// Regular statement node.
if (node.getNodeType() == Node.ELEMENT_NODE
- && node.getLocalName().equals("statement")
+ && node.getLocalName().equals(selectName)
&& (ns = node.getNamespaceURI()) != null
&& ns.equals(DC_NAMESPACE_URI)) {
return node;
@@ -185,7 +195,7 @@
String macroName = ((Element)node).getAttribute("name");
Node inMacroNode =
- findStatementNode(getMacroChildren(macroName));
+ findSelectNode(getMacroChildren(macroName), selectName);
if (inMacroNode != null) {
return inMacroNode;
}
@@ -196,6 +206,127 @@
return null;
}
+ private String[][] extractProperties(Element propertiesNode) {
+ ArrayList<String[]> props = new ArrayList<String[]>();
+ NodeList list = propertiesNode.getElementsByTagNameNS(
+ DC_NAMESPACE_URI, "property");
+ for (int i = 0, L = list.getLength(); i < L; ++i) {
+ Element property = (Element)list.item(i);
+ String name = property.getAttribute("name");
+ if (name.isEmpty()) {
+ log.warn("dc:property without name");
+ continue;
+ }
+ String alias = property.getAttribute("alias");
+ if (alias.isEmpty()) {
+ alias = name;
+ }
+ props.add(new String [] { name, alias });
+ }
+ return props.toArray(new String[props.size()][]);
+ }
+
+ /**
+ * Handle a dc:context node.
+ */
+ protected void containerContext(Node parent, Element current)
+ throws SQLException
+ {
+ log.debug("dc:container-context");
+
+ String container = expand(current.getAttribute("container"));
+
+ if (container.isEmpty()) {
+ log.warn("dc:container-context: no 'container' attribute found");
+ return;
+ }
+
+ NodeList subs = current.getChildNodes();
+ Node propertiesNode = findPropertiesNode(subs);
+
+ if (propertiesNode == null) {
+ log.warn("dc:container-context: cannot find properties.");
+ return;
+ }
+
+ String [][] properties = extractProperties((Element)propertiesNode);
+
+ if (properties.length == 0) {
+ log.warn("dc:properties: No properties defined.");
+ }
+
+ Object [] result = new Object[1];
+ if (!frames.getStore(container, result)) {
+ log.warn("dc:container-context: cannot find container.");
+ return;
+ }
+ Object c = result[0];
+ if (c instanceof Object []) {
+ c = Arrays.asList((Object [])c);
+ }
+ if (!(c instanceof Collection)) {
+ log.warn("dc:container-context: container is not a collection.");
+ return;
+ }
+
+ String [] columnNames = new String[properties.length];
+ for (int i = 0; i < columnNames.length; ++i) {
+ columnNames[i] = properties[i][1];
+ }
+
+ ResultData rd = new ResultData(columnNames);
+
+ for (Object obj: (Collection<?>)c) {
+ Object [] row = new Object[properties.length];
+ for (int i = 0; i < properties.length; ++i) {
+ row[i] = getProperty(obj, properties[i][0]);
+ }
+ rd.add(row);
+ }
+
+ // only descent if there are results
+ if (!rd.isEmpty()) {
+ // A bit of a fake because the data is not from a
+ // real connection.
+ NamedConnection connection = connectionsStack.isEmpty()
+ ? connections.get(0)
+ : connectionsStack.peek().getA();
+
+ connectionsStack.push(
+ new Pair<NamedConnection, ResultData>(connection, rd));
+ try {
+ for (int i = 0, S = subs.getLength(); i < S; ++i) {
+ build(parent, subs.item(i));
+ }
+ }
+ finally {
+ connectionsStack.pop();
+ }
+ }
+ }
+
+ /** Poor man's bean access. */
+ private Object getProperty(Object obj, String name) {
+ String mname =
+ "get" + Character.toUpperCase(name.charAt(0))
+ + name.substring(1);
+
+ try {
+ Method meth = obj.getClass().getMethod(mname);
+ return meth.invoke(obj);
+ }
+ catch (InvocationTargetException ite) {
+ log.warn(ite);
+ }
+ catch (IllegalAccessException iae) {
+ log.warn(iae);
+ }
+ catch (NoSuchMethodException nsme) {
+ log.warn(nsme);
+ }
+ return null;
+ }
+
/**
* Handle a dc:context node.
*/
@@ -206,7 +337,6 @@
NodeList subs = current.getChildNodes();
Node stmntNode = findStatementNode(subs);
- int S = subs.getLength();
if (stmntNode == null) {
log.warn("dc:context: cannot find statement");
@@ -250,7 +380,7 @@
connectionsStack.push(
new Pair<NamedConnection, ResultData>(connection, rd));
try {
- for (int i = 0; i < S; ++i) {
+ for (int i = 0, S = subs.getLength(); i < S; ++i) {
build(parent, subs.item(i));
}
}
@@ -973,6 +1103,9 @@
else if ("context".equals(localName)) {
context(parent, curr);
}
+ else if ("container-context".equals(localName)) {
+ containerContext(parent, curr);
+ }
else if ("if".equals(localName)) {
ifClause(parent, curr);
}
More information about the Dive4elements-commits
mailing list