de.quamoco.qm.editor.CustomQmEditor.java Source code

Java tutorial

Introduction

Here is the source code for de.quamoco.qm.editor.CustomQmEditor.java

Source

/*-------------------------------------------------------------------------+
|                                                                          |
| Copyright 2012 Technische Universitaet Muenchen and                      |
| Fraunhofer-Institut fuer Experimentelles Software Engineering (IESE)     |
|                                                                          |
| Licensed under the Apache License, Version 2.0 (the "License");          |
| you may not use this file except in compliance with the License.         |
| You may obtain a copy of the License at                                  |
|                                                                          |
|    http://www.apache.org/licenses/LICENSE-2.0                            |
|                                                                          |
| Unless required by applicable law or agreed to in writing, software      |
| distributed under the License is distributed on an "AS IS" BASIS,        |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and      |
| limitations under the License.                                           |
|                                                                          |
+-------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------+
 $Id: CustomQmEditor.java 4974 2012-02-17 09:34:10Z lochmann $
 |                                                                          |
 | Copyright 2005-2010 Technische Universitaet Muenchen                     |
 |                                                                          |
 | Licensed under the Apache License, Version 2.0 (the "License");          |
 | you may not use this file except in compliance with the License.         |
 | You may obtain a copy of the License at                                  |
 |                                                                          |
 |    http://www.apache.org/licenses/LICENSE-2.0                            |
 |                                                                          |
 | Unless required by applicable law or agreed to in writing, software      |
 | distributed under the License is distributed on an "AS IS" BASIS,        |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
 | See the License for the specific language governing permissions and      |
 | limitations under the License.                                           |
 +--------------------------------------------------------------------------*/
package de.quamoco.qm.editor;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.ui.ViewerPane;
import org.eclipse.emf.common.ui.dialogs.WorkspaceResourceDialog;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edapt.common.URIUtils;
import org.eclipse.emf.edapt.history.Release;
import org.eclipse.emf.edapt.migration.MigrationException;
import org.eclipse.emf.edapt.migration.ReleaseUtils;
import org.eclipse.emf.edapt.migration.execution.Migrator;
import org.eclipse.emf.edapt.migration.execution.MigratorRegistry;
import org.eclipse.emf.edit.command.CreateChildCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.util.EditUIUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.INavigationLocationProvider;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ISection;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;

import de.quamoco.qm.Entity;
import de.quamoco.qm.Factor;
import de.quamoco.qm.QmPackage;
import de.quamoco.qm.QualityModelResult;
import de.quamoco.qm.editor.action.ShowResultTreeMapAction;
import de.quamoco.qm.editor.pages.EntityHierarchyViewerPane;
import de.quamoco.qm.editor.pages.EntityTableViewerPane;
import de.quamoco.qm.editor.pages.FactorHierarchyViewerPane;
import de.quamoco.qm.editor.pages.FactorTableViewerPane;
import de.quamoco.qm.editor.pages.MeasureTableViewerPane;
import de.quamoco.qm.editor.pages.SelectionViewerPane;
import de.quamoco.qm.presentation.QmEditor;
import de.quamoco.qm.presentation.QmEditorPlugin;
import de.quamoco.qm.provider.QmItemProviderAdapterFactory;
import edu.tum.cs.emf.commons.cache.Cache;
import edu.tum.cs.emf.commons.sections.FeaturePropertySectionBase;
import edu.tum.cs.emf.commons.sections.ILocator;
import edu.tum.cs.emf.commons.validation.ResourceSetValidation;
import edu.tum.cs.emf.commons.validation.Validation;
import edu.tum.cs.emf.commons.validation.view.DefaultValidatedEditor;
import edu.tum.cs.emf.commons.validation.view.IValidatedEditor;

/**
 * Customized quality model editor
 * 
 * @author herrmama
 * @author $Author: lochmann $
 * @version $Rev: 4974 $
 * @levd.rating YELLOW Hash: 6F3AFB38C97EFCE342DC02A4ED879282
 */
public class CustomQmEditor extends QmEditor
        implements ITabbedPropertySheetPageContributor, INavigationLocationProvider, ILocator {

    /** This is the property sheet page. */
    protected TabbedPropertySheetPage customPropertySheetPage;

    /**
     * Adapter used to update the problem indication when resources are demanded
     * loaded. <!-- begin-user-doc --> <!-- end-user-doc -->
     * 
     * @generated
     */
    protected EContentAdapter problemIndicationAdapter = new EContentAdapter() {
        @Override
        public void notifyChanged(Notification notification) {
            if (notification.getNotifier() instanceof Resource) {
                switch (notification.getFeatureID(Resource.class)) {
                case Resource.RESOURCE__IS_LOADED:
                    showResultTreeMap((Resource) notification.getNotifier());
                case Resource.RESOURCE__ERRORS:
                case Resource.RESOURCE__WARNINGS: {
                    Resource resource = (Resource) notification.getNotifier();
                    Diagnostic diagnostic = analyzeResourceProblems(resource, null);
                    if (diagnostic.getSeverity() != Diagnostic.OK) {
                        resourceToDiagnosticMap.put(resource, diagnostic);
                    } else {
                        resourceToDiagnosticMap.remove(resource);
                    }

                    if (updateProblemIndication) {
                        getSite().getShell().getDisplay().asyncExec(new Runnable() {
                            public void run() {
                                updateProblemIndication();
                            }
                        });
                    }
                    break;
                }
                }
            } else {
                super.notifyChanged(notification);
            }
        }

        @Override
        protected void setTarget(Resource target) {
            basicSetTarget(target);
        }

        @Override
        protected void unsetTarget(Resource target) {
            basicUnsetTarget(target);
        }
    };

    /** {@inheritDoc} */
    @Override
    protected void initializeEditingDomain() {
        // Create an adapter factory that yields item providers.
        //
        adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);

        adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
        adapterFactory.addAdapterFactory(new QmItemProviderAdapterFactory());
        adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());

        // Create the command stack that will notify this editor as commands are
        // executed.
        //
        BasicCommandStack commandStack = new BasicCommandStack();

        // Add a listener to set the most recent command's affected objects to
        // be the selection of the viewer with focus.
        //
        commandStack.addCommandStackListener(new CommandStackListener() {
            public void commandStackChanged(final EventObject event) {
                getContainer().getDisplay().asyncExec(new Runnable() {
                    public void run() {
                        firePropertyChange(IEditorPart.PROP_DIRTY);

                        // Try to select the affected objects.
                        //
                        CommandStack commandStack = (CommandStack) event.getSource();
                        Command mostRecentCommand = commandStack.getMostRecentCommand();
                        if (isCreate(mostRecentCommand) || isUndo(commandStack, mostRecentCommand)) {
                            setFocus();
                            setSelectionToViewer(mostRecentCommand.getAffectedObjects());
                        }
                        if (customPropertySheetPage != null && !customPropertySheetPage.getControl().isDisposed()
                                && customPropertySheetPage.getCurrentTab() != null) {
                            customPropertySheetPage.refresh();
                        }

                        if (isCreate(mostRecentCommand) && !isUndo(commandStack, mostRecentCommand)) {
                            enterTextField();
                        }
                    }

                    private boolean isCreate(Command command) {
                        if (command == null) {
                            return false;
                        }
                        if (command instanceof CompoundCommand) {
                            CompoundCommand compound = (CompoundCommand) command;
                            for (Command subCommand : compound.getCommandList()) {
                                if (isCreate(subCommand)) {
                                    return true;
                                }
                            }
                        }
                        return command instanceof CreateChildCommand;
                    }

                    private boolean isUndo(CommandStack commandStack, Command command) {
                        if (command == null) {
                            return false;
                        }
                        return command == commandStack.getRedoCommand();
                    }
                });
            }
        });

        // Create the editing domain with a special command stack.
        editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack,
                new HashMap<Resource, Boolean>());
    }

    /** Show the result in a tree map. */
    protected void showResultTreeMap(Resource resource) {
        if (!resource.getContents().isEmpty() && resource.getContents().get(0) instanceof QualityModelResult) {
            EcoreUtil.resolveAll(resource);
            QualityModelResult modelResult = (QualityModelResult) resource.getContents().get(0);
            ShowResultTreeMapAction.showResultTreeMap(modelResult, this);
        }
    }

    /** Enter the first text field in the properties view. */
    @SuppressWarnings("unchecked")
    private void enterTextField() {
        Display.getDefault().asyncExec(new Runnable() {

            public void run() {
                if (customPropertySheetPage == null || customPropertySheetPage.getCurrentTab() == null) {
                    return;
                }
                for (ISection section : customPropertySheetPage.getCurrentTab().getSections()) {
                    if (section instanceof FeaturePropertySectionBase) {
                        final FeaturePropertySectionBase featureSection = (FeaturePropertySectionBase) section;
                        if (featureSection.getFeature() == QmPackage.Literals.NAMED_ELEMENT__NAME) {
                            customPropertySheetPage.setFocus();
                            featureSection.setFocus();
                        }

                        return;
                    }
                }
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void createModel() {
        final URI resourceURI = EditUIUtil.getURI(getEditorInput());
        Exception exception = null;
        Resource resource = null;

        checkMigration(resourceURI);

        try {
            // Load the resource through the editing domain.
            resource = editingDomain.getResourceSet().getResource(resourceURI, true);
        } catch (Exception e) {
            exception = e;
            resource = editingDomain.getResourceSet().getResource(resourceURI, false);
        }

        EcoreUtil.resolveAll(getEditingDomain().getResourceSet());

        Diagnostic diagnostic = analyzeResourceProblems(resource, exception);
        if (diagnostic.getSeverity() != Diagnostic.OK) {
            resourceToDiagnosticMap.put(resource, analyzeResourceProblems(resource, exception));
        }
        editingDomain.getResourceSet().eAdapters().add(problemIndicationAdapter);
    }

    /** Perform migration of the model if necessary. */
    private void checkMigration(final URI resourceURI) {
        String nsURI = ReleaseUtils.getNamespaceURI(resourceURI);
        final Migrator migrator = MigratorRegistry.getInstance().getMigrator(nsURI);
        if (migrator != null) {
            final Release release = migrator.getRelease(resourceURI).iterator().next();
            if (!release.isLatestRelease()) {
                IFile[] files = WorkspaceResourceDialog.openFileSelection(Display.getDefault().getActiveShell(),
                        "Select Files", "Select the files that need to be migrated together", true,
                        new Object[] { URIUtils.getFile(resourceURI) }, Collections.<ViewerFilter>emptyList());
                if (files.length == 0) {
                    return;
                }
                final List<URI> uris = new ArrayList<URI>();
                for (IFile file : files) {
                    uris.add(URIUtils.getURI(file));
                }
                IRunnableWithProgress runnable = new IRunnableWithProgress() {

                    public void run(IProgressMonitor monitor) throws InvocationTargetException {
                        try {
                            ResourceSet resourceSet = migrator.migrateAndLoad(uris, release, null, monitor);
                            editingDomain.getResourceSet().getResources().addAll(resourceSet.getResources());
                        } catch (MigrationException e) {
                            throw new InvocationTargetException(e);
                        }
                    }

                };
                try {
                    new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(false, false, runnable);
                } catch (InvocationTargetException e) {
                    MessageDialog.openError(Display.getDefault().getActiveShell(), "Migration error",
                            "An error occured during migration of the model. More information on the error can be found in the error log.");
                    QmEditorPlugin.getPlugin().log(e.getCause());
                } catch (InterruptedException e) {
                    QmEditorPlugin.getPlugin().log(e);
                }
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void createPages() {
        // Creates the model from the editor input
        createModel();

        // Only creates the other pages if there is something that can be edited
        if (!getEditingDomain().getResourceSet().getResources().isEmpty()) {

            createDefaultTree();

            createFactorHierarchyTree();
            createEntityHierarchyTree();

            createFactorTable();
            createEntityTable();
            createMeasureTable();

            updateProblemIndication();
        }
    }

    private boolean open = true;

    private int selectionPageIndex;

    /** {@inheritDoc} */
    @Override
    protected void handleActivate() {
        super.handleActivate();

        if (open) {
            for (Resource r : getEditingDomain().getResourceSet().getResources()) {
                showResultTreeMap(r);
            }
            open = false;
        }
    }

    /** Create the default tree view. */
    private void createDefaultTree() {
        SelectionViewerPane selectionViewerPane = new SelectionViewerPane(this);
        selectionViewerPane.createControl(getContainer());

        selectionViewer = selectionViewerPane.getViewer();
        createContextMenuFor(selectionViewer);

        selectionPageIndex = addPage(selectionViewerPane.getControl());
        setPageText(selectionPageIndex, QmEditorPlugin.INSTANCE.getString("_UI_SelectionPage_label"));
    }

    /** Activates the selection viewer pane */
    public void activateSelectionViewerPane() {
        setActivePage(selectionPageIndex);
    }

    /** Create the tree to show the factor hierarchy. */
    private void createFactorHierarchyTree() {
        FactorHierarchyViewerPane factorHierarchyPane = new FactorHierarchyViewerPane(this);

        addViewerPane(factorHierarchyPane, "Factor Hierarchy");
    }

    /** Create the tree to show the entity hierarchy. */
    private void createEntityHierarchyTree() {
        EntityHierarchyViewerPane entityHierarchyPane = new EntityHierarchyViewerPane(this);
        addViewerPane(entityHierarchyPane, "Entity Hierarchy");
    }

    /** Create the table to list all factors. */
    private void createFactorTable() {
        FactorTableViewerPane tableViewerPane = new FactorTableViewerPane(this);

        addViewerPane(tableViewerPane, "Factor List");

        createContextMenuFor(
                tableViewerPane.getViewer().getMainViewer().getQmTableViewer().getDelegateTableViewer());
    }

    /** Create the table to list all entities. */
    private void createEntityTable() {
        EntityTableViewerPane tableViewerPane = new EntityTableViewerPane(this);

        addViewerPane(tableViewerPane, "Entity List");

        createContextMenuFor(tableViewerPane.getViewer().getQmTableViewer().getDelegateTableViewer());
    }

    /** Create the table to list all measures. */
    private void createMeasureTable() {
        MeasureTableViewerPane tableViewerPane = new MeasureTableViewerPane(this);

        addViewerPane(tableViewerPane, "Measure List");

        createContextMenuFor(tableViewerPane.getViewer().getQmTableViewer().getDelegateTableViewer());
    }

    /** Adds a viewer pane to the editor view with the specified title. */
    public void addViewerPane(ViewerPane viewerPane, String title) {
        viewerPane.createControl(getContainer());

        int selectionPageIndex = addPage(viewerPane.getControl());
        setPageText(selectionPageIndex, title);
    }

    /** {@inheritDoc} */
    public String getContributorId() {
        return getSite().getId();
    }

    /** {@inheritDoc} */
    @Override
    public IPropertySheetPage getPropertySheetPage() {
        customPropertySheetPage = new TabbedPropertySheetPage(this);
        return customPropertySheetPage;
    }

    /** {@inheritDoc} */
    public INavigationLocation createEmptyNavigationLocation() {
        return createNavigationLocation();
    }

    /** {@inheritDoc} */
    public INavigationLocation createNavigationLocation() {
        return new QmNavigationLocation(CustomQmEditor.this);
    }

    /** {@inheritDoc} */
    @Override
    public void setSelection(ISelection selection) {
        super.setSelection(selection);

        List<String> uris = getSelectedURIs();
        if (!uris.isEmpty()) {
            if (isCreated()) {
                getSite().getPage().getNavigationHistory().markLocation(this);
            }
        }
    }

    /** Checks whether the editor is created. */
    private boolean isCreated() {
        return getPageCount() > 0;
    }

    /** Set selection based on a list of URIs. */
    public void setSelection(List<String> uris) {
        List<Object> elements = new ArrayList<Object>();
        for (String uri : uris) {
            ResourceSet resourceSet = editingDomain.getResourceSet();
            try {
                EObject element = resourceSet.getEObject(URI.createURI(uri), true);
                if (element != null) {
                    elements.add(element);
                }
            } catch (NullPointerException e) {
                Resource resource = resourceSet.getResource(URI.createURI(uri), true);
                if (resource != null) {
                    elements.add(resource);
                }
            }
        }

        getViewer().setSelection(new StructuredSelection(elements), true);
    }

    /** Get the identifiers of the selected elements. */
    public List<String> getSelectedURIs() {
        List<String> elements = new ArrayList<String>();
        IStructuredSelection structuredSelection = (IStructuredSelection) getSelection();
        for (Iterator<?> i = structuredSelection.iterator(); i.hasNext();) {
            Object object = i.next();
            if (object instanceof Resource) {
                Resource resource = (Resource) object;
                elements.add(resource.getURI().toString());
            } else if (object instanceof EObject) {
                EObject element = (EObject) object;
                elements.add(EcoreUtil.getURI(element).toString());
            }
        }
        return elements;
    }

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    @Override
    public void locate(List values) {
        getViewer().setSelection(new StructuredSelection(values), true);

        int successfullSelections = ((IStructuredSelection) getViewer().getSelection()).size();
        if (successfullSelections < values.size()) {
            if (allOfType(values, Factor.class)) {
                setActivePage(1);
            } else if (allOfType(values, Entity.class)) {
                setActivePage(2);
            } else {
                setActivePage(0);
            }
            getViewer().setSelection(new StructuredSelection(values), true);
        }
    }

    /** Check whether all elements in the list are instances of a certain type. */
    @SuppressWarnings("unchecked")
    private boolean allOfType(List values, Class type) {
        for (Object value : values) {
            if (!type.isInstance(value)) {
                return false;
            }
        }
        return true;
    }

    /** {@inheritDoc} */
    @Override
    protected void updateProblemIndication() {
        super.updateProblemIndication();

        for (Resource resource : getEditingDomain().getResourceSet().getResources()) {
            new TaskUpdateJob(resource).schedule();
        }

        ResourceSetValidation validation = Validation.getValidation(editingDomain.getResourceSet());
        validation.revalidate();
    }

    /** {@inheritDoc} */
    @Override
    public void gotoMarker(IMarker marker) {
        String uri = getURIString(marker);
        if (uri != null) {
            setSelection(Collections.singletonList(uri));
        }
    }

    /** Get the URI of the element to which a marker is referring. */
    private String getURIString(IMarker marker) {
        String uriFragment = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
        IResource resource = marker.getResource();
        return getURIString(resource, uriFragment);
    }

    /** Assemble a URI based on a resource and fragment. */
    private String getURIString(IResource resource, String uriFragment) {
        if (uriFragment == null) {
            return null;
        }
        URI resourceURI = URI.createPlatformResourceURI(resource.getFullPath().toString(), true);
        URI uri = resourceURI.appendFragment(uriFragment);
        return uri.toString();
    }

    /** {@inheritDoc} */
    @Override
    public void dispose() {
        Cache.disposeCaches(getEditingDomain().getResourceSet());
        if (customPropertySheetPage != null) {
            customPropertySheetPage.dispose();
        }
        super.dispose();
    }

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    @Override
    public Object getAdapter(Class key) {
        if (key == IValidatedEditor.class) {
            return new DefaultValidatedEditor(this, false);
        }
        return super.getAdapter(key);
    }
}