1
2
3
4
5
6
7
8
9
10
11
12
13
14 package olg.csv.base.ods;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.io.OutputStream;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import olg.csv.base.AbstractSheetWriter;
23 import olg.csv.base.Cell;
24 import olg.csv.base.Row;
25 import olg.csv.base.WriterException;
26 import olg.csv.bean.parser.AbstractParser;
27 import olg.csv.bean.parser.ParseException;
28
29 import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
30 import org.odftoolkit.odfdom.doc.table.OdfTable;
31 import org.odftoolkit.odfdom.doc.table.OdfTableCell;
32 import org.odftoolkit.odfdom.doc.table.OdfTableRow;
33 import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42
43 public class ODSWriter extends AbstractSheetWriter {
44
45
46
47 private static final Logger LOGGER = LoggerFactory.getLogger(ODSWriter.class);
48
49
50
51 private OdfSpreadsheetDocument outputDocument = null;
52
53
54
55 private OdfTable table = null;
56
57
58
59 private File outFile = null;
60
61
62
63 private OutputStream out = null;
64
65
66
67 private final AbstractParser<List<String>> cellParser;
68
69
70
71 private int size;
72
73
74
75 private int currentLine = 1;
76
77
78
79
80
81 private final boolean emptyingCell;
82
83
84
85
86
87 private final boolean emtpyingRow;
88
89
90
91
92
93 private boolean overridding = false;
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public ODSWriter(File outFile, ODSSettings settings) throws IOException {
108 super(settings);
109 if (outFile == null) {
110 throw new IllegalArgumentException("ODSWriter constructor File argument must not be null");
111 }
112
113 if (settings.getStringParser() == null) {
114 throw new IllegalArgumentException(
115 "ODSWriter constructor ODSSettings argument must have not null StringParser attribut");
116 }
117 this.outFile = outFile;
118 this.cellParser = settings.getStringParser();
119 this.emptyingCell = settings.isEmptyingCell();
120 this.emtpyingRow = settings.isEmptyingRow();
121
122 if (this.outFile.isFile()) {
123 loadDocument(sheetName);
124 } else {
125 createNewDocument(sheetName);
126 }
127
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 public ODSWriter(OutputStream out, ODSSettings settings) throws IOException {
142 super(settings);
143 if (out == null) {
144 throw new IllegalArgumentException("ODSWriter constructor out argument must not be null");
145 }
146 if (settings.getStringParser() == null) {
147 throw new IllegalArgumentException(
148 "ODSWriter constructor ODSSettings argument must have not null StringParser attribut");
149 }
150
151 this.out = out;
152 this.cellParser = settings.getStringParser();
153 this.emptyingCell = settings.isEmptyingCell();
154 this.emtpyingRow = settings.isEmptyingRow();
155
156 try {
157 createNewDocument(sheetName);
158 } catch (Exception e) {
159 LOGGER.debug("Unable to create ODS Document", e);
160 throw new IOException("Unable to create ODS Document", e);
161 }
162 }
163
164
165
166
167
168
169
170 public void close() {
171 if (outputDocument != null) {
172 try {
173 if (outFile != null) {
174 outputDocument.save(outFile);
175 }
176 if (out != null) {
177 outputDocument.save(out);
178 }
179 } catch (Exception e) {
180 LOGGER.info("Error on closing ODSWriter : Unable to save ODS file " + outFile, e);
181 } finally {
182 outputDocument.close();
183 }
184 }
185 }
186
187
188
189
190 public void addRow(Row row) {
191 if (row == null) {
192 throw new IllegalArgumentException("ODSWriter#addRow argument must not be null");
193 }
194 if (row.getNum() < currentLine) {
195 throw new WriterException(String.format("Row num[%s] but %s was expected or superior", row.getNum(),
196 currentLine));
197 }
198 if (size == 0) {
199 size = row.getSize();
200 }
201 if (size != row.getSize()) {
202 throw new WriterException(String.format("Row size[%s] differs from the expected size[%s] ", row.getSize(),
203 size));
204 }
205
206 emptyRows(row.getNum());
207
208 OdfTableRow odfRow = table.getRowByIndex(row.getNum() + beginAtRow - 2);
209
210 int column = 0;
211 for (Cell cell : row) {
212 if (cell.getNum() < column) {
213 throw new WriterException("ODSWriter#addRow cells must be ordered ");
214 }
215
216 emptyCells(odfRow, column, cell.getNum(), false);
217
218 insertCell(odfRow, cell);
219 column = cell.getNum() + 1;
220 }
221
222 emptyCells(odfRow, column, size, false);
223
224 currentLine = row.getNum() + 1;
225
226 }
227
228
229
230
231 public void addLine(String[] values) {
232 if (values == null || values.length == 0) {
233 throw new IllegalArgumentException("ODSWriter#addLine argument must not be null");
234 }
235 if (size == 0) {
236 size = values.length;
237 }
238 if (size != values.length) {
239 throw new WriterException(String.format("Values size[%s] differs from the expected size[%s]",
240 values.length, size));
241 }
242
243 int column = 0;
244 OdfTableRow odfRow = table.getRowByIndex(currentLine + beginAtRow - 2);
245
246 for (String value : values) {
247 insertCellAtNum(odfRow, column++, value);
248
249 }
250 currentLine++;
251
252 }
253
254
255
256
257
258
259
260
261 private OdfTable createSheet(String sheetName) {
262 OdfTable table = OdfTable.newTable(outputDocument);
263 table.removeRowsByIndex(0, 5);
264 table.removeColumnsByIndex(0, 4);
265 table.setTableName(sheetName);
266 return table;
267 }
268
269
270
271
272
273
274
275
276
277
278 private void createNewDocument(String sheetName) throws IOException {
279 try {
280 this.outputDocument = OdfSpreadsheetDocument.newSpreadsheetDocument();
281 } catch (Exception e) {
282 LOGGER.debug("Unable to create new ODS Document", e);
283 throw new IOException("Unable to create new ODS Document", e);
284 }
285 for (OdfTable feuille : this.outputDocument.getTableList()) {
286
287
288 if (!sheetName.equals(feuille.getTableName())) {
289 feuille.remove();
290 }
291 }
292 this.table = createSheet(sheetName);
293 }
294
295
296
297
298
299
300
301
302
303
304 private void loadDocument(String sheetName) throws IOException {
305 try {
306 this.outputDocument = OdfSpreadsheetDocument.loadDocument(this.outFile);
307 } catch (Exception e) {
308 LOGGER.debug("Unable to load ODS Document", e);
309 throw new IOException("Unable to load ODS Document", e);
310 }
311
312 for (OdfTable feuille : this.outputDocument.getTableList()) {
313
314
315 if (sheetName.equals(feuille.getTableName())) {
316 this.table = feuille;
317 this.overridding = true;
318 break;
319 }
320 }
321 if (this.table == null) {
322 this.table = createSheet(sheetName);
323 }
324
325 }
326
327
328
329
330
331
332
333
334
335 private void insertCell(OdfTableRow odfRow, Cell cell) {
336 OdfTableCell odfCell = odfRow.getCellByIndex(cell.getNum() + beginAtColumn);
337
338 if (cell.isEmpty()) {
339 odfCell.setStringValue(null);
340 } else {
341 insertCell(odfCell, cell.getValue());
342 }
343 }
344
345
346
347
348
349
350
351
352
353
354
355 private void insertCellAtNum(OdfTableRow odfRow, int num, String value) {
356 OdfTableCell odfCell = odfRow.getCellByIndex(num + beginAtColumn);
357
358 if (value == null) {
359 odfCell.setStringValue(null);
360 } else {
361 insertCell(odfCell, value);
362 }
363 }
364
365
366
367
368
369
370
371
372
373
374 private void insertCell(OdfTableCell odfCell, String value) {
375 odfCell.removeContent();
376 for (String line : cellParser.parse(value)) {
377 OdfTextParagraph paragraph;
378 try {
379 paragraph = new OdfTextParagraph(this.outputDocument.getContentDom());
380
381
382
383
384
385 paragraph.setTextContent(line);
386 odfCell.getOdfElement().appendChild(paragraph);
387 } catch (Exception e) {
388 LOGGER.debug("Error on copy [" + value + "]", e);
389 throw new WriterException("Error on copy [" + value + "]", e);
390
391 }
392
393 }
394 }
395
396
397
398
399
400
401
402
403 private void emptyRows(int num) {
404 if (overridding && emtpyingRow) {
405 for (int i = currentLine; i < num; i++) {
406 emptyCells(table.getRowByIndex(i + beginAtRow - 2), 0, size, true);
407 }
408 }
409 }
410
411
412
413
414
415
416
417
418
419
420
421
422
423 private void emptyCells(OdfTableRow row, int begin, int end, boolean force) {
424 if (force || (overridding && emptyingCell)) {
425 for (int j = begin; j < end; j++) {
426 row.getCellByIndex(j + beginAtColumn).removeContent();
427 }
428 }
429 }
430
431
432
433
434
435
436
437
438
439
440
441
442 public static class ODSParser extends AbstractParser<List<String>> {
443
444 @Override
445 public List<String> parse(String str) throws ParseException {
446
447 ArrayList<String> lines = new ArrayList<String>();
448 int beginAt = 0;
449
450 boolean skipLF = false;
451 boolean reindex = false;
452 char[] chars = str.toCharArray();
453 for (int i = 0; i < chars.length; i++) {
454 if (reindex) {
455 beginAt = i;
456 reindex = false;
457 }
458
459 if (chars[i] == '\r') {
460 lines.add(String.copyValueOf(chars, beginAt, i - beginAt));
461 if (chars[i] == '\r') {
462 skipLF = true;
463 }
464 reindex = true;
465 }
466
467 if (chars[i] == '\n') {
468 if (skipLF) {
469 skipLF = false;
470 } else {
471 lines.add(String.copyValueOf(chars, beginAt, i - beginAt));
472 }
473 reindex = true;
474 }
475 }
476
477 if (reindex) {
478 lines.add(String.copyValueOf(chars, beginAt, 0));
479 } else {
480 lines.add(String.copyValueOf(chars, beginAt, chars.length - beginAt));
481 }
482
483 return lines;
484
485 }
486 }
487
488 }