com.mirth.connect.client.ui.panels.export.MessageExportPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.mirth.connect.client.ui.panels.export.MessageExportPanel.java

Source

/*
 * Copyright (c) Mirth Corporation. All rights reserved.
 * 
 * http://www.mirthcorp.com
 * 
 * The software in this package is published under the terms of the MPL license a copy of which has
 * been included with this distribution in the LICENSE.txt file.
 */

package com.mirth.connect.client.ui.panels.export;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.prefs.Preferences;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;

import net.miginfocom.swing.MigLayout;

import org.apache.commons.lang3.StringUtils;

import com.mirth.connect.client.ui.UIConstants;
import com.mirth.connect.client.ui.components.MirthButton;
import com.mirth.connect.client.ui.components.MirthCheckBox;
import com.mirth.connect.client.ui.components.MirthComboBox;
import com.mirth.connect.client.ui.components.MirthFieldConstraints;
import com.mirth.connect.client.ui.components.MirthRadioButton;
import com.mirth.connect.client.ui.components.MirthTextField;
import com.mirth.connect.client.ui.components.MirthTextPane;
import com.mirth.connect.client.ui.components.MirthVariableList;
import com.mirth.connect.donkey.model.message.ContentType;
import com.mirth.connect.util.messagewriter.MessageWriterOptions;

public class MessageExportPanel extends JPanel {
    private final static String ARCHIVER_MODE_PATTERN = "[timestamp]/[channel id]";
    private final static String EXPORT_MODE_PATTERN = "[timestamp]";
    private final static String XML_EXPORT_FORMAT = "XML serialized message";
    private final static String NO_COMPRESSION = "none";

    private Preferences userPreferences;
    private boolean archiverMode;
    private boolean initialized;
    private Component[] archiveComponents;

    private MirthVariableList varList = new MirthVariableList();
    private JScrollPane varListScrollPane = new JScrollPane();
    private JPanel varListPanel = new JPanel();

    private ButtonGroup archiveButtonGroup = new ButtonGroup();
    private JLabel archiveLabel = new JLabel("Enable Archiving:");
    private JRadioButton archiveYes = new MirthRadioButton("Yes");
    private JRadioButton archiveNo = new MirthRadioButton("No");
    private JLabel archiverBlockSizeLabel = new JLabel("Archiver Block Size:");
    private JTextField archiverBlockSizeField = new MirthTextField();
    private JLabel contentLabel = new JLabel("Content:");
    private JComboBox contentComboBox = new MirthComboBox();
    private JCheckBox encryptCheckBox = new MirthCheckBox("Encrypt");
    private JCheckBox attachmentsCheckBox = new MirthCheckBox("Include Attachments");
    private JLabel compressLabel = new JLabel("Compression:");
    private JComboBox compressComboBox = new MirthComboBox();
    private JLabel exportToLabel = new JLabel("Export To:");
    private ButtonGroup exportButtonGroup = new ButtonGroup();
    private JRadioButton exportServerRadio = new MirthRadioButton("Server");
    private JRadioButton exportLocalRadio = new MirthRadioButton("My Computer");
    private JButton browseButton = new MirthButton("Browse...");
    private JLabel rootPathLabel = new JLabel("Root Path:");
    private JTextField rootPathTextField = new MirthTextField();
    private JLabel filePatternLabel = new JLabel("File Pattern:");
    private JScrollPane filePatternScrollPane = new JScrollPane();
    private JTextPane filePatternTextPane = new MirthTextPane();
    private JLabel rootPathExtLabel = new JLabel();

    /**
     * Construct a message export panel.
     * 
     * @param parent
     *            The parent swing component.
     * @param userPreferences
     *            User preferences to store/retrieve the last browsed directory on the local
     *            file-system
     * @param archiver
     *            If true, enables the Archive yes/no radio buttons that enable/disable all the
     *            other components
     * @param allowLocalExport
     *            If true, enables components that allow the user to select a local file-system
     *            folder to export to
     */
    public MessageExportPanel(Preferences userPreferences, boolean archiverMode, boolean allowLocalExport) {
        this.userPreferences = userPreferences;
        this.archiverMode = archiverMode;

        initComponents();
        initLayout(allowLocalExport);
        initialized = true;
    }

