OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 174 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 174 Rev 182
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
9
 * language governing permissions and limitations under the License.
10
 * 
10
 * 
11
 * When distributing the software, include this License Header Notice in each file.
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
12
 */
13
 
13
 
14
 package org.openconcerto.erp.generationDoc;
14
 package org.openconcerto.erp.generationDoc;
15
 
15
 
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
17
import org.openconcerto.erp.core.common.ui.PreviewFrame;
17
import org.openconcerto.erp.core.common.ui.PreviewFrame;
-
 
18
import org.openconcerto.erp.core.customerrelationship.mail.EmailTemplate;
-
 
19
import org.openconcerto.erp.core.customerrelationship.mail.ValueListener;
18
import org.openconcerto.erp.core.sales.invoice.report.VenteFactureXmlSheet;
20
import org.openconcerto.erp.core.sales.invoice.report.VenteFactureXmlSheet;
19
import org.openconcerto.erp.core.sales.quote.report.PaypalStamper;
21
import org.openconcerto.erp.core.sales.quote.report.PaypalStamper;
20
import org.openconcerto.erp.generationDoc.element.TypeModeleSQLElement;
22
import org.openconcerto.erp.generationDoc.element.TypeModeleSQLElement;
-
 
23
import org.openconcerto.erp.model.MouseSheetXmlListeListener;
21
import org.openconcerto.erp.preferences.PayPalPreferencePanel;
24
import org.openconcerto.erp.preferences.PayPalPreferencePanel;
22
import org.openconcerto.erp.storage.CloudStorageEngine;
25
import org.openconcerto.erp.storage.CloudStorageEngine;
23
import org.openconcerto.erp.storage.StorageEngine;
26
import org.openconcerto.erp.storage.StorageEngine;
24
import org.openconcerto.erp.storage.StorageEngines;
27
import org.openconcerto.erp.storage.StorageEngines;
25
import org.openconcerto.openoffice.OOUtils;
28
import org.openconcerto.openoffice.OOUtils;
26
import org.jopendocument.link.Component;
29
import org.jopendocument.link.Component;
27
import org.openconcerto.sql.Configuration;
30
import org.openconcerto.sql.Configuration;
-
 
31
import org.openconcerto.sql.element.SQLComponent;
28
import org.openconcerto.sql.element.SQLElement;
32
import org.openconcerto.sql.element.SQLElement;
29
import org.openconcerto.sql.model.SQLBase;
33
import org.openconcerto.sql.model.SQLBase;
30
import org.openconcerto.sql.model.SQLRow;
34
import org.openconcerto.sql.model.SQLRow;
31
import org.openconcerto.sql.model.SQLRowAccessor;
35
import org.openconcerto.sql.model.SQLRowAccessor;
-
 
36
import org.openconcerto.sql.model.SQLTable;
32
import org.openconcerto.sql.preferences.SQLPreferences;
37
import org.openconcerto.sql.preferences.SQLPreferences;
-
 
38
import org.openconcerto.sql.view.EditFrame;
-
 
39
import org.openconcerto.sql.view.EditPanel.EditMode;
-
 
40
import org.openconcerto.ui.FrameUtil;
-
 
41
import org.openconcerto.utils.Action;
33
import org.openconcerto.utils.ExceptionHandler;
42
import org.openconcerto.utils.ExceptionHandler;
34
import org.openconcerto.utils.cc.ITransformer;
43
import org.openconcerto.utils.cc.ITransformer;
-
 
44
import org.openconcerto.utils.i18n.Grammar;
-
 
45
import org.openconcerto.utils.i18n.TranslationManager;
35
 
46
 
36
import java.awt.GraphicsEnvironment;
47
import java.awt.GraphicsEnvironment;
37
import java.awt.print.PrinterJob;
48
import java.awt.print.PrinterJob;
38
import java.io.BufferedInputStream;
49
import java.io.BufferedInputStream;
39
import java.io.File;
50
import java.io.File;
40
import java.io.FileInputStream;
51
import java.io.FileInputStream;
41
import java.io.FileNotFoundException;
52
import java.io.FileNotFoundException;
42
import java.io.IOException;
53
import java.io.IOException;
43
import java.io.InputStream;
54
import java.io.InputStream;
44
import java.io.InputStreamReader;
55
import java.io.InputStreamReader;
45
import java.io.OutputStream;
56
import java.io.OutputStream;
46
import java.lang.Thread.UncaughtExceptionHandler;
57
import java.lang.Thread.UncaughtExceptionHandler;
47
import java.net.HttpURLConnection;
58
import java.net.HttpURLConnection;
48
import java.net.URL;
59
import java.net.URL;
49
import java.net.URLConnection;
60
import java.net.URLConnection;
50
import java.net.URLEncoder;
61
import java.net.URLEncoder;
51
import java.nio.charset.StandardCharsets;
62
import java.nio.charset.StandardCharsets;
-
 
63
import java.util.ArrayList;
52
import java.util.Arrays;
64
import java.util.Arrays;
-
 
65
import java.util.Collections;
53
import java.util.HashMap;
66
import java.util.HashMap;
54
import java.util.List;
67
import java.util.List;
55
import java.util.Map;
68
import java.util.Map;
56
import java.util.StringJoiner;
69
import java.util.StringJoiner;
57
import java.util.concurrent.Callable;
70
import java.util.concurrent.Callable;
58
import java.util.concurrent.ExecutionException;
71
import java.util.concurrent.ExecutionException;
59
import java.util.concurrent.ExecutorService;
72
import java.util.concurrent.ExecutorService;
60
import java.util.concurrent.Future;
73
import java.util.concurrent.Future;
61
import java.util.concurrent.LinkedBlockingQueue;
74
import java.util.concurrent.LinkedBlockingQueue;
62
import java.util.concurrent.ThreadFactory;
75
import java.util.concurrent.ThreadFactory;
63
import java.util.concurrent.ThreadPoolExecutor;
76
import java.util.concurrent.ThreadPoolExecutor;
64
import java.util.concurrent.TimeUnit;
77
import java.util.concurrent.TimeUnit;
65
 
