1 package fr.ifremer.dali.ui.swing.util.table.export;
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 import com.google.common.base.Joiner;
27 import com.google.common.escape.Escaper;
28 import com.google.common.escape.Escapers;
29 import fr.ifremer.quadrige3.ui.core.dto.QuadrigeBean;
30 import fr.ifremer.dali.dto.DaliBeans;
31 import fr.ifremer.dali.ui.swing.action.AbstractDaliAction;
32 import fr.ifremer.dali.ui.swing.util.DaliUI;
33 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliRowUIModel;
34 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
35 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIModel;
36 import fr.ifremer.dali.ui.swing.util.table.DaliColumnIdentifier;
37 import fr.ifremer.quadrige3.core.dao.technical.Assert;
38 import fr.ifremer.quadrige3.core.dao.technical.csv.CSVDao;
39 import fr.ifremer.quadrige3.ui.swing.ApplicationUIUtil;
40 import fr.ifremer.quadrige3.ui.swing.table.CheckTableColumn;
41 import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
42 import org.apache.commons.lang3.CharUtils;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.nuiton.util.DateUtil;
46
47 import javax.swing.JEditorPane;
48 import javax.swing.JLabel;
49 import javax.swing.JOptionPane;
50 import javax.swing.event.HyperlinkEvent;
51 import javax.swing.table.TableColumn;
52 import java.awt.Component;
53 import java.io.BufferedWriter;
54 import java.io.File;
55 import java.io.IOException;
56 import java.net.URL;
57 import java.nio.charset.StandardCharsets;
58 import java.nio.file.Files;
59 import java.util.*;
60
61 import static org.nuiton.i18n.I18n.t;
62
63
64
65
66
67
68 public class ExportToCSVAction<M extends AbstractDaliTableUIModel<?, ?, M>, UI extends DaliUI<M, ?>, H extends AbstractDaliTableUIHandler<?, M, UI>>
69 extends AbstractDaliAction<M, UI, H> {
70
71 public static final Log LOG = LogFactory.getLog(ExportToCSVAction.class);
72
73
74
75
76 private final String tableName;
77
78 private Collection<DaliColumnIdentifier<? extends AbstractDaliRowUIModel>> ignoredColumnIdentifiers;
79
80 private File outputFile;
81
82 private char separator = 0;
83
84 private Escaper csvEscaper;
85
86
87
88
89
90
91 @SafeVarargs
92 public ExportToCSVAction(H handler, String tableName, DaliColumnIdentifier<? extends AbstractDaliRowUIModel>... identifiersToIgnore) {
93 super(handler, false);
94 setActionDescription(t("dali.action.extract.table.label"));
95 Assert.notBlank(tableName);
96 this.tableName = tableName;
97 if (identifiersToIgnore != null) {
98 getIgnoredColumnIdentifiers().addAll(Arrays.asList(identifiersToIgnore));
99 }
100 }
101
102 private Collection<DaliColumnIdentifier<? extends AbstractDaliRowUIModel>> getIgnoredColumnIdentifiers() {
103 if (ignoredColumnIdentifiers == null) {
104 ignoredColumnIdentifiers = new ArrayList<>();
105 }
106 return ignoredColumnIdentifiers;
107 }
108
109
110
111
112
113
114 private File getOutputFile() {
115 return outputFile;
116 }
117
118
119
120
121
122
123 protected SwingTable getTable() {
124 return getHandler().getTable();
125 }
126
127
128
129
130
131
132 protected List<TableColumn> getColumns() {
133 return DaliBeans.filterCollection(getTable().getColumns(false),
134 column -> column != null
135 && !(column instanceof CheckTableColumn)
136 && column.getIdentifier() instanceof DaliColumnIdentifier
137 && !getIgnoredColumnIdentifiers().contains(column.getIdentifier())
138 );
139 }
140
141
142
143
144
145
146 protected char getSeparator() {
147 if (separator == 0) {
148 separator = getConfig().getCsvSeparator().charAt(0);
149 }
150 return separator;
151 }
152
153
154
155
156
157
158 private Escaper getCsvEscaper() {
159 if (csvEscaper == null) {
160 csvEscaper = Escapers.builder().addEscape(CharUtils.CR, "").addEscape(CharUtils.LF, "").addEscape(getSeparator(), "").build();
161 }
162 return csvEscaper;
163 }
164
165
166
167
168 @Override
169 public boolean prepareAction() throws Exception {
170 if (!super.prepareAction()) {
171 return false;
172 }
173
174
175 String date = DateUtil.formatDate(new Date(), "yyyy-MM-dd");
176 String fileName = String.format("%s-%s-%s", t("dali.service.extraction.file.prefix"), tableName, date);
177 String fileExtension = getConfig().getExtractionResultFileExtension();
178
179
180 outputFile = saveFile(
181 fileName,
182 fileExtension,
183 t("dali.action.extract.table.choose.file.title", tableName),
184 t("dali.action.extract.table.choose.file.buttonLabel"),
185 "^.*\\." + fileExtension,
186 t("dali.common.file." + fileExtension));
187
188 return outputFile != null;
189 }
190
191
192
193
194 @Override
195 public void doAction() throws Exception {
196
197
198 try (BufferedWriter writer = Files.newBufferedWriter(getOutputFile().toPath(), StandardCharsets.UTF_8)) {
199
200
201 writer.write(CSVDao.UTF8_BOM);
202
203
204 writeHeader(writer);
205
206
207 writeLines(writer);
208
209
210 writer.flush();
211
212 }
213
214 }
215
216
217
218
219 @Override
220 public void postSuccessAction() {
221
222 String text = t("dali.action.extract.table.done", tableName, outputFile.getAbsoluteFile().toURI(), outputFile.getAbsolutePath());
223
224 JEditorPane editorPane = new JEditorPane("text/html", text);
225 editorPane.setEditable(false);
226 editorPane.addHyperlinkListener(e -> {
227 if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
228 URL url = e.getURL();
229 if (LOG.isInfoEnabled()) {
230 LOG.info("open url: " + url);
231 }
232 ApplicationUIUtil.openLink(url);
233 }
234 });
235
236 getContext().getDialogHelper().showOptionDialog(
237 null,
238 editorPane,
239 t("dali.action.extract.table.title", tableName),
240 JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION);
241
242 }
243
244
245
246
247 @Override
248 protected void releaseAction() {
249 outputFile = null;
250 super.releaseAction();
251 }
252
253 private void writeHeader(BufferedWriter writer) throws IOException {
254
255 writer.write(getHeader());
256 writer.newLine();
257
258 }
259
260
261
262
263
264
265 protected String getHeader() {
266
267 return Joiner.on(getSeparator()).skipNulls().join(DaliBeans.transformCollection(getColumns(), tableColumn -> {
268 DaliColumnIdentifier identifier = (DaliColumnIdentifier) tableColumn.getIdentifier();
269 return t(identifier.getHeaderI18nKey());
270 }));
271 }
272
273
274
275
276
277
278
279 private void writeLines(BufferedWriter writer) throws IOException {
280
281 int nbRows = getTable().getRowCount();
282
283 for (int rowIndex = 0; rowIndex < nbRows; rowIndex++) {
284
285
286 List<String> rowValues = new ArrayList<>(getColumns().size());
287
288
289 for (TableColumn column : getColumns()) {
290
291
292 String stringValue = "";
293
294
295 Object value = getTable().getModel().getValueAt(rowIndex, column.getModelIndex());
296
297
298 if (value != null) {
299 stringValue = getStringValue(value, rowIndex, column);
300 }
301
302
303 rowValues.add(getCsvEscaper().escape(stringValue));
304 }
305
306
307 writer.write(Joiner.on(getSeparator()).join(rowValues));
308 writer.newLine();
309 }
310 }
311
312
313
314
315
316
317
318
319
320 private String getStringValue(Object value, int rowIndex, TableColumn column) {
321
322 if (value instanceof QuadrigeBean && column.getCellRenderer() != null) {
323
324 Component component = column.getCellRenderer().getTableCellRendererComponent(getTable(), value, false, false, rowIndex, column.getModelIndex());
325 if (component instanceof JLabel) {
326 return ((JLabel) component).getText();
327 }
328 }
329
330
331 return value.toString();
332 }
333 }