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 :

http://dive4elements.wald.intevation.org