78
 
66
import javax.swing.JOptionPane;
79
import javax.swing.JOptionPane;
67
 
80
 
68
import org.jopendocument.model.OpenDocument;
81
import org.jopendocument.model.OpenDocument;
69
 
82
 
70
public abstract class SheetXml {
83
public abstract class SheetXml {
71
 
84
 
72
    private ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess = null;
85
    private ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess = null;
73
 
86
 
74
    public ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> getPostProcess() {
87
    public ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> getPostProcess() {
75
        return postProcess;
88
        return postProcess;
76
    }
89
    }
77
 
90
 
78
    // INSTEAD USE THE PREF IN L.O. CALC --> Formules, toujours recalculer
91
    // INSTEAD USE THE PREF IN L.O. CALC --> Formules, toujours recalculer
79
    private boolean refreshFormulasRequired = false;
92
    private boolean refreshFormulasRequired = false;
80
 
93
 
81
    // return null to keep default value
94
    // return null to keep default value
82
    public interface StorageDirs {
95
    public interface StorageDirs {
83
        public File getDocumentOutputDirectory(SheetXml sheet);
96
        public File getDocumentOutputDirectory(SheetXml sheet);
84
 
97
 
85
        public File getPDFOutputDirectory(SheetXml sheet);
98
        public File getPDFOutputDirectory(SheetXml sheet);
86
 
99
 
87
        public String getStoragePath(SheetXml sheet);
100
        public String getStoragePath(SheetXml sheet);
88
    }
101
    }
89
 
102
 
90
    /**
103
    /**
91
     * Post process line
104
     * Post process line
92
     * 
105
     * 
93
     * @param postProcess
106
     * @param postProcess
94
     */
107
     */
95
    public void setPostProcess(ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess) {
108
    public void setPostProcess(ITransformer<List<SQLRowAccessor>, List<SQLRowAccessor>> postProcess) {
96
        this.postProcess = postProcess;
109
        this.postProcess = postProcess;
97
    }
110
    }
98
 
111
 
99
    private static StorageDirs STORAGE_DIRS;
112
    private static StorageDirs STORAGE_DIRS;
100
 
113
 
101
    // allow to redirect all documents
114
    // allow to redirect all documents
102
    public static void setStorageDirs(StorageDirs d) {
115
    public static void setStorageDirs(StorageDirs d) {
103
        STORAGE_DIRS = d;
116
        STORAGE_DIRS = d;
104
    }
117
    }
105
 
118
 
106
    public static final String DEFAULT_PROPERTY_NAME = "Default";
119
    public static final String DEFAULT_PROPERTY_NAME = "Default";
107
    protected SQLElement elt;
120
    protected SQLElement elt;
108
 
121
 
109
    // nom de l'imprimante à utiliser
122
    // nom de l'imprimante à utiliser
110
    protected String printer;
123
    protected String printer;
111
 
124
 
112
    // id
125
    // id
113
    protected SQLRow row;
126
    protected SQLRow row;
114
 
127
 
115
    // Language du document
128
    // Language du document
116
    protected SQLRow rowLanguage;
129
    protected SQLRow rowLanguage;
117
 
130
 
118
    protected static final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
131
    protected static final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
119
 
132
 
120
    // single threaded and kill its thread after 3 seconds (to allow the program to exit)
133
    // single threaded and kill its thread after 3 seconds (to allow the program to exit)
121
    protected static final ExecutorService runnableQueue = new ThreadPoolExecutor(0, 1, 3L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
134
    protected static final ExecutorService runnableQueue = new ThreadPoolExecutor(0, 1, 3L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
122
 
135
 
123
        @Override
136
        @Override
124
        public Thread newThread(Runnable r) {
137
        public Thread newThread(Runnable r) {
125
            final Thread res = new Thread(r);
138
            final Thread res = new Thread(r);
126
            res.setUncaughtExceptionHandler(DEFAULT_HANDLER);
139
            res.setUncaughtExceptionHandler(DEFAULT_HANDLER);
127
 
140
 
128
            return res;
141
            return res;
129
        }
142
        }
130
    });
143
    });
131
 
144
 
132
    protected static UncaughtExceptionHandler DEFAULT_HANDLER = new UncaughtExceptionHandler() {
145
    protected static UncaughtExceptionHandler DEFAULT_HANDLER = new UncaughtExceptionHandler() {
133
        @Override
146
        @Override
134
        public void uncaughtException(Thread t, Throwable e) {
147
        public void uncaughtException(Thread t, Throwable e) {
135
            ExceptionHandler.handle("Erreur de generation", e);
148
            ExceptionHandler.handle("Erreur de generation", e);
136
        }
149
        }
137
    };
150
    };
138
 
151
 
139
    public final SQLElement getElement() {
152
    public final SQLElement getElement() {
140
        return this.elt;
153
        return this.elt;
141
    }
154
    }
142
 
155
 
-
 
156
    public Future<SheetXml> showPrintAndExportAsynchronous(final boolean showDocument, final boolean printDocument, final boolean exportToPDF) {
-
 
157
        return showPrintAndExportAsynchronous(showDocument, printDocument, exportToPDF, Collections.emptyList());
-
 
158
    }
-
 
159
 
143
    /**
160
    /**
144
     * Show, print and export the document to PDF. This method is asynchronous, but is executed in a
161
     * Show, print and export the document to PDF. This method is asynchronous, but is executed in a
145
     * single threaded queue shared with createDocument
162
     * single threaded queue shared with createDocument
146
     */
163
     */
147
    public Future<SheetXml> showPrintAndExportAsynchronous(final boolean showDocument, final boolean printDocument, final boolean exportToPDF) {
164
    public Future<SheetXml> showPrintAndExportAsynchronous(final boolean showDocument, final boolean printDocument, final boolean exportToPDF, List<Action> actions) {
148
        final Callable<SheetXml> c = new Callable<SheetXml>() {
165
        final Callable<SheetXml> c = new Callable<SheetXml>() {
149
            @Override
166
            @Override
150
            public SheetXml call() throws Exception {
167
            public SheetXml call() throws Exception {
-
 
168
                showPrintAndExport(showDocument, printDocument, exportToPDF, actions);
-
 
169
                return SheetXml.this;
-
 
170
            }
-
 
171
        };
-
 
172
        return runnableQueue.submit(c);
-
 
173
 
-
 
174
    }
-
 
175
 
-
 
176
    public Future<SheetXml> showPrintAndExportAsynchronous(final boolean showDocument, final boolean printDocument, final boolean exportToPDF, final SQLElement element, SQLRow row) {
-
 
177
        final Callable<SheetXml> c = new Callable<SheetXml>() {
-
 
178
 
-
 
179
            @Override
-
 
180
            public SheetXml call() throws Exception {
-
 
181
                final List<Action> actions = new ArrayList<>();
-
 
182
                if (SheetXml.this instanceof AbstractSheetXml) {
-
 
183
                    final SQLTable table = element.getTable();
-
 
184
                    final Action emailAction = new Action(TranslationManager.getInstance().getTranslationForAction("document.pdf.send.email")) {
-
 
185
 
-
 
186
                        @Override
-
 
187
                        public void run(Object source) {
-
 
188
                            EmailTemplate.askTemplate(null, table.getDBRoot(), new ValueListener() {
-
 
189
 
-
 
190
                                @Override
-
 
191
                                public void valueSelected(Object value) {
-
 
192
                                    final MouseSheetXmlListeListener l = new MouseSheetXmlListeListener(element, ((AbstractSheetXml) SheetXml.this).getClass());
-
 
193
                                    l.sendMail((EmailTemplate) value, (AbstractSheetXml) SheetXml.this, true);
-
 
194
                                }
-
 
195
                            });
-
 
196
 
-
 
197
                        }
-
 
198
                    };
-
 
199
                    actions.add(emailAction);
-
 
200
                }
-
 
201
                final Action modifyAction = new Action(TranslationManager.getInstance().getTranslationForAction("modify") + " " + element.getName().getVariant(Grammar.DEFINITE_ARTICLE_SINGULAR)) {
-
 
202
 
-
 
203
                    @Override
-
 
204
                    public void run(Object source) {
-
 
205
                        if (source instanceof PreviewFrame) {
-
 
206
                            ((PreviewFrame) source).dispose();
-
 
207
                        }
-
 
208
 
-
 
209
                        final SQLComponent component = element.createDefaultComponent();
-
 
210
                        final EditFrame f = new EditFrame(component, EditMode.MODIFICATION);
-
 
211
                        f.selectionId(row.getID());
-
 
212
                        FrameUtil.show(f);
-
 
213
 
-
 
214
                    }
-
 
215
                };
-
 
216
                actions.add(modifyAction);
151
                showPrintAndExport(showDocument, printDocument, exportToPDF);
217
                showPrintAndExport(showDocument, printDocument, exportToPDF, actions);
152
                return SheetXml.this;
218
                return SheetXml.this;
153
            }
219
            }
154
        };
220
        };
155
        return runnableQueue.submit(c);
221
        return runnableQueue.submit(c);
156
 
222
 
157
    }
223
    }
158
 
224
 
159
    public static Future<?> submitInQueue(final Runnable r) {
225
    public static Future<?> submitInQueue(final Runnable r) {
160
 
226
 
161
        return runnableQueue.submit(r);
227
        return runnableQueue.submit(r);
162
    }
228
    }
163
 
229
 
164
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF) {
230
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF) {
-
 
231
        showPrintAndExport(showDocument, printDocument, exportToPDF, Boolean.getBoolean("org.openconcerto.oo.useODSViewer"), false, Collections.emptyList());
-
 
232
    }
-
 
233
 
-
 
234
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF, List<Action> actions) {
165
        showPrintAndExport(showDocument, printDocument, exportToPDF, Boolean.getBoolean("org.openconcerto.oo.useODSViewer"), false);
235
        showPrintAndExport(showDocument, printDocument, exportToPDF, Boolean.getBoolean("org.openconcerto.oo.useODSViewer"), false, actions);
-
 
236
    }
-
 
237
 
-
 
238
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF, boolean useODSViewer, boolean exportPDFSynch) {
-
 
239
        showPrintAndExport(showDocument, printDocument, exportToPDF, useODSViewer, exportPDFSynch, Collections.emptyList());
166
    }
240
    }
167
 
241
 
168
    /**
242
    /**
169
     * Show, print and export the document to PDF. This method is synchronous
243
     * Show, print and export the document to PDF. This method is synchronous
170
     */
244
     */
