r4fterman/pdf.forms

View on GitHub
src/main/java/org/pdf/forms/gui/commands/OpenDesignerFileCommand.java

Summary

Maintainability
B
5 hrs
Test Coverage
F
7%
package org.pdf.forms.gui.commands;

import static java.util.stream.Collectors.toUnmodifiableList;
import static java.util.stream.Collectors.toUnmodifiableMap;

import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.swing.*;

import org.pdf.forms.document.FormsDocument;
import org.pdf.forms.document.Page;
import org.pdf.forms.gui.IMainFrame;
import org.pdf.forms.gui.windows.FileFinderDialog;
import org.pdf.forms.model.des.CheckBoxGroups;
import org.pdf.forms.model.des.DesDocument;
import org.pdf.forms.model.des.PageData;
import org.pdf.forms.model.des.RadioButtonGroups;
import org.pdf.forms.model.des.Version;
import org.pdf.forms.model.des.Widget;
import org.pdf.forms.readers.des.DesignerProjectFileReader;
import org.pdf.forms.readers.properties.DesignerPropertiesFile;
import org.pdf.forms.widgets.ButtonGroup;
import org.pdf.forms.widgets.GroupWidget;
import org.pdf.forms.widgets.IWidget;
import org.pdf.forms.widgets.utils.WidgetFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OpenDesignerFileCommand implements Command {

    private final Logger logger = LoggerFactory.getLogger(OpenDesignerFileCommand.class);

    private final IMainFrame mainFrame;
    private final Version version;
    private final JMenuItem[] recentDesignerDocuments;
    private final WidgetFactory widgetFactory;
    private final DesignerPropertiesFile designerPropertiesFile;

    public OpenDesignerFileCommand(
            final IMainFrame mainFrame,
            final Version version,
            final WidgetFactory widgetFactory,
            final DesignerPropertiesFile designerPropertiesFile) {
        this.mainFrame = mainFrame;
        this.version = version;
        this.widgetFactory = widgetFactory;
        this.designerPropertiesFile = designerPropertiesFile;

        final int noOfRecentDocs = DesignerPropertiesFile.NO_OF_RECENT_DOCS;
        this.recentDesignerDocuments = new JMenuItem[noOfRecentDocs];
    }

    @Override
    public void execute() {
        selectDesignerFile().ifPresent(file -> openDesignerFile(file.getAbsolutePath()));
    }

    private Optional<File> selectDesignerFile() {
        final JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        chooser.addChoosableFileFilter(new DesFileFilter());
        final int state = chooser.showOpenDialog((Component) mainFrame);
        if (state == JFileChooser.APPROVE_OPTION) {
            return Optional.ofNullable(chooser.getSelectedFile());
        }
        return Optional.empty();
    }

    public void openDesignerFile(final String designerFileToOpen) {
        closePDF();

        mainFrame.setPanelsState(true);
        mainFrame.setCurrentDesignerFileName(designerFileToOpen);

        readDesignerFile(designerFileToOpen);

        mainFrame.setCurrentPage(1);
        // draw page
        mainFrame.displayPage(1);
        mainFrame.setTotalNoOfDisplayedPages(mainFrame.getTotalNoOfPages());
        mainFrame.setTitle(designerFileToOpen + " - PDF Forms Designer Version " + version.getVersion());

        designerPropertiesFile.addRecentDesignerDocument(designerFileToOpen);
        updateRecentDocuments(designerPropertiesFile.getRecentDesignerDocuments());
    }

    private void readDesignerFile(final String designerFileToOpen) {
        try {
            final File desFile = new File(designerFileToOpen);
            final DesDocument desDocument = new DesignerProjectFileReader(desFile).getDesDocument();

            mainFrame.setFormsDocument(new FormsDocument(desDocument));

            final List<org.pdf.forms.model.des.Page> pages = desDocument.getPage();

            final Map<String, String> changedFiles = getChangedPdfFileLocations(pages);
            for (final org.pdf.forms.model.des.Page page : pages) {
                final Page newPage = convertToFormsPage(changedFiles, page);

                addRadioButtonGroupsToPage(page, newPage);
                addCheckBoxButtonGroupsToPage(page, newPage);

                mainFrame.setCurrentPage(mainFrame.getCurrentPage() + 1);
                addPage(mainFrame.getCurrentPage(), newPage);

                final List<IWidget> widgets = getWidgetsFromPage(page);
                for (final IWidget widget : widgets) {
                    mainFrame.addWidgetToHierarchy(widget);
                }
                newPage.setWidgets(widgets);
            }
        } catch (final Exception e) {
            logger.error("Error opening designer file {}", designerFileToOpen, e);
        }
    }

    private Page convertToFormsPage(
            final Map<String, String> changedFiles,
            final org.pdf.forms.model.des.Page page) {
        final String pageName = page.getPageName().orElse("");
        if (page.isPdfPage()) {
            // PDF page
            final PageData pageData = page.getPageData();
            final String pdfFileToUse = changedFiles.get(pageData.getPdfFileLocation().orElse(""));
            final int pdfPageNumber = pageData.getPdfPageNumber().orElse(1);
            //todo check for skip PDF files
            return new Page(pageName, pdfFileToUse, pdfPageNumber);
        }

        // simple page
        final PageData pageData = page.getPageData();
        final int width = pageData.getWidth().orElse(1);
        final int height = pageData.getHeight().orElse(1);
        return new Page(pageName, width, height);
    }

    private void closePDF() {
        mainFrame.setFormsDocument(null);

        mainFrame.getDesigner().close();

        mainFrame.setCurrentDesignerFileName("");
        mainFrame.setTitle("PDF Forms Designer Version " + version.getVersion());

        mainFrame.setPropertiesCompound(Set.of());
        mainFrame.setPropertiesToolBar(Set.of());

        mainFrame.setPanelsState(false);

        mainFrame.setCurrentPage(0);
    }

    private Map<String, String> getChangedPdfFileLocations(final List<org.pdf.forms.model.des.Page> pages) {
        return pages.stream()
                .map(org.pdf.forms.model.des.Page::getPdfFileLocation)
                .filter(Optional::isPresent)
                .map(Optional::get)
                .collect(toUnmodifiableMap(
                        pdfFile -> pdfFile,
                        pdfFile -> pdfFileName(new File(pdfFile))
                ));
    }

    private String pdfFileName(final File pdfFile) {
        if (!pdfFile.exists()) {
            final FileFinderDialog fileFinderDialog = new FileFinderDialog((JFrame) mainFrame, pdfFile);
            fileFinderDialog.setVisible(true);
            final String pdfFileLocation = fileFinderDialog.getFileLocation();

            if (!new File(pdfFileLocation).exists()) {
                JOptionPane.showMessageDialog(
                        (JFrame) mainFrame,
                        "The file you have entered does not exist, please select an existing file!",
                        "File Not Found",
                        JOptionPane.ERROR_MESSAGE
                );
            }
        }
        return pdfFile.getAbsolutePath();
    }

    private void addRadioButtonGroupsToPage(
            final org.pdf.forms.model.des.Page page,
            final Page newPage) {
        final RadioButtonGroups radioButtonGroups = page.getRadioButtonGroups();
        radioButtonGroups.getButtonGroupNames().forEach(buttonGroupName -> {
            final ButtonGroup buttonGroup = new ButtonGroup(IWidget.RADIO_BUTTON);
            buttonGroup.setName(buttonGroupName);
            newPage.getRadioButtonGroups().add(buttonGroup);
        });
    }

    private void addCheckBoxButtonGroupsToPage(
            final org.pdf.forms.model.des.Page page,
            final Page newPage) {
        final CheckBoxGroups checkBoxGroups = page.getCheckBoxGroups();
        checkBoxGroups.getButtonGroupNames().forEach(buttonGroupName -> {
            final ButtonGroup buttonGroup = new ButtonGroup(IWidget.CHECK_BOX);
            buttonGroup.setName(buttonGroupName);
            newPage.getCheckBoxGroups().add(buttonGroup);
        });
    }

    private void updateRecentDocuments(final List<String> recentDocs) {
        if (recentDocs.isEmpty()) {
            return;
        }

        final JMenuItem[] recentDocuments = recentDesignerDocuments;

        for (int i = 0; i < recentDocs.size(); i++) {
            if (recentDocs.get(i) != null) {
                final String shortenedFileName = FileUtil.getShortenedFileName(recentDocs.get(i), File.separator);
                if (recentDocuments[i] == null) {
                    recentDocuments[i] = new JMenuItem();
                }
                recentDocuments[i].setText(i + 1 + ": " + shortenedFileName);
                recentDocuments[i].setVisible(!recentDocuments[i].getText().equals(i + 1 + ": "));
                recentDocuments[i].setName(recentDocs.get(i));
            }
        }
    }

    private List<IWidget> getWidgetsFromPage(final org.pdf.forms.model.des.Page page) {
        return page.getWidget().stream()
                .map(this::createWidgetByType)
                .collect(toUnmodifiableList());
    }

    private IWidget createWidgetByType(final org.pdf.forms.model.des.Widget widget) {
        final int widgetType = getWidgetType(widget);
        //todo: move to WidgetFactory
        if (widgetType == IWidget.GROUP) {
            final GroupWidget groupWidget = new GroupWidget();

            final List<IWidget> widgetsInGroup = new ArrayList<>();
            final List<Widget> widgetInGroupList = widget.getWidgets().getWidget();
            for (final Widget widgetInGroup : widgetInGroupList) {
                widgetsInGroup.add(createWidgetByType(widgetInGroup));
            }
            groupWidget.setWidgetsInGroup(widgetsInGroup);

            return groupWidget;
        }
        return widgetFactory.createWidget(widgetType, widget);
    }

    private int getWidgetType(final Widget widget) {
        return widget.getType()
                .map(type -> IWidget.WIDGET_TYPES.getOrDefault(type.toLowerCase(), IWidget.NONE))
                .orElse(IWidget.NONE);
    }

    private void addPage(
            final int pageNumber,
            final Page newPage) {
        mainFrame.getFormsDocument().addPage(pageNumber, newPage);
        mainFrame.addPageToHierarchyPanel(pageNumber, newPage);
    }

}