DesktopImportControllerUI.java 28.9 KB
Newer Older
M
Mathieu Bastian 已提交
1
/*
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 28 29 30 31 32 33 34 35 36 37 38 39 40
 Copyright 2008-2010 Gephi
 Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
 Website : http://www.gephi.org

 This file is part of Gephi.

 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.

 Copyright 2011 Gephi Consortium. All rights reserved.

 The contents of this file are subject to the terms of either the GNU
 General Public License Version 3 only ("GPL") or the Common
 Development and Distribution License("CDDL") (collectively, the
 "License"). You may not use this file except in compliance with the
 License. You can obtain a copy of the License at
 http://gephi.org/about/legal/license-notice/
 or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
 specific language governing permissions and limitations under the
 License.  When distributing the software, include this License Header
 Notice in each file and include the License files at
 /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
 License Header, with the fields enclosed by brackets [] replaced by
 your own identifying information:
 "Portions Copyrighted [year] [name of copyright owner]"

 If you wish your version of this file to be governed by only the CDDL
 or only the GPL Version 3, indicate your decision by adding
 "[Contributor] elects to include this software in this distribution
 under the [CDDL or GPL Version 3] license." If you do not indicate a
 single choice of license, a recipient has the option to distribute
 your version of this file under either the CDDL, the GPL Version 3 or
 to extend the choice of license to its licensees as provided above.
 However, if you add GPL Version 3 code and therefore, elected the GPL
 Version 3 license, then the option applies only if the new code is
 made subject to such option by the copyright holder.

 Contributor(s):

 Portions Copyrighted 2011 Gephi Consortium.
M
Mathieu Bastian 已提交
41
 */
42

M
Mathieu Bastian 已提交
43 44
package org.gephi.desktop.importer;

45
import java.awt.Dialog;
M
Mathieu Bastian 已提交
46 47 48 49 50
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
M
Mathieu Bastian 已提交
51
import java.lang.reflect.Array;
M
Mathieu Bastian 已提交
52
import java.lang.reflect.InvocationTargetException;
53
import java.text.MessageFormat;
M
Mathieu Bastian 已提交
54
import java.util.ArrayList;
55
import java.util.Arrays;
56
import java.util.Collections;
M
Mathieu Bastian 已提交
57 58 59
import java.util.HashMap;
import java.util.List;
import java.util.Map;
M
Mathieu Bastian 已提交
60
import java.util.concurrent.atomic.AtomicInteger;
M
Mathieu Bastian 已提交
61 62 63 64 65 66 67 68 69
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.gephi.desktop.importer.api.ImportControllerUI;
import org.gephi.desktop.mrufiles.api.MostRecentFiles;
import org.gephi.io.importer.api.Container;
import org.gephi.io.importer.api.Database;
import org.gephi.io.importer.api.ImportController;
70
import org.gephi.io.importer.api.ImportUtils;
M
Mathieu Bastian 已提交
71
import org.gephi.io.importer.api.Issue;
M
Mathieu Bastian 已提交
72 73 74 75 76
import org.gephi.io.importer.api.Report;
import org.gephi.io.importer.spi.DatabaseImporter;
import org.gephi.io.importer.spi.FileImporter;
import org.gephi.io.importer.spi.ImporterUI;
import org.gephi.io.importer.spi.ImporterWizardUI;
77
import org.gephi.io.importer.spi.WizardImporter;
M
Mathieu Bastian 已提交
78 79
import org.gephi.io.processor.spi.Processor;
import org.gephi.io.processor.spi.ProcessorUI;
80
import org.gephi.lib.validation.DialogDescriptorWithValidation;
81
import org.gephi.project.api.Project;
M
Mathieu Bastian 已提交
82 83
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
84
import org.gephi.utils.CharsetToolkit;
85
import org.gephi.utils.TempDirUtils;
M
Mathieu Bastian 已提交
86 87 88
import org.gephi.utils.longtask.api.LongTaskErrorHandler;
import org.gephi.utils.longtask.api.LongTaskExecutor;
import org.gephi.utils.longtask.spi.LongTask;
89
import org.gephi.utils.progress.ProgressTicket;
M
Mathieu Bastian 已提交
90 91 92
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
93
import org.openide.WizardDescriptor;
M
Mathieu Bastian 已提交
94 95 96 97 98 99
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
100
import org.openide.util.io.ReaderInputStream;
M
Mathieu Bastian 已提交
101 102 103 104 105 106 107 108 109 110
import org.openide.util.lookup.ServiceProvider;

/**
 * @author Mathieu Bastian
 * @author Sebastien Heymann
 */
@ServiceProvider(service = ImportControllerUI.class)
public class DesktopImportControllerUI implements ImportControllerUI {

    private final LongTaskExecutor executor;
M
Mathieu Bastian 已提交
111
    private final LongTaskErrorHandler defaultErrorHandler;
M
Mathieu Bastian 已提交
112 113 114 115
    private final ImportController controller;

    public DesktopImportControllerUI() {
        controller = Lookup.getDefault().lookup(ImportController.class);
M
Mathieu Bastian 已提交
116
        defaultErrorHandler = new LongTaskErrorHandler() {
117
            @Override
M
Mathieu Bastian 已提交
118 119 120 121
            public void fatalError(Throwable t) {
                if (t instanceof OutOfMemoryError) {
                    return;
                }
122
                Exceptions.printStackTrace(t);
M
Mathieu Bastian 已提交
123 124 125 126 127
            }
        };
        executor = new LongTaskExecutor(true, "Importer", 10);
    }

128
    @Override
M
Mathieu Bastian 已提交
129
    public void importFile(FileObject fileObject) {
130
        importFiles(new FileObject[] {fileObject});
131
    }
M
Mathieu Bastian 已提交
132

133 134 135
    @Override
    public void importFiles(FileObject[] fileObjects) {
        MostRecentFiles mostRecentFiles = Lookup.getDefault().lookup(MostRecentFiles.class);
M
Mathieu Bastian 已提交
136

137 138 139 140 141 142 143 144 145
        fileObjects = Arrays.copyOf(fileObjects, fileObjects.length);

        //Extract files if they are zipped:
        for (int i = 0; i < fileObjects.length; i++) {
            fileObjects[i] = ImportUtils.getArchivedFile(fileObjects[i]);
            if (FileUtil.isArchiveArtifact(fileObjects[i])) {
                try {
                    //Copy the archived file so we never have problems converting it to a simple File during import:
                    File tempDir = TempDirUtils.createTempDirectory();
146 147
                    fileObjects[i] =
                        FileUtil.copyFile(fileObjects[i], FileUtil.toFileObject(tempDir), fileObjects[i].getName());
148 149 150 151 152 153
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }

154 155 156 157 158
        Reader[] readers = new Reader[fileObjects.length];
        FileImporter[] importers = new FileImporter[fileObjects.length];
        try {
            for (int i = 0; i < fileObjects.length; i++) {
                FileObject fileObject = fileObjects[i];
159
                importers[i] = controller.getFileImporter(fileObject);
160 161

                if (importers[i] == null) {
162 163 164
                    NotifyDescriptor.Message msg = new NotifyDescriptor.Message(
                        NbBundle.getMessage(getClass(), "DesktopImportControllerUI.error_no_matching_file_importer"),
                        NotifyDescriptor.WARNING_MESSAGE);
165
                    DialogDisplayer.getDefault().notify(msg);
M
Mathieu Bastian 已提交
166 167 168
                    return;
                }

169 170 171 172
                readers[i] = ImportUtils.getTextReader(fileObject);

                //MRU
                mostRecentFiles.addFile(fileObject.getPath());
M
Mathieu Bastian 已提交
173 174
            }

175
            importFiles(readers, importers, fileObjects, null);
176 177
        } catch (IOException ex) {
            throw new RuntimeException(ex);
M
Mathieu Bastian 已提交
178 179 180
        }
    }

M
Mathieu Bastian 已提交
181
    @Override
182
    public void importStream(final InputStream stream, String importerName) {
183 184 185 186 187
        importStream(stream, null, importerName);
    }

    @Override
    public void importStream(final InputStream stream, String streamName, String importerName) {
188 189
        final FileImporter importer = controller.getFileImporter(importerName);
        if (importer == null) {
190 191 192
            NotifyDescriptor.Message msg = new NotifyDescriptor.Message(
                NbBundle.getMessage(getClass(), "DesktopImportControllerUI.error_no_matching_file_importer"),
                NotifyDescriptor.WARNING_MESSAGE);
193 194 195 196 197 198
            DialogDisplayer.getDefault().notify(msg);
            return;
        }

        try {
            Reader reader = ImportUtils.getTextReader(stream);
199
            importFile(reader, streamName, importer);
200 201 202 203 204 205 206
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public void importFile(final Reader reader, String importerName) {
207 208 209 210 211
        importFile(reader, null, importerName);
    }

    @Override
    public void importFile(final Reader reader, String fileName, String importerName) {
212 213
        final FileImporter importer = controller.getFileImporter(importerName);
        if (importer == null) {
214 215 216
            NotifyDescriptor.Message msg = new NotifyDescriptor.Message(
                NbBundle.getMessage(getClass(), "DesktopImportControllerUI.error_no_matching_file_importer"),
                NotifyDescriptor.WARNING_MESSAGE);
217 218 219 220
            DialogDisplayer.getDefault().notify(msg);
            return;
        }

221
        importFile(reader, fileName, importer);
222 223
    }

224 225
    private void importFile(final Reader reader, final String fileName, final FileImporter importer) {
        importFiles(new Reader[] {reader}, new FileImporter[] {importer}, new String[] {fileName});
226 227
    }

228 229
    private void importFiles(final Reader[] readers, final FileImporter[] importers, final String[] names) {
        importFiles(readers, importers, null, names);
230 231
    }

232
    private void importFiles(final Reader[] readers, final FileImporter[] importers, FileObject[] fileObjects, String[] names) {
M
Mathieu Bastian 已提交
233
        try {
234 235
            File[] files = new File[readers.length];

236
            Map<ImporterUI, List<FileImporter>> importerUIs = new HashMap<>();
237 238
            for (int i = 0; i < importers.length; i++) {
                FileImporter importer = importers[i];
M
Mathieu Bastian 已提交
239 240 241 242
                ImporterUI ui = controller.getUI(importer);
                if (ui != null) {
                    List<FileImporter> l = importerUIs.get(ui);
                    if (l == null) {
243
                        l = new ArrayList<>();
M
Mathieu Bastian 已提交
244 245 246 247 248
                        importerUIs.put(ui, l);
                    }
                    l.add(importer);
                }

249 250
                if (importer instanceof FileImporter.FileAware) {
                    try (Reader reader = readers[i]) {
251
                        File file = null;
252 253
                        if (fileObjects != null) {
                            file = FileUtil.toFile(fileObjects[i]);
254 255 256
                        }

                        if (file == null) {
257
                            //There is no source file but the importer needs it, create temporary copy:
258 259
                            String fileName = "tmp_file" + 1;
                            String charset = "UTF-8";
260 261
                            if (fileObjects != null &&
                                fileObjects[i] != null) {//Netbeans FileUtil.toFile bug returning null?? Try to recover:
262 263 264 265 266 267
                                fileName = fileObjects[i].getNameExt();
                                CharsetToolkit charsetToolkit = new CharsetToolkit(fileObjects[i].getInputStream());
                                charset = charsetToolkit.getCharset().name();
                            }

                            file = TempDirUtils.createTempDir().createFile(fileName);
268
                            try (FileOutputStream fos = new FileOutputStream(file)) {
269
                                FileUtil.copy(new ReaderInputStream(reader, charset), fos);
270 271 272 273 274 275 276
                            }
                        }

                        files[i] = file;
                        ((FileImporter.FileAware) importer).setFile(file);
                    }
                }
M
Mathieu Bastian 已提交
277 278 279 280
            }

            for (Map.Entry<ImporterUI, List<FileImporter>> entry : importerUIs.entrySet()) {
                ImporterUI ui = entry.getKey();
281 282 283
                String title = NbBundle
                    .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.file.ui.dialog.title",
                        ui.getDisplayName());
M
Mathieu Bastian 已提交
284
                JPanel panel = ui.getPanel();
285

M
Mathieu Bastian 已提交
286
                FileImporter[] fi = entry.getValue()
287
                    .toArray((FileImporter[]) Array.newInstance(entry.getValue().get(0).getClass(), 0));
M
Mathieu Bastian 已提交
288
                ui.setup(fi);
M
Mathieu Bastian 已提交
289

290
                if (panel != null) {
291
                    final DialogDescriptor dd = DialogDescriptorWithValidation.dialog(panel, title);
292 293 294 295
                    Object result = DialogDisplayer.getDefault().notify(dd);
                    if (!result.equals(NotifyDescriptor.OK_OPTION)) {
                        ui.unsetup(false);
                        return;
M
Mathieu Bastian 已提交
296 297 298
                    }
                }

299 300 301 302 303 304
                if (ui instanceof ImporterUI.WithWizard) {
                    boolean finishedOk = showWizard(ui, ((ImporterUI.WithWizard) ui).getWizardDescriptor());
                    if (!finishedOk) {
                        ui.unsetup(false);
                        return;
                    }
M
Mathieu Bastian 已提交
305 306 307 308 309
                }

                ui.unsetup(true);
            }

M
Mathieu Bastian 已提交
310
            ImportErrorHandler errorHandler = new ImportErrorHandler();
311 312
            final List<Container> results = new ArrayList<>();
            for (int i = 0; i < importers.length; i++) {
313
                doImport(results, readers[i], names != null ? names[0] : null, fileObjects != null ? fileObjects[i] : null, files[i], importers[i],
M
Mathieu Bastian 已提交
314
                    errorHandler);
M
Mathieu Bastian 已提交
315 316
            }

317 318 319
            String taskName = null;
            if (importers.length == 1) {
                taskName = NbBundle
M
Mathieu Bastian 已提交
320 321
                    .getMessage(DesktopImportControllerUI.class,
                        "DesktopImportControllerUI.finishingImport",
322
                        fileObjects != null ? fileObjects[0].getNameExt() : (names != null ? names[0] : null));
323 324 325 326 327 328
            } else {
                taskName = NbBundle
                    .getMessage(DesktopImportControllerUI.class,
                        "DesktopImportControllerUI.multiImport.finishingImport",
                        importers.length);
            }
M
Mathieu Bastian 已提交
329 330
            FinishImport finishImport = new FinishImport(results, errorHandler);
            executor.execute(finishImport, finishImport, taskName, defaultErrorHandler);
M
Mathieu Bastian 已提交
331
        } catch (Exception ex) {
332
            Exceptions.printStackTrace(ex);
M
Mathieu Bastian 已提交
333 334 335
        }
    }

336
    private void doImport(final List<Container> results, final Reader reader, final String containerName, final FileObject fileObject,
M
Mathieu Bastian 已提交
337
                          final File file,
M
Mathieu Bastian 已提交
338 339
                          final FileImporter importer,
                          final ImportErrorHandler errorHandler) {
340 341 342 343
        LongTask task = null;
        if (importer instanceof LongTask) {
            task = (LongTask) importer;
        }
M
Mathieu Bastian 已提交
344

345 346 347
        if (file == null && reader == null) {
            throw new NullPointerException("Null file and reader!");
        }
M
Mathieu Bastian 已提交
348

349 350 351
        if (importer == null) {
            throw new NullPointerException("Null importer!");
        }
M
Mathieu Bastian 已提交
352

353
        //Execute task
354
        final String containerSource = fileObject != null ? fileObject.getNameExt() : (containerName != null ? containerName : NbBundle
355
            .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.streamSource",
356
                importer.getClass().getSimpleName()));
357 358
        String taskName =
            NbBundle.getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.taskName", containerSource);
359 360 361 362 363 364 365 366
        executor.execute(task, () -> {
            try {
                Container container;
                if (importer instanceof FileImporter.FileAware && file != null) {
                    container = controller.importFile(file, importer);
                } else {
                    container = controller.importFile(reader, importer);
                }
M
Mathieu Bastian 已提交
367

368 369 370
                if (container != null) {
                    container.setSource(containerSource);
                    results.add(container);
M
Mathieu Bastian 已提交
371
                }
372 373
            } catch (Exception ex) {
                throw new RuntimeException(ex);
374
            }
M
Mathieu Bastian 已提交
375
        }, taskName, errorHandler.createHandler(containerSource));
376 377 378 379 380
    }

    private boolean showWizard(ImporterUI importer, WizardDescriptor wizardDescriptor) {
        if (wizardDescriptor == null) {
            return true;//Nothing to show
M
Mathieu Bastian 已提交
381
        }
382 383 384 385 386 387 388 389

        wizardDescriptor.setTitleFormat(new MessageFormat("{0} ({1})"));
        wizardDescriptor.setTitle(importer.getDisplayName());
        Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
        dialog.setVisible(true);
        dialog.toFront();

        return wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION;
M
Mathieu Bastian 已提交
390 391
    }

392
    @Override
M
Mathieu Bastian 已提交
393 394 395 396
    public void importDatabase(DatabaseImporter importer) {
        importDatabase(null, importer);
    }

397
    @Override
M
Mathieu Bastian 已提交
398 399 400
    public void importDatabase(Database database, final DatabaseImporter importer) {
        try {
            if (importer == null) {
401 402 403
                NotifyDescriptor.Message msg = new NotifyDescriptor.Message(NbBundle
                    .getMessage(DesktopImportControllerUI.class,
                        "DesktopImportControllerUI.error_no_matching_db_importer"), NotifyDescriptor.WARNING_MESSAGE);
M
Mathieu Bastian 已提交
404 405 406 407 408 409
                DialogDisplayer.getDefault().notify(msg);
                return;
            }

            ImporterUI ui = controller.getUI(importer);
            if (ui != null) {
410 411
                String title = NbBundle
                    .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.database.ui.dialog.title");
M
Mathieu Bastian 已提交
412
                JPanel panel = ui.getPanel();
413
                ui.setup(new DatabaseImporter[] {importer});
414
                final DialogDescriptor dd = DialogDescriptorWithValidation.dialog(panel, title);
M
Mathieu Bastian 已提交
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432

                Object result = DialogDisplayer.getDefault().notify(dd);
                if (result.equals(NotifyDescriptor.CANCEL_OPTION) || result.equals(NotifyDescriptor.CLOSED_OPTION)) {
                    ui.unsetup(false);
                    return;
                }
                ui.unsetup(true);
                if (database == null) {
                    database = importer.getDatabase();
                }
            }

            LongTask task = null;
            if (importer instanceof LongTask) {
                task = (LongTask) importer;
            }

            //Execute task
433 434
            final String containerSource = database != null ? database.getName() :
                (ui != null ? ui.getDisplayName() : importer.getClass().getSimpleName());
M
Mathieu Bastian 已提交
435
            final Database db = database;
436 437
            String taskName = NbBundle
                .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.taskName", containerSource);
M
Mathieu Bastian 已提交
438
            executor.execute(task, new Runnable() {
439
                @Override
M
Mathieu Bastian 已提交
440 441 442 443 444
                public void run() {
                    try {
                        Container container = controller.importDatabase(db, importer);
                        if (container != null) {
                            container.setSource(containerSource);
M
Mathieu Bastian 已提交
445
                            new FinishImport(Collections.singletonList(container), null).run();
M
Mathieu Bastian 已提交
446 447 448 449 450
                        }
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                }
M
Mathieu Bastian 已提交
451
            }, taskName, defaultErrorHandler);
M
Mathieu Bastian 已提交
452
        } catch (Exception ex) {
M
Debug  
Mathieu Bastian 已提交
453
            Logger.getLogger("").log(Level.SEVERE, "", ex);
M
Mathieu Bastian 已提交
454 455 456
        }
    }

457
    @Override
M
Mathieu Bastian 已提交
458
    public void importWizard(final WizardImporter importer) {
M
Mathieu Bastian 已提交
459 460
        try {
            if (importer == null) {
461 462 463
                NotifyDescriptor.Message msg = new NotifyDescriptor.Message(NbBundle
                    .getMessage(DesktopImportControllerUI.class,
                        "DesktopImportControllerUI.error_no_matching_db_importer"), NotifyDescriptor.WARNING_MESSAGE);
M
Mathieu Bastian 已提交
464 465 466 467
                DialogDisplayer.getDefault().notify(msg);
                return;
            }

468 469
            String containerSource =
                NbBundle.getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.wizardSource", "");
M
Mathieu Bastian 已提交
470 471
            ImporterUI ui = controller.getUI(importer);
            if (ui != null) {
472 473 474
                String title = NbBundle
                    .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.wizard.ui.dialog.title",
                        ui.getDisplayName());
M
Mathieu Bastian 已提交
475
                JPanel panel = ui.getPanel();
476
                ui.setup(new WizardImporter[] {importer});
477
                final DialogDescriptor dd = DialogDescriptorWithValidation.dialog(panel, title);
M
Mathieu Bastian 已提交
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
                Object result = DialogDisplayer.getDefault().notify(dd);
                if (result.equals(NotifyDescriptor.CANCEL_OPTION) || result.equals(NotifyDescriptor.CLOSED_OPTION)) {
                    ui.unsetup(false);
                    return;
                }
                ui.unsetup(true);
                containerSource = ui.getDisplayName();
            }
            ImporterWizardUI wizardUI = controller.getWizardUI(importer);
            if (wizardUI != null) {
                containerSource = wizardUI.getCategory() + ":" + wizardUI.getDisplayName();
            }

            LongTask task = null;
            if (importer instanceof LongTask) {
                task = (LongTask) importer;
            }

            //Execute task
            final String source = containerSource;
498 499
            String taskName = NbBundle
                .getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.taskName", containerSource);
M
Mathieu Bastian 已提交
500
            executor.execute(task, new Runnable() {
501
                @Override
M
Mathieu Bastian 已提交
502 503
                public void run() {
                    try {
M
Mathieu Bastian 已提交
504
                        Container container = controller.importWizard(importer);
M
Mathieu Bastian 已提交
505 506
                        if (container != null) {
                            container.setSource(source);
M
Mathieu Bastian 已提交
507
                            new FinishImport(Collections.singletonList(container), null).run();
M
Mathieu Bastian 已提交
508 509 510 511 512
                        }
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                }
M
Mathieu Bastian 已提交
513
            }, taskName, defaultErrorHandler);
M
Mathieu Bastian 已提交
514 515 516 517 518
        } catch (Exception ex) {
            Logger.getLogger("").log(Level.WARNING, "", ex);
        }
    }

519 520 521 522
    private void showProcessorIssues(Report report) {
        ProcessorIssuesReportPanel issuesReport = new ProcessorIssuesReportPanel();
        issuesReport.setData(report);

523 524 525 526
        DialogDescriptor dd = new DialogDescriptor(issuesReport,
            NbBundle.getMessage(DesktopImportControllerUI.class, "ProcessorIssuesReportPanel.title"));
        dd.setOptions(
            new Object[] {NbBundle.getMessage(DesktopImportControllerUI.class, "ProcessorIssuesReportPanel.close")});
527 528 529 530 531

        DialogDisplayer.getDefault().notify(dd);
        issuesReport.destroy();
    }

532
    @Override
M
Mathieu Bastian 已提交
533 534 535 536 537 538 539 540 541 542 543 544
    public ImportController getImportController() {
        return controller;
    }

    private ProcessorUI getProcessorUI(Processor processor) {
        for (ProcessorUI pui : Lookup.getDefault().lookupAll(ProcessorUI.class)) {
            if (pui.isUIFoProcessor(processor)) {
                return pui;
            }
        }
        return null;
    }
545

M
Mathieu Bastian 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
    private static class ImportErrorHandler {
        private final Report errorReport = new Report("temperrorhandler");
        private final AtomicInteger count = new AtomicInteger();

        public LongTaskErrorHandler createHandler(String source) {
            return new LongTaskErrorHandler() {
                @Override
                public void fatalError(Throwable t) {
                    handleError(source, t);
                }
            };
        }

        public void handleError(String source, Throwable t) {
            if (t instanceof OutOfMemoryError) {
                return;
            }
            count.incrementAndGet();
            String msg =
                NbBundle.getMessage(DesktopImportControllerUI.class, "DesktopImportControllerUI.errorHandler.critical",
                    source, t.getMessage());
            errorReport.logIssue(new Issue(msg, Issue.Level.SEVERE, t));
            Exceptions.printStackTrace(t);
        }

        public int countErrors() {
            return count.get();
        }

        public Report closeAndGetReport() {
            errorReport.close();
            return errorReport;
        }
    }

581 582 583 584 585 586 587 588 589 590 591 592
    private static class ValidResult {

        private boolean result = true;

        public boolean isResult() {
            return result;
        }

        public void setResult(boolean result) {
            this.result = result;
        }
    }
593 594 595 596

    private class FinishImport implements LongTask, Runnable {

        private final List<Container> containers;
M
Mathieu Bastian 已提交
597
        private final ImportErrorHandler errorHandler;
598 599
        private ProgressTicket progressTicket;

M
Mathieu Bastian 已提交
600
        public FinishImport(List<Container> containers, ImportErrorHandler errorHandler) {
601
            this.containers = containers;
M
Mathieu Bastian 已提交
602
            this.errorHandler = errorHandler;
603 604 605 606
        }

        @Override
        public void run() {
M
Mathieu Bastian 已提交
607 608 609 610 611 612 613 614 615
            // If exceptions were thrown we show them in the processor panel
            if (errorHandler != null) {
                Report errorReport = errorHandler.closeAndGetReport();
                if (errorHandler.countErrors() > 0) {
                    showProcessorIssues(errorReport);
                    return;
                }
            }

616 617 618 619 620 621 622 623 624 625 626 627 628
            Report finalReport = new Report();
            for (Container container : containers) {
                if (container.verify()) {
                    Report report = container.getReport();
                    report.close();
                    finalReport.append(report);
                } else {
                    //TODO
                }
            }
            finalReport.close();

            //Report panel
M
Mathieu Bastian 已提交
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
            if (!containers.isEmpty()) {
                ReportPanel reportPanel = new ReportPanel();
                reportPanel.setData(finalReport, containers.toArray(new Container[0]));
                DialogDescriptor dd = new DialogDescriptor(reportPanel,
                    NbBundle.getMessage(DesktopImportControllerUI.class, "ReportPanel.title"));
                Object response = DialogDisplayer.getDefault().notify(dd);
                reportPanel.destroy();
                finalReport.clean();
                for (Container c : containers) {
                    c.getReport().clean();
                }
                if (!response.equals(NotifyDescriptor.OK_OPTION)) {
                    return;
                }
                final Processor processor = reportPanel.getProcessor();
                processor.setProgressTicket(progressTicket);

                //Project
                Workspace workspace = null;
                ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
                if (pc.getCurrentProject() == null) {
650 651
                    Project project = pc.newProject();
                    workspace = project.getCurrentWorkspace();
M
Mathieu Bastian 已提交
652
                }
653

M
Mathieu Bastian 已提交
654 655 656 657 658 659 660 661 662 663 664 665 666 667
                //Process
                final ProcessorUI pui = getProcessorUI(processor);
                final ValidResult validResult = new ValidResult();
                if (pui != null) {
                    try {
                        final JPanel panel = pui.getPanel();
                        if (panel != null) {
                            SwingUtilities.invokeAndWait(new Runnable() {
                                @Override
                                public void run() {
                                    String title = NbBundle.getMessage(DesktopImportControllerUI.class,
                                        "DesktopImportControllerUI.processor.ui.dialog.title");

                                    pui.setup(processor);
668
                                    final DialogDescriptor dd2 = DialogDescriptorWithValidation.dialog(panel, title);
M
Mathieu Bastian 已提交
669 670 671 672 673 674 675 676
                                    Object result = DialogDisplayer.getDefault().notify(dd2);
                                    if (result.equals(NotifyDescriptor.CANCEL_OPTION) ||
                                        result.equals(NotifyDescriptor.CLOSED_OPTION)) {
                                        validResult.setResult(false);
                                    } else {
                                        pui.unsetup(); //true
                                        validResult.setResult(true);
                                    }
677
                                }
M
Mathieu Bastian 已提交
678 679 680 681
                            });
                        }
                    } catch (InterruptedException | InvocationTargetException ex) {
                        Exceptions.printStackTrace(ex);
682 683 684
                    }
                }

M
Mathieu Bastian 已提交
685 686
                if (validResult.isResult()) {
                    controller.process(containers.toArray(new Container[0]), processor, workspace);
687

M
Mathieu Bastian 已提交
688 689 690 691
                    Report report = processor.getReport();
                    if (report != null && !report.isEmpty()) {
                        showProcessorIssues(report);
                    }
692

M
Mathieu Bastian 已提交
693 694 695 696 697 698
                    //StatusLine notify
                    StatusDisplayer.getDefault().setStatusText(NbBundle
                        .getMessage(DesktopImportControllerUI.class,
                            "DesktopImportControllerUI.status.multiImportSuccess",
                            containers.size()));
                }
699 700 701 702 703 704 705 706 707 708 709 710 711
            }
        }

        @Override
        public boolean cancel() {
            return false;
        }

        @Override
        public void setProgressTicket(ProgressTicket progressTicket) {
            this.progressTicket = progressTicket;
        }
    }
M
Mathieu Bastian 已提交
712
}