View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.benerator.consumer;
28  
29  import com.rapiddweller.common.ConfigurationError;
30  import com.rapiddweller.common.IOUtil;
31  import com.rapiddweller.common.SystemInfo;
32  import org.apache.logging.log4j.LogManager;
33  import org.apache.logging.log4j.Logger;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.io.PrintWriter;
38  
39  /**
40   * Parent class for Exporters that export data to a text file.<br/>
41   * <br/>
42   * Created: 11.07.2008 09:50:46
43   *
44   * @author Volker Bergmann
45   * @since 0.5.4
46   */
47  public class TextFileExporter extends FormattingConsumer implements FileExporter {
48  
49    private static final Logger LOG = LogManager.getLogger(TextFileExporter.class);
50  
51    // attributes ------------------------------------------------------------------------------------------------------
52  
53    /**
54     * The Uri.
55     */
56    protected String uri;
57    /**
58     * The Encoding.
59     */
60    protected String encoding;
61    /**
62     * The Line separator.
63     */
64    protected String lineSeparator;
65    /**
66     * The Append.
67     */
68    protected boolean append;
69    /**
70     * The Was appended.
71     */
72    protected boolean wasAppended;
73  
74    /**
75     * The Printer.
76     */
77    protected PrintWriter printer;
78  
79    // constructors ----------------------------------------------------------------------------------------------------
80  
81    /**
82     * Instantiates a new Text file exporter.
83     */
84    public TextFileExporter() {
85      this(null, null, null);
86    }
87  
88    /**
89     * Instantiates a new Text file exporter.
90     *
91     * @param uri the uri
92     */
93    public TextFileExporter(String uri) {
94      this(uri, null, null);
95    }
96  
97    /**
98     * Instantiates a new Text file exporter.
99     *
100    * @param uri           the uri
101    * @param encoding      the encoding
102    * @param lineSeparator the line separator
103    */
104   public TextFileExporter(String uri, String encoding, String lineSeparator) {
105     this.uri = (uri != null ? uri : "export.txt");
106     this.encoding = (encoding != null ? encoding : SystemInfo.getFileEncoding());
107     this.lineSeparator = (lineSeparator != null ? lineSeparator : SystemInfo.getLineSeparator());
108     this.append = false;
109   }
110 
111   // callback interface for child classes ----------------------------------------------------------------------------
112 
113   /**
114    * This method is called after printer initialization and before writing the first data entry.
115    * Overwrite this method in child classes e.g. for writing a file header.
116    *
117    * @param data the first data item to write to the file
118    */
119   protected void postInitPrinter(Object data) {
120     // overwrite this in child classes, e.g. for writing a file header
121   }
122 
123   /**
124    * Writes the data to the output file.
125    * It uses the parent class settings for rendering the object.
126    * Overwrite this in a child class for custom output format.
127    *
128    * @param data the data object to output
129    */
130   protected void startConsumingImpl(Object data) {
131     printer.print(plainConverter.convert(data));
132     println();
133   }
134 
135   /**
136    * This method is called after writing the last data entry and before closing the underlying printer.
137    * Overwrite this method in child classes e.g. for writing a file footer.
138    */
139   protected void preClosePrinter() {
140     // overwrite this in child classes, e.g. for writing a file footer
141   }
142 
143   // properties ------------------------------------------------------------------------------------------------------
144 
145   @Override
146   public String getUri() {
147     return uri;
148   }
149 
150   /**
151    * Sets uri.
152    *
153    * @param uri the uri
154    */
155   public void setUri(String uri) {
156     this.uri = uri;
157   }
158 
159   /**
160    * Gets encoding.
161    *
162    * @return the encoding
163    */
164   public String getEncoding() {
165     return encoding;
166   }
167 
168   /**
169    * Sets encoding.
170    *
171    * @param encoding the encoding
172    */
173   public void setEncoding(String encoding) {
174     this.encoding = encoding;
175   }
176 
177   /**
178    * Gets line separator.
179    *
180    * @return the line separator
181    */
182   public String getLineSeparator() {
183     return lineSeparator;
184   }
185 
186   /**
187    * Sets line separator.
188    *
189    * @param lineSeparator the line separator
190    */
191   public void setLineSeparator(String lineSeparator) {
192     this.lineSeparator = lineSeparator;
193   }
194 
195   /**
196    * Is append boolean.
197    *
198    * @return the boolean
199    */
200   public boolean isAppend() {
201     return append;
202   }
203 
204   /**
205    * Sets append.
206    *
207    * @param append the append
208    */
209   public void setAppend(boolean append) {
210     this.append = append;
211   }
212 
213   // Consumer interface ----------------------------------------------------------------------------------------------
214 
215   @Override
216   public final synchronized void startProductConsumption(Object data) {
217     try {
218       if (printer == null) {
219         initPrinter(data);
220       }
221       startConsumingImpl(data);
222     } catch (IOException e) {
223       throw new RuntimeException(e);
224     }
225   }
226 
227   @Override
228   public void flush() {
229     if (printer != null) {
230       printer.flush();
231     }
232   }
233 
234   @Override
235   public void close() {
236     try {
237       if (printer == null) {
238         try {
239           initPrinter(null);
240         } catch (IOException e) {
241           LOG.error("Error initializing empty file", e);
242         }
243       }
244       preClosePrinter();
245     } finally {
246       assert printer != null;
247       printer.close();
248     }
249   }
250 
251   // private helpers -------------------------------------------------------------------------------------------------
252 
253   /**
254    * Init printer.
255    *
256    * @param data the data
257    * @throws IOException the io exception
258    */
259   protected void initPrinter(Object data) throws IOException {
260     if (uri == null) {
261       throw new ConfigurationError("Property 'uri' not set on bean " + getClass().getName());
262     }
263     wasAppended = (append && IOUtil.isURIAvailable(uri));
264 
265     // check if path exists, if not make sure it exists
266     File directory = new File(uri);
267     if (!wasAppended
268         && directory.getParent() != null
269         && !directory.isDirectory()
270         && !directory.getParentFile().exists()) {
271       boolean result = directory.getParentFile().mkdirs();
272       if (!result) {
273         throw new ConfigurationError("filepath does not exists and can not be created ...");
274       }
275     }
276 
277     printer = IOUtil.getPrinterForURI(uri, encoding, append, lineSeparator, true);
278     postInitPrinter(data);
279   }
280 
281   /**
282    * Println.
283    */
284   protected void println() {
285     printer.print(lineSeparator);
286   }
287 
288   // java.lang.Object overrides --------------------------------------------------------------------------------------
289 
290   @Override
291   public String toString() {
292     return getClass().getSimpleName() + "[" + uri + "]";
293   }
294 
295 }