/**
 * <copyright>
 * 
 * Copyright (c) 2008 IBM Corporation and others.
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 * IBM - Initial API and implementation
 * 
 * </copyright>
 * 
 * $Id: GenerateHandler.java,v 1.1 2008/12/19 00:18:10 marcelop Exp $
 */
package org.eclipse.emf.codegen.ecore.genmodel.handler;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.emf.codegen.ecore.generator.Generator;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter;
import org.eclipse.emf.codegen.ecore.genmodel.presentation.GeneratorUIUtil;
import org.eclipse.emf.codegen.ecore.genmodel.presentation.TargetPlatformGeneratorUIUtil;
import org.eclipse.emf.codegen.ecore.genmodel.provider.GenModelEditPlugin;
import org.eclipse.emf.codegen.ecore.genmodel.util.GenModelUtil;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog;
import org.eclipse.ui.handlers.HandlerUtil;

/**
 * PROVISIONAL
 * This API is subject to arbitrary change, including renaming or removal.
 * 
 * @since 2.5
 */
public class TargetPlatformGenerateHandler extends AbstractHandler {

    protected static List<URI> getGenModelURIs(IProgressMonitor progressMonitor, Object[] objects) {
        if (objects.length > 0) {
            progressMonitor.beginTask(GenModelEditPlugin.INSTANCE.getString("_UI_AnalyzingObjects_message"), objects.length); //$NON-NLS-1$
            List<URI> uris = new ArrayList<URI>(objects.length);
            for (Object object : objects) {
                IFile file = null;
                if (object instanceof IFile) {
                    file = (IFile) object;
                } else if (object instanceof IAdaptable) {
                    file = (IFile) ((IAdaptable) object).getAdapter(IFile.class);
                }

                if (file != null && "genmodel".equals(file.getFileExtension())) { //$NON-NLS-1$
                    progressMonitor.subTask(file.getName());
                    URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
                    uris.add(uri);
                }
                progressMonitor.worked(1);
            }
            return uris;
        }
        return new ArrayList<URI>();
    }

    protected static class GenModelSelectionDialog extends FilteredResourcesSelectionDialog {

        protected class GenModelResourceFilter extends FilteredResourcesSelectionDialog.ResourceFilter {

            public GenModelResourceFilter(IContainer container) {
                super(container, false, IResource.FILE);
            }

            @Override
            public boolean matchItem(Object item) {
                return item instanceof IFile && "genmodel".equals(((IFile) item).getFileExtension()) && super.matchItem(item); //$NON-NLS-1$
            }

        }

        protected IContainer container;

        protected IStatus status;

        protected StatusLineManager statusLineManager;

        protected List<GenModel> genModels;

        protected Point size;

        protected Point location;

        public GenModelSelectionDialog(Shell shell, boolean multi, IContainer container, int typesMask) {
            super(shell, multi, container, typesMask);
            this.container = container;
        }

        public void initialize(Point innerSize, Point innerLocation) {
            this.size = innerSize;
            this.location = innerLocation;
        }

        public List<GenModel> getGenModels() {
            if (genModels == null) {
                genModels = new ArrayList<GenModel>();
            }
            return genModels;
        }

        public Point getSize() {
            return size;
        }

        public Point getLocation() {
            return location;
        }

        @Override
        protected void configureShell(Shell newShell) {
            super.configureShell(newShell);
            if (size != null) {
                newShell.setSize(size);
            }
            if (location != null) {
                newShell.setLocation(location);
            }
        }

        @Override
        public void create() {
            super.create();

            if (size != null) {
                Point shellSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
                getShell().setSize(Math.max(shellSize.x, size.x), size.y);
            }
            if (location != null) {
                getShell().setLocation(location);
            }
        }

        @Override
        protected Control createDialogArea(Composite parent) {

            Composite composite = (Composite) super.createDialogArea(parent);

            statusLineManager = new StatusLineManager();
            statusLineManager.createControl(composite);
            statusLineManager.setCancelEnabled(true);
            GridData gridData = new GridData();
            gridData.horizontalAlignment = GridData.FILL;
            gridData.grabExcessHorizontalSpace = true;
            gridData.heightHint = convertVerticalDLUsToPixels(9);
            statusLineManager.getControl().setLayoutData(gridData);

            return composite;

        }

        @Override
        protected void createButtonsForButtonBar(Composite parent) {
            super.createButtonsForButtonBar(parent);

            Button okButton = getOkButton();
            okButton.setText(IDialogConstants.NEXT_LABEL);

            Button button = createButton(parent, IDialogConstants.BACK_ID, IDialogConstants.BACK_LABEL, false);
            button.moveAbove(okButton);
            button.setEnabled(false);
            button = createButton(parent, IDialogConstants.FINISH_ID, IDialogConstants.FINISH_LABEL, false);
            button.moveBelow(okButton);
            button.setEnabled(false);
        }

