View Javadoc
1   package fr.ifremer.tutti.service.csv;
2   
3   /*
4    * #%L
5    * Tutti :: Service
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
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   * Created on 2/11/15.
55   *
56   * @author Tony Chemit - chemit@codelutin.com
57   * @since 3.14
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              // should never happen
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 }