at.ac.tuwien.inso.subcat.ui.ViewFactory.java Source code

Java tutorial

Introduction

Here is the source code for at.ac.tuwien.inso.subcat.ui.ViewFactory.java

Source

/* ViewFactory.java
 *
 * Copyright (C) 2014 Florian Brosch
 *
 * Based on work from Andreas Mauczka
 *
 * This program is developed as part of the research project
 * "Lexical Repository Analyis" which is part of the PhD thesis
 * "Design and evaluation for identification, mapping and profiling
 * of medium sized software chunks" by Andreas Mauczka at
 * INSO - University of Technology Vienna. For questions in regard
 * to the research project contact andreas.mauczka(at)inso.tuwien.ac.at
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License 2.0
 * as published by the Free Software Foundation.
 *
 * This program 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Author:
 *       Florian Brosch <flo.brosch@gmail.com>
 */

package at.ac.tuwien.inso.subcat.ui;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;

import at.ac.tuwien.inso.subcat.config.ChartGroupConfig;
import at.ac.tuwien.inso.subcat.config.ConfigVisitor;
import at.ac.tuwien.inso.subcat.config.Configuration;
import at.ac.tuwien.inso.subcat.config.DistributionChartConfig;
import at.ac.tuwien.inso.subcat.config.Parser;
import at.ac.tuwien.inso.subcat.config.ParserException;
import at.ac.tuwien.inso.subcat.config.PieChartGroupConfig;
import at.ac.tuwien.inso.subcat.config.ProjectViewConfig;
import at.ac.tuwien.inso.subcat.config.SemanticException;
import at.ac.tuwien.inso.subcat.config.TeamViewConfig;
import at.ac.tuwien.inso.subcat.config.TrendChartGroupConfig;
import at.ac.tuwien.inso.subcat.config.UserViewConfig;
import at.ac.tuwien.inso.subcat.config.ViewConfig;
import at.ac.tuwien.inso.subcat.model.Model;
import at.ac.tuwien.inso.subcat.model.ModelPool;
import at.ac.tuwien.inso.subcat.model.Project;
import at.ac.tuwien.inso.subcat.ui.controller.DistributionChartController;
import at.ac.tuwien.inso.subcat.ui.controller.PieChartController;
import at.ac.tuwien.inso.subcat.ui.controller.TrendChartController;
import at.ac.tuwien.inso.subcat.ui.controller.ViewController;
import at.ac.tuwien.inso.subcat.ui.events.UserListListener;
import at.ac.tuwien.inso.subcat.ui.widgets.DistributionChart;
import at.ac.tuwien.inso.subcat.ui.widgets.PieChart;
import at.ac.tuwien.inso.subcat.ui.widgets.TrendChart;
import at.ac.tuwien.inso.subcat.ui.widgets.UserList;
import at.ac.tuwien.inso.subcat.utility.Reporter;

import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;

public class ViewFactory {
    private Configuration config;
    private Model model;
    private List<String> flags;

    private class ViewBuilder extends ConfigVisitor {
        private TabFolder folder;
        private Project project;

        private ViewController viewController;

        // Used to pass exceptions to builder ()
        private SemanticException semanticException;

        public ViewBuilder() {
        }

        public ViewController build(ViewConfig config, TabFolder folder, Project project,
                HashMap<String, Object> vars) throws SemanticException, SQLException {
            assert (project != null);
            assert (config != null);
            assert (folder != null);

            // TODO: ViewConfig-visitors to select the right
            //   viewController
            viewController = new ViewController(project, vars);

            this.project = project;
            this.folder = folder;

            for (ChartGroupConfig groupConf : config.getChartGroups()) {
                groupConf.accept(this);

                if (semanticException != null) {
                    SemanticException e = this.semanticException;
                    this.semanticException = null;
                    throw e;
                }
            }

            this.folder = null;
            return viewController;
        }

        @Override
        public void visitPieChartGroupConfig(PieChartGroupConfig groupConfig) {
            assert (project != null);
            assert (folder != null);

            if (!groupConfig.show(flags)) {
                return;
            }

            TabItem page = new TabItem(folder, SWT.NONE);
            page.setText(groupConfig.getName());

            ScrolledComposite scroll = new ScrolledComposite(folder, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
            scroll.setLayout(new FillLayout());

            PieChart view = new PieChart(scroll, SWT.NONE);
            PieChartController pieController = new PieChartController(model, view, groupConfig, flags,
                    viewController);
            viewController.addChartController(pieController);

            scroll.setExpandHorizontal(true);
            scroll.setExpandVertical(true);
            page.setControl(scroll);

            scroll.setContent(view);
            scroll.setMinSize(view.computeSize(SWT.DEFAULT, SWT.DEFAULT));
        }

        @Override
        public void visitTrendChartGroupConfig(TrendChartGroupConfig groupConfig) {
            assert (project != null);
            assert (folder != null);

            if (!groupConfig.show(flags)) {
                return;
            }

            TabItem page = new TabItem(folder, SWT.NONE);
            page.setText(groupConfig.getName());

            TrendChart view = new TrendChart(folder, SWT.NONE);
            TrendChartController trendController = new TrendChartController(model, flags, view, groupConfig,
                    viewController);
            view.addTrendViewListener(trendController);
            viewController.addChartController(trendController);
            page.setControl(view);
        }

        @Override
        public void visitDistributionChartConfig(DistributionChartConfig config) {
            assert (project != null);
            assert (folder != null);

            if (!config.show(flags)) {
                return;
            }

            TabItem page = new TabItem(folder, SWT.NONE);
            page.setText(config.getName());

            DistributionChart view = new DistributionChart(folder, SWT.NONE);
            DistributionChartController distController = new DistributionChartController(model, flags, view, config,
                    viewController);
            view.addDistributionViewListener(distController);
            viewController.addChartController(distController);
            page.setControl(view);
        }
    }

    public ViewFactory(Model model, Configuration config) {
        this.model = model;
        this.config = config;
    }

    public Composite createUserViewComposite(Composite parent, int style, Project proj, int commitDictId,
            int bugDictId, UserViewConfig config) throws SemanticException, SQLException {
        assert (config != null);
        assert (proj != null);
        assert (proj.getId() != null);

        this.flags = model.getFlags(proj);

        SashForm sash = new SashForm(parent, SWT.HORIZONTAL);
        sash.setLayout(new FillLayout());
        final UserList users = new UserList(sash, SWT.NONE, model.getUsers(proj), false);

        TabFolder folder = new TabFolder(sash, SWT.NONE);
        model.updateUserSelection(new ArrayList<Integer>());
        final HashMap<String, Object> vars = new HashMap<String, Object>();
        vars.put("project", proj.getId());
        vars.put("commitDict", commitDictId);
        vars.put("bugDict", bugDictId);
        vars.put("user", -1);

        ViewBuilder builder = new ViewBuilder();
        final ViewController viewController = builder.build(config, folder, proj, vars);

        users.addUserListListener(new UserListListener() {
            @Override
            public void selectionChanged() {
                List<Integer> selectedUsers = users.getSelectedIDs();
                assert (selectedUsers.size() <= 1);
                if (selectedUsers.size() > 0) {
                    vars.put("user", selectedUsers.get(0));
                } else {
                    vars.put("user", -1);
                }
                viewController.variableChanged();
            }
        });

        return sash;
    }

    public Composite createTeamViewComposite(Composite parent, int style, Project proj, int commitDictId,
            int bugDictId, TeamViewConfig config) throws SemanticException, SQLException {
        assert (config != null);
        assert (proj != null);
        assert (proj.getId() != null);

        this.flags = model.getFlags(proj);

        SashForm sash = new SashForm(parent, SWT.HORIZONTAL);
        sash.setLayout(new FillLayout());
        final UserList users = new UserList(sash, SWT.NONE, model.getUsers(proj), true);

        TabFolder folder = new TabFolder(sash, SWT.NONE);
        model.updateUserSelection(new ArrayList<Integer>());
        final HashMap<String, Object> vars = new HashMap<String, Object>();
        vars.put("project", proj.getId());
        vars.put("commitDict", commitDictId);
        vars.put("bugDict", bugDictId);

        ViewBuilder builder = new ViewBuilder();
        final ViewController viewController = builder.build(config, folder, proj, vars);

        users.addUserListListener(new UserListListener() {
            @Override
            public void selectionChanged() {
                try {
                    List<Integer> selectedUsers = users.getSelectedIDs();
                    model.updateUserSelection(selectedUsers);
                    viewController.variableChanged();
                    if (model.getPrintTemplates()) {
                        System.out.println("Selected Users:");
                        for (Integer id : model.getUserSelection()) {
                            System.out.println(" - " + id);
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                    assert (false);
                }
            }
        });

        return sash;
    }

    public Composite createProjectViewComposite(Composite parent, int style, Project proj, int commitDictId,
            int bugDictId, ProjectViewConfig config) throws SemanticException, SQLException {
        assert (config != null);
        assert (proj != null);
        assert (proj.getId() != null);

        this.flags = model.getFlags(proj);

        Composite composite = new Composite(parent, style);
        composite.setLayout(new FillLayout());

        TabFolder folder = new TabFolder(composite, SWT.NONE);
        HashMap<String, Object> vars = new HashMap<String, Object>();
        vars.put("project", proj.getId());
        vars.put("commitDict", commitDictId);
        vars.put("bugDict", bugDictId);

        ViewBuilder builder = new ViewBuilder();
        builder.build(config, folder, proj, vars);

        return composite;
    }

    public Configuration getConfiguration() {
        return config;
    }

    //
    // Test Method:
    //

    public static void main(String[] args) {
        Options options = new Options();
        options.addOption("h", "help", false, "Show this options");
        options.addOption("d", "db", true, "The database to process (required)");
        options.addOption("p", "project", true, "The project ID to process");
        options.addOption("P", "list-projects", false, "List all registered projects");
        options.addOption("C", "config", true, "A configuration file including reports");
        options.addOption("c", "commit-dictionary", true, "The commit dictionary ID to use");
        options.addOption("b", "bug-dictionary", true, "The bug dictionary ID to use");
        options.addOption("D", "list-dictionaries", false, "List all dictionaries");
        options.addOption("e", "db-extension", true, "Sqlite extension");
        options.addOption("v", "verbose", false, "Show details");

        Reporter reporter = new Reporter(false);
        String[] extensions = new String[0];
        ModelPool pool = null;
        Model model = null;

        CommandLineParser parser = new PosixParser();
        boolean printDetails = false;

        try {
            CommandLine cmd = parser.parse(options, args);
            printDetails = cmd.hasOption("verbose");

            if (cmd.hasOption("help")) {
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp("postprocessor", options);
                return;
            }

            if (cmd.hasOption("db-extension")) {
                extensions = cmd.getOptionValues("db-extension");
            }

            if (cmd.hasOption("db") == false) {
                reporter.error("explorer", "Option --db is required");
                reporter.printSummary();
                return;
            }

            if (cmd.hasOption("config") == false) {
                reporter.error("explorer", "Option --config is required");
                reporter.printSummary();
                return;
            }

            Configuration config = new Configuration();
            Parser configParser = new Parser();
            try {
                configParser.parse(config, new File(cmd.getOptionValue("config")));
            } catch (IOException e) {
                reporter.error("explorer", "Could not read configuration file: " + e.getMessage());
                reporter.printSummary();
                return;
            } catch (ParserException e) {
                reporter.error("explorer", "Could not parse configuration file: " + e.getMessage());
                reporter.printSummary();
                return;
            }

            File dbf = new File(cmd.getOptionValue("db"));
            if (dbf.exists() == false || dbf.isFile() == false) {
                reporter.error("explorer", "Invalid database file path");
                reporter.printSummary();
                return;
            }

            pool = new ModelPool(cmd.getOptionValue("db"), 2, extensions);
            pool.setPrintTemplates(printDetails);
            model = pool.getModel();

            if (cmd.hasOption("list-projects")) {
                for (Project proj : model.getProjects()) {
                    System.out.println("  " + proj.getId() + ": " + proj.getDate());
                }

                return;
            }

            Integer projId = null;
            if (cmd.hasOption("project") == false) {
                reporter.error("explorer", "Option --project is required");
                reporter.printSummary();
                return;
            } else {
                try {
                    projId = Integer.parseInt(cmd.getOptionValue("project"));
                } catch (NumberFormatException e) {
                    reporter.error("explorer", "Invalid project ID");
                    reporter.printSummary();
                    return;
                }
            }

            Project project = model.getProject(projId);
            if (project == null) {
                reporter.error("explorer", "Invalid project ID");
                reporter.printSummary();
                return;
            }

            if (cmd.hasOption("list-dictionaries")) {
                List<at.ac.tuwien.inso.subcat.model.Dictionary> dictionaries = model.getDictionaries(project);
                for (at.ac.tuwien.inso.subcat.model.Dictionary dict : dictionaries) {
                    System.out.println("  (" + dict.getId() + ") " + dict.getContext() + " " + dict.getName());
                }
                return;
            }

            int bugDictId = -1;
            if (cmd.hasOption("bug-dictionary")) {
                try {
                    bugDictId = Integer.parseInt(cmd.getOptionValue("bug-dictionary"));
                    List<at.ac.tuwien.inso.subcat.model.Dictionary> dictionaries = model.getDictionaries(project);
                    boolean valid = false;

                    for (at.ac.tuwien.inso.subcat.model.Dictionary dict : dictionaries) {
                        if (dict.getId() == bugDictId) {
                            valid = true;
                            break;
                        }
                    }

                    if (valid == false) {
                        reporter.error("explorer", "Invalid bug dictionary ID");
                        reporter.printSummary();
                        return;
                    }
                } catch (NumberFormatException e) {
                    reporter.error("explorer", "Invalid bug dictionary ID");
                    reporter.printSummary();
                    return;
                }
            } else {
                List<at.ac.tuwien.inso.subcat.model.Dictionary> dictionaries = model.getDictionaries(project);
                for (at.ac.tuwien.inso.subcat.model.Dictionary dict : dictionaries) {
                    if (dict.getContext().equals("bug")) {
                        bugDictId = dict.getId();
                        break;
                    }
                }
            }

            int commitDictId = -1;
            if (cmd.hasOption("commit-dictionary")) {
                try {
                    commitDictId = Integer.parseInt(cmd.getOptionValue("commit-dictionary"));
                    List<at.ac.tuwien.inso.subcat.model.Dictionary> dictionaries = model.getDictionaries(project);
                    boolean valid = false;

                    for (at.ac.tuwien.inso.subcat.model.Dictionary dict : dictionaries) {
                        if (dict.getId() == commitDictId) {
                            valid = true;
                            break;
                        }
                    }

                    if (valid == false) {
                        reporter.error("explorer", "Invalid commit dictionary ID");
                        reporter.printSummary();
                        return;
                    }
                } catch (NumberFormatException e) {
                    reporter.error("explorer", "Invalid commit dictionary ID");
                    reporter.printSummary();
                    return;
                }
            } else {
                List<at.ac.tuwien.inso.subcat.model.Dictionary> dictionaries = model.getDictionaries(project);
                for (at.ac.tuwien.inso.subcat.model.Dictionary dict : dictionaries) {
                    if (dict.getContext().equals("src")) {
                        commitDictId = dict.getId();
                        break;
                    }
                }
            }

            // UI:
            Display display = new Display();
            final Shell shell = new Shell(display);
            final StackLayout stack = new StackLayout();
            shell.setLayout(stack);

            Composite _projectControl = null;
            Composite _teamControl = null;
            Composite _userControl = null;

            if (config.getProjectViewConfig() != null) {
                ViewFactory factory = new ViewFactory(model, config);
                _projectControl = factory.createProjectViewComposite(shell, SWT.NONE, project, commitDictId,
                        bugDictId, config.getProjectViewConfig());
            }

            if (config.getTeamViewConfig() != null) {
                ViewFactory factory = new ViewFactory(model, config);
                _teamControl = factory.createTeamViewComposite(shell, SWT.NONE, project, commitDictId, bugDictId,
                        config.getTeamViewConfig());
            }

            if (config.getUserViewConfig() != null) {
                ViewFactory factory = new ViewFactory(model, config);
                _userControl = factory.createUserViewComposite(shell, SWT.NONE, project, commitDictId, bugDictId,
                        config.getUserViewConfig());
            }

            final Composite projectControl = _projectControl;
            final Composite teamControl = _teamControl;
            final Composite userControl = _userControl;

            // Menu:
            Menu menu = new Menu(shell, SWT.BAR);
            shell.setMenuBar(menu);

            MenuItem mntmNewSubmenu = new MenuItem(menu, SWT.CASCADE);
            mntmNewSubmenu.setText("Views");

            Menu viewMenu = new Menu(shell, SWT.DROP_DOWN);
            mntmNewSubmenu.setMenu(viewMenu);

            Composite defaultView = null;

            if (projectControl != null) {
                MenuItem projectRadio = new MenuItem(viewMenu, SWT.RADIO);
                projectRadio.setText("Project View");
                projectRadio.addSelectionListener(new SelectionListener() {
                    @Override
                    public void widgetDefaultSelected(SelectionEvent arg0) {
                        stack.topControl = projectControl;
                        shell.layout();
                    }

                    @Override
                    public void widgetSelected(SelectionEvent arg0) {
                        stack.topControl = projectControl;
                        shell.layout();
                    }
                });

                defaultView = projectControl;
                projectRadio.setSelection(true);
            }

            if (teamControl != null) {
                MenuItem teamRadio = new MenuItem(viewMenu, SWT.RADIO);
                teamRadio.setText("Team View");
                teamRadio.addSelectionListener(new SelectionListener() {
                    @Override
                    public void widgetDefaultSelected(SelectionEvent arg0) {
                        stack.topControl = teamControl;
                        shell.layout();
                    }

                    @Override
                    public void widgetSelected(SelectionEvent arg0) {
                        stack.topControl = teamControl;
                        shell.layout();
                    }
                });

                if (defaultView == null) {
                    defaultView = teamControl;
                    teamRadio.setSelection(true);
                }
            }

            if (userControl != null) {
                MenuItem userRadio = new MenuItem(viewMenu, SWT.RADIO);
                userRadio.setText("User View");
                userRadio.addSelectionListener(new SelectionListener() {
                    @Override
                    public void widgetDefaultSelected(SelectionEvent arg0) {
                        stack.topControl = userControl;
                        shell.layout();
                    }

                    @Override
                    public void widgetSelected(SelectionEvent arg0) {
                        stack.topControl = userControl;
                        shell.layout();
                    }
                });

                if (defaultView == null) {
                    defaultView = userControl;
                    userRadio.setSelection(true);
                }
            }

            stack.topControl = defaultView;

            // Display:
            shell.pack();
            shell.open();

            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
            display.dispose();

            /*/ UI:
            Display display = new Display ();
                
            Shell teamShell = new Shell (display, SWT.CLOSE);
            teamShell.setLayout (new FillLayout ());
                
            Shell projectShell = new Shell (display, SWT.CLOSE);
            projectShell.setLayout (new FillLayout ());
                
            projectShell.setText ("Project View");
            teamShell.setText ("Team View");
                
            if (config.getTeamViewConfig () != null) {
               ViewFactory factory = new ViewFactory (model, config);
               factory.createTeamViewComposite (teamShell, SWT.NONE, project, commitDictId, bugDictId, config.getTeamViewConfig ());
                
               teamShell.pack();
               teamShell.open ();
            } else {
               teamShell.dispose ();
            }
                
            if (config.getProjectViewConfig () != null) {
               ViewFactory factory = new ViewFactory (model, config);
               factory.createProjectViewComposite (projectShell, SWT.NONE, project, commitDictId, bugDictId, config.getProjectViewConfig ());
                
               projectShell.pack();
               projectShell.open ();
            } else {
               projectShell.dispose ();
            }
                
            teamShell.addListener (SWT.CLOSE, new Listener () {
               @Override
               public void handleEvent (Event event) {
                  teamShell.dispose ();
               }
            });
                
            projectShell.addListener (SWT.CLOSE, new Listener () {
               @Override
               public void handleEvent (Event event) {
                  projectShell.dispose ();
               }
            });
                
              while (!display.isDisposed ()) {
                 if (teamShell.isDisposed () && projectShell.isDisposed ()) {
             break;
                 }
               if (!display.readAndDispatch ()) {
                  display.sleep ();
               }
            }
                
            display.dispose();
            */
        } catch (ParseException e) {
            reporter.error("explorer", "Parsing failed: " + e.getMessage());
            if (printDetails == true) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            reporter.error("explorer", "Failed to create a database connection: " + e.getMessage());
            if (printDetails == true) {
                e.printStackTrace();
            }
        } catch (SQLException e) {
            reporter.error("explorer", "Failed to create a database connection: " + e.getMessage());
            if (printDetails == true) {
                e.printStackTrace();
            }
        } catch (SemanticException e) {
            reporter.error("explorer", "Semantic Error: " + e.getMessage());
            if (printDetails == true) {
                e.printStackTrace();
            }
        } finally {
            if (model != null) {
                model.close();
            }
            if (pool != null) {
                pool.close();
            }
        }

        reporter.printSummary();
    }
}