        @Override
        protected ItemsFilter createFilter() {
            return new GenModelResourceFilter(container);
        }

        @Override
        protected void updateStatus(IStatus innerStatus) {
            this.status = innerStatus;
            super.updateStatus(innerStatus);
        }

        @Override
        protected void cancelPressed() {
            super.cancelPressed();
        }

        @Override
        public boolean close() {
            location = getShell().getLocation();
            size = getShell().getSize();

            return super.close();
        }

        @Override
        protected void okPressed() {
            if (status != null && (status.isOK() || status.getCode() == IStatus.INFO)) {
                computeResult();

                IProgressMonitor progressMonitor = statusLineManager.getProgressMonitor();
                progressMonitor.beginTask("", 10); //$NON-NLS-1$
                List<URI> uris = getGenModelURIs(new SubProgressMonitor(progressMonitor, 3, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK), getResult());
                List<GenModel> innerGenModels = TargetPlatformGeneratorUIUtil.loadGenModels(new SubProgressMonitor(progressMonitor, 7), uris, getShell());
                progressMonitor.done();

                if (!innerGenModels.isEmpty()) {
                    getGenModels().addAll(innerGenModels);
                    close();
                }
            }
        }
    }

    protected static class GenModelGenerationDialog extends TrayDialog {

        protected enum ProjectType {
            MODEL {

                @Override
                public String getID() {
                    return GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE;
                }

                @Override
                public String getLabel() {
                    return GenModelEditPlugin.INSTANCE.getString("_UI_Model_title"); //$NON-NLS-1$
                }

                @Override
                public boolean canGenerate(GenModel genModel) {
                    return genModel.canGenerate();
                }
            },

            EDIT {

                @Override
                public String getID() {
                    return GenBaseGeneratorAdapter.EDIT_PROJECT_TYPE;
                }

                @Override
                public String getLabel() {
                    return GenModelEditPlugin.INSTANCE.getString("_UI_Edit_title"); //$NON-NLS-1$
                }

                @Override
                public boolean canGenerate(GenModel genModel) {
                    return genModel.canGenerateEdit();
                }
            },

            EDITOR {

                @Override
                public String getID() {
                    return GenBaseGeneratorAdapter.EDITOR_PROJECT_TYPE;
                }

                @Override
                public String getLabel() {
                    return GenModelEditPlugin.INSTANCE.getString("_UI_Editor_title"); //$NON-NLS-1$
                }

                @Override
                public boolean canGenerate(GenModel genModel) {
                    return genModel.canGenerateEditor();
                }
            },

            TESTS {

                @Override
                public String getID() {
                    return GenBaseGeneratorAdapter.TESTS_PROJECT_TYPE;
                }

                @Override
                public String getLabel() {
                    return GenModelEditPlugin.INSTANCE.getString("_UI_Tests_title"); //$NON-NLS-1$
                }

                @Override
                public boolean canGenerate(GenModel genModel) {
                    return genModel.canGenerateTests();
                }
            };

            public abstract boolean canGenerate(GenModel genModel);

            public abstract String getID();

            public abstract String getLabel();
        }

        protected List<GenModel> genModels;

        protected List<Object[]> generatorAndArgumentsList;

        protected boolean startWithProjectSelected = true;

        protected Point size;

        protected Point location;

        protected Table genModelTable;

        protected CLabel genModelLabel;

        protected boolean showBackButton = false;

        public GenModelGenerationDialog(Shell shell, List<GenModel> genModels) {
            super(shell);
            this.genModels = genModels;
            setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
        }

        public boolean isShowBackButton() {
            return showBackButton;
        }

        public void setShowBackButton(boolean showBackButton) {
            this.showBackButton = showBackButton;
        }

        public List<Object[]> getGeneratorAndArgumentsList() {
            if (generatorAndArgumentsList == null) {
                generatorAndArgumentsList = new ArrayList<Object[]>();
            }
            return generatorAndArgumentsList;
        }

        public void initialize(Point innerSize, Point innerLocation) {
            this.size = innerSize;
            this.location = innerLocation;
        }

        public Point getSize() {
            return size;
        }

        public Point getLocation() {
            return location;
        }

        @Override
        protected void configureShell(Shell newShell) {
            super.configureShell(newShell);
            newShell.setText(GenModelEditPlugin.INSTANCE.getString("_UI_GenModelGenerationDialog_title")); //$NON-NLS-1$
        }

