1 /*
2 * CSVeed (https://github.com/42BV/CSVeed)
3 *
4 * Copyright 2013-2023 CSVeed.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of The Apache Software License,
8 * Version 2.0 which accompanies this distribution, and is available at
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 */
11 package org.csveed.api;
12
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Locale;
16
17 import org.csveed.bean.AbstractMapper;
18 import org.csveed.bean.conversion.Converter;
19
20 /**
21 * <p>
22 * The CsvClient is responsible for reading/writing CSV rows and converting those into beans/rows. There are a couple of
23 * ways to initialize a {@link org.csveed.api.CsvClientImpl}:
24 * </p>
25 * <ul>
26 * <li>Just use a Reader/Writer. In this case you can only use the row functionality of CSVeed, not the bean
27 * functionality</li>
28 * <li>Pass a Reader or Writer and point it to class. The {@link org.csveed.annotations} in the class are read, as is
29 * the order of the properties within the class.</li>
30 * <li>Pass a Reader or Writer and roll your own instructions. Pass a {@link org.csveed.bean.BeanInstructions}
31 * implementation with your own configuration settings</li>
32 * </ul>
33 *
34 * @param <T>
35 * the bean class into which the rows are converted
36 */
37 public interface CsvClient<T> {
38
39 /**
40 * Writes a collection of Beans to the table.
41 *
42 * @param beans
43 * beans to write to the table
44 */
45 void writeBeans(Collection<T> beans);
46
47 /**
48 * Writes a single Bean to the table.
49 *
50 * @param bean
51 * bean to write to the table
52 */
53 void writeBean(T bean);
54
55 /**
56 * Writes a single row to the table.
57 *
58 * @param row
59 * single row
60 */
61 void writeRow(Row row);
62
63 /**
64 * Writes a single row (consisting of String cells) to the table.
65 *
66 * @param row
67 * single row
68 *
69 * @return the written row
70 */
71 Row writeRow(String[] row);
72
73 /**
74 * Writes a collection of rows to the table.
75 *
76 * @param rows
77 * collections of rows
78 */
79 void writeRows(Collection<Row> rows);
80
81 /**
82 * Writes a two-dimensional array of cells (rows with cells) to the table.
83 *
84 * @param rows
85 * two-dimensional array of cells
86 */
87 void writeRows(String[][] rows);
88
89 /**
90 * Writes the header to the table.
91 *
92 * @param header
93 * the header row
94 *
95 * @return the converted Header
96 */
97 Header writeHeader(String[] header);
98
99 /**
100 * Writes the header to the table.
101 *
102 * @param header
103 * the header row
104 */
105 void writeHeader(Header header);
106
107 /**
108 * Writes a header based on the bean properties to the table.
109 */
110 void writeHeader();
111
112 /**
113 * Reads all rows from the file and return these as beans.
114 *
115 * @return all beans read from the Reader
116 */
117 List<T> readBeans();
118
119 /**
120 * Reads a single row and returns this as a bean. The RowReader will keep track of its state.
121 *
122 * @return Bean read from the Reader
123 */
124 T readBean();
125
126 /**
127 * Reads all rows from the file and returns them as a List. After this, the RowReader will be finished
128 *
129 * @return all Rows read from the Reader
130 */
131 List<Row> readRows();
132
133 /**
134 * Reads a single row from the file and returns this. The RowReader will keep track of its state.
135 *
136 * @return Row read from the Reader
137 */
138 Row readRow();
139
140 /**
141 * Returns the header of the CSV file. Only possibly returns a value when useHeader==true
142 *
143 * @return header or null if the useHeader==false
144 */
145 Header readHeader();
146
147 /**
148 * Returns the line from which the row was read. Note that a line is seen as a legitimate CSV row, not necessarily a
149 * printable line (unless multi-lines are used, these values are the same).
150 *
151 * @return current line number
152 */
153 int getCurrentLine();
154
155 /**
156 * States whether the Reader is done with the file.
157 *
158 * @return true if file is finished
159 */
160 boolean isFinished();
161
162 /**
163 * Makes sure that the first readable line is interpreted as the header line. That line will not be read as content.
164 * This method is called whenever {@link org.csveed.annotations.CsvFile#useHeader()} is used. The default value for
165 * this setting is true. This call is a facade for {@link org.csveed.row.RowInstructions#setUseHeader(boolean)}.
166 *
167 * @param useHeader
168 * true if the header is interpreted and used
169 *
170 * @return convenience for chaining
171 */
172 CsvClient<T> setUseHeader(boolean useHeader);
173
174 /**
175 * Sets the start row of the CSV file. If {@link #setUseHeader(boolean)} == true, this will be the header row and
176 * the next ones are all content rows. This method is called whenever
177 * {@link org.csveed.annotations.CsvFile#startRow()} is used. The default value for this setting is 1. This call is
178 * a facade for {@link org.csveed.row.RowInstructions#setStartRow(int)}.
179 *
180 * @param startRow
181 * the first row to start reading, including the header row
182 *
183 * @return convenience for chaining
184 */
185 CsvClient<T> setStartRow(int startRow);
186
187 /**
188 * Sets the character that will be interpreted as an escape symbol while within a quoted field. This method is
189 * called whenever {@link org.csveed.annotations.CsvFile#escape()} is used. The default value for this setting is a
190 * double quote (") symbol. This call is a facade for {@link org.csveed.row.RowInstructions#setEscape(char)}.
191 *
192 * @param symbol
193 * the symbol to use for escaping characters within a quoted field
194 *
195 * @return convenience for chaining
196 */
197 CsvClient<T> setEscape(char symbol);
198
199 /**
200 * Sets the character that will be interpreted as a quote symbol, signifying either the start or the end of a quoted
201 * field. This method is called whenever {@link org.csveed.annotations.CsvFile#quote()} is used. The default value
202 * for this setting is a double quote (") symbol. This call is a facade for
203 * {@link org.csveed.row.RowInstructions#setQuote(char)}.
204 *
205 * @param symbol
206 * the symbol to use for indicating start/end of a quoted field
207 *
208 * @return convenience for chaining
209 */
210 CsvClient<T> setQuote(char symbol);
211
212 /**
213 * Sets the character that will be interpreted as a separator between cells. This method is called whenever
214 * {@link org.csveed.annotations.CsvFile#separator()} is used. The default value for this setting is a semi-colon
215 * (;). This call is a facade for {@link org.csveed.row.RowInstructions#setSeparator(char)}.
216 *
217 * @param symbol
218 * the symbol to use as a separator between cells
219 *
220 * @return convenience for chaining
221 */
222 CsvClient<T> setSeparator(char symbol);
223
224 /**
225 * Sets the character that will be interpreted as a comment field on the first position of a row. This method is
226 * called whenever {@link org.csveed.annotations.CsvFile#comment()} is used. The default value for this setting is a
227 * hashtag (#).
228 *
229 * @param symbol
230 * the symbol to use as the 0-position comment marker
231 *
232 * @return convenience for chaining
233 */
234 CsvClient<T> setComment(char symbol);
235
236 /**
237 * Sets the characters (plural) that will be interpreted as end-of-line markers (unless within a quoted field). This
238 * method is called whenever {@link org.csveed.annotations.CsvFile#endOfLine()} is used. The default values for this
239 * setting are \r and \n. This call is a facade for {@link org.csveed.row.RowInstructions#setEndOfLine(char[])}.
240 *
241 * @param symbols
242 * the symbol to interpret as end-of-line markers (unless within a quoted field)
243 *
244 * @return convenience for chaining
245 */
246 CsvClient<T> setEndOfLine(char[] symbols);
247
248 /**
249 * Determines whether empty lines must be skipped or treated as single-column rows. This method is called whenever
250 * {@link org.csveed.annotations.CsvFile#skipEmptyLines()} is used. The default value for this setting is to skip
251 * the empty lines.
252 *
253 * @param skip
254 * true to skip empty lines, false to treat as single-column rows
255 *
256 * @return convenience for chaining
257 */
258 CsvClient<T> skipEmptyLines(boolean skip);
259
260 /**
261 * Determines whether comment lines must be skipped. This method is called whenever
262 * {@link org.csveed.annotations.CsvFile#skipCommentLines()} is used. The default value for this setting is to skip
263 * comment lines. This method exists to guarantee that lines are not accidentally treated as comment lines.
264 *
265 * @param skip
266 * true to skip comment lines, identified as starting with a comment marker
267 *
268 * @return convenience for chaining
269 */
270 CsvClient<T> skipCommentLines(boolean skip);
271
272 /**
273 * A file can have a special layout with a dynamic number of columns. If the intention is to duplicate rows for
274 * every separate column, this is the method you require. It will remember the start position of the dynamic columns
275 * and treat every column after that as dynamic. For every dynamic column a row will be created. If a bean has
276 * fields annotated with @CsvHeaderName or @CsvHeaderValue, it will store the values of the header or the cell for
277 * that index column in the fields.
278 *
279 * @param startIndex
280 * the index where the dynamic columns start
281 *
282 * @return convenience for chaining
283 */
284 CsvClient<T> setStartIndexDynamicColumns(int startIndex);
285
286 /**
287 * Determines which mapping strategy is to be employed for mapping cells to bean properties. This method is called
288 * whenever {@link org.csveed.annotations.CsvFile#mappingStrategy()} is used. The default mapping strategy is
289 * {@link org.csveed.bean.ColumnIndexMapper}, which looks at either the position of a property within the class or
290 * the custom index if {@link org.csveed.annotations.CsvCell#columnIndex()} or
291 * {@link #mapColumnIndexToProperty(int, String)} has been set.
292 *
293 * @param mapper
294 * the mapping strategy to employ for mapping cells to bean properties
295 *
296 * @return convenience for chaining
297 */
298 CsvClient<T> setMapper(Class<? extends AbstractMapper> mapper);
299
300 /**
301 * Determines what dateformat to apply to the cell value before storing it as a date. This method is called whenever
302 * {@link org.csveed.annotations.CsvDate} is used. The default for date format is dd-MM-yyyy.
303 *
304 * @param propertyName
305 * the name of the property to write the date to
306 * @param dateFormat
307 * the date format to apply for parsing the date value
308 *
309 * @return convenience for chaining
310 */
311 CsvClient<T> setDate(String propertyName, String dateFormat);
312
313 /**
314 * Determines what Locale to apply to the cell value before converting it to a number. This method is called
315 * whenever {@link org.csveed.annotations.CsvLocalizedNumber} is used. The default for Locale is the Locale of the
316 * server.
317 *
318 * @param propertyName
319 * the name of the property to write the data to
320 * @param locale
321 * the Locale to apply for converting the number
322 *
323 * @return convenience for chaining
324 */
325 CsvClient<T> setLocalizedNumber(String propertyName, Locale locale);
326
327 /**
328 * Determines if the field is required. If so, the cell may not be empty and a
329 * {@link org.csveed.report.CsvException} will be thrown if this occurs. This method is called whenever
330 * {@link org.csveed.annotations.CsvCell#required()} is used. The default for a property is false.
331 *
332 * @param propertyName
333 * property for which the requirement applies
334 * @param required
335 * whether the cell must be not-null
336 *
337 * @return convenience for chaining
338 */
339 CsvClient<T> setRequired(String propertyName, boolean required);
340
341 /**
342 * Sets a custom {@link java.beans.PropertyEditor} for the property. This PropertyEditor is called to convert the
343 * text to the type of the property and set it on the bean. This method is called whenever
344 * {@link org.csveed.annotations.CsvConverter#converter()} is used. The default for a property is based on the
345 * wonderful set of PropertyEditors that Spring offers, which is all basics and some extras as well.
346 *
347 * @param propertyName
348 * property to which the converter must be applied
349 * @param converter
350 * PropertyEditor to apply to the property
351 *
352 * @return convenience for chaining
353 */
354 CsvClient<T> setConverter(String propertyName, Converter converter);
355
356 /**
357 * Sets a field to be ignored for purposes of mapping. This method is called whenever
358 * {@link org.csveed.annotations.CsvIgnore} is used. By default none of the fields are ignored unless, custom
359 * instructions are used. In this case, all fields are ignored by default.
360 *
361 * @param propertyName
362 * property which must be ignored for mapping
363 *
364 * @return convenience for chaining
365 */
366 CsvClient<T> ignoreProperty(String propertyName);
367
368 /**
369 * Maps a column in the CSV to a specific property. This method is called whenever
370 * {@link org.csveed.annotations.CsvCell#columnIndex()} is used. By default there is NO mapping when custom
371 * instructions are used, so you should roll your own. Note that column indexes are 1-based, not 0-based.
372 *
373 * @param columnIndex
374 * index of the column for which the property mapping must be applied
375 * @param propertyName
376 * property to which the index-based mapping must be applied
377 *
378 * @return convenience for chaining
379 */
380 CsvClient<T> mapColumnIndexToProperty(int columnIndex, String propertyName);
381
382 /**
383 * Maps a column name (which is found in the header) to a specific property. Note that to use this, headers must be
384 * enabled. This method is called whenever {@link org.csveed.annotations.CsvCell#columnName()} is used. By default
385 * there is NO mapping when custom instructions are used, so you should roll your own. Also, don't forget to
386 * {@link #setMapper(Class)} to {@link org.csveed.bean.ColumnNameMapper} for this to work.
387 *
388 * @param columnName
389 * name of the column for which the property mapping must be applied
390 * @param propertyName
391 * property to which the name-based mapping must be applied
392 *
393 * @return convenience for chaining
394 */
395 CsvClient<T> mapColumnNameToProperty(String columnName, String propertyName);
396
397 /**
398 * Determines what property will receive the header name in the currently active dynamic column.
399 *
400 * @param propertyName
401 * property in which the active dynamic header name must be stored
402 *
403 * @return convenience for chaining
404 */
405 CsvClient<T> setHeaderNameToProperty(String propertyName);
406
407 /**
408 * Determines what property will receive the cell value in the currently active dynamic column.
409 *
410 * @param propertyName
411 * property in which the active dynamic column value must be stored
412 *
413 * @return convenience for chaining
414 */
415 CsvClient<T> setHeaderValueToProperty(String propertyName);
416
417 }