org.eclipse.virgo.ide.ui.editors.SpringBundleSourcePage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.virgo.ide.ui.editors.SpringBundleSourcePage.java

Source

/*******************************************************************************
 * Copyright (c) 2009 SpringSource, a divison of VMware, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     SpringSource, a division of VMware, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.virgo.ide.ui.editors;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.pde.core.IBaseModel;
import org.eclipse.pde.core.plugin.IPluginLibrary;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.core.text.IDocumentKey;
import org.eclipse.pde.internal.core.text.IDocumentRange;
import org.eclipse.pde.internal.core.text.IEditingModel;
import org.eclipse.pde.internal.core.text.bundle.Bundle;
import org.eclipse.pde.internal.core.text.bundle.BundleClasspathHeader;
import org.eclipse.pde.internal.core.text.bundle.BundleModel;
import org.eclipse.pde.internal.core.text.bundle.ExecutionEnvironment;
import org.eclipse.pde.internal.core.text.bundle.ExportPackageHeader;
import org.eclipse.pde.internal.core.text.bundle.ExportPackageObject;
import org.eclipse.pde.internal.core.text.bundle.ImportPackageHeader;
import org.eclipse.pde.internal.core.text.bundle.ImportPackageObject;
import org.eclipse.pde.internal.core.text.bundle.ManifestHeader;
import org.eclipse.pde.internal.core.text.bundle.PackageObject;
import org.eclipse.pde.internal.core.text.bundle.RequireBundleHeader;
import org.eclipse.pde.internal.core.text.bundle.RequireBundleObject;
import org.eclipse.pde.internal.core.text.bundle.RequiredExecutionEnvironmentHeader;
import org.eclipse.pde.internal.core.text.plugin.PluginModel;
import org.eclipse.pde.internal.ui.PDELabelProvider;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEPluginImages;
import org.eclipse.pde.internal.ui.editor.IFoldingStructureProvider;
import org.eclipse.pde.internal.ui.editor.PDEFormEditor;
import org.eclipse.pde.internal.ui.editor.PDEFormEditorContributor;
import org.eclipse.pde.internal.ui.editor.actions.HyperlinkAction;
import org.eclipse.pde.internal.ui.editor.actions.PDEActionConstants;
import org.eclipse.pde.internal.ui.editor.plugin.BundleSourcePage;
import org.eclipse.pde.internal.ui.editor.plugin.ExtensionHyperLink;
import org.eclipse.pde.internal.ui.editor.plugin.PluginFoldingStructureProvider;
import org.eclipse.pde.internal.ui.editor.text.ChangeAwareSourceViewerConfiguration;
import org.eclipse.pde.internal.ui.editor.text.IColorManager;
import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
import org.eclipse.pde.internal.ui.util.SharedLabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.texteditor.ContentAssistAction;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.virgo.ide.manifest.core.IHeaderConstants;
import org.eclipse.virgo.ide.manifest.core.editor.model.ImportBundleHeader;
import org.eclipse.virgo.ide.manifest.core.editor.model.ImportBundleObject;
import org.eclipse.virgo.ide.manifest.core.editor.model.ImportLibraryHeader;
import org.eclipse.virgo.ide.manifest.core.editor.model.ImportLibraryObject;
import org.eclipse.virgo.ide.ui.ServerIdeUiPlugin;
import org.eclipse.virgo.ide.ui.editors.text.BundleColorManager;
import org.eclipse.virgo.ide.ui.editors.text.BundleManifestConfiguration;
import org.eclipse.virgo.ide.ui.internal.actions.ManifestFormatAction;
import org.springframework.util.ReflectionUtils;

/**
 * @author Christian Dupuis
 * @author Steffen Pingel
 * @author Leo Dos Santos
 */
public class SpringBundleSourcePage extends BundleSourcePage {

    private final String ID_CONTEXT_MENU = "org.eclipse.virgo.ide.bundlemanifest.text.menu";

    private IFoldingStructureProvider fFoldingStructureProvider;

    private final ChangeAwareSourceViewerConfiguration fConfiguration;

    public SpringBundleSourcePage(PDEFormEditor editor, String id, String title) {
        super(editor, id, title);
        fConfiguration = createSourceViewerConfiguration(BundleColorManager.getDefault());
        if (fConfiguration != null) {
            setSourceViewerConfiguration(fConfiguration);
        }
    }

    protected ChangeAwareSourceViewerConfiguration createSourceViewerConfiguration(IColorManager colorManager) {
        return new BundleManifestConfiguration(colorManager, this);
    }