        @Override
        public void create() {
            super.create();

            if (size != null) {
                Point shellSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
                getShell().setSize(Math.max(shellSize.x, size.x), size.y);
            }
            if (location != null) {
                getShell().setLocation(location);
            }

            if (genModelTable.getSelectionCount() == 0) {
                genModelTable.select(0);
                selectionChanged((GenModel) genModelTable.getItem(0).getData());
            }
        }

        @Override
        protected Control createDialogArea(Composite parent) {
            Composite composite = (Composite) super.createDialogArea(parent);
            createControls(composite);
            refresh();
            return composite;
        }

        protected void createControls(Composite parent) {
            createTable(parent);
            createGenModelDetailControl(parent);
        }

        @Override
        protected void createButtonsForButtonBar(Composite parent) {
            if (isShowBackButton()) {
                Button backButton = createButton(parent, IDialogConstants.BACK_ID, IDialogConstants.BACK_LABEL, false);
                Listener backButtonListener = new Listener() {

                    public void handleEvent(Event event) {
                        setReturnCode(IDialogConstants.BACK_ID);
                        close();
                    }
                };
                backButton.addListener(SWT.Selection, backButtonListener);

                Button button = createButton(parent, IDialogConstants.NEXT_ID, IDialogConstants.NEXT_LABEL, false);
                button.setEnabled(false);
            }

            super.createButtonsForButtonBar(parent);

            if (isShowBackButton()) {
                getButton(IDialogConstants.OK_ID).setText(IDialogConstants.FINISH_LABEL);
            }

            updateButtons(false);
        }

        protected void createTable(Composite parent) {
            CLabel label = new CLabel(parent, SWT.NONE);
            label.setText(GenModelEditPlugin.INSTANCE.getString("_UI_GenModelGenerationDialog_message")); //$NON-NLS-1$

            genModelTable = new Table(parent, SWT.BORDER);
            genModelTable.setLinesVisible(true);
            genModelTable.setHeaderVisible(true);
            GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
            genModelTable.setLayoutData(gridData);

            Listener tableListener = new Listener() {

                public void handleEvent(Event event) {
                    if (genModelTable.getSelectionCount() == 1) {
                        if (event.type == SWT.MouseDoubleClick) {
                            Boolean select = null;
                            TableColumn[] tableColumns = genModelTable.getColumns();
                            for (int i = 1; i < tableColumns.length; i++) {
                                select = checkBoxColumnHeaderSelected(tableColumns[i], genModelTable.getSelectionIndex(), select);
                            }
                            updateButtons(select);
                        }
                        TableItem tableItem = genModelTable.getSelection()[0];
                        selectionChanged((GenModel) tableItem.getData());
                    }
                }
            };
            genModelTable.addListener(SWT.Selection, tableListener);
            genModelTable.addListener(SWT.MouseDoubleClick, tableListener);

            TableColumn genModelColumn = new TableColumn(genModelTable, SWT.NONE);
            genModelColumn.setText(GenModelEditPlugin.INSTANCE.getString("_UI_GenModelFile_title")); //$NON-NLS-1$

            Listener genModelColumnListener = new Listener() {

                public void handleEvent(Event event) {
                    Boolean select = null;
                    TableColumn[] tableColumns = genModelTable.getColumns();
                    for (int i = 1; i < tableColumns.length; i++) {
                        select = checkBoxColumnHeaderSelected(tableColumns[i], -1, select);
                    }
                    updateButtons(select);
                }
            };
            genModelColumn.addListener(SWT.Selection, genModelColumnListener);

            Listener checkBoxColumnListener = new Listener() {

                public void handleEvent(Event event) {
                    TableColumn tableColumn = (TableColumn) event.widget;
                    Boolean select = checkBoxColumnHeaderSelected(tableColumn, -1, null);
                    updateButtons(select);
                }
            };

            int maxWidth = 0;
            for (ProjectType projectType : ProjectType.values()) {
                maxWidth = Math.max(maxWidth, createCheckBoxColumn(projectType, checkBoxColumnListener));
            }

            TableColumn[] tableColumns = genModelTable.getColumns();
            for (int i = 1; i < tableColumns.length; i++) {
                tableColumns[i].setWidth(maxWidth);
            }
        }

        protected int createCheckBoxColumn(ProjectType projectType, Listener listener) {
            TableColumn tableColumn = new TableColumn(genModelTable, SWT.NONE);
            tableColumn.setText("  " + projectType.getLabel() + "  "); //$NON-NLS-1$ //$NON-NLS-2$
            tableColumn.setData("type", projectType); //$NON-NLS-1$
            tableColumn.setResizable(false);
            tableColumn.pack();
            tableColumn.addListener(SWT.Selection, listener);
            return tableColumn.getWidth();
        }

