Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java @ 6399:10fe6758dfb0
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.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Fri, 21 Jun 2013 20:02:15 +0200 |
parents | a02d27da17ca |
children | da1d1df9ab23 |
comparison
equal
deleted
inserted
replaced
6398:13ecaf6c0f20 | 6399:10fe6758dfb0 |
---|---|
10 | 10 |
11 import org.dive4elements.artifacts.common.utils.XMLUtils; | 11 import org.dive4elements.artifacts.common.utils.XMLUtils; |
12 | 12 |
13 import org.dive4elements.river.utils.Pair; | 13 import org.dive4elements.river.utils.Pair; |
14 | 14 |
15 import java.lang.reflect.InvocationTargetException; | |
16 import java.lang.reflect.Method; | |
15 import java.sql.Connection; | 17 import java.sql.Connection; |
16 import java.sql.SQLException; | 18 import java.sql.SQLException; |
17 | 19 |
18 import java.util.ArrayDeque; | 20 import java.util.ArrayDeque; |
19 import java.util.ArrayList; | 21 import java.util.ArrayList; |
162 /** | 164 /** |
163 * Return first statement node in NodeList, respecting | 165 * Return first statement node in NodeList, respecting |
164 * macros but not doing evaluation (e.g. of <dc:if>s). | 166 * macros but not doing evaluation (e.g. of <dc:if>s). |
165 */ | 167 */ |
166 private Node findStatementNode(NodeList nodes) { | 168 private Node findStatementNode(NodeList nodes) { |
169 return findSelectNode(nodes, "statement"); | |
170 } | |
171 | |
172 private Node findPropertiesNode(NodeList nodes) { | |
173 return findSelectNode(nodes, "properties"); | |
174 } | |
175 | |
176 private Node findSelectNode(NodeList nodes, String selectName) { | |
167 int S = nodes.getLength(); | 177 int S = nodes.getLength(); |
168 | 178 |
169 // Check direct children and take special care of macros. | 179 // Check direct children and take special care of macros. |
170 for (int i = 0; i < S; ++i) { | 180 for (int i = 0; i < S; ++i) { |
171 Node node = nodes.item(i); | 181 Node node = nodes.item(i); |
172 String ns; | 182 String ns; |
173 // Regular statement node. | 183 // Regular statement node. |
174 if (node.getNodeType() == Node.ELEMENT_NODE | 184 if (node.getNodeType() == Node.ELEMENT_NODE |
175 && node.getLocalName().equals("statement") | 185 && node.getLocalName().equals(selectName) |
176 && (ns = node.getNamespaceURI()) != null | 186 && (ns = node.getNamespaceURI()) != null |
177 && ns.equals(DC_NAMESPACE_URI)) { | 187 && ns.equals(DC_NAMESPACE_URI)) { |
178 return node; | 188 return node; |
179 } | 189 } |
180 // Macro node. Descend. | 190 // Macro node. Descend. |
183 && (ns = node.getNamespaceURI()) != null | 193 && (ns = node.getNamespaceURI()) != null |
184 && ns.equals(DC_NAMESPACE_URI)) { | 194 && ns.equals(DC_NAMESPACE_URI)) { |
185 | 195 |
186 String macroName = ((Element)node).getAttribute("name"); | 196 String macroName = ((Element)node).getAttribute("name"); |
187 Node inMacroNode = | 197 Node inMacroNode = |
188 findStatementNode(getMacroChildren(macroName)); | 198 findSelectNode(getMacroChildren(macroName), selectName); |
189 if (inMacroNode != null) { | 199 if (inMacroNode != null) { |
190 return inMacroNode; | 200 return inMacroNode; |
191 } | 201 } |
192 } | 202 } |
193 | 203 |
194 } | 204 } |
195 | 205 |
206 return null; | |
207 } | |
208 | |
209 private String[][] extractProperties(Element propertiesNode) { | |
210 ArrayList<String[]> props = new ArrayList<String[]>(); | |
211 NodeList list = propertiesNode.getElementsByTagNameNS( | |
212 DC_NAMESPACE_URI, "property"); | |
213 for (int i = 0, L = list.getLength(); i < L; ++i) { | |
214 Element property = (Element)list.item(i); | |
215 String name = property.getAttribute("name"); | |
216 if (name.isEmpty()) { | |
217 log.warn("dc:property without name"); | |
218 continue; | |
219 } | |
220 String alias = property.getAttribute("alias"); | |
221 if (alias.isEmpty()) { | |
222 alias = name; | |
223 } | |
224 props.add(new String [] { name, alias }); | |
225 } | |
226 return props.toArray(new String[props.size()][]); | |
227 } | |
228 | |
229 /** | |
230 * Handle a dc:context node. | |
231 */ | |
232 protected void containerContext(Node parent, Element current) | |
233 throws SQLException | |
234 { | |
235 log.debug("dc:container-context"); | |
236 | |
237 String container = expand(current.getAttribute("container")); | |
238 | |
239 if (container.isEmpty()) { | |
240 log.warn("dc:container-context: no 'container' attribute found"); | |
241 return; | |
242 } | |
243 | |
244 NodeList subs = current.getChildNodes(); | |
245 Node propertiesNode = findPropertiesNode(subs); | |
246 | |
247 if (propertiesNode == null) { | |
248 log.warn("dc:container-context: cannot find properties."); | |
249 return; | |
250 } | |
251 | |
252 String [][] properties = extractProperties((Element)propertiesNode); | |
253 | |
254 if (properties.length == 0) { | |
255 log.warn("dc:properties: No properties defined."); | |
256 } | |
257 | |
258 Object [] result = new Object[1]; | |
259 if (!frames.getStore(container, result)) { | |
260 log.warn("dc:container-context: cannot find container."); | |
261 return; | |
262 } | |
263 Object c = result[0]; | |
264 if (c instanceof Object []) { | |
265 c = Arrays.asList((Object [])c); | |
266 } | |
267 if (!(c instanceof Collection)) { | |
268 log.warn("dc:container-context: container is not a collection."); | |
269 return; | |
270 } | |
271 | |
272 String [] columnNames = new String[properties.length]; | |
273 for (int i = 0; i < columnNames.length; ++i) { | |
274 columnNames[i] = properties[i][1]; | |
275 } | |
276 | |
277 ResultData rd = new ResultData(columnNames); | |
278 | |
279 for (Object obj: (Collection<?>)c) { | |
280 Object [] row = new Object[properties.length]; | |
281 for (int i = 0; i < properties.length; ++i) { | |
282 row[i] = getProperty(obj, properties[i][0]); | |
283 } | |
284 rd.add(row); | |
285 } | |
286 | |
287 // only descent if there are results | |
288 if (!rd.isEmpty()) { | |
289 // A bit of a fake because the data is not from a | |
290 // real connection. | |
291 NamedConnection connection = connectionsStack.isEmpty() | |
292 ? connections.get(0) | |
293 : connectionsStack.peek().getA(); | |
294 | |
295 connectionsStack.push( | |
296 new Pair<NamedConnection, ResultData>(connection, rd)); | |
297 try { | |
298 for (int i = 0, S = subs.getLength(); i < S; ++i) { | |
299 build(parent, subs.item(i)); | |
300 } | |
301 } | |
302 finally { | |
303 connectionsStack.pop(); | |
304 } | |
305 } | |
306 } | |
307 | |
308 /** Poor man's bean access. */ | |
309 private Object getProperty(Object obj, String name) { | |
310 String mname = | |
311 "get" + Character.toUpperCase(name.charAt(0)) | |
312 + name.substring(1); | |
313 | |
314 try { | |
315 Method meth = obj.getClass().getMethod(mname); | |
316 return meth.invoke(obj); | |
317 } | |
318 catch (InvocationTargetException ite) { | |
319 log.warn(ite); | |
320 } | |
321 catch (IllegalAccessException iae) { | |
322 log.warn(iae); | |
323 } | |
324 catch (NoSuchMethodException nsme) { | |
325 log.warn(nsme); | |
326 } | |
196 return null; | 327 return null; |
197 } | 328 } |
198 | 329 |
199 /** | 330 /** |
200 * Handle a dc:context node. | 331 * Handle a dc:context node. |
204 { | 335 { |
205 log.debug("dc:context"); | 336 log.debug("dc:context"); |
206 | 337 |
207 NodeList subs = current.getChildNodes(); | 338 NodeList subs = current.getChildNodes(); |
208 Node stmntNode = findStatementNode(subs); | 339 Node stmntNode = findStatementNode(subs); |
209 int S = subs.getLength(); | |
210 | 340 |
211 if (stmntNode == null) { | 341 if (stmntNode == null) { |
212 log.warn("dc:context: cannot find statement"); | 342 log.warn("dc:context: cannot find statement"); |
213 return; | 343 return; |
214 } | 344 } |
248 // only descent if there are results | 378 // only descent if there are results |
249 if (!rd.isEmpty()) { | 379 if (!rd.isEmpty()) { |
250 connectionsStack.push( | 380 connectionsStack.push( |
251 new Pair<NamedConnection, ResultData>(connection, rd)); | 381 new Pair<NamedConnection, ResultData>(connection, rd)); |
252 try { | 382 try { |
253 for (int i = 0; i < S; ++i) { | 383 for (int i = 0, S = subs.getLength(); i < S; ++i) { |
254 build(parent, subs.item(i)); | 384 build(parent, subs.item(i)); |
255 } | 385 } |
256 } | 386 } |
257 finally { | 387 finally { |
258 connectionsStack.pop(); | 388 connectionsStack.pop(); |
971 attribute(parent, curr); | 1101 attribute(parent, curr); |
972 } | 1102 } |
973 else if ("context".equals(localName)) { | 1103 else if ("context".equals(localName)) { |
974 context(parent, curr); | 1104 context(parent, curr); |
975 } | 1105 } |
1106 else if ("container-context".equals(localName)) { | |
1107 containerContext(parent, curr); | |
1108 } | |
976 else if ("if".equals(localName)) { | 1109 else if ("if".equals(localName)) { |
977 ifClause(parent, curr); | 1110 ifClause(parent, curr); |
978 } | 1111 } |
979 else if ("choose".equals(localName)) { | 1112 else if ("choose".equals(localName)) { |
980 choose(parent, curr); | 1113 choose(parent, curr); |