    public boolean isArchiveEnabled() {
        return archiveYes.isSelected();
    }

    public void setArchiveEnabled(boolean archiveEnabled) {
        if (archiveEnabled) {
            archiveYes.setSelected(true);
            archiveNo.setSelected(false);
        } else {
            archiveYes.setSelected(false);
            archiveNo.setSelected(true);
        }

        archiveChanged();
    }

    public String getArchiverBlockSize() {
        return archiverBlockSizeField.getText();
    }

    public void setArchiverBlockSize(String size) {
        archiverBlockSizeField.setText(size);
    }

    public boolean isIncludeAttachments() {
        return attachmentsCheckBox.isSelected();
    }

    public void setIncludeAttachments(boolean includeAttachments) {
        attachmentsCheckBox.setSelected(includeAttachments);
    }

    public boolean isExportLocal() {
        return exportLocalRadio.isSelected();
    }

    public void setExportLocal(boolean exportLocal) {
        exportLocalRadio.setSelected(exportLocal);
        exportServerRadio.setSelected(!exportLocal);
        exportDestinationChanged();
    }

    public MessageWriterOptions getMessageWriterOptions() {
        MessageWriterOptions options = new MessageWriterOptions();

        if (contentComboBox.getSelectedItem() instanceof ExportFormat) {
            ExportFormat exportFormat = (ExportFormat) contentComboBox.getSelectedItem();
            options.setContentType(exportFormat.getContentType());
            options.setDestinationContent(exportFormat.isDestination());
        }

        options.setEncrypt(encryptCheckBox.isSelected());

        if (compressComboBox.getSelectedItem() instanceof ArchiveFormat) {
            ArchiveFormat archiveFormat = (ArchiveFormat) compressComboBox.getSelectedItem();
            options.setArchiveFormat(archiveFormat.getArchiver());
            options.setCompressFormat(archiveFormat.getCompressor());
        }

        options.setIncludeAttachments(attachmentsCheckBox.isSelected());
        options.setRootFolder(rootPathTextField.getText());
        options.setFilePattern(filePatternTextPane.getText());

        return options;
    }

    public void setMessageWriterOptions(MessageWriterOptions options) {
        if (options.getContentType() == null) {
            contentComboBox.setSelectedItem(XML_EXPORT_FORMAT);
        } else {
            DefaultComboBoxModel model = (DefaultComboBoxModel) contentComboBox.getModel();

            for (int i = 0; i < model.getSize(); i++) {
                Object element = model.getElementAt(i);

                if (element instanceof ExportFormat) {
                    ExportFormat exportFormat = (ExportFormat) element;

                    if (exportFormat.getContentType().equals(options.getContentType())
                            && exportFormat.isDestination() == options.isDestinationContent()) {
                        contentComboBox.setSelectedItem(exportFormat);
                    }
                }
            }
        }

        encryptCheckBox.setSelected(options.isEncrypt());

        ArchiveFormat archiveFormat = ArchiveFormat.lookup(options.getArchiveFormat(), options.getCompressFormat());

        if (archiveFormat == null) {
            compressComboBox.setSelectedItem(NO_COMPRESSION);
        } else {
            compressComboBox.setSelectedItem(archiveFormat);
        }

        compressComboBoxChanged();

        rootPathTextField.setText(options.getRootFolder());
        filePatternTextPane.setText(options.getFilePattern());

        repaint();
    }

    /**
     * Overrides JPanel.setBackground() so that it also sets the background for the radio and
     * checkbox components in the panel
     */
    @Override
    public void setBackground(Color color) {
        super.setBackground(color);

        if (initialized) {
            archiveYes.setBackground(color);
            archiveNo.setBackground(color);
            encryptCheckBox.setBackground(color);
            attachmentsCheckBox.setBackground(color);
            exportServerRadio.setBackground(color);
            exportLocalRadio.setBackground(color);
        }
    }

