com.nokia.sdt.uidesigner.ui.AbstractDesignerDataModelEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.sdt.uidesigner.ui.AbstractDesignerDataModelEditor.java

Source

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/
package com.nokia.sdt.uidesigner.ui;

import com.nokia.carbide.internal.api.updater.IProjectUpdateManager;
import com.nokia.carbide.updater.CarbideUpdaterPlugin;
import com.nokia.sdt.datamodel.*;
import com.nokia.sdt.datamodel.images.IProjectImageInfo;
import com.nokia.sdt.datamodel.images.IProjectImageInfoListener;
import com.nokia.sdt.datamodel.util.ModelUtils;
import com.nokia.sdt.displaymodel.adapter.ILayoutObject;
import com.nokia.sdt.editor.*;
import com.nokia.sdt.sourcegen.ISourceGenChangeListener;
import com.nokia.sdt.uidesigner.ui.command.ApplySourceChangesCommand;
import com.nokia.sdt.uidesigner.ui.utils.*;
import com.nokia.sdt.utils.*;
import com.nokia.cpp.internal.api.utils.core.Check;
import com.nokia.cpp.internal.api.utils.core.ListenerList;
import com.nokia.cpp.internal.api.utils.core.Logging;
import com.nokia.cpp.internal.api.utils.ui.ShowDialogWhenWorkbenchVisibleJob;
import com.nokia.cpp.internal.api.utils.ui.editor.ErrorPage;
import com.nokia.sdt.workspace.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.dialogs.*;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.*;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.ide.ResourceUtil;

import java.text.MessageFormat;
import java.util.*;

public abstract class AbstractDesignerDataModelEditor extends FormEditor
        implements IDesignerDataModelEditor, ISourceGenChangeListener, IProjectImageInfoListener {

    final QualifiedName activePagePropertyName = new QualifiedName(UIDesignerPlugin.PLUGIN_ID, "activePage"); //$NON-NLS-1$

    protected List saveListeners;
    private IDesignerDataModel dataModel;
    private DesignerDataModelEditorResourceListener resourceListener;
    private EditValidatingCommandStack commandStack;
    // since FormEditor only notifies when page changes to FormPage,
    // we'll notify for embedded editors
    private ListenerList<IPageChangedListener> pageListeners;
    private IStatus openErrorStatus;

    public AbstractDesignerDataModelEditor() {
        commandStack = new EditValidatingCommandStack();
        pageListeners = new ListenerList<IPageChangedListener>();
    }

    @Override
    public void dispose() {
        super.dispose();
        if (dataModel != null) {
            disableExternalChangeListeners();
            dataModel.dispose();
        }
        if (resourceListener != null)
            resourceListener.dispose();
        EditorServices.removeEditor(this);
    }

    public Object getAdapter(Class adapter) {
        if (adapter.isAssignableFrom(getClass()))
            return this;
        else if (adapter.equals(IResource.class) && dataModel != null) {
            return dataModel.getModelSpecifier().getPrimaryResource();
        }
        return super.getAdapter(adapter);
    }

    @Override
    public void setInput(IEditorInput input) {
        super.setInputWithNotify(input);
        IFile file = ResourceUtil.getFile(input);
        setPartName(file.getName()); // set title of editor doc window
    }

    public void addSaveListener(SaveListener listener) {
        if (saveListeners == null)
            saveListeners = new ArrayList();

        if (!saveListeners.contains(listener))
            saveListeners.add(listener);
    }

    public void removeSaveListener(SaveListener listener) {
        if (saveListeners == null)
            return;

        saveListeners.remove(listener);
    }

    protected boolean fireQueryAboutToSave() {
        if (saveListeners == null)
            return true;

        for (Iterator iter = (new ArrayList(saveListeners)).iterator(); iter.hasNext();) {
            SaveListener listener = (SaveListener) iter.next();
            if (!listener.queryAboutToSave(this))
                return false;
        }

        return true;
    }

    protected void firePreSaveNotify(IProgressMonitor monitor) {
        if (saveListeners == null)
            return;

        for (Iterator iter = (new ArrayList(saveListeners)).iterator(); iter.hasNext();) {
            SaveListener listener = (SaveListener) iter.next();
            listener.preSaveNotify(this, monitor);
        }
    }

    protected void firePostSaveNotify(IProgressMonitor monitor) {
        if (saveListeners == null)
            return;

        for (Iterator iter = (new ArrayList(saveListeners)).iterator(); iter.hasNext();) {
            SaveListener listener = (SaveListener) iter.next();
            listener.postSaveNotify(this, monitor);
        }
    }

    protected void enableExternalChangeListeners() {
        IProjectContext projectContext = dataModel != null ? dataModel.getProjectContext() : null;
        if (projectContext != null && projectContext.getSourceGenProvider() != null) {
            // list for changes to source
            projectContext.getSourceGenProvider().addSourceChangeListener(this);
            // scan for changes since last open
            projectContext.getSourceGenProvider().fireSourceChanged(true);
        }
        if (dataModel != null) {
            IProjectImageInfo projectImageInfo = ModelUtils.getProjectImageInfo(dataModel.getRoot());
            projectImageInfo.addListener(this);
        }

    }

    protected void disableExternalChangeListeners() {
        IProjectContext projectContext = dataModel.getProjectContext();
        if (projectContext != null && projectContext.getSourceGenProvider() != null) {
            projectContext.getSourceGenProvider().removeSourceChangeListener(this);
        }
        IProjectImageInfo projectImageInfo = ModelUtils.getProjectImageInfo(dataModel.getRoot());
        if (projectImageInfo != null)
            projectImageInfo.removeListener(this);

    }

    public void setListenToResourceChanges(boolean listen) {
        if (listen)
            resourceListener.postSaveNotify(this, null);
        else
            resourceListener.preSaveNotify(this, null);
    }

    public IDesignerDataModel getDataModel() {
        return dataModel;
    }

    @Override
    public boolean isDirty() {
        if (commandStack == null || !commandStack.isDirty())
            return super.isDirty();

        return true;
    }

    public void applyModifiedSourceChanges(Command command) {
        ApplySourceChangesCommand gefCommand = new ApplySourceChangesCommand(this, getListeningDataModel());
        gefCommand.setDataModelCommand(command);
        commandStack.execute(gefCommand);
    }

    public IDesignerDataModel getListeningDataModel() {
        if (commandStack != null)
            return dataModel;
        else
            return null;
    }

    @Override
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        super.init(site, input);
        IStatus status = EditorServices.runWithProgressAndStatus((Shell) getAdapter(Shell.class),
                new IRunnableWithProgressAndStatus() {
                    public IStatus run(IProgressMonitor monitor) {
                        return loadInput(monitor);
                    }
                });
        if (status != null) {
            dataModel = null;
            openErrorStatus = status;
        }
    }

    protected IStatus preLoadInput(IProgressMonitor monitor) {
        return Status.OK_STATUS;
    }

    protected IStatus postLoadInput(IProgressMonitor monitor) {
        return Status.OK_STATUS;
    }

    /**
     * Begins and ends the progress monitor and calls doLoadInput
     * @param monitor
     * @return
     */
    protected IStatus loadInput(IProgressMonitor monitor) {
        monitor.beginTask(Strings.getString("AbstractDesignerDataModelEditor.LoadingDesignMessage"), 6); //$NON-NLS-1$

        IStatus status = preLoadInput(monitor);

        if (status == null || status.isOK())
            status = doLoadInput(monitor);

        if (status == null || status.isOK()) {
            status = postLoadInput(monitor);

            Collection<IModelMessage> messages = ModelMessages.validateAndUpdateMarkers(dataModel);
            Shell shell = (Shell) getAdapter(Shell.class);
            Dialog loadProblemsDialog = EditorServices.createModelValidationMessagesDialog(shell, dataModel,
                    messages);
            ShowDialogWhenWorkbenchVisibleJob.start(shell, loadProblemsDialog);

            monitor.worked(1);
        }

        monitor.done();
        return status;
    }

    /**
     * Does the work of loading the input, but assumes the progress monitor has begun and does not end it
     * @param monitor
     * @return IStatus
     */
    protected IStatus doLoadInput(IProgressMonitor monitor) {
        IFile file = ResourceUtil.getFile(getEditorInput());

        if ((file == null) || !file.exists()) {
            if (file != null && !file.getProject().isOpen())
                return EditorUtils.makeOrReportEditorOpenStatus(
                        Strings.getString("AbstractDesignerDataModelEditor.LoadFailedProjectClosedError"), null); //$NON-NLS-1$
            return EditorUtils.makeOrReportEditorOpenStatus(
                    Strings.getString("AbstractDesignerDataModelEditor.LoadFailedNoFileError"), null); //$NON-NLS-1$
        }

        WorkspaceContext wc = WorkspaceContext.getContext();
        IDesignerDataModelSpecifier modelSpecifier = wc.findSpecifierForResource(file);
        boolean neededUpdating = false;
        IProject project = file.getProject();

        // first we check if the project needs updating
        IProjectUpdateManager pum = CarbideUpdaterPlugin.getProjectUpdateManager();
        if (modelSpecifier == null && pum.projectNeedsUpdate(project, null)) {
            EditorUtils.tryToUpdateProject(project);
            modelSpecifier = wc.findSpecifierForResource(file);
            neededUpdating = true;
        }

        if (modelSpecifier == null) {
            String errorString = neededUpdating
                    ? Strings.getString("AbstractDesignerDataModelEditor.LoadFailedNeedsUpdatingError") //$NON-NLS-1$
                    : Strings.getString("AbstractDesignerDataModelEditor.LoadFailedNoSpecifierError"); //$NON-NLS-1$
            return EditorUtils.makeOrReportEditorOpenStatus(errorString, null);
        }

        monitor.worked(1);

        String failureMsg = modelSpecifier.isEditable();
        if (failureMsg != null)
            return EditorUtils.makeOrReportEditorOpenStatus(failureMsg, null); //$NON-NLS-1$

        StatusHolder holder = new StatusHolder();
        dataModel = EditorUtils.loadModel(modelSpecifier, holder);
        IStatus status = holder.getStatus();
        if (status != null && !status.isOK())
            return status;

        // now check if the model needs updating
        if (!neededUpdating && !dataModel.isModelUpToDate()) {
            boolean wantsUpdate = MessageDialog.openQuestion((Shell) getAdapter(Shell.class),
                    Strings.getString("AbstractDesignerDataModelEditor.LoadUpgradeQueryTitle"), //$NON-NLS-1$
                    Strings.getString("AbstractDesignerDataModelEditor.LoadUpgradeQuery")); //$NON-NLS-1$
            if (wantsUpdate) {
                dataModel.dispose();
                EditorUtils.tryToUpgradeProjectDesigns(project);
                dataModel = EditorUtils.loadModel(modelSpecifier, holder);
                status = holder.getStatus();
                if (status != null && !status.isOK())
                    return status;
            }
        }

        Check.checkState(dataModel != null);
        resourceListener = new DesignerDataModelEditorResourceListener(this);
        commandStack.initialize(getSite().getShell(), dataModel);
        EditorServices.addEditor(this);

        monitor.worked(1);

        enableExternalChangeListeners();

        monitor.worked(1);

        return Status.OK_STATUS;
    }

    private boolean checkProjectExists() {
        IProject project = null;
        IProjectContext projectContext = dataModel.getProjectContext();
        if (projectContext != null)
            project = projectContext.getProject();
        if (project == null) {
            String message = Strings.getString("AbstractDesignerDataModelEditor.NoProjectMessage"); //$NON-NLS-1$
            IStatus status = Logging.newStatus(UIDesignerPlugin.getDefault(), IStatus.ERROR, message);
            Logging.showErrorDialog(null, Strings.getString("AbstractDesignerDataModelEditor.SavingFailedError"), //$NON-NLS-1$
                    status);
            return false;
        }
        return true;
    }

    @Override
    public void doSave(IProgressMonitor monitor) {
        if (!checkProjectExists())
            return;

        IStatus status = dataModel.validateEdit(getEditorSite().getShell());
        if (!status.isOK()) {
            return;
        }

        if (!fireQueryAboutToSave())
            return;

        firePreSaveNotify(monitor);

        // Changes are committed when the user switches the
        // active page, but changes buffered in the current page
        // are not committed automatically when saving.
        IFormPage activePage = getActivePageInstance();
        if (activePage != null) {
            IManagedForm managedForm = activePage.getManagedForm();
            if (managedForm != null) {
                managedForm.commit(true);
            }
        }

        try {
            dataModel.saveModel(monitor);
            if (commandStack != null)
                commandStack.markSaveLocation();
            Collection<IModelMessage> messages = ModelMessages.validateAndUpdateMarkers(dataModel);

            Shell shell = (Shell) getAdapter(Shell.class);
            //EditorServices.notifyIfDataModelSourceGenProblems(shell, dataModel);
            Dialog dialog = EditorServices.createModelValidationMessagesDialog(shell, dataModel, messages);
            dialog.open();
        } catch (Exception e) {
            status = Logging.newStatus(UIDesignerPlugin.getDefault(), e);
            Logging.log(UIDesignerPlugin.getDefault(), status);
            Logging.showErrorDialog(null, Strings.getString("AbstractDesignerDataModelEditor.SavingFailedError"), //$NON-NLS-1$
                    status);
        } finally {
            firePostSaveNotify(monitor);
        }
    }

    @Override
    public boolean isSaveAsAllowed() {
        return false;
    }

    @Override
    public void doSaveAs() {
        // not allowed
    }

    protected void reloadDataModel() {
        IDesignerDataModelSpecifier spec = dataModel.getModelSpecifier();
        dataModel.dispose();
        LoadResult lr = spec.load();
        Check.checkState(lr != null);
        dataModel = lr.getModel();
        Check.checkState(dataModel != null);
    }

    protected void reloadPageData() {
        if (pages != null) {
            for (Object page : pages) {
                if (page instanceof IDesignerDataModelEditorPage) {
                    ((IDesignerDataModelEditorPage) page).reload();
                }
            }
        }
    }

    public void reload() {
        EditorServices.removeEditor(this);
        reloadDataModel();
        reloadPageData();
        flushCommandStack();
        editorDirtyStateChanged();
        enableExternalChangeListeners();
        EditorServices.addEditor(this);
    }

    protected void flushCommandStack() {
        commandStack.flush();
        commandStack.initialize(getSite().getShell(), dataModel);
    }

    protected void setCommandStack(EditValidatingCommandStack commandStack) {
        this.commandStack = commandStack;
    }

    public CommandStack getCommandStack() {
        return commandStack;
    }

    public FormEditor getFormEditor() {
        return this;
    }

    protected void initializeExtenders() throws CoreException {
        IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
        IExtensionPoint extensionPoint = extensionRegistry
                .getExtensionPoint(IDesignerDataModelEditorExtender.EXTENSION_ID);
        IExtension[] extensions = extensionPoint.getExtensions();
        for (int i = 0; i < extensions.length; i++) {
            IExtension extension = extensions[i];
            IConfigurationElement[] elements = extension.getConfigurationElements();
            Check.checkContract(elements.length == 1);
            IConfigurationElement element = elements[0];
            String filter = element.getAttribute(IDesignerDataModelEditorExtender.EDITOR_ID_FILTER);
            if (filter == null || filter.length() == 0 || getEditorSite().getId().matches(filter)) {
                initializeExtender(element);
            }
        }
        IResource resource = (IResource) getAdapter(IResource.class);
        if (resource != null) {
            try {
                Object pageIndexObj = resource.getSessionProperty(activePagePropertyName);
                if (pageIndexObj instanceof Integer) {
                    int index = ((Integer) pageIndexObj).intValue();
                    int pageCount = getPageCount();
                    if (index < pageCount)
                        setActivePage(index);
                }
            } catch (CoreException e) {
                Logging.log(UIDesignerPlugin.getDefault(), e.getStatus());
            }
        }

    }

    private void initializeExtender(IConfigurationElement element) throws CoreException {
        IDesignerDataModelEditorExtender editorExtenders = (IDesignerDataModelEditorExtender) element
                .createExecutableExtension(IDesignerDataModelEditorExtender.EXTENDER);
        Check.checkContract(editorExtenders != null);
        editorExtenders.editorInitialized(this);
    }

    public void setTabTitle(int pageIndex, String title) {
        setPageText(pageIndex, title);
    }

    public void activatePage(int pageIndex) {
        if (getActivePage() != pageIndex)
            setActivePage(pageIndex);
    }

    public void addPageChangedListener(IPageChangedListener listener) {
        super.addPageChangedListener(listener);
        pageListeners.add(listener);
    }

    public void removePageChangedListener(IPageChangedListener listener) {
        super.removePageChangedListener(listener);
        pageListeners.remove(listener);
    }

    protected void pageChange(int newPageIndex) {
        super.pageChange(newPageIndex);
        IFormPage formPage = getActivePageInstance();
        if (formPage == null) {
            Object page = pages.get(newPageIndex);
            firePageChanged(new PageChangedEvent(this, page));
        }
        IResource resource = (IResource) getAdapter(IResource.class);
        if (resource != null) {
            try {
                resource.setSessionProperty(activePagePropertyName, new Integer(newPageIndex));
            } catch (CoreException e) {
                Logging.log(UIDesignerPlugin.getDefault(), e.getStatus());
            }
        }
    }

    private void firePageChanged(final PageChangedEvent event) {
        for (IPageChangedListener l : pageListeners) {
            l.pageChanged(event);
        }
    }

    public void dirtyNotification(IProjectImageInfo info) {
        info.refresh();
    }

    public void changed(IProjectImageInfo info) {
        Display.getDefault().asyncExec(new Runnable() {

            public void run() {
                EObject[] rootContainers = dataModel.getRootContainers();
                if (rootContainers != null && rootContainers.length > 0) {
                    ILayoutObject object = Adapters.getLayoutObject(rootContainers[0]);
                    if (object != null)
                        object.forceRedraw();
                }
            }
        });
    }

    public boolean hasOpenError() {
        return openErrorStatus != null;
    }

    protected void addErrorPage() {
        ErrorPage errorPage = new ErrorPage(this, "error", //$NON-NLS-1$
                Strings.getString("AbstractDesignerDataModelEditor.ErrorTabTitle")); //$NON-NLS-1$
        String error = MessageFormat.format(Strings.getString("AbstractDesignerDataModelEditor.OpenErrorTitle"), //$NON-NLS-1$
                new Object[] { getTitle() });
        errorPage.setTitleString(error);
        errorPage.setErrorString(openErrorStatus.getMessage());
        try {
            addPage(errorPage);
        } catch (PartInitException e) {
            Logging.log(UIDesignerPlugin.getDefault(), e.getStatus());
        }
    }
}