        protected Boolean checkBoxColumnHeaderSelected(TableColumn tableColumn, int itemIndex, Boolean select) {
            @SuppressWarnings("unchecked")
            List<Button> buttons = (List<Button>) tableColumn.getData("buttons"); //$NON-NLS-1$
            if (buttons != null && !buttons.isEmpty()) {
                if (itemIndex > -1) {
                    buttons = buttons.subList(itemIndex, itemIndex + 1);
                }

                for (Button button : buttons) {
                    if (button.isEnabled()) {
                        if (select == null) {
                            select = !button.getSelection();
                        }
                        button.setSelection(select);
                    }
                }
            }
            return select;
        }

        protected void selectionChanged(GenModel genModel) {
            StringBuilder text = new StringBuilder();
            for (GenPackage genPackage : genModel.getGenPackages()) {
                text.append(", ").append(genPackage.getEcorePackage().getNsURI()); //$NON-NLS-1$
            }
            Image image = ExtendedImageRegistry.INSTANCE.getImage(URI.createPlatformPluginURI("/org.eclipse.emf.ecore.edit/icons/full/obj16/EPackage.gif", false)); //$NON-NLS-1$
            genModelLabel.setImage(image);
            genModelLabel.setText(text.substring(", ".length())); //$NON-NLS-1$
        }

        protected void refresh() {
            genModelLabel.setText(""); //$NON-NLS-1$
            genModelTable.clearAll();

            TableColumn[] tableColumns = genModelTable.getColumns();
            for (int i = 1; i < tableColumns.length; i++) {
                @SuppressWarnings("unchecked")
                List<Button> buttons = (List<Button>) tableColumns[i].getData("buttons"); //$NON-NLS-1$
                if (buttons != null) {
                    for (Button button : buttons) {
                        button.dispose();
                    }
                    buttons.clear();
                } else {
                    tableColumns[i].setData("buttons", new ArrayList<Button>()); //$NON-NLS-1$
                }
            }

            for (GenModel genModel : genModels) {
                TableItem tableItem = new TableItem(genModelTable, SWT.NONE);
                tableItem.setText(0, genModel.eResource().getURI().toPlatformString(true) + "   "); //$NON-NLS-1$
                tableItem.setImage(ExtendedImageRegistry.INSTANCE.getImage(URI.createPlatformPluginURI("/org.eclipse.emf.codegen.ecore.ui/icons/full/obj16/GenModel.gif", false))); //$NON-NLS-1$
                tableItem.setData(genModel);

                for (int i = 1; i < tableColumns.length; i++) {
                    TableColumn tableColumn = tableColumns[i];
                    ProjectType projectType = (ProjectType) tableColumn.getData("type"); //$NON-NLS-1$

                    Button button = new Button(genModelTable, SWT.CHECK);
                    if (projectType.canGenerate(genModel)) {
                        button.setSelection(startWithProjectSelected);
                    } else {
                        button.setEnabled(false);
                    }
                    button.pack();

                    Listener buttonListener = new Listener() {

                        public void handleEvent(Event event) {
                            updateButtons(((Button) event.widget).getSelection());
                        }
                    };
                    button.addListener(SWT.Selection, buttonListener);

                    @SuppressWarnings("unchecked")
                    List<Button> buttons = (List<Button>) tableColumn.getData("buttons"); //$NON-NLS-1$
                    buttons.add(button);

                    TableEditor editor = new TableEditor(genModelTable);
                    editor.minimumWidth = button.getSize().x;
                    editor.horizontalAlignment = SWT.CENTER;
                    editor.setEditor(button, tableItem, i);
                }
            }
            tableColumns[0].pack();
            updateButtons(false);
        }

        protected void createGenModelDetailControl(Composite parent) {
            ViewForm viewForm = new ViewForm(parent, SWT.BORDER | SWT.FLAT);
            viewForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

            genModelLabel = new CLabel(viewForm, SWT.FLAT);
            genModelLabel.setFont(parent.getFont());
            genModelLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
            genModelLabel.setToolTipText(GenModelEditPlugin.INSTANCE.getString("_UI_GenModelGenerationDetail_message")); //$NON-NLS-1$
            genModelLabel.pack();

            viewForm.setContent(genModelLabel);
        }

        @Override
        protected void okPressed() {
            getGeneratorAndArgumentsList().addAll(prepareGenerators());
            super.okPressed();
        }

        protected void updateButtons(Boolean hasSelection) {
            Button okButton = getButton(IDialogConstants.OK_ID);
            if (okButton != null) {
                if (hasSelection == null) {
                    hasSelection = false;
                } else if (!hasSelection) {
                    TableColumn[] tableColumns = genModelTable.getColumns();
                    LOOP: for (int column = 1; column < tableColumns.length; column++) {
                        @SuppressWarnings("unchecked")
                        List<Button> buttons = (List<Button>) tableColumns[column].getData("buttons"); //$NON-NLS-1$
                        for (Button button : buttons) {
                            hasSelection |= button.isEnabled() && button.getSelection();
                            if (hasSelection) {
                                break LOOP;
                            }
                        }
                    }
                }
                okButton.setEnabled(hasSelection);
            }
        }

        @Override
        public boolean close() {
            location = getShell().getLocation();
            size = getShell().getSize();

            return super.close();
        }

        protected List<Object[]> prepareGenerators() {
            TableColumn[] tableColumns = genModelTable.getColumns();
            TableItem[] tableItems = genModelTable.getItems();
            List<Object[]> innerGeneratorAndArgumentsList = new ArrayList<Object[]>(tableItems.length * (tableColumns.length - 1));
            for (int line = 0; line < tableItems.length; line++) {
                GenModel genModel = (GenModel) tableItems[line].getData();
                for (int column = 1; column < tableColumns.length; column++) {
                    @SuppressWarnings("unchecked")
                    Button button = ((List<Button>) tableColumns[column].getData("buttons")).get(line); //$NON-NLS-1$
                    if (button.isEnabled() && button.getSelection()) {
                        ProjectType projectType = (ProjectType) tableColumns[column].getData("type"); //$NON-NLS-1$

                        Generator generator = GenModelUtil.createGenerator(genModel);

                        Object[] generatorAndArguments = new Object[4];
                        generatorAndArguments[0] = generator;
                        generatorAndArguments[1] = genModel;
                        generatorAndArguments[2] = projectType.getID();
                        generatorAndArguments[3] = projectType.getLabel();
                        innerGeneratorAndArgumentsList.add(generatorAndArguments);
                    }
                }
            }
            return innerGeneratorAndArgumentsList;
        }
    }

    protected Point dialogSize = null;

    protected Point dialogLocation = null;

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {
        Shell shell = HandlerUtil.getActiveShell(event);
        List<GenModel> genModels = null;

        boolean usingSelection = false;
        ISelection selection = HandlerUtil.getCurrentSelection(event);
        if (selection instanceof IStructuredSelection) {
            Object[] selectedObjects = ((IStructuredSelection) selection).toArray();
            if (selectedObjects.length >= 1) {
                IProgressMonitor progressMonitor = new NullProgressMonitor();
                List<URI> uris = getGenModelURIs(progressMonitor, selectedObjects);
                if (uris.isEmpty() == false) {
                    genModels = TargetPlatformGeneratorUIUtil.loadGenModels(progressMonitor, uris, shell);
                    if (genModels.isEmpty()) {
                        return null;
                    }
                    usingSelection = true;
                }
            }
        }

        if (usingSelection == false) {
            GenModelSelectionDialog selectionDialog = new GenModelSelectionDialog(shell, true, ResourcesPlugin.getWorkspace().getRoot(), IResource.FILE);
            selectionDialog.initialize(dialogSize, dialogLocation);
            selectionDialog.setTitle(GenModelEditPlugin.INSTANCE.getString("_UI_GenModelSelectionDialog_title")); //$NON-NLS-1$
            selectionDialog.setInitialPattern("*.genmodel"); //$NON-NLS-1$

            if (selectionDialog.open() == Window.OK) {
                dialogSize = selectionDialog.getSize();
                dialogLocation = selectionDialog.getLocation();
                genModels = selectionDialog.getGenModels();
            }
        }

        if (genModels != null && genModels.isEmpty() == false) {
            GenModelGenerationDialog generationDialog = new GenModelGenerationDialog(shell, genModels);
            generationDialog.setShowBackButton(!usingSelection);
            generationDialog.initialize(dialogSize, dialogLocation);
            int ret = generationDialog.open();
            if (ret == Window.OK) {
                try {
                    new ProgressMonitorDialog(shell).run(true, true, new GeneratorUIUtil.GeneratorOperation(shell, generationDialog.getGeneratorAndArgumentsList()));
                } catch (Exception exception) {
                    GenModelEditPlugin.INSTANCE.log(exception);
                }
            } else if (ret == IDialogConstants.BACK_ID) {
                dialogSize = generationDialog.getSize();
                dialogLocation = generationDialog.getLocation();
                execute(event);
            }
        }

        return null;
    }
}