    public String validate(boolean highlight) {
        resetInvalidProperties();
        StringBuilder builder = new StringBuilder();

        if (!isEnabled() || archiveNo.isSelected()) {
            return null;
        }

        String archiverBlockSize = archiverBlockSizeField.getText();
        if (archiverMode && archiveYes.isSelected() && (StringUtils.isBlank(archiverBlockSize)
                || Integer.parseInt(archiverBlockSize) <= 0 || Integer.parseInt(archiverBlockSize) > 1000)) {
            builder.append(
                    "Archiver block size must be between 1 and 1000. The recommended value for most servers is 50.");
            builder.append("\n");

            if (highlight) {
                archiverBlockSizeField.setBackground(UIConstants.INVALID_COLOR);
            }
        }

        if (StringUtils.isBlank(rootPathTextField.getText())) {
            builder.append("Root path is required.");
            builder.append("\n");

            if (highlight) {
                rootPathTextField.setBackground(UIConstants.INVALID_COLOR);
            }
        }

        if (StringUtils.isBlank(filePatternTextPane.getText())) {
            builder.append("File pattern is required.");
            builder.append("\n");

            if (highlight) {
                filePatternTextPane.setBackground(UIConstants.INVALID_COLOR);
            }
        }

        return builder.toString();
    }

    public void resetInvalidProperties() {
        rootPathTextField.setBackground(getBackground());
        filePatternTextPane.setBackground(getBackground());
        archiverBlockSizeField.setBackground(getBackground());
    }

    private void initComponents() {
        contentComboBox.setToolTipText(
                "<html>The content that will be exported: Either the entire message serialized into XML, or a specific content type<br />from either the source connector message or the destination connector messages.</html>");
        encryptCheckBox.setToolTipText("<html>If checked, the exported message content will be encrypted.</html>");
        attachmentsCheckBox.setToolTipText(
                "<html>If checked and the content type is set to XML serialized message,<br/>the exported message will contain any attachments.</html>");
        compressComboBox.setToolTipText(
                "<html>When compression is enabled, the files/folders created according to the<br />File Pattern will be put into a compressed file in the Root Path.</html>");
        exportServerRadio.setToolTipText(
                "<html>Store exported files on the Mirth Connect Server, in the Root Path specified below.</html>");
        exportLocalRadio.setToolTipText(
                "<html>Store exported files on this computer, in the Root Path specified below.</html>");
        rootPathTextField.setToolTipText(
                "<html>The root path to store the exported files/folders or compressed file.<br/>Relative paths will be resolved against the Mirth Connect Server home directory.</html>");
        filePatternTextPane.setToolTipText(
                "<html>The file/folder pattern in which to write the exported message files.<br />Variables from the Variables list to the right may be used in the pattern.</html>");
        archiverBlockSizeField.setToolTipText(
                "<html>The number of messages that will be cached by the archiver. Increase this value<br/>to improve performance. Decrease this value to reduce memory usage. This value<br/>must be between 1 and 1000. The recommended value for most servers is 50.</html>");

        archiveYes = new MirthRadioButton("Yes");
        archiveNo = new MirthRadioButton("No");

        DefaultComboBoxModel model = new DefaultComboBoxModel();
        model.addElement(XML_EXPORT_FORMAT);
        model.addElement(new ExportFormat(false, "Source", ContentType.RAW));
        model.addElement(new ExportFormat(false, "Source", ContentType.PROCESSED_RAW));
        model.addElement(new ExportFormat(false, "Source", ContentType.TRANSFORMED));
        model.addElement(new ExportFormat(false, "Source", ContentType.ENCODED));
        model.addElement(new ExportFormat(false, "Source", ContentType.RESPONSE));
        model.addElement(new ExportFormat(true, "Destination", ContentType.RAW));
        model.addElement(new ExportFormat(true, "Destination", ContentType.TRANSFORMED));
        model.addElement(new ExportFormat(true, "Destination", ContentType.ENCODED));
        model.addElement(new ExportFormat(true, "Destination", ContentType.SENT));
        model.addElement(new ExportFormat(true, "Destination", ContentType.RESPONSE));
        model.addElement(new ExportFormat(true, "Destination", ContentType.PROCESSED_RESPONSE));

        model.addElement(new ExportFormat(false, "", ContentType.SOURCE_MAP));
        model.addElement(new ExportFormat(false, "", ContentType.CHANNEL_MAP));
        model.addElement(new ExportFormat(false, "", ContentType.RESPONSE_MAP));
        contentComboBox.setModel(model);

        contentComboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (!contentComboBox.getSelectedItem().toString().equalsIgnoreCase(XML_EXPORT_FORMAT)) {
                    attachmentsCheckBox.setEnabled(false);
                    attachmentsCheckBox.setSelected(false);
                } else {
                    attachmentsCheckBox.setEnabled(true);
                }
            }

        });

        model = new DefaultComboBoxModel();
        model.addElement(NO_COMPRESSION);

        for (ArchiveFormat archiveFormat : ArchiveFormat.values()) {
            model.addElement(archiveFormat);
        }

        compressComboBox.setModel(model);

        ArrayList<String> variables = new ArrayList<String>();
        variables.add("Message ID");
        variables.add("Server ID");
        variables.add("Channel ID");
        variables.add("Original File Name");
        variables.add("Formatted Message Date");
        variables.add("Formatted Current Date");
        variables.add("Timestamp");
        variables.add("Unique ID");
        variables.add("Count");

        varListScrollPane.setBackground(UIConstants.BACKGROUND_COLOR);
        varListPanel.setBackground(UIConstants.BACKGROUND_COLOR);
        varListPanel.setBorder(BorderFactory.createEmptyBorder());
        varListPanel.setLayout(new BorderLayout());
        varListPanel.add(varListScrollPane);
        varListScrollPane.setViewportView(varList);
        varList.setListData(variables.toArray());

        archiveButtonGroup.add(archiveYes);
        archiveButtonGroup.add(archiveNo);
        archiveYes.setSelected(true);

        archiverBlockSizeField.setDocument(new MirthFieldConstraints(4, false, false, true));

        if (archiverMode) {
            rootPathExtLabel.setText("/" + ARCHIVER_MODE_PATTERN + "/");
        } else {
            rootPathExtLabel.setVisible(false);
        }

        exportButtonGroup.add(exportServerRadio);
        exportButtonGroup.add(exportLocalRadio);
        exportServerRadio.setSelected(true);
        browseButton.setEnabled(false);

        filePatternTextPane.setText("message_${message.messageId}.xml");
        filePatternScrollPane.setViewportView(filePatternTextPane);

        // this is the list of components that will be disabled when the archive radio "No" is selected, see archiveChanged()
        archiveComponents = new Component[] { archiverBlockSizeLabel, archiverBlockSizeField, contentLabel,
                contentComboBox, encryptCheckBox, attachmentsCheckBox, varList, varListScrollPane, varListPanel,
                compressLabel, compressComboBox, exportToLabel, exportServerRadio, exportLocalRadio, browseButton,
                rootPathLabel, rootPathTextField, rootPathExtLabel, filePatternLabel, filePatternScrollPane,
                filePatternTextPane };

        // @formatter:off
        archiveYes.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                archiveChanged();
            }
        });

        archiveNo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                archiveChanged();
            }
        });

        compressComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                compressComboBoxChanged();
            }
        });

        browseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                browseSelected();
            }
        });

        exportServerRadio.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                exportDestinationChanged();
            }
        });

        exportLocalRadio.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                exportDestinationChanged();
            }
        });
        // @formatter:on
    }

    private void browseSelected() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        if (userPreferences != null) {
            File currentDir = new File(userPreferences.get("currentDirectory", ""));

            if (currentDir.exists()) {
                chooser.setCurrentDirectory(currentDir);
            }
        }

        if (chooser.showOpenDialog(getParent()) == JFileChooser.APPROVE_OPTION) {
            if (userPreferences != null) {
                userPreferences.put("currentDirectory", chooser.getCurrentDirectory().getPath());
            }

            rootPathTextField.setText(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    private void archiveChanged() {
        if (archiveYes.isSelected()) {
            for (Component component : archiveComponents) {
                component.setEnabled(true);
            }
        } else {
            resetInvalidProperties();

            for (Component component : archiveComponents) {
                component.setEnabled(false);
            }
        }
    }

    private void exportDestinationChanged() {
        if (exportServerRadio.isSelected()) {
            rootPathTextField.setText(null);
            browseButton.setEnabled(false);
        } else {
            rootPathTextField.setText(null);
            browseButton.setEnabled(true);
        }
    }

    private void compressComboBoxChanged() {
        if (compressComboBox.getSelectedItem() instanceof ArchiveFormat) {
            ArchiveFormat archiveFormat = (ArchiveFormat) compressComboBox.getSelectedItem();
            rootPathExtLabel.setText(
                    "/" + ((archiverMode) ? ARCHIVER_MODE_PATTERN : EXPORT_MODE_PATTERN) + "." + archiveFormat);
            rootPathExtLabel.setVisible(true);
        } else if (archiverMode) {
            rootPathExtLabel.setText("/" + ARCHIVER_MODE_PATTERN + "/");
        } else {
            rootPathExtLabel.setVisible(false);
        }
    }

    private void initLayout(boolean allowLocalExport) {
        String rowGap = "2"; // TODO find a better way in mig layout to set the row gap for all rows, given that # of rows can change

        setLayout(new MigLayout("insets 0 0 0 0, wrap, fillx, hidemode 3", "[right]12[left, grow][170!]", ""));

        if (archiverMode) {
            add(archiveLabel);
            add(archiveYes, "split 2");
            add(archiveNo, "wrap");

            add(archiverBlockSizeLabel);
            add(archiverBlockSizeField, "w 71!, h 22!, gapbottom " + rowGap);

            add(varListPanel, "spany 5, growy, width 170!");
        }

        add(contentLabel);
        add(contentComboBox, "split 3, gapbottom " + rowGap);
        add(encryptCheckBox, "gapleft 8");
        add(attachmentsCheckBox, "gapleft 8");

        if (!archiverMode) {
            add(varListPanel, "spany 5, growy, width 170!");
        }

        add(compressLabel);
        add(compressComboBox, "gapbottom " + rowGap);

        if (allowLocalExport) {
            add(exportToLabel);
            add(exportServerRadio, "split 3");
            add(exportLocalRadio);
            add(browseButton, "gapbottom " + rowGap);
        }

        add(rootPathLabel);
        add(rootPathTextField, "grow, split 2, height 22!, gapbottom " + rowGap);
        add(rootPathExtLabel, "hidemode 2");

        add(filePatternLabel, "aligny top");
        add(filePatternScrollPane, "grow, push, split 2");
        add(new JLabel(), "gapbottom " + rowGap);
    }

    /**
     * Launches the panel in a test frame
     */
    //    public static void main(String[] args) {
    //        Mirth.initUIManager();
    //        PlatformUI.MIRTH_FRAME = new Frame() {
    //            public void setSaveEnabled(boolean enabled) {}
    //        };
    //
    //        final JFrame frame = new JFrame();
    //
    //        MessageExportPanel panel = new MessageExportPanel(null, false, true);
    //        panel.setBackground(new Color(255, 255, 255));
    //
    //        frame.setSize(800, 300);
    //        frame.getContentPane().setBackground(new Color(255, 255, 255));
    //        frame.setLayout(new MigLayout("fill, insets dialog", "", ""));
    //        frame.add(panel, "grow");
    //        frame.setLocationRelativeTo(null);
    //        frame.setVisible(true);
    //        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //        frame.getRootPane().registerKeyboardAction(new ActionListener() {
    //            @Override
    //            public void actionPerformed(ActionEvent event) {
    //                frame.dispose();
    //            }
    //        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
    //    }
}