1 package fr.ifremer.tutti.service.csv;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import com.google.common.base.Charsets;
28 import com.google.common.base.Joiner;
29 import com.google.common.collect.ImmutableMap;
30 import com.google.common.io.Files;
31 import org.apache.commons.io.IOUtils;
32 import org.nuiton.csv.AbstractImportErrorInfo;
33 import org.nuiton.csv.Import2;
34 import org.nuiton.csv.ImportConf;
35 import org.nuiton.csv.ImportRow;
36 import org.nuiton.csv.ImportableColumn;
37 import org.nuiton.jaxx.application.ApplicationBusinessException;
38 import org.nuiton.jaxx.application.ApplicationTechnicalException;
39
40 import java.io.BufferedReader;
41 import java.io.Closeable;
42 import java.io.FileNotFoundException;
43 import java.io.IOException;
44 import java.nio.file.Path;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedHashMap;
48 import java.util.Map;
49 import java.util.Set;
50
51 import static org.nuiton.i18n.I18n.t;
52
53
54
55
56
57
58
59 public abstract class CsvComsumer<O, M extends AbstractTuttiImportExportModel<O>> implements Closeable, Iterable<ImportRow<O>> {
60
61 private final BufferedReader reader;
62
63 private final Import2<O> importer;
64
65 private final boolean failFast;
66
67 private final Map<Long, Set<String>> rowsInError;
68
69 public CsvComsumer(Path file, M model, boolean failFast) {
70 this.failFast = failFast;
71 this.rowsInError = new LinkedHashMap<>();
72 try {
73 this.reader = Files.newReader(file.toFile(), Charsets.UTF_8);
74 } catch (FileNotFoundException e) {
75
76 throw new ApplicationTechnicalException("file not found " + file, e);
77 }
78
79 ImportConf importConf = new ImportConf();
80 importConf.setStrictMode(failFast);
81 this.importer = Import2.newImport(importConf, model, reader);
82
83 }
84
85 @Override
86 public Iterator<ImportRow<O>> iterator() {
87 return this.importer.iterator();
88 }
89
90 @Override
91 public void close() throws IOException {
92 IOUtils.closeQuietly(reader);
93 IOUtils.closeQuietly(importer);
94 }
95
96 public void addCheckError(ImportRow<O> row, Exception e) {
97
98 row.addError(new CheckImportErrorInfo<>(row, null, e));
99
100 }
101
102 public String rowErrorsToExceptionMessage(ImportRow<O> bean) {
103
104 Set<String> errors = new HashSet<>();
105 for (AbstractImportErrorInfo<O> errorInfo : bean.getErrors()) {
106
107 Throwable cause = errorInfo.getCause();
108
109 if (errorInfo.getField() == null) {
110
111 errors.add(cause.getMessage());
112
113 } else {
114
115 errors.add(t("tutti.csv.import.error.on.field", errorInfo.getField().getHeaderName(), cause.getMessage()));
116 }
117
118 }
119
120 return t("tutti.csv.import.error.on.row", bean.getLineNumber(), Joiner.on("\n").join(errors));
121
122 }
123
124
125 public Set<String> rowErrorsToMessage(ImportRow<O> bean) {
126
127 Set<String> errors = new HashSet<>();
128 for (AbstractImportErrorInfo<O> errorInfo : bean.getErrors()) {
129
130 Throwable cause = errorInfo.getCause();
131
132 if (errorInfo.getField() == null) {
133
134 errors.add(cause.getMessage());
135
136 } else {
137
138 errors.add(t("tutti.csv.import.error.on.field", errorInfo.getField().getHeaderName(), cause.getMessage()));
139 }
140
141 }
142
143 return errors;
144
145 }
146
147 public int getNbRowsInErrors() {
148 return rowsInError.size();
149 }
150
151 public Map<Long, Set<String>> getRowsInError() {
152 return ImmutableMap.copyOf(rowsInError);
153 }
154
155 protected void reportError(ImportRow<O> row) {
156
157 if (!row.isValid()) {
158
159
160 if (failFast) {
161
162 String message = rowErrorsToExceptionMessage(row);
163 throw new ApplicationBusinessException(message);
164
165 } else {
166
167 rowsInError.put(row.getLineNumber(), rowErrorsToMessage(row));
168
169 }
170
171 }
172
173 }
174
175 public static class CheckImportErrorInfo<E> extends AbstractImportErrorInfo<E> {
176
177 public CheckImportErrorInfo(ImportRow<E> row, ImportableColumn<E, Object> field, Throwable cause) {
178 super(row, field, cause);
179 }
180
181 }
182 }