171
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF, boolean useODSViewer, boolean exportPDFSynch) {
245
    public void showPrintAndExport(final boolean showDocument, final boolean printDocument, boolean exportToPDF, boolean useODSViewer, boolean exportPDFSynch, List<Action> actions) {
172
 
246
 
173
        final File generatedFile = getGeneratedFile();
247
        final File generatedFile = getGeneratedFile();
174
        final File pdfFile = getGeneratedPDFFile();
248
        final File pdfFile = getGeneratedPDFFile();
175
        if (generatedFile == null || !generatedFile.exists()) {
249
        if (generatedFile == null || !generatedFile.exists()) {
176
            JOptionPane.showMessageDialog(null, "Fichier généré manquant : " + generatedFile);
250
            JOptionPane.showMessageDialog(null, "Fichier généré manquant : " + generatedFile);
177
            return;
251
            return;
178
        }
252
        }
179
 
253
 
180
        try {
254
        try {
181
            if (!useODSViewer) {
255
            if (!useODSViewer) {
182
                if (exportToPDF || printDocument) {
256
                if (exportToPDF || printDocument) {
183
                    final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(generatedFile, !showDocument);
257
                    final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(generatedFile, !showDocument);
184
 
258
 
185
                    if (printDocument) {
259
                    if (printDocument) {
186
                        Map<String, Object> map = new HashMap<String, Object>();
260
                        Map<String, Object> map = new HashMap<String, Object>();
187
                        map.put("Name", this.printer);
261
                        map.put("Name", this.printer);
188
                        doc.printDocument(map);
262
                        doc.printDocument(map);
189
                    }
263
                    }
190
                    if (exportToPDF) {
264
                    if (exportToPDF) {
191
                        doc.saveToPDF(pdfFile).get();
265
                        doc.saveToPDF(pdfFile).get();
192
                    }
266
                    }
193
                    if (!showDocument) {
267
                    if (!showDocument) {
194
                        doc.close();
268
                        doc.close();
195
                    }
269
                    }
196
                } else {
270
                } else {
197
                    openDocument(false);
271
                    openDocument(false);
198
                }
272
                }
199
            } else {
273
            } else {
200
                final OpenDocument doc = new OpenDocument(generatedFile);
274
                final OpenDocument doc = new OpenDocument(generatedFile);
201
 
275
 
202
                if (showDocument) {
276
                if (showDocument) {
203
                    showPreviewDocument();
277
                    showPreviewDocument(actions);
204
                }
278
                }
205
                if (printDocument) {
279
                if (printDocument) {
206
                    // Print !
280
                    // Print !
207
                    DefaultNXDocumentPrinter printer = new DefaultNXDocumentPrinter();
281
                    DefaultNXDocumentPrinter printer = new DefaultNXDocumentPrinter();
208
                    printer.print(Arrays.asList(doc));
282
                    printer.print(Arrays.asList(doc));
209
                }
283
                }
210
 
284
 
211
                // FIXME Profiler pour utiliser moins de ram --> ex : demande trop de mémoire pour
285
                // FIXME Profiler pour utiliser moins de ram --> ex : demande trop de mémoire pour
212
                // faire
286
                // faire
213
                // un grand livre KD
287
                // un grand livre KD
214
                if (exportToPDF) {
288
                if (exportToPDF) {
215
 
289
 
216
                    Thread t = new Thread(new Runnable() {
290
                    Thread t = new Thread(new Runnable() {
217
 
291
 
218
                        @Override
292
                        @Override
219
                        public void run() {
293
                        public void run() {
220
                            createPDF(generatedFile, pdfFile, doc, getStoragePath());
294
                            createPDF(generatedFile, pdfFile, doc, getStoragePath());
221
 
295
 
222
                        }
296
                        }
223
 
297
 
224
                    }, "convert and upload to pdf");
298
                    }, "convert and upload to pdf");
225
 
299
 
226
                    t.setDaemon(true);
300
                    t.setDaemon(true);
227
                    t.start();
301
                    t.start();
228
                    if (exportPDFSynch) {
302
                    if (exportPDFSynch) {
229
                        t.join();
303
                        t.join();
230
                    }
304
                    }
231
                }
305
                }
232
            }
306
            }
233
 
307
 
234
        } catch (Exception e) {
308
        } catch (Exception e) {
235
            ExceptionHandler.handle("Impossible de charger le document OpenOffice " + pdfFile.getAbsolutePath() + "(viewer : " + useODSViewer + ")", e);
309
            ExceptionHandler.handle("Impossible de charger le document OpenOffice " + pdfFile.getAbsolutePath() + "(viewer : " + useODSViewer + ")", e);
236
        }
310
        }
237
    }
311
    }
238
 
312
 
239
    MetaDataSheet meta;
313
    MetaDataSheet meta;
240
 
314
 
241
    /**
315
    /**
242
     * MetaData à inclure lors de la génération
316
     * MetaData à inclure lors de la génération
243
     * 
317
     * 
244
     * @param meta
318
     * @param meta
245
     */
319
     */
246
    public void setMetaGeneration(MetaDataSheet meta) {
320
    public void setMetaGeneration(MetaDataSheet meta) {
247
        this.meta = meta;
321
        this.meta = meta;
248
    }
322
    }
249
 
323
 
250
    /**
324
    /**
251
     * MetaData à inclure lors de la génération
325
     * MetaData à inclure lors de la génération
252
     * 
326
     * 
253
     * @param meta
327
     * @param meta
254
     */
328
     */
255
 
329
 
256
    public MetaDataSheet getMetaGeneration() {
330
    public MetaDataSheet getMetaGeneration() {
257
        return this.meta;
331
        return this.meta;
258
    }
332
    }
259
 
333
 
