Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java @ 9150:23945061daec
gigantic refactoring: exporter, result, results
to support multiple jaspers -> collisions
author | gernotbelger |
---|---|
date | Thu, 14 Jun 2018 16:56:31 +0200 |
parents | 93ea282c33e8 |
children | 13a0c4be17ea |
comparison
equal
deleted
inserted
replaced
9149:5be112fba832 | 9150:23945061daec |
---|---|
9 package org.dive4elements.river.exports; | 9 package org.dive4elements.river.exports; |
10 | 10 |
11 import java.io.IOException; | 11 import java.io.IOException; |
12 import java.io.OutputStream; | 12 import java.io.OutputStream; |
13 import java.io.OutputStreamWriter; | 13 import java.io.OutputStreamWriter; |
14 | |
15 import java.text.NumberFormat; | 14 import java.text.NumberFormat; |
16 | 15 |
17 import org.w3c.dom.Document; | |
18 | |
19 import org.apache.log4j.Logger; | 16 import org.apache.log4j.Logger; |
20 | 17 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; |
21 import au.com.bytecode.opencsv.CSVWriter; | 18 import org.dive4elements.artifactdatabase.state.Settings; |
22 | |
23 import org.dive4elements.artifacts.Artifact; | 19 import org.dive4elements.artifacts.Artifact; |
24 import org.dive4elements.artifacts.CallContext; | 20 import org.dive4elements.artifacts.CallContext; |
25 | |
26 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; | |
27 import org.dive4elements.artifactdatabase.state.Settings; | |
28 | |
29 import org.dive4elements.artifacts.common.ArtifactNamespaceContext; | 21 import org.dive4elements.artifacts.common.ArtifactNamespaceContext; |
30 import org.dive4elements.artifacts.common.utils.XMLUtils; | 22 import org.dive4elements.artifacts.common.utils.XMLUtils; |
31 | |
32 import org.dive4elements.river.artifacts.resources.Resources; | 23 import org.dive4elements.river.artifacts.resources.Resources; |
33 import org.dive4elements.river.collections.D4EArtifactCollection; | 24 import org.dive4elements.river.collections.D4EArtifactCollection; |
34 | |
35 import org.dive4elements.river.themes.ThemeDocument; | 25 import org.dive4elements.river.themes.ThemeDocument; |
36 import org.dive4elements.river.utils.Formatter; | 26 import org.dive4elements.river.utils.Formatter; |
37 | 27 import org.w3c.dom.Document; |
28 | |
29 import au.com.bytecode.opencsv.CSVWriter; | |
38 | 30 |
39 /** | 31 /** |
40 * Abstract exporter that implements some basic methods for exporting data of | 32 * Abstract exporter that implements some basic methods for exporting data of |
41 * artifacts. | 33 * artifacts. |
42 * | 34 * |
43 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | 35 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> |
44 */ | 36 */ |
45 public abstract class AbstractExporter implements OutGenerator { | 37 public abstract class AbstractExporter implements OutGenerator { |
46 | 38 |
47 /** The log used in this exporter.*/ | 39 /** The log used in this exporter. */ |
48 private static Logger log = Logger.getLogger(AbstractExporter.class); | 40 private static Logger log = Logger.getLogger(AbstractExporter.class); |
49 | 41 |
50 /* XXX: Why does AbstractExporter do not implement FacetTypes? */ | 42 /* XXX: Why does AbstractExporter do not implement FacetTypes? */ |
51 public static String FIX_PARAMETERS = "fix_parameters"; | 43 public static String FIX_PARAMETERS = "fix_parameters"; |
52 | 44 |
80 protected CallContext context; | 72 protected CallContext context; |
81 | 73 |
82 /** The selected facet. */ | 74 /** The selected facet. */ |
83 protected String facet; | 75 protected String facet; |
84 | 76 |
85 /** The collection.*/ | 77 /** The collection. */ |
86 protected D4EArtifactCollection collection; | 78 protected D4EArtifactCollection collection; |
87 | 79 |
88 /** The master artifact. */ | 80 /** The master artifact. */ |
89 protected Artifact master; | 81 protected Artifact master; |
90 | 82 |
104 | 96 |
105 /** | 97 /** |
106 * Concrete subclasses need to use this method to write their special data | 98 * Concrete subclasses need to use this method to write their special data |
107 * objects into the CSV document. | 99 * objects into the CSV document. |
108 * | 100 * |
109 * @param writer The CSVWriter. | 101 * @param writer |
102 * The CSVWriter. | |
110 */ | 103 */ |
111 protected abstract void writeCSVData(CSVWriter writer) throws IOException; | 104 protected abstract void writeCSVData(CSVWriter writer) throws IOException; |
112 | |
113 | 105 |
114 /** | 106 /** |
115 * Write lines of informative content to CSV file. | 107 * Write lines of informative content to CSV file. |
116 * Usually this will be done above the column headers from within | 108 * Usually this will be done above the column headers from within |
117 * the implementation of writeCSVData in concret subclasses. | 109 * the implementation of writeCSVData in concret subclasses. |
118 * | 110 * |
119 * @param writer The CSVWriter | 111 * @param writer |
120 * @param infolines Array of Strings with informative content. | 112 * The CSVWriter |
121 * Each will be written to a separate line prefixed with START_META_CHAR. | 113 * @param infolines |
122 */ | 114 * Array of Strings with informative content. |
123 protected void writeCSVInfo(CSVWriter writer, String[] infolines) { | 115 * Each will be written to a separate line prefixed with START_META_CHAR. |
124 String[] metaline = new String[1]; | 116 */ |
125 | 117 protected void writeCSVInfo(final CSVWriter writer, final String[] infolines) { |
126 for (String infoline: infolines) { | 118 final String[] metaline = new String[1]; |
119 | |
120 for (final String infoline : infolines) { | |
127 metaline[0] = START_META_CHAR + " " + infoline; | 121 metaline[0] = START_META_CHAR + " " + infoline; |
128 writer.writeNext(metaline); | 122 writer.writeNext(metaline); |
129 } | 123 } |
130 | 124 |
131 } | 125 } |
134 * Concrete subclasses need to use this method to write their special data | 128 * Concrete subclasses need to use this method to write their special data |
135 * objects into the PDF document. | 129 * objects into the PDF document. |
136 */ | 130 */ |
137 protected abstract void writePDF(OutputStream out); | 131 protected abstract void writePDF(OutputStream out); |
138 | 132 |
139 | |
140 /** | 133 /** |
141 * This method enables concrete subclasses to collected its own special | 134 * This method enables concrete subclasses to collected its own special |
142 * data. | 135 * data. |
143 * | 136 * |
144 * @param data The artifact that stores the data that has to be | 137 * @param data |
145 * exported. | 138 * The artifact that stores the data that has to be |
139 * exported. | |
146 */ | 140 */ |
147 protected abstract void addData(Object data); | 141 protected abstract void addData(Object data); |
148 | 142 |
149 public void setup(Object config) { | 143 @Override |
144 public void setup(final Object config) { | |
150 log.debug("AbstractExporter.setup"); | 145 log.debug("AbstractExporter.setup"); |
151 } | 146 } |
152 | 147 |
153 | 148 @Override |
154 @Override | 149 public void init(final String outName, final Document request, final OutputStream out, final CallContext context) { |
155 public void init( | |
156 String outName, | |
157 Document request, | |
158 OutputStream out, | |
159 CallContext context | |
160 ) { | |
161 log.debug("AbstractExporter.init"); | 150 log.debug("AbstractExporter.init"); |
162 | 151 |
163 this.outName = outName; | 152 this.outName = outName; |
164 this.request = request; | 153 this.request = request; |
165 this.out = out; | 154 this.out = out; |
166 this.context = context; | 155 this.context = context; |
167 } | 156 } |
168 | 157 |
169 | 158 @Override |
170 @Override | 159 public void setMasterArtifact(final Artifact master) { |
171 public void setMasterArtifact(Artifact master) { | |
172 this.master = master; | 160 this.master = master; |
173 } | 161 } |
174 | 162 |
175 /** Get the callcontext that this exporter has been initialized | 163 /** |
176 * with. */ | 164 * Get the callcontext that this exporter has been initialized |
165 * with. | |
166 */ | |
177 public CallContext getCallContext() { | 167 public CallContext getCallContext() { |
178 return this.context; | 168 return this.context; |
179 } | 169 } |
180 | 170 |
181 | 171 @Override |
182 @Override | 172 public void setCollection(final D4EArtifactCollection collection) { |
183 public void setCollection(D4EArtifactCollection collection) { | |
184 this.collection = collection; | 173 this.collection = collection; |
185 } | 174 } |
186 | |
187 | 175 |
188 /** | 176 /** |
189 * This doOut() just collects the data of multiple artifacts. Therefore, it | 177 * This doOut() just collects the data of multiple artifacts. Therefore, it |
190 * makes use of the addData() method which enables concrete subclasses to | 178 * makes use of the addData() method which enables concrete subclasses to |
191 * store its data on its own. The real output creation takes place in the | 179 * store its data on its own. The real output creation takes place in the |
192 * concrete generate() methods. | 180 * concrete generate() methods. |
193 * | 181 * |
194 * @param artifactFacet The artifact and facet. | 182 * @param artifactFacet |
195 * The facet to add - NOTE: the facet needs to fit to the first | 183 * The artifact and facet. |
196 * facet inserted into this exporter. Otherwise this artifact/facet is | 184 * The facet to add - NOTE: the facet needs to fit to the first |
197 * skipped. | 185 * facet inserted into this exporter. Otherwise this artifact/facet is |
198 * @param attr The attr document. | 186 * skipped. |
199 */ | 187 * @param attr |
200 @Override | 188 * The attr document. |
201 public void doOut( | 189 */ |
202 ArtifactAndFacet artifactFacet, | 190 @Override |
203 ThemeDocument attr, | 191 public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) { |
204 boolean visible | 192 final String name = artifactFacet.getFacetName(); |
205 ) { | |
206 String name = artifactFacet.getFacetName(); | |
207 | 193 |
208 log.debug("AbstractExporter.doOut: " + name); | 194 log.debug("AbstractExporter.doOut: " + name); |
209 | 195 |
210 if (!isFacetValid(name)) { | 196 if (!isFacetValid(name)) { |
211 log.warn("Facet '" + name + "' not valid. No output created!"); | 197 log.warn("Facet '" + name + "' not valid. No output created!"); |
212 return; | 198 return; |
213 } | 199 } |
214 | 200 |
215 addData(artifactFacet.getData(context)); | 201 addData(artifactFacet.getData(this.context)); |
216 } | 202 } |
217 | |
218 | 203 |
219 /** | 204 /** |
220 * Generates an export based on a specified facet. | 205 * Generates an export based on a specified facet. |
221 */ | 206 */ |
222 @Override | 207 @Override |
223 public void generate() | 208 public void generate() throws IOException { |
224 throws IOException | |
225 { | |
226 log.debug("AbstractExporter.generate"); | 209 log.debug("AbstractExporter.generate"); |
227 | 210 |
228 if (facet == null) { | 211 if (this.facet == null) { |
229 throw new IOException("invalid (null) facet for exporter"); | 212 throw new IOException("invalid (null) facet for exporter"); |
230 } | 213 } |
231 | 214 |
232 if (facet.equals(FACET_CSV)) { | 215 if (this.facet.equals(FACET_CSV)) { |
233 generateCSV(); | 216 generateCSV(); |
234 } | 217 } else if (this.facet.equals(FACET_PDF)) { |
235 else if (facet.equals(FACET_PDF)) { | |
236 generatePDF(); | 218 generatePDF(); |
237 } | 219 } else { |
238 else { | 220 throw new IOException("invalid facet for exporter: '" + this.facet + "'"); |
239 throw new IOException( | 221 } |
240 "invalid facet for exporter: '" + facet + "'"); | 222 } |
241 } | |
242 } | |
243 | |
244 | 223 |
245 /** | 224 /** |
246 * Determines if the desired facet is valid for this exporter. If no facet | 225 * Determines if the desired facet is valid for this exporter. If no facet |
247 * is currently set, <i>facet</i> is set. | 226 * is currently set, <i>facet</i> is set. |
248 * | 227 * |
249 * @param facet The desired facet. | 228 * @param facet |
229 * The desired facet. | |
250 * | 230 * |
251 * @return true, if <i>facet</i> is valid, otherwise false. | 231 * @return true, if <i>facet</i> is valid, otherwise false. |
252 */ | 232 */ |
253 protected boolean isFacetValid(String facet) { | 233 protected boolean isFacetValid(final String facet) { |
254 log.debug("AbstractExporter.isFacetValid : " | 234 log.debug("AbstractExporter.isFacetValid : " + facet + " (" + getFacet() + ")"); |
255 + facet + " (" + getFacet() + ")" ); | 235 |
256 | 236 final String thisFacet = getFacet(); |
257 String thisFacet = getFacet(); | |
258 | 237 |
259 if (thisFacet == null || thisFacet.length() == 0) { | 238 if (thisFacet == null || thisFacet.length() == 0) { |
260 return false; | 239 return false; |
261 } | 240 } else if (facet == null || facet.length() == 0) { |
262 else if (facet == null || facet.length() == 0) { | |
263 return false; | 241 return false; |
264 } | 242 } else { |
265 else { | |
266 return thisFacet.equals(facet); | 243 return thisFacet.equals(facet); |
267 } | 244 } |
268 } | 245 } |
269 | 246 |
270 | |
271 /** | 247 /** |
272 * Returns the name of the desired facet. | 248 * Returns the name of the desired facet. |
273 * | 249 * |
274 * @return the name of the desired facet. | 250 * @return the name of the desired facet. |
275 */ | 251 */ |
276 protected String getFacet() { | 252 protected String getFacet() { |
277 if (facet == null) { | 253 if (this.facet == null) { |
278 facet = getFacetFromRequest(); | 254 this.facet = getFacetFromRequest(); |
279 } | 255 } |
280 | 256 |
281 return facet; | 257 return this.facet; |
282 } | 258 } |
283 | |
284 | 259 |
285 /** | 260 /** |
286 * Extracts the name of the requested facet from request document. | 261 * Extracts the name of the requested facet from request document. |
287 * | 262 * |
288 * @return the name of the requested facet. | 263 * @return the name of the requested facet. |
289 */ | 264 */ |
290 protected String getFacetFromRequest() { | 265 protected String getFacetFromRequest() { |
291 return XMLUtils.xpathString( | 266 return XMLUtils.xpathString(this.request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE); |
292 request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE); | |
293 } | 267 } |
294 | 268 |
295 protected String msg(final String key) { | 269 protected String msg(final String key) { |
296 return Resources.getMsg(context.getMeta(), key, key); | 270 return Resources.getMsg(this.context.getMeta(), key, key); |
297 } | 271 } |
298 | 272 |
299 protected String msg(String key, final String def) { | 273 protected String msg(final String key, final String def) { |
300 return Resources.getMsg(context.getMeta(), key, def); | 274 return Resources.getMsg(this.context.getMeta(), key, def); |
301 } | 275 } |
302 | 276 |
303 protected String msg(String key, Object[] args) { | 277 protected String msg(final String key, final Object[] args) { |
304 return Resources.getMsg(context.getMeta(), key, key, args); | 278 return Resources.getMsg(this.context.getMeta(), key, key, args); |
305 } | 279 } |
306 | 280 |
307 protected String msg(String key, String def, Object[] args) { | 281 protected String msg(final String key, final String def, final Object[] args) { |
308 return Resources.getMsg(context.getMeta(), key, def, args); | 282 return Resources.getMsg(this.context.getMeta(), key, def, args); |
309 } | 283 } |
310 | 284 |
311 protected String msgVarg(final String key, final Object... args) { | 285 protected String msgVarg(final String key, final Object... args) { |
312 return Resources.getMsg(context.getMeta(), key, key, args); | 286 return Resources.getMsg(this.context.getMeta(), key, key, args); |
313 } | 287 } |
314 | 288 |
315 /** | 289 /** |
316 * Formats header with unit: msg [unit] | 290 * Formats header with unit: msg [unit] |
317 */ | 291 */ |
292 // TODO: REMOVE, because it has moved to ExportContextCSV | |
318 protected final String msgUnit(final String key, final String unit) { | 293 protected final String msgUnit(final String key, final String unit) { |
319 final String msg = msg(key); | 294 final String msg = msg(key); |
320 return String.format("%s [%s]", msg, unit); | 295 return String.format("%s [%s]", msg, unit); |
321 } | 296 } |
322 | 297 |
323 /** | 298 /** |
324 * This method starts CSV creation. It makes use of writeCSVData() which has | 299 * This method starts CSV creation. It makes use of writeCSVData() which has |
325 * to be implemented by concrete subclasses. | 300 * to be implemented by concrete subclasses. |
326 */ | 301 */ |
327 protected void generateCSV() | 302 protected void generateCSV() throws IOException { |
328 throws IOException | |
329 { | |
330 log.info("AbstractExporter.generateCSV"); | 303 log.info("AbstractExporter.generateCSV"); |
331 | 304 |
332 char quote = '"'; | 305 final char quote = '"'; |
333 char escape = '\\'; | 306 final char escape = '\\'; |
334 | 307 |
335 CSVWriter writer = new CSVWriter( | 308 final CSVWriter writer = new CSVWriter(new OutputStreamWriter(this.out, DEFAULT_CSV_CHARSET), DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n"); |
336 new OutputStreamWriter( | |
337 out, | |
338 DEFAULT_CSV_CHARSET), | |
339 DEFAULT_CSV_SEPARATOR, quote, escape, "\r\n"); | |
340 | 309 |
341 writeCSVData(writer); | 310 writeCSVData(writer); |
342 | 311 |
343 writer.close(); | 312 writer.close(); |
344 } | 313 } |
345 | 314 |
346 | |
347 /** | 315 /** |
348 * This method starts PDF creation. | 316 * This method starts PDF creation. |
349 */ | 317 */ |
350 protected void generatePDF() | 318 protected void generatePDF() throws IOException { |
351 throws IOException | |
352 { | |
353 log.info("AbstractExporter.generatePDF"); | 319 log.info("AbstractExporter.generatePDF"); |
354 writePDF(this.out); | 320 writePDF(this.out); |
355 } | 321 } |
356 | 322 |
357 | |
358 /** | 323 /** |
359 * Returns an instance of <i>EmptySettings</i> currently! | 324 * Returns an instance of <i>EmptySettings</i> currently! |
360 * | 325 * |
361 * @return an instance of <i>EmptySettings</i>. | 326 * @return an instance of <i>EmptySettings</i>. |
362 */ | 327 */ |
328 @Override | |
363 public Settings getSettings() { | 329 public Settings getSettings() { |
364 return new EmptySettings(); | 330 return new EmptySettings(); |
365 } | 331 } |
366 | 332 |
367 | |
368 /** | 333 /** |
369 * This method is not implemented. Override it in subclasses if those need a | 334 * This method is not implemented. Override it in subclasses if those need a |
370 * <i>Settings</i> object. | 335 * <i>Settings</i> object. |
371 */ | 336 */ |
372 public void setSettings(Settings settings) { | 337 @Override |
338 public void setSettings(final Settings settings) { | |
373 // do nothing | 339 // do nothing |
374 } | 340 } |
375 | 341 |
376 | |
377 /** | 342 /** |
378 * Returns the number formatter for kilometer values. | 343 * Returns the number formatter for kilometer values. |
379 * | 344 * |
380 * @return the number formatter for kilometer values. | 345 * @return the number formatter for kilometer values. |
381 */ | 346 */ |
382 protected NumberFormat getKmFormatter() { | 347 protected NumberFormat getKmFormatter() { |
383 if (kmFormat == null) { | 348 if (this.kmFormat == null) { |
384 kmFormat = Formatter.getWaterlevelKM(context); | 349 this.kmFormat = Formatter.getWaterlevelKM(this.context); |
385 } | 350 } |
386 return kmFormat; | 351 return this.kmFormat; |
387 } | 352 } |
388 | |
389 | 353 |
390 /** | 354 /** |
391 * Returns the number formatter for W values. | 355 * Returns the number formatter for W values. |
392 * | 356 * |
393 * @return the number formatter for W values. | 357 * @return the number formatter for W values. |
394 */ | 358 */ |
395 protected NumberFormat getWFormatter() { | 359 protected NumberFormat getWFormatter() { |
396 if (wFormat == null) { | 360 if (this.wFormat == null) { |
397 wFormat = Formatter.getWaterlevelW(context); | 361 this.wFormat = Formatter.getWaterlevelW(this.context); |
398 } | 362 } |
399 return wFormat; | 363 return this.wFormat; |
400 } | 364 } |
401 | |
402 | 365 |
403 /** | 366 /** |
404 * Returns the number formatter for Q values. | 367 * Returns the number formatter for Q values. |
405 * | 368 * |
406 * @return the number formatter for Q values. | 369 * @return the number formatter for Q values. |
407 */ | 370 */ |
408 protected NumberFormat getQFormatter() { | 371 protected NumberFormat getQFormatter() { |
409 if (qFormat == null) { | 372 if (this.qFormat == null) { |
410 qFormat = Formatter.getWaterlevelQ(context); | 373 this.qFormat = Formatter.getWaterlevelQ(this.context); |
411 } | 374 } |
412 return qFormat; | 375 return this.qFormat; |
413 } | 376 } |
414 | 377 |
415 protected final NumberFormat getMeanBedHeighFormatter() { | 378 protected final NumberFormat getMeanBedHeighFormatter() { |
416 if( meanBedHeightFormat == null ) | 379 if (this.meanBedHeightFormat == null) |
417 meanBedHeightFormat = Formatter.getMeanBedHeight(context); | 380 this.meanBedHeightFormat = Formatter.getMeanBedHeight(this.context); |
418 return meanBedHeightFormat; | 381 return this.meanBedHeightFormat; |
419 } | 382 } |
420 | 383 |
421 protected final NumberFormat getTkhFormatter() { | 384 protected final NumberFormat getTkhFormatter() { |
422 if( tkhFormat == null ) | 385 if (this.tkhFormat == null) |
423 tkhFormat = Formatter.getTkh(context); | 386 this.tkhFormat = Formatter.getTkh(this.context); |
424 return tkhFormat; | 387 return this.tkhFormat; |
425 } | 388 } |
426 | 389 |
427 protected final NumberFormat getFlowDepthFormatter() { | 390 protected final NumberFormat getFlowDepthFormatter() { |
428 if( flowDepthFormat == null ) | 391 if (this.flowDepthFormat == null) |
429 flowDepthFormat = Formatter.getFlowDepth(context); | 392 this.flowDepthFormat = Formatter.getFlowDepth(this.context); |
430 return flowDepthFormat; | 393 return this.flowDepthFormat; |
431 } | 394 } |
432 | 395 |
433 protected final NumberFormat getW2Formatter() { | 396 protected final NumberFormat getW2Formatter() { |
434 if( w2Format == null ) | 397 if (this.w2Format == null) |
435 w2Format = Formatter.getFlowDepth(context); | 398 this.w2Format = Formatter.getFlowDepth(this.context); |
436 return w2Format; | 399 return this.w2Format; |
437 } | 400 } |
438 } | 401 } |
439 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 402 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |