ca.sqlpower.swingui.enterprise.client.ServerProjectsManagerPanel.java Source code

Java tutorial

Introduction

Here is the source code for ca.sqlpower.swingui.enterprise.client.ServerProjectsManagerPanel.java

Source

/*
 * Copyright (c) 2010, SQL Power Group Inc.
 *
 * This file is part of Power*Architect.
 *
 * Power*Architect is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Power*Architect is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

package ca.sqlpower.swingui.enterprise.client;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import org.apache.http.client.CookieStore;
import org.json.JSONException;

import ca.sqlpower.enterprise.ClientSideSessionUtils;
import ca.sqlpower.enterprise.client.ProjectLocation;
import ca.sqlpower.enterprise.client.SPServerInfo;
import ca.sqlpower.enterprise.client.SPServerInfoManager;
import ca.sqlpower.swingui.SPSUtils;
import ca.sqlpower.util.UserPrompterFactory;
import ca.sqlpower.util.UserPrompter.UserPromptOptions;
import ca.sqlpower.util.UserPrompter.UserPromptResponse;
import ca.sqlpower.util.UserPrompterFactory.UserPromptType;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * This class can create a dialog to display server connections and the projects
 * in them.
 */
public abstract class ServerProjectsManagerPanel {

    private final Component dialogOwner;
    private final UserPrompterFactory upf;
    private final File defaultFileDirectory;

    private final JPanel panel;
    private final Action closeAction;
    private final JList projects;
    private final JList servers;

    private final Action refreshAction = new AbstractAction("Refresh") {
        public void actionPerformed(ActionEvent e) {
            refreshInfoList();
        }
    };

    private final Action newAction = new AbstractAction("New...") {
        public void actionPerformed(ActionEvent e) {

            if (getSelectedServerInfo() != null) {

                String name = JOptionPane.showInputDialog(dialogOwner, "Please specify the name of your project",
                        "", JOptionPane.QUESTION_MESSAGE);

                if (name != null) {
                    DefaultListModel model = (DefaultListModel) projects.getModel();
                    for (int i = 0; i < model.size(); i++) {
                        if (((ProjectLocation) model.getElementAt(i)).getName().trim()
                                .equalsIgnoreCase(name.trim())) {
                            JOptionPane.showMessageDialog(dialogOwner,
                                    "A project called \"" + name
                                            + "\" already exists. Please use a different name.",
                                    "Duplicate project name", JOptionPane.ERROR_MESSAGE);
                            return;
                        }
                    }

                    try {
                        Window frame = SwingUtilities.getWindowAncestor(dialogOwner);

                        JLabel messageLabel = new JLabel("Creating New Project");
                        JProgressBar progressBar = new JProgressBar();
                        progressBar.setIndeterminate(true);

                        final JDialog dialog = new JDialog(frame, "Creating New Project");

                        DefaultFormBuilder builder = new DefaultFormBuilder(
                                new FormLayout("pref:grow, 5dlu, pref"));
                        builder.setDefaultDialogBorder();
                        builder.append(messageLabel, 3);
                        builder.nextLine();
                        builder.append(progressBar, 3);
                        dialog.add(builder.getPanel());

                        dialog.setSize(new Dimension(300, 90));
                        dialog.setLocationRelativeTo(frame);
                        dialog.setAlwaysOnTop(true);
                        dialog.setVisible(true);

                        ClientSideSessionUtils.createNewServerSession(getSelectedServerInfo(), name, cookieStore,
                                upf);

                        dialog.dispose();

                    } catch (Exception ex) {
                        throw new RuntimeException("Unable to create new project", ex);
                    }

                    refreshInfoList();
                }
            }
        }
    };

    private final Action uploadAction = new AbstractAction("Upload") {

        public void actionPerformed(ActionEvent e) {
            final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(dialogOwner), "Upload Project",
                    ModalityType.DOCUMENT_MODAL);

            JPanel panel = new JPanel();
            FormLayout layout = new FormLayout("4dlu, pref, 4dlu, max(150dlu;pref), 4dlu, pref, 4dlu",
                    "pref, pref, pref");
            DefaultFormBuilder builder = new DefaultFormBuilder(layout, panel);
            CellConstraints cc = new CellConstraints();

            final JTextField nameField = new JTextField();
            builder.add(new JLabel("Name"), cc.xy(2, 1));
            builder.add(nameField, cc.xyw(4, 1, 3));

            final JTextField fileField = new JTextField();
            JButton fileButton = new JButton("...");
            fileButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    JFileChooser chooser = new JFileChooser(defaultFileDirectory);
                    chooser.addChoosableFileFilter(SPSUtils.ARCHITECT_FILE_FILTER);
                    chooser.setDialogTitle("Choose Project to Upload");

                    int response = chooser.showOpenDialog(dialog);

                    if (response != JFileChooser.APPROVE_OPTION) {
                        return;
                    }

                    fileField.setText(chooser.getSelectedFile().getAbsolutePath());
                }
            });
            builder.add(new JLabel("File"), cc.xy(2, 2));
            builder.add(fileField, cc.xy(4, 2));
            builder.add(fileButton, cc.xy(6, 2));

            final JButton okButton = new JButton("Upload");
            okButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    File f = new File(fileField.getText());
                    if (!f.canRead()) {
                        JOptionPane.showMessageDialog(dialogOwner, "File cannot be read", "Invalid File",
                                JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                    try {
                        ClientSideSessionUtils.uploadProject(getSelectedServerInfo(), nameField.getText(), f, upf,
                                cookieStore);
                        dialog.dispose();
                        refreshInfoList();
                    } catch (Exception ex) {
                        SPSUtils.showExceptionDialogNoReport(dialog, "Unable to upload project", ex);
                    }
                }
            });
            JButton cancelButton = new JButton("Cancel");
            cancelButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dialog.dispose();
                }
            });

            okButton.setEnabled(false);
            DocumentListener documentListener = new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    textChanged(e);
                }

                @Override
                public void insertUpdate(DocumentEvent e) {
                    textChanged(e);
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    textChanged(e);
                }

                private void textChanged(DocumentEvent e) {
                    okButton.setEnabled(!fileField.getText().isEmpty() && !nameField.getText().isEmpty());
                }
            };
            fileField.getDocument().addDocumentListener(documentListener);
            nameField.getDocument().addDocumentListener(documentListener);

            JPanel buttonBar = ButtonBarFactory.buildRightAlignedBar(okButton, cancelButton);
            builder.add(buttonBar, cc.xyw(2, 3, 5));
            dialog.add(panel);
            SPSUtils.makeJDialogCancellable(dialog, null);
            dialog.pack();
            dialog.setLocationRelativeTo(dialogOwner);
            dialog.setVisible(true);
        }
    };

    private final Action deleteAction = new AbstractAction("Delete") {
        public void actionPerformed(ActionEvent e) {

            if (getSelectedServerInfo() != null) {

                int[] indices = projects.getSelectedIndices();

                if (indices.length >= 1) {

                    final Object[] objs = new Object[indices.length];
                    for (int i = 0; i < indices.length; i++) {
                        objs[i] = projects.getModel().getElementAt(indices[i]);
                    }

                    String promptMessage;
                    if (indices.length == 1) {
                        promptMessage = "Are you sure you want to delete the selected project?"
                                + "\nThis action cannot be undone.";
                    } else {
                        promptMessage = "Are you sure you want to delete these " + indices.length
                                + " selected projects?" + "\nThis action cannot be undone.";
                    }

                    if (JOptionPane.showConfirmDialog(dialogOwner, promptMessage, "Confirm Delete Projects",
                            JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
                        for (Object obj : objs) {
                            if (obj instanceof ProjectLocation) {
                                ProjectLocation location = (ProjectLocation) obj;
                                try {
                                    ClientSideSessionUtils.deleteServerWorkspace(location, cookieStore, upf);
                                } catch (Exception ex) {
                                    throw new RuntimeException("Unable to delete project", ex);
                                }
                            }
                        }

                        refreshInfoList();
                    }
                }
            }
        }
    };

    private boolean connected = false;
    private SPServerInfo serverInfo = null;
    private final CookieStore cookieStore;
    private final JButton securityButton = new JButton();
    private final JButton openButton = new JButton();

    /**
     * This constructor creates a dialog for modifying and loading a project
     * from a single server designated by the given serverInfo parameter.
     * 
     * @param serverInfo
     *            Projects will be retrieved from this server based on the
     *            information and displayed. The dialog will allow editing the
     *            security as well as creating and deleting projects on this
     *            server.
     * @param dialogOwner
     *            The dialog to parent new dialogs to.
     * @param upf
     *            A user prompter factory for displaying error and warning
     *            messages to users.
     * @param closeAction
     *            An action that will close the dialog or frame that this dialog
     *            is contained in.
     * @param defaultFileDirectory
     *            A default file directory to start looking for files in if the
     *            user wants to upload a project. If null this will default to
     *            the user's home directory.
     * @param cookieStore
     *            A cookie store for HTTP requests. Used by the
     *            {@link ClientSideSessionUtils}.
     */
    public ServerProjectsManagerPanel(SPServerInfo serverInfo, Component dialogOwner, UserPrompterFactory upf,
            Action closeAction, File defaultFileDirectory, CookieStore cookieStore) {
        this.serverInfo = serverInfo;
        this.dialogOwner = dialogOwner;
        this.upf = upf;
        this.closeAction = closeAction;
        this.defaultFileDirectory = defaultFileDirectory;
        this.cookieStore = cookieStore;

        cookieStore.clear();

        DefaultFormBuilder builder = new DefaultFormBuilder(
                new FormLayout("pref:grow, 5dlu, pref", "pref, pref, pref"));

        servers = null;

        projects = new JList(new DefaultListModel());
        projects.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                refreshPanel();
                if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
                    getOpenAction().actionPerformed(null);
                }
            }
        });

        JScrollPane projectsPane = new JScrollPane(projects);
        projectsPane.setPreferredSize(new Dimension(250, 300));

        CellConstraints cc = new CellConstraints();
        builder.add(new JLabel(serverInfo.getName() + "'s projects:"), cc.xyw(1, 1, 2));
        builder.nextLine();
        builder.add(projectsPane, cc.xywh(1, 2, 1, 2));

        DefaultFormBuilder buttonBarBuilder = new DefaultFormBuilder(new FormLayout("pref"));
        buttonBarBuilder.append(new JButton(refreshAction));
        buttonBarBuilder.append(securityButton);
        buttonBarBuilder.append(new JButton(newAction));
        buttonBarBuilder.append(openButton);
        buttonBarBuilder.append(new JButton(deleteAction));
        buttonBarBuilder.append(new JButton(closeAction));
        builder.add(buttonBarBuilder.getPanel(), cc.xy(3, 2));
        builder.setDefaultDialogBorder();
        panel = builder.getPanel();
    }

    /**
     * Creates a dialog that lets the user choose a server connection and then a
     * project.
     * 
     * @param serverManager
     *            This object contains all of the server information objects
     *            known and the servers based on their information will be
     *            displayed in a list so a user can navigate to different
     *            projects in different servers.
     * @param dialogOwner
     *            The dialog to parent new dialogs to.
     * @param upf
     *            A user prompter factory for displaying error and warning
     *            messages to users.
     * @param closeAction
     *            An action that will close the dialog or frame that this dialog
     *            is contained in.
     * @param defaultFileDirectory
     *            A default file directory to start looking for files in if the
     *            user wants to upload a project. If null this will default to
     *            the user's home directory.
     * @param cookieStore
     *            A cookie store for HTTP requests. Used by the
     *            {@link ClientSideSessionUtils}.
     */
    public ServerProjectsManagerPanel(SPServerInfoManager serverManager, Component dialogOwner,
            UserPrompterFactory upf, Action closeAction, File defaultFileDirectory, CookieStore cookieStore) {
        this.dialogOwner = dialogOwner;
        this.upf = upf;
        this.closeAction = closeAction;
        this.defaultFileDirectory = defaultFileDirectory;
        this.cookieStore = cookieStore;

        cookieStore.clear();

        DefaultFormBuilder builder = new DefaultFormBuilder(
                new FormLayout("pref:grow, 5dlu, pref:grow, 5dlu, pref", "pref, pref, pref"));

        servers = new JList(new DefaultListModel());
        servers.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                if (SwingUtilities.isLeftMouseButton(e)) {
                    refreshInfoList();
                }
            }
        });

        DefaultListModel serversModel = (DefaultListModel) servers.getModel();
        serversModel.removeAllElements();
        if (serverManager.getServers(false).size() > 0) {
            for (SPServerInfo serverInfo : serverManager.getServers(false)) {
                serversModel.addElement(serverInfo);
            }
        } else {
            serversModel.addElement("No Servers");
            servers.setEnabled(false);
        }

        projects = new JList(new DefaultListModel());
        projects.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                refreshPanel();
                if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
                    getOpenAction().actionPerformed(null);
                }
            }
        });

        JScrollPane projectsPane = new JScrollPane(projects);
        projectsPane.setPreferredSize(new Dimension(250, 300));

        JScrollPane serverPane = new JScrollPane(servers);
        serverPane.setPreferredSize(new Dimension(250, 300));

        CellConstraints cc = new CellConstraints();
        builder.add(new JLabel("Servers:"), cc.xyw(1, 1, 2));
        builder.add(new JLabel("Projects:"), cc.xyw(3, 1, 2));
        builder.nextLine();
        builder.add(serverPane, cc.xywh(1, 2, 1, 2));
        builder.add(projectsPane, cc.xywh(3, 2, 1, 2));

        DefaultFormBuilder buttonBarBuilder = new DefaultFormBuilder(new FormLayout("pref"));
        buttonBarBuilder.append(new JButton(refreshAction));
        buttonBarBuilder.append(securityButton);
        buttonBarBuilder.append(new JButton(newAction));
        buttonBarBuilder.append(openButton);
        buttonBarBuilder.append(new JButton(uploadAction));
        buttonBarBuilder.append(new JButton(deleteAction));
        buttonBarBuilder.append(new JButton(closeAction));
        builder.add(buttonBarBuilder.getPanel(), cc.xy(5, 2));
        builder.setDefaultDialogBorder();
        panel = builder.getPanel();
    }

    public boolean isConnected() {
        refreshInfoList();
        return connected;
    }

    public JPanel getPanel() {
        openButton.setAction(getOpenAction());
        securityButton.setAction(getSecurityAction());

        refreshInfoList();
        return panel;
    }

    private void refreshPanel() {
        // Update the status of buttons and lists .
        if (connected) {

            securityButton.setEnabled(true);
            newAction.setEnabled(true);
            uploadAction.setEnabled(true);

            if (projects.isSelectionEmpty()) {
                openButton.setEnabled(false);
                deleteAction.setEnabled(false);
            } else {
                openButton.setEnabled(true);
                deleteAction.setEnabled(true);
            }

            projects.setEnabled(true);
        } else {
            securityButton.setEnabled(false);
            newAction.setEnabled(false);
            openButton.setEnabled(false);
            uploadAction.setEnabled(false);
            deleteAction.setEnabled(false);
            projects.setEnabled(false);
        }
    }

    protected void refreshInfoList() {
        DefaultListModel model = (DefaultListModel) projects.getModel();
        model.removeAllElements();

        SPServerInfo serviceInfo = getSelectedServerInfo();
        if (serviceInfo != null) {
            try {
                List<ProjectLocation> projectLocations = getProjectLocations();

                // Sorts the project locations alphabetically
                Collections.sort(projectLocations, new Comparator<ProjectLocation>() {
                    public int compare(ProjectLocation proj1, ProjectLocation proj2) {
                        return proj1.getName().compareToIgnoreCase(proj2.getName());
                    }
                });

                model.clear();
                for (ProjectLocation pl : projectLocations) {
                    model.addElement(pl);
                }

                connected = true;
            } catch (Exception ex) {
                model.removeAllElements();
                model.addElement("Unable to get projects from server");
                connected = false;
                upf.createUserPrompter("Server Unavailable", UserPromptType.MESSAGE, UserPromptOptions.OK,
                        UserPromptResponse.OK, "OK", "OK").promptUser("");
            }

            refreshPanel();
        } else {
            model.addElement("No Server Selected");
            connected = false;
            refreshPanel();
        }
    }

    /**
     * Returns all of the project locations for the selected server.
     */
    protected abstract List<ProjectLocation> getProjectLocations()
            throws IOException, URISyntaxException, JSONException;

    /**
     * Returns the server info for the selected server the user is currently
     * viewing.
     */
    protected SPServerInfo getSelectedServerInfo() {
        if (serverInfo != null)
            return serverInfo;

        int index = servers.getSelectedIndex();
        Object obj;

        if (index >= 0) {
            obj = servers.getModel().getElementAt(index);

            if (obj instanceof SPServerInfo) {
                return (SPServerInfo) obj;
            }
        }

        return null;
    }

    protected Component getDialogOwner() {
        return dialogOwner;
    }

    protected Action getCloseAction() {
        return closeAction;
    }

    protected List<ProjectLocation> getSelectedProjects() {
        List<ProjectLocation> projectLocations = new ArrayList<ProjectLocation>();
        if (getSelectedServerInfo() != null) {

            int[] indices = projects.getSelectedIndices();

            if (indices.length >= 1) {

                for (int i = 0; i < indices.length; i++) {
                    projectLocations.add((ProjectLocation) projects.getModel().getElementAt(indices[i]));
                }
            }
        }
        return projectLocations;
    }

    /**
     * This action will open the selected project(s).
     */
    protected abstract Action getOpenAction();

    /**
     * This action will open a security editor for the selected server.
     */
    protected abstract Action getSecurityAction();
}