260
    public void createPDF(final File generatedFile, final File pdfFile, final OpenDocument doc, String storagePath) {
334
    public void createPDF(final File generatedFile, final File pdfFile, final OpenDocument doc, String storagePath) {
261
        if (pdfFile == null) {
335
        if (pdfFile == null) {
262
            throw new IllegalArgumentException("null PDF file");
336
            throw new IllegalArgumentException("null PDF file");
263
        }
337
        }
264
        try {
338
        try {
265
            if (VenteFactureXmlSheet.TEMPLATE_ID.equals(getDefaultTemplateId())) {
-
 
266
                final SQLPreferences prefs = SQLPreferences.getMemCached(getElement().getTable().getDBRoot());
-
 
267
                if (prefs.getBoolean(PayPalPreferencePanel.PAYPAL_INVOICE, false)) {
-
 
268
                    try {
-
 
269
                        final File inFile = File.createTempFile("oc_", pdfFile.getName());
-
 
270
                        SheetUtils.convert2PDF(doc, inFile);
-
 
271
                        PaypalStamper s = new PaypalStamper();
-
 
272
                        int x = prefs.getInt(PayPalPreferencePanel.PAYPAL_INVOICE_X, 0);
-
 
273
                        int y = prefs.getInt(PayPalPreferencePanel.PAYPAL_INVOICE_Y, 0);
-
 
274
 
-
 
275
                        // Reference
-
 
276
                        String ref = getSQLRow().getString("NUMERO");
-
 
277
                        // Montant : ex : 10.55
-
 
278
                        long cents = getSQLRow().getLong("NET_A_PAYER");
-
 
279
                        String amount = cents / 100 + "." + cents % 100;
-
 
280
                        // Devise
-
 
281
                        // TODO : autres devises
-
 
282
                        String currency = "EUR";
-
 
283
                        // POST
-
 
284
                        final URL url = new URL("https://cloud.openconcerto.org/payment");
-
 
285
                        final URLConnection con = url.openConnection();
-
 
286
                        final HttpURLConnection http = (HttpURLConnection) con;
-
 
287
                        http.setRequestMethod("POST");
-
 
288
                        http.setDoOutput(true);
-
 
289
                        http.setDefaultUseCaches(false);
-
 
290
 
-
 
291
                        String hyperlink = null;
-
 
292
                        // x-www-form-urlencoded
-
 
293
                        final Map<String, String> arguments = new HashMap<>();
-
 
294
                        arguments.put("pI", prefs.get(PayPalPreferencePanel.PAYPAL_CLIENTID, ""));
-
 
295
                        arguments.put("pS", prefs.get(PayPalPreferencePanel.PAYPAL_SECRET, ""));
-
 
296
                        arguments.put("ref", ref);
-
 
297
                        arguments.put("amount", amount);
-
 
298
                        arguments.put("currency", currency);
-
 
299
                        arguments.put("type", "paypal");
-
 
300
                        final StringJoiner sj = new StringJoiner("&");
-
 
301
                        for (Map.Entry<String, String> entry : arguments.entrySet()) {
-
 
302
                            sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
-
 
303
                        }
-
 
304
                        final String postData = sj.toString();
-
 
305
                        System.err.println("SheetXml.createPDF() " + postData);
-
 
306
                        byte[] out = postData.getBytes(StandardCharsets.UTF_8);
-
 
307
                        int length = out.length;
-
 
308
                        http.setFixedLengthStreamingMode(length);
-
 
309
                        http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
-
 
310
                        http.connect();
-
 
311
                        try (OutputStream os = http.getOutputStream()) {
-
 
312
                            os.write(out);
-
 
313
                        }
-
 
314
                        if (http.getResponseCode() != 401) {
-
 
315
 
-
 
316
                            InputStream is = http.getInputStream();
-
 
317
                            InputStreamReader isr = new InputStreamReader(is);
-
 
318
 
-
 
319
                            int numCharsRead;
-
 
320
                            char[] charArray = new char[1024];
-
 
321
                            StringBuilder sb = new StringBuilder();
-
 
322
                            while ((numCharsRead = isr.read(charArray)) > 0) {
-
 
323
                                sb.append(charArray, 0, numCharsRead);
-
 
324
                            }
-
 
325
                            //
-
 
326
                            hyperlink = sb.toString();
-
 
327
                        }
-
 
328
                        s.addLink(inFile, pdfFile, x, y, hyperlink);
-
 
329
                    } catch (Exception e) {
-
 
330
                        e.printStackTrace();
-
 
331
                        SheetUtils.convert2PDF(doc, pdfFile);
339
            SheetUtils.convert2PDF(doc, pdfFile);
332
                    }
-
 
333
 
-
 
334
                } else {
-
 
335
                    SheetUtils.convert2PDF(doc, pdfFile);
-
 
336
                }
-
 
337
            } else {
-
 
338
                SheetUtils.convert2PDF(doc, pdfFile);
-
 
339
            }
-
 
340
 
-
 
341
        } catch (Throwable e) {
340
        } catch (Exception e) {
342
            ExceptionHandler.handle("Impossible de créer le PDF " + pdfFile.getAbsolutePath(), e);
341
            ExceptionHandler.handle("Impossible de créer le PDF " + pdfFile.getAbsolutePath(), e);
343
        }
342
        }
344
        if (!pdfFile.canRead()) {
343
        if (!pdfFile.canRead()) {
345
            ExceptionHandler.handle("Le fichier PDF " + pdfFile.getAbsolutePath() + " ne peut être lu.");
344
            ExceptionHandler.handle("Le fichier PDF " + pdfFile.getAbsolutePath() + " ne peut être lu.");
346
        }
345
        }
-
 
346
        storeWithStorageEngines(generatedFile, pdfFile, storagePath);
-
 
347
    }
-
 
348
 
-
 
349
    protected void storeWithStorageEngines(final File generatedFile, final File pdfFile, String storagePath) {
347
        List<StorageEngine> engines = StorageEngines.getInstance().getActiveEngines();
350
        List<StorageEngine> engines = StorageEngines.getInstance().getActiveEngines();
348
        for (StorageEngine storageEngine : engines) {
351
        for (StorageEngine storageEngine : engines) {
349
            if (storageEngine.isConfigured() && storageEngine.allowAutoStorage()) {
352
            if (storageEngine.isConfigured() && storageEngine.allowAutoStorage()) {
350
                final String path = storagePath;
353
                final String path = storagePath;
351
                try {
354
                try {
352
                    storageEngine.connect();
355
                    storageEngine.connect();
353
                    final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(pdfFile));
356
                    final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(pdfFile));
354
                    storageEngine.store(inStream, path, pdfFile.getName(), true);
357
                    storageEngine.store(inStream, path, pdfFile.getName(), true);
355
                    inStream.close();
358
                    inStream.close();
356
                    storageEngine.disconnect();
359
                    storageEngine.disconnect();
357
                } catch (IOException e) {
360
                } catch (IOException e) {
358
                    ExceptionHandler.handle("Impossible de sauvegarder le PDF " + pdfFile.getAbsolutePath() + " vers " + path + "(" + storageEngine + ")", e);
361
                    ExceptionHandler.handle("Impossible de sauvegarder le PDF " + pdfFile.getAbsolutePath() + " vers " + path + "(" + storageEngine + ")", e);
359
                }
362
                }
360
                if (storageEngine instanceof CloudStorageEngine) {
363
                if (storageEngine instanceof CloudStorageEngine) {
361
                    try {
364
                    try {
362
                        storageEngine.connect();
365
                        storageEngine.connect();
363
                        final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(generatedFile));
366
                        final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(generatedFile));
364
                        storageEngine.store(inStream, path, generatedFile.getName(), true);
367
                        storageEngine.store(inStream, path, generatedFile.getName(), true);
365
                        inStream.close();
368
                        inStream.close();
366
                        storageEngine.disconnect();
369
                        storageEngine.disconnect();
367
                    } catch (IOException e) {
370
                    } catch (IOException e) {
368
                        ExceptionHandler.handle("Impossible de sauvegarder le fichier généré " + generatedFile.getAbsolutePath() + " vers " + path + "(" + storageEngine + ")", e);
371
                        ExceptionHandler.handle("Impossible de sauvegarder le fichier généré " + generatedFile.getAbsolutePath() + " vers " + path + "(" + storageEngine + ")", e);
369
                    }
372
                    }
370
                }
373
                }
371
            }
374
            }
372
        }
375
        }
373
    }
376
    }
374
 
377
 
375
    public abstract String getDefaultTemplateId();
378
    public abstract String getDefaultTemplateId();
376
 
379
 
377
    /**
380
    /**
378
     * Path of the directory used for storage. Ex: Devis/2010
381
     * Path of the directory used for storage. Ex: Devis/2010
379
     */
382
     */
380
    public final String getStoragePath() {
383
    public final String getStoragePath() {
381
        final String res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getStoragePath(this);
384
        final String res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getStoragePath(this);
382
        if (res != null)
385
        if (res != null)
383
            return res;
386
            return res;
384
        else
387
        else
385
            return this.getStoragePathP();
388
            return this.getStoragePathP();
386
    }
389
    }
387
 
390
 
388
    public final File getDocumentOutputDirectory() {
391
    public final File getDocumentOutputDirectory() {
389
        final File res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getDocumentOutputDirectory(this);
392
        final File res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getDocumentOutputDirectory(this);
390
        if (res != null)
393
        if (res != null)
391
            return res;
394
            return res;
392
        else
395
        else
393
            return this.getDocumentOutputDirectoryP();
396
            return this.getDocumentOutputDirectoryP();
394
    }
397
    }
395
 
398
 
396
    public final File getPDFOutputDirectory() {
399
    public final File getPDFOutputDirectory() {
397
        final File res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getPDFOutputDirectory(this);
400
        final File res = STORAGE_DIRS == null ? null : STORAGE_DIRS.getPDFOutputDirectory(this);
398
        if (res != null)
401
        if (res != null)
399
            return res;
402
            return res;
400
        else
403
        else
401
            return this.getPDFOutputDirectoryP();
404
            return this.getPDFOutputDirectoryP();
402
    }
405
    }
403
 
406
 
404
    protected abstract String getStoragePathP();
407
    protected abstract String getStoragePathP();
405
 
408
 
406
    protected abstract File getDocumentOutputDirectoryP();
409
    protected abstract File getDocumentOutputDirectoryP();
407
 
410
 
408
    protected abstract File getPDFOutputDirectoryP();
411
    protected abstract File getPDFOutputDirectoryP();
409
 
412
 
410
    /**
413
    /**
411
     * Name of the generated document (without extension), do not rely on this name.
414
     * Name of the generated document (without extension), do not rely on this name.
412
     * 
415
     * 
413
     * Use getGeneratedFile().getName() to get the generated file name.
416
     * Use getGeneratedFile().getName() to get the generated file name.
414
     */
417
     */
415
    public abstract String getName();
418
    public abstract String getName();
416
 
419
 
417
    /**
420
    /**
418
     * @return the template id for this template (ex: "sales.quote")
421
     * @return the template id for this template (ex: "sales.quote")
419
     */
422
     */
420
    public String getTemplateId() {
423
    public String getTemplateId() {
421
        if (this.row != null && this.row.getTable().getFieldsName().contains("ID_MODELE")) {
424
        if (this.row != null && this.row.getTable().getFieldsName().contains("ID_MODELE")) {
422
            if (row.getObject("ID_MODELE") == null || row.isForeignEmpty("ID_MODELE")) {
425
            if (row.getObject("ID_MODELE") == null || row.isForeignEmpty("ID_MODELE")) {
423
                TypeModeleSQLElement typeModele = Configuration.getInstance().getDirectory().getElement(TypeModeleSQLElement.class);
426
                TypeModeleSQLElement typeModele = Configuration.getInstance().getDirectory().getElement(TypeModeleSQLElement.class);
424
                String modele = typeModele.getTemplateMapping().get(this.row.getTable().getName());
427
                String modele = typeModele.getTemplateMapping().get(this.row.getTable().getName());
425
                if (modele == null) {
428
                if (modele == null) {
426
                    System.err.println("No default modele in table TYPE_MODELE for table " + this.row.getTable().getName());
429
                    System.err.println("No default modele in table TYPE_MODELE for table " + this.row.getTable().getName());
427
                    Thread.dumpStack();
430
                    Thread.dumpStack();
428
                    return getDefaultTemplateId();
431
                    return getDefaultTemplateId();
429
                } else {
432
                } else {
430
                    return modele;
433
                    return modele;
431
                }
434
                }
432
            } else {
435
            } else {
433
                SQLRow rowModele = this.row.getForeignRow("ID_MODELE");
436
                SQLRow rowModele = this.row.getForeignRow("ID_MODELE");
434
                return rowModele.getString("NOM");
437
                return rowModele.getString("NOM");
435
            }
438
            }
436
        }
439
        }
437
        return getDefaultTemplateId();
440
        return getDefaultTemplateId();
438
    }
441
    }
439
 
442
 
440
    public abstract Future<SheetXml> createDocumentAsynchronous();
443
    public abstract Future<SheetXml> createDocumentAsynchronous();
441
 
444
 
442
    public void createDocument() throws InterruptedException, ExecutionException {
445
    public void createDocument() throws InterruptedException, ExecutionException {
443
        createDocumentAsynchronous().get();
446
        createDocumentAsynchronous().get();
444
    }
447
    }
445
 
448
 
446
    /**
449
    /**
447
     * get the File that is, or must be generated.
450
     * get the File that is, or must be generated.
448
     * 
451
     * 
449
     * @return a file (not null)
452
     * @return a file (not null)
450
     */
453
     */
451
    public abstract File getGeneratedFile();
454
    public abstract File getGeneratedFile();
452
 
455
 
453
    public File getGeneratedPDFFile() {
456
    public File getGeneratedPDFFile() {
454
        return SheetUtils.getFileWithExtension(getGeneratedFile(), ".pdf");
457
        return SheetUtils.getFileWithExtension(getGeneratedFile(), ".pdf");
455
    }
458
    }
456
 
459
 
457
    public SQLRow getRowLanguage() {
460
    public SQLRow getRowLanguage() {
458
        return this.rowLanguage;
461
        return this.rowLanguage;
459
    }
462
    }
460
 
463
 
461
    public String getReference() {
464
    public String getReference() {
462
        return "";
465
        return "";
463
    }
466
    }
464
 
467
 
465
    /**
468
    /**
466
     * Creates the document if needed and returns the generated file (OpenDocument)
469
     * Creates the document if needed and returns the generated file (OpenDocument)
467
     */
470
     */
468
    public File getOrCreateDocumentFile() throws Exception {
471
    public File getOrCreateDocumentFile() throws Exception {
469
        File f = getGeneratedFile();
472
        File f = getGeneratedFile();
470
        if (!f.exists()) {
473
        if (!f.exists()) {
471
            return createDocumentAsynchronous().get().getGeneratedFile();
474
            return createDocumentAsynchronous().get().getGeneratedFile();
472
        } else {
475
        } else {
473
            return f;
476
            return f;
474
        }
477
        }
475
    }
478
    }
476
 
479
 
477
    /**
480
    /**
478
     * Creates the document if needed and returns the generated file (OpenDocument)
481
     * Creates the document if needed and returns the generated file (OpenDocument)
479
     * 
482
     * 
480
     * @param createRecent true for recreate the pdf document if older than ods
483
     * @param createRecent true for recreate the pdf document if older than ods
481
     * @return
484
     * @return
482
     * @throws Exception
485
     * @throws Exception
483
     * 
486
     * 
484
     */
487
     */
485
    public File getOrCreatePDFDocumentFile(boolean createRecent) throws Exception {
488
    public File getOrCreatePDFDocumentFile(boolean createRecent) throws Exception {
486
        return getOrCreatePDFDocumentFile(createRecent, Boolean.getBoolean("org.openconcerto.oo.useODSViewer"));
489
        return getOrCreatePDFDocumentFile(createRecent, Boolean.getBoolean("org.openconcerto.oo.useODSViewer"));
487
    }
490
    }
488
 
491
 
489
    public File getOrCreatePDFDocumentFile(boolean createRecent, boolean useODSViewer) throws Exception {
492
    public File getOrCreatePDFDocumentFile(boolean createRecent, boolean useODSViewer) throws Exception {
490
        File f = getGeneratedPDFFile();
493
        File f = getGeneratedPDFFile();
491
        if (!f.exists()) {
494
        if (!f.exists()) {
492
            getOrCreateDocumentFile();
495
            getOrCreateDocumentFile();
493
            showPrintAndExport(false, false, true, useODSViewer, true);
496
            showPrintAndExport(false, false, true, useODSViewer, true, Collections.emptyList());
494
            return f;
497
            return f;
495
        } else {
498
        } else {
496
            File fODS = getOrCreateDocumentFile();
499
            File fODS = getOrCreateDocumentFile();
497
            if (fODS.lastModified() > f.lastModified()) {
500
            if (fODS.lastModified() > f.lastModified()) {
498
                showPrintAndExport(false, false, true, useODSViewer, true);
501
                showPrintAndExport(false, false, true, useODSViewer, true, Collections.emptyList());
499
            }
502
            }
500
            return f;
503
            return f;
501
        }
504
        }
502
    }
505
    }
503
 
506
 
504
    /**
507
    /**
505
     * Open the document with the native application
508
     * Open the document with the native application
506
     * 
509
     * 
507
     * @param synchronous
510
     * @param synchronous
508
     */
511
     */
509
    public void openDocument(boolean synchronous) {
512
    public void openDocument(boolean synchronous) {
510
        Runnable r = new Runnable() {
513
        Runnable r = new Runnable() {
511
 
514
 
512
            @Override
515
            @Override
513
            public void run() {
516
            public void run() {
514
                File f;
517
                File f;
515
                try {
518
                try {
516
                    f = getOrCreateDocumentFile();
519
                    f = getOrCreateDocumentFile();
517
                    if (f != null && f.exists()) {
520
                    if (f != null && f.exists()) {
518
                        OOUtils.open(f);
521
                        OOUtils.open(f);
519
                    } else {
522
                    } else {
520
                        if (!GraphicsEnvironment.isHeadless()) {
523
                        if (!GraphicsEnvironment.isHeadless()) {
521
                            if (f != null) {
524
                            if (f != null) {
522
                                JOptionPane.showMessageDialog(null, "Le fichier " + f.getAbsolutePath() + " est manquant");
525
                                JOptionPane.showMessageDialog(null, "Le fichier " + f.getAbsolutePath() + " est manquant");
523
                            } else {
526
                            } else {
524
                                JOptionPane.showMessageDialog(null, "Fichier manquant");
527
                                JOptionPane.showMessageDialog(null, "Fichier manquant");
525
                            }
528
                            }
526
                        } else {
529
                        } else {
527
                            if (f != null) {
530
                            if (f != null) {
528
                                throw new FileNotFoundException(f.getAbsolutePath() + " missing");
531
                                throw new FileNotFoundException(f.getAbsolutePath() + " missing");
529
                            } else {
532
                            } else {
530
                                throw new NullPointerException("null document");
533
                                throw new NullPointerException("null document");
531
                            }
534
                            }
532
                        }
535
                        }
533
                    }
536
                    }
534
                } catch (Exception e) {
537
                } catch (Exception e) {
535
                    ExceptionHandler.handle("Impossible d'ouvrir le document.", e);
538
                    ExceptionHandler.handle("Impossible d'ouvrir le document.", e);
536
                }
539
                }
537
            }
540
            }
538
        };
541
        };
539
        if (synchronous) {
542
        if (synchronous) {
540
            r.run();
543
            r.run();
541
        } else {
544
        } else {
542
            Thread thread = new Thread(r, "openDocument: " + getGeneratedFile().getAbsolutePath());
545
            Thread thread = new Thread(r, "openDocument: " + getGeneratedFile().getAbsolutePath());
543
            thread.setDaemon(true);
546
            thread.setDaemon(true);
544
            thread.start();
547
            thread.start();
545
        }
548
        }
546
 
549
 
547
    }
550
    }
548
 
551
 
549
    public void showPreviewDocument() throws Exception {
552
    public void showPreviewDocument() throws Exception {
550
        showPreviewDocument(null, null);
553
        showPreviewDocument(Collections.emptyList());
551
    }
554
    }
552
 
555
 
553
    public void showPreviewDocument(String actionName, Runnable r) throws Exception {
556
    public void showPreviewDocument(List<Action> actions) throws Exception {
554
        File f = null;
557
        File f = null;
555
        f = getOrCreateDocumentFile();
558
        f = getOrCreateDocumentFile();
556
        PreviewFrame.show(f, actionName, r);
559
        PreviewFrame.show(f, actions);
557
    }
560
    }
558
 
561
 
559
    public void printDocument() {
562
    public void printDocument() {
560
        printDocument(null);
563
        printDocument(null);
561
    }
564
    }
562
 
565
 
563
    public void printDocument(PrinterJob job) {
566
    public void printDocument(PrinterJob job) {
564
 
567
 
565
        try {
568
        try {
566
            final File f = getOrCreateDocumentFile();
569
            final File f = getOrCreateDocumentFile();
567
 
570
 
568
            if (!Boolean.getBoolean("org.openconcerto.oo.useODSViewer")) {
571
            if (!Boolean.getBoolean("org.openconcerto.oo.useODSViewer")) {
569
                final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(f, true);
572
                final Component doc = ComptaPropsConfiguration.getOOConnexion().loadDocument(f, true);
570
                doc.printDocument(job);
573
                doc.printDocument(job);
571
                doc.close();
574
                doc.close();
572
            } else {
575
            } else {
573
                // Load the spreadsheet.
576
                // Load the spreadsheet.
574
                final OpenDocument doc = new OpenDocument(f);
577
                final OpenDocument doc = new OpenDocument(f);
575
                // Print !
578
                // Print !
576
                DefaultNXDocumentPrinter printer = new DefaultNXDocumentPrinter();
579
                DefaultNXDocumentPrinter printer = new DefaultNXDocumentPrinter();
577
                printer.print(Arrays.asList(doc), job);
580
                printer.print(Arrays.asList(doc), job);
578
            }
581
            }
579
 
582
 
580
        } catch (Exception e) {
583
        } catch (Exception e) {
581
            ExceptionHandler.handle("Impossible d'imprimer le document OpenOffice", e);
584
            ExceptionHandler.handle("Impossible d'imprimer le document OpenOffice", e);
582
            e.printStackTrace();
585
            e.printStackTrace();
583
        }
586
        }
584
    }
587
    }
585
 
588
 
586
    public SQLRow getSQLRow() {
589
    public SQLRow getSQLRow() {
587
        return this.row;
590
        return this.row;
588
    }
591
    }
589
 
592
 
590
    /**
593
    /**
591
     * Remplace tous les caracteres non alphanumeriques (seul le _ est autorisé) par un -. Cela
594
     * Remplace tous les caracteres non alphanumeriques (seul le _ est autorisé) par un -. Cela
592
     * permet d'avoir toujours un nom de fichier valide.
595
     * permet d'avoir toujours un nom de fichier valide.
593
     * 
596
     * 
594
     * @param fileName nom du fichier à créer ex:FACTURE_2007/03/001
597
     * @param fileName nom du fichier à créer ex:FACTURE_2007/03/001
595
     * @return un nom fichier valide ex:FACTURE_2007-03-001
598
     * @return un nom fichier valide ex:FACTURE_2007-03-001
596
     */
599
     */
597
    public static String getValidFileName(String fileName) {
600
    public static String getValidFileName(String fileName) {
598
        final StringBuffer result = new StringBuffer(fileName.length());
601
        final StringBuffer result = new StringBuffer(fileName.length());
599
        for (int i = 0; i < fileName.length(); i++) {
602
        for (int i = 0; i < fileName.length(); i++) {
600
            char ch = fileName.charAt(i);
603
            char ch = fileName.charAt(i);
601
 
604
 
602
            // Si c'est un caractere alphanumerique
605
            // Si c'est un caractere alphanumerique
603
            if (Character.isLetterOrDigit(ch) || (ch == '_') || (ch == ' ')) {
606
            if (Character.isLetterOrDigit(ch) || (ch == '_') || (ch == ' ')) {
604
                result.append(ch);
607
                result.append(ch);
605
            } else {
608
            } else {
606
                result.append('-');
609
                result.append('-');
607
            }
610
            }
608
        }
611
        }
609
        return result.toString();
612
        return result.toString();
610
    }
613
    }
611
 
614
 
612
    public String getPrinter() {
615
    public String getPrinter() {
613
        return this.printer;
616
        return this.printer;
614
    }
617
    }
615
 
618
 
616
    public void setRefreshFormulasRequired(boolean refreshFormulasRequired) {
619
    public void setRefreshFormulasRequired(boolean refreshFormulasRequired) {
617
        this.refreshFormulasRequired = refreshFormulasRequired;
620
        this.refreshFormulasRequired = refreshFormulasRequired;
618
    }
621
    }
619
 
622
 
620
    public boolean isRefreshFormulasRequired() {
623
    public boolean isRefreshFormulasRequired() {
621
            return refreshFormulasRequired;
624
            return refreshFormulasRequired;
622
    }
625
    }
623
 
626
 
624
}
627
}