View Javadoc
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.row;
12  
13  import java.io.IOException;
14  import java.io.Writer;
15  import java.util.Collection;
16  import java.util.Iterator;
17  
18  import org.csveed.api.Header;
19  import org.csveed.api.Row;
20  import org.csveed.report.CsvException;
21  import org.csveed.report.GeneralError;
22  import org.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  
25  /**
26   * The Class RowWriterImpl.
27   */
28  public class RowWriterImpl implements RowWriter {
29  
30      /** The Constant LOG. */
31      private static final Logger LOG = LoggerFactory.getLogger(RowWriterImpl.class);
32  
33      /** The writer. */
34      private final Writer writer;
35  
36      /** The row instructions. */
37      private RowInstructions rowInstructions;
38  
39      /** The header. */
40      private Header header;
41  
42      /**
43       * Instantiates a new row writer impl.
44       *
45       * @param writer
46       *            the writer
47       */
48      public RowWriterImpl(Writer writer) {
49          this(writer, new RowInstructionsImpl());
50      }
51  
52      /**
53       * Instantiates a new row writer impl.
54       *
55       * @param writer
56       *            the writer
57       * @param rowInstructions
58       *            the row instructions
59       */
60      public RowWriterImpl(Writer writer, RowInstructions rowInstructions) {
61          this.writer = writer;
62          this.rowInstructions = rowInstructions;
63      }
64  
65      @Override
66      public void writeRows(String[][] rows) {
67          for (String[] row : rows) {
68              writeRow(row);
69          }
70      }
71  
72      @Override
73      public void writeRows(Collection<Row> rows) {
74          for (Row row : rows) {
75              writeRow(row);
76          }
77      }
78  
79      @Override
80      public Row writeRow(String[] cells) {
81          Row row = new RowImpl(convertToLine(cells), header);
82          writeRow(row);
83          return row;
84      }
85  
86      @Override
87      public void writeRow(Row row) {
88          if (rowInstructions.isUseHeader() && this.header == null) {
89              throw new CsvException(
90                      new GeneralError("Header has not been set for this table. Make sure to write it or configure "
91                              + "it to be not used: .setUseHeader(false)"));
92          }
93          writeCells(row.iterator());
94      }
95  
96      @Override
97      public Header writeHeader(String[] headerNames) {
98          Header header = new HeaderImpl(convertToLine(headerNames));
99          writeHeader(header);
100         return header;
101     }
102 
103     @Override
104     public void writeHeader(Header header) {
105         this.header = header;
106         writeCells(header.iterator());
107     }
108 
109     @Override
110     public RowInstructions getRowInstructions() {
111         return this.rowInstructions;
112     }
113 
114     /**
115      * Write cells.
116      *
117      * @param cells
118      *            the cells
119      */
120     private void writeCells(Iterator<String> cells) {
121         int columnPosition = 1;
122         try {
123             while (cells.hasNext()) {
124                 String cell = cells.next();
125                 String nullSafeCell = cell != null ? cell : "";
126                 String headerValue = header != null ? header.getName(columnPosition) : "";
127                 LOG.debug("Writing cell value [{}] in column position [{}], header value is [{}].", nullSafeCell,
128                         columnPosition, headerValue);
129                 if (columnPosition != 1) {
130                     writeSeparator();
131                 }
132                 if (rowInstructions.getQuotingEnabled()) {
133                     writeQuotedCell(nullSafeCell);
134                 } else {
135                     writeCell(nullSafeCell);
136                 }
137                 columnPosition++;
138             }
139             writeEOL();
140         } catch (IOException e) {
141             LOG.trace("", e);
142             throw new CsvException(new GeneralError("Error in writing to the writer: " + e.getMessage()));
143         }
144     }
145 
146     /**
147      * Write EOL.
148      *
149      * @throws IOException
150      *             Signals that an I/O exception has occurred.
151      */
152     private void writeEOL() throws IOException {
153         writer.write(rowInstructions.getEndOfLine());
154     }
155 
156     /**
157      * Write separator.
158      *
159      * @throws IOException
160      *             Signals that an I/O exception has occurred.
161      */
162     private void writeSeparator() throws IOException {
163         writer.write(rowInstructions.getSeparator());
164     }
165 
166     /**
167      * Write quoted cell.
168      *
169      * @param cell
170      *            the cell
171      *
172      * @throws IOException
173      *             Signals that an I/O exception has occurred.
174      */
175     private void writeQuotedCell(String cell) throws IOException {
176         writer.write(rowInstructions.getQuote());
177         String searchString = Character.toString(rowInstructions.getQuote());
178         String replaceString = new String(new char[] { rowInstructions.getEscape(), rowInstructions.getQuote() });
179         String replacedString = cell.replace(searchString, replaceString);
180         writeCell(replacedString);
181         writer.write(rowInstructions.getQuote());
182     }
183 
184     /**
185      * Write cell.
186      *
187      * @param cell
188      *            the cell
189      *
190      * @throws IOException
191      *             Signals that an I/O exception has occurred.
192      */
193     private void writeCell(String cell) throws IOException {
194         writer.write(cell);
195     }
196 
197     /**
198      * Convert to line.
199      *
200      * @param cells
201      *            the cells
202      *
203      * @return the line with info
204      */
205     private LineWithInfo convertToLine(String[] cells) {
206         LineWithInfo line = new LineWithInfo();
207         for (String cell : cells) {
208             line.addCell(cell);
209         }
210         return line;
211     }
212 
213 }