    @Override
    protected void setEditorContextMenuId(String contextMenuId) {
        super.setEditorContextMenuId(ID_CONTEXT_MENU);
    }

    @Override
    public void projectionEnabled() {
        IBaseModel model = getInputContext().getModel();
        if (model instanceof IEditingModel) {
            fFoldingStructureProvider = getFoldingStructureProvider((IEditingModel) model);
            if (fFoldingStructureProvider != null) {
                fFoldingStructureProvider.initialize();
                IReconciler rec = getSourceViewerConfiguration().getReconciler(getSourceViewer());
                IReconcilingStrategy startegy = rec.getReconcilingStrategy(new String());
                if (startegy instanceof ReconcilingStrategy) {
                    ((ReconcilingStrategy) startegy).addParticipant(fFoldingStructureProvider);
                }
            }
        }
    }

    protected IFoldingStructureProvider getFoldingStructureProvider(IEditingModel model) {
        if (model instanceof PluginModel) {
            return new PluginFoldingStructureProvider(this, model);
        }
        if (model instanceof BundleModel) {
            return new SpringBundleFoldingStructureProvider(this, model);
        }
        // return super.getFoldingStructureProvider(model);
        return null;
    }

    @Override
    public void projectionDisabled() {
        fFoldingStructureProvider = null;
    }

    @Override
    protected boolean affectsTextPresentation(PropertyChangeEvent event) {
        if (fConfiguration == null) {
            return false;
        }
        return fConfiguration.affectsTextPresentation(event) || super.affectsTextPresentation(event);
    }

    @Override
    public void dispose() {
        if (fConfiguration != null) {
            fConfiguration.dispose();
        }
        super.dispose();
    }

    @Override
    protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
        try {
            if (fConfiguration != null) {
                ISourceViewer sourceViewer = getSourceViewer();
                if (sourceViewer != null) {
                    fConfiguration.adaptToPreferenceChange(event);
                }
            }
        } finally {
            super.handlePreferenceStoreChanged(event);
        }
    }

    @Override
    protected void editorContextMenuAboutToShow(IMenuManager menu) {
        super.editorContextMenuAboutToShow(menu);
        PDEFormEditorContributor contributor = ((PDEFormEditor) getEditor()).getContributor();
        if (contributor instanceof BundleManifestEditorContributor) {
            BundleManifestEditorContributor textContributor = (BundleManifestEditorContributor) contributor;
            HyperlinkAction action = textContributor.getHyperlinkAction();
            if ((action != null) && action.isEnabled()
                    && ((action.getHyperLink() instanceof ExtensionHyperLink) == false)) {
                // Another detector handles this the extension hyperlink case
                // org.eclipse.pde.internal.ui.editor.plugin.
                // ExtensionAttributePointDectector.java
                // Implemented at a higher level. As a result, need to disable
                // the action here to prevent duplicate entries in the context
                // menu
                menu.add(action);
            }
            ManifestFormatAction formatManifestAction = textContributor.getFormatAction();
            if (formatManifestAction != null && formatManifestAction.isEnabled()) {
                // add format action after Outline. This is the same order as
                // the hyperlink actions
                menu.insertAfter(PDEActionConstants.COMMAND_ID_QUICK_OUTLINE, formatManifestAction);
            }
        }
    }

    @Override
    protected void createActions() {
        super.createActions();
        PDEFormEditorContributor contributor = ((PDEFormEditor) getEditor()).getContributor();
        if (contributor instanceof BundleManifestEditorContributor) {
            BundleManifestEditorContributor textContributor = (BundleManifestEditorContributor) contributor;
            setAction(PDEActionConstants.OPEN, textContributor.getHyperlinkAction());
            setAction(PDEActionConstants.FORMAT, textContributor.getFormatAction());
            if (textContributor.supportsContentAssist()) {
                createContentAssistAction();
            }
        }
    }

    private void createContentAssistAction() {
        IAction contentAssist = new ContentAssistAction(getBundleForConstructedKeys(), "ContentAssistProposal.", //$NON-NLS-1$
                this);
        contentAssist.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
        setAction("ContentAssist", contentAssist); //$NON-NLS-1$
        markAsStateDependentAction("ContentAssist", true); //$NON-NLS-1$      
    }

    @Override
    public ILabelProvider createOutlineLabelProvider() {
        return new SpringBundleLabelProvider();
    }

    @Override
    public ITreeContentProvider createOutlineContentProvider() {
        return new SpringBundleOutlineContentProvider();
    }

    @Override
    public IDocumentRange findRange() {
        try {
            java.lang.reflect.Field field = ReflectionUtils.findField(this.getClass(), "fSelection", Object.class);
            field.setAccessible(true);
            Object selection = field.get(this);

            if (selection instanceof ImportLibraryObject) {
                return getSpecificRange(((ImportLibraryObject) selection).getModel(),
                        IHeaderConstants.IMPORT_LIBRARY, ((ImportLibraryObject) selection).getId());
            } else if (selection instanceof ImportBundleObject) {
                return getSpecificRange(((ImportBundleObject) selection).getModel(), IHeaderConstants.IMPORT_BUNDLE,
                        ((ImportBundleObject) selection).getId());
            } else if (selection instanceof ImportPackageObject) {
                ImportPackageObject impObj = (ImportPackageObject) selection;
                String key = impObj.getHeader().getKey();
                if (key != null && key.equalsIgnoreCase(IHeaderConstants.IMPORT_TEMPLATE)) {
                    return getSpecificRange(((ImportPackageObject) selection).getModel(),
                            IHeaderConstants.IMPORT_TEMPLATE, ((ImportPackageObject) selection).getValue());
                } else if (key != null && key.equalsIgnoreCase(IHeaderConstants.EXCLUDED_IMPORTS)) {
                    return getSpecificRange(((ImportPackageObject) selection).getModel(),
                            IHeaderConstants.EXCLUDED_IMPORTS, ((ImportPackageObject) selection).getValue());
                } else if (key != null && key.equalsIgnoreCase(IHeaderConstants.UNVERSIONED_IMPORTS)) {
                    return getSpecificRange(((ImportPackageObject) selection).getModel(),
                            IHeaderConstants.UNVERSIONED_IMPORTS, ((ImportPackageObject) selection).getValue());
                }
            } else if (selection instanceof ExportPackageObject) {
                ExportPackageObject expObj = (ExportPackageObject) selection;
                String key = expObj.getHeader().getKey();
                if (key != null && key.equalsIgnoreCase(IHeaderConstants.EXPORT_TEMPLATE)) {
                    return getSpecificRange(((ExportPackageObject) selection).getModel(),
                            IHeaderConstants.EXPORT_TEMPLATE, ((ExportPackageObject) selection).getValue());
                } else if (key != null && key.equalsIgnoreCase(IHeaderConstants.EXCLUDED_EXPORTS)) {
                    return getSpecificRange(((ExportPackageObject) selection).getModel(),
                            IHeaderConstants.EXCLUDED_EXPORTS, ((ExportPackageObject) selection).getValue());
                }
            } else {
                return super.findRange();
            }
        } catch (Exception e) {
        }
        return super.findRange();
    }

    private class SpringBundleOutlineContentProvider extends DefaultContentProvider
            implements ITreeContentProvider {

        public Object[] getChildren(Object parent) {
            // Need an identifying class for label provider
            if (parent instanceof ImportPackageHeader) {
                return ((ImportPackageHeader) parent).getPackages();
            } else if (parent instanceof ExportPackageHeader) {
                return ((ExportPackageHeader) parent).getPackages();
            } else if (parent instanceof RequiredExecutionEnvironmentHeader) {
                return ((RequiredExecutionEnvironmentHeader) parent).getEnvironments();
            } else if (parent instanceof RequireBundleHeader) {
                return ((RequireBundleHeader) parent).getRequiredBundles();
            } else if (parent instanceof BundleClasspathHeader) {
                return getPluginLibraries();
            } else if (parent instanceof ImportBundleHeader) {
                return ((ImportBundleHeader) parent).getImportedBundles();
            } else if (parent instanceof ImportLibraryHeader) {
                return ((ImportLibraryHeader) parent).getImportedLibraries();
            }
            return new Object[0];
        }

        private Object[] getPluginLibraries() {
            IPluginLibrary[] libraries = getBundleClasspathLibraries();
            if ((libraries == null) || (libraries.length == 0)) {
                return new Object[0];
            }
            return libraries;
        }

        public boolean hasChildren(Object parent) {
            return getChildren(parent).length > 0;
        }

        public Object getParent(Object child) {
            return null;
        }

        @SuppressWarnings("unchecked")
        public Object[] getElements(Object parent) {
            if (parent instanceof BundleModel) {
                BundleModel model = (BundleModel) parent;
                Map manifest = ((Bundle) model.getBundle()).getHeaders();
                ArrayList keys = new ArrayList();
                for (Iterator elements = manifest.keySet().iterator(); elements.hasNext();) {
                    IDocumentKey key = (IDocumentKey) manifest.get(elements.next());
                    if (key.getOffset() > -1) {
                        keys.add(key);
                    }
                }
                return keys.toArray();
            }
            return new Object[0];
        }
    }

    private IPluginLibrary[] getBundleClasspathLibraries() {
        // The bundle classpath header has no model data members
        // Retrieve the plug-in library equivalents from the editor model
        FormEditor editor = getEditor();
        if (editor instanceof PDEFormEditor) {
            PDEFormEditor formEditor = (PDEFormEditor) editor;
            IBaseModel baseModel = formEditor.getAggregateModel();
            if (baseModel instanceof IPluginModelBase) {
                IPluginLibrary[] libraries = ((IPluginModelBase) baseModel).getPluginBase().getLibraries();
                return libraries;
            }
        }
        return null;
    }

    private class SpringBundleLabelProvider extends LabelProvider {
        // TODO: MP: QO: LOW: Move to PDELabelProvider
        @Override
        public String getText(Object obj) {
            if (obj instanceof PackageObject) {
                return ((PackageObject) obj).getName();
            } else if (obj instanceof ExecutionEnvironment) {
                return ((ExecutionEnvironment) obj).getName();
            } else if (obj instanceof RequireBundleObject) {
                return getTextRequireBundle(((RequireBundleObject) obj));
            } else if (obj instanceof ImportLibraryObject) {
                return ((ImportLibraryObject) obj).getId();
            } else if (obj instanceof ImportBundleObject) {
                return ((ImportBundleObject) obj).getId();
            } else if (obj instanceof ManifestHeader) {
                return ((ManifestHeader) obj).getName();
            }
            return super.getText(obj);
        }

        private String getTextRequireBundle(RequireBundleObject bundle) {
            StringBuffer label = new StringBuffer();
            // Append the ID
            label.append(bundle.getId());
            // Get the version
            String version = bundle.getVersion();
            // If there is no version, just return what we have
            if ((version == null) || (version.length() == 0)) {
                return label.toString();
            }
            // Append a space
            label.append(' ');
            // If the first character does not have a range indicator,
            // add a default one. This can happen when there is only one
            // value specified for either min or max
            char firstChar = version.charAt(0);
            if ((firstChar != '(') && (firstChar != '[')) {
                label.append('(');
            }
            // Append the version
            label.append(version);
            // If the last character does not have a range indicator,
            // add a default one. This can happen when there is only one
            // value specified for either min or max
            char lastChar = version.charAt(version.length() - 1);
            if ((lastChar != ')') && (lastChar != ']')) {
                label.append(')');
            }
            // Return what we have
            return label.toString();
        }

        @Override
        public Image getImage(Object obj) {
            PDELabelProvider labelProvider = PDEPlugin.getDefault().getLabelProvider();
            if (obj instanceof PackageObject) {
                return labelProvider.get(PDEPluginImages.DESC_PACKAGE_OBJ);
            } else if (obj instanceof ExecutionEnvironment) {
                return labelProvider.get(PDEPluginImages.DESC_JAVA_LIB_OBJ);
            } else if (obj instanceof RequireBundleObject) {
                int flags = SharedLabelProvider.F_EXTERNAL;
                if (((RequireBundleObject) obj).isReexported()) {
                    flags = flags | SharedLabelProvider.F_EXPORT;
                }
                return labelProvider.get(PDEPluginImages.DESC_REQ_PLUGIN_OBJ, flags);
            } else if (obj instanceof ImportLibraryObject) {
                return labelProvider.get(PDEPluginImages.DESC_JAR_LIB_OBJ);
            } else if (obj instanceof ImportBundleObject) {
                return labelProvider.get(PDEPluginImages.DESC_BUNDLE_OBJ);
            } else if (obj instanceof ManifestHeader) {
                if (isSpringHeader(((ManifestHeader) obj).getKey())) {
                    return labelProvider
                            .get(ServerIdeUiPlugin.getImageDescriptor("full/view16/green_ball_obj.gif"));
                }
                return labelProvider.get(PDEPluginImages.DESC_BUILD_VAR_OBJ);
            } else if (obj instanceof IPluginLibrary) {
                return labelProvider.get(PDEPluginImages.DESC_JAVA_LIB_OBJ);
            }
            return null;
        }
    }

    private boolean isSpringHeader(String key) {
        ResourceBundle bundle = ResourceBundle.getBundle("org.eclipse.virgo.ide.ui.editors.text.headers");
        List<String> headers = Collections.list(bundle.getKeys());
        return headers.contains(key);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object getAdapter(Class adapter) {
        if (IHyperlinkDetector.class.equals(adapter)) {
            return new SpringBundleHyperlinkDetector(this);
        }
        return super.getAdapter(adapter);
    }
}