org.eclipse.edt.ide.ui.internal.contentassist.EGLCompletionProposalComputerRegistry.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.edt.ide.ui.internal.contentassist.EGLCompletionProposalComputerRegistry.java

Source

/*******************************************************************************
 * Copyright  2011, 2013 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.edt.ide.ui.internal.contentassist;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.edt.ide.ui.EDTUIPlugin;
import org.eclipse.edt.ide.ui.EDTUIPreferenceConstants;
import org.eclipse.edt.ide.ui.internal.preferences.Messages;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.dialogs.PreferencesUtil;

public final class EGLCompletionProposalComputerRegistry {

    private static final String EXTENSION_POINT = "eglCompletionProposalComputer"; //$NON-NLS-1$
    private static final String NUM_COMPUTERS_PREF_KEY = "content_assist_number_of_computers"; //$NON-NLS-1$

    /** The singleton instance. */
    private static EGLCompletionProposalComputerRegistry eglCplProposalRegistrySingleton = null;

    public static synchronized EGLCompletionProposalComputerRegistry getDefault() {
        if (null == eglCplProposalRegistrySingleton) {
            eglCplProposalRegistrySingleton = new EGLCompletionProposalComputerRegistry();
        }

        return eglCplProposalRegistrySingleton;
    }

    private final Map fDescriptorsByPartition = new HashMap();
    private final Map fPublicDescriptorsByPartition = new HashMap();
    private final List fDescriptors = new ArrayList();
    private final List fPublicDescriptors = Collections.unmodifiableList(fDescriptors);

    private final List fCategories = new ArrayList();
    private final List fPublicCategories = Collections.unmodifiableList(fCategories);

    /**
     * <code>true</code> if this registry has been loaded.
     */
    private boolean fLoaded = false;
    private boolean fHasUninstalledComputers = false;

    /**
     * Creates a new instance.
     */
    public EGLCompletionProposalComputerRegistry() {

    }

    List getProposalComputerDescriptors() {
        ensureExtensionPointRead();
        return fPublicDescriptors;
    }

    List getProposalComputerDescriptors(String partition) {
        ensureExtensionPointRead();
        List result = (List) fPublicDescriptorsByPartition.get(partition);
        return result != null ? result : Collections.EMPTY_LIST;
    }

    public List getProposalCategories() {
        ensureExtensionPointRead();
        return fPublicCategories;
    }

    /**
     * Ensures that the extensions are read and stored in
     * <code>fDescriptorsByPartition</code>.
     */
    private void ensureExtensionPointRead() {
        boolean reload;
        synchronized (this) {
            reload = !fLoaded;
            fLoaded = true;
        }
        if (reload) {
            reload();
            updateUninstalledComputerCount();
        }
    }

    private void updateUninstalledComputerCount() {
        IPreferenceStore preferenceStore = EDTUIPreferenceConstants.getPreferenceStore();
        int lastNumberOfComputers = preferenceStore.getInt(NUM_COMPUTERS_PREF_KEY);
        int currNumber = fDescriptors.size();
        fHasUninstalledComputers = lastNumberOfComputers > currNumber;
        preferenceStore.putValue(NUM_COMPUTERS_PREF_KEY, Integer.toString(currNumber));
        EDTUIPlugin.getDefault().savePluginPreferences();
    }

    public void reload() {
        IExtensionRegistry registry = Platform.getExtensionRegistry();
        List elements = new ArrayList(
                Arrays.asList(registry.getConfigurationElementsFor(EDTUIPlugin.getPluginId(), EXTENSION_POINT)));

        Map map = new HashMap();
        List all = new ArrayList();

        List categories = getCategories(elements);
        for (Iterator iter = elements.iterator(); iter.hasNext();) {
            IConfigurationElement element = (IConfigurationElement) iter.next();
            try {
                EGLCompletionProposalComputerDescriptor desc = new EGLCompletionProposalComputerDescriptor(element,
                        this, categories);
                Set partitions = desc.getPartitions();
                for (Iterator it = partitions.iterator(); it.hasNext();) {
                    String partition = (String) it.next();
                    List list = (List) map.get(partition);
                    if (list == null) {
                        list = new ArrayList();
                        map.put(partition, list);
                    }
                    list.add(desc);
                }
                all.add(desc);

            } catch (InvalidRegistryObjectException x) {
            } catch (CoreException x) {
            }
        }

        synchronized (this) {
            fCategories.clear();
            fCategories.addAll(categories);

            Set partitions = map.keySet();
            fDescriptorsByPartition.keySet().retainAll(partitions);
            fPublicDescriptorsByPartition.keySet().retainAll(partitions);
            for (Iterator it = partitions.iterator(); it.hasNext();) {
                String partition = (String) it.next();
                List old = (List) fDescriptorsByPartition.get(partition);
                List current = (List) map.get(partition);
                if (old != null) {
                    old.clear();
                    old.addAll(current);
                } else {
                    fDescriptorsByPartition.put(partition, current);
                    fPublicDescriptorsByPartition.put(partition, Collections.unmodifiableList(current));
                }
            }

            fDescriptors.clear();
            fDescriptors.addAll(all);
        }
    }

    boolean hasUninstalledComputers(String partition, List included) {
        return (fHasUninstalledComputers);
    }

    private List getCategories(List elements) {
        IPreferenceStore store = EDTUIPlugin.getDefault().getPreferenceStore();
        String preference = store.getString(EDTUIPreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
        Set disabled = new HashSet();
        StringTokenizer tok = new StringTokenizer(preference, "\0"); //$NON-NLS-1$
        while (tok.hasMoreTokens())
            disabled.add(tok.nextToken());
        Map ordered = new HashMap();
        preference = store.getString(EDTUIPreferenceConstants.CODEASSIST_CATEGORY_ORDER);
        tok = new StringTokenizer(preference, "\0"); //$NON-NLS-1$
        while (tok.hasMoreTokens()) {
            StringTokenizer inner = new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$
            String id = inner.nextToken();
            int rank = Integer.parseInt(inner.nextToken());
            ordered.put(id, new Integer(rank));
        }

        EGLCompletionProposalCategory allProposals = null;

        List categories = new ArrayList();
        for (Iterator iter = elements.iterator(); iter.hasNext();) {
            IConfigurationElement element = (IConfigurationElement) iter.next();
            try {
                if (element.getName().equals("proposalCategory")) { //$NON-NLS-1$
                    iter.remove(); // remove from list to leave only computers

                    EGLCompletionProposalCategory category = new EGLCompletionProposalCategory(element, this);
                    categories.add(category);
                    category.setIncluded(!disabled.contains(category.getId()));
                    Integer rank = (Integer) ordered.get(category.getId());
                    if (rank != null) {
                        int r = rank.intValue();
                        boolean separate = r < 0xffff;
                        if (!separate)
                            r = r - 0xffff;
                        category.setSeparateCommand(separate);
                        category.setSortOrder(r);
                    }
                }
            } catch (InvalidRegistryObjectException x) {
                Object[] args = { element.toString() };
                String message = Messages.format(EGLTextMessages.CompletionProposalComputerRegistry_invalid_message,
                        args);
                IStatus status = new Status(IStatus.WARNING, EDTUIPlugin.getPluginId(), IStatus.OK, message, x);
                informUser(status);
            } catch (CoreException x) {
                informUser(x.getStatus());
            }
        }

        preventDuplicateCategories(store, disabled, allProposals);
        return categories;
    }

    private void preventDuplicateCategories(IPreferenceStore store, Set disabled,
            EGLCompletionProposalCategory allProposals) {
        if (allProposals == null || !allProposals.isIncluded())
            return;
        StringBuffer buf = new StringBuffer(50 * disabled.size());
        Iterator iter = disabled.iterator();
        while (iter.hasNext()) {
            buf.append(iter.next());
            buf.append('\0');
        }
        store.putValue(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, buf.toString());
    }

    void resetUnistalledComputers() {
        fHasUninstalledComputers = false;
    }

    private void informUser(IStatus status) {
        EDTUIPlugin.log(status);
        String title = EGLTextMessages.CompletionProposalComputerRegistry_error_dialog_title;
        String message = status.getMessage();
        MessageDialog.openError(EDTUIPlugin.getActiveWorkbenchShell(), title, message);
    }

    void informUser(EGLCompletionProposalComputerDescriptor descriptor, IStatus status) {
        EDTUIPlugin.log(status);
        String title = EGLTextMessages.CompletionProposalComputerRegistry_error_dialog_title;
        EGLCompletionProposalCategory category = descriptor.getCategory();
        IContributor culprit = descriptor.getContributor();
        Set affectedPlugins = getAffectedContributors(category, culprit);

        final String avoidHint;
        final String culpritName = culprit == null ? null : culprit.getName();
        if (affectedPlugins.isEmpty())
            avoidHint = Messages.format(EGLTextMessages.CompletionProposalComputerRegistry_messageAvoidanceHint,
                    new Object[] { culpritName, category.getDisplayName() });
        else
            avoidHint = Messages.format(
                    EGLTextMessages.CompletionProposalComputerRegistry_messageAvoidanceHintWithWarning,
                    new Object[] { culpritName, category.getDisplayName(), toString(affectedPlugins) });

        String message = status.getMessage();
        // inlined from MessageDialog.openError
        MessageDialog dialog = new MessageDialog(EDTUIPlugin.getActiveWorkbenchShell(), title,
                null /* default image */, message, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL },
                0) {
            protected Control createCustomArea(Composite parent) {
                Link link = new Link(parent, SWT.NONE);
                link.setText(avoidHint);
                link.addSelectionListener(new SelectionAdapter() {
                    public void widgetSelected(SelectionEvent e) {
                        PreferencesUtil
                                .createPreferenceDialogOn(getShell(),
                                        "org.eclipse.edt.ide.ui.ContentAssistAdvancedPreferences", null, null) //$NON-NLS-1$
                                .open();
                    }
                });
                GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
                gridData.widthHint = this.getMinimumMessageWidth();
                link.setLayoutData(gridData);
                return link;
            }
        };
        dialog.open();
    }

    private Set getAffectedContributors(EGLCompletionProposalCategory category, IContributor culprit) {
        Set affectedPlugins = new HashSet();
        for (Iterator it = getProposalComputerDescriptors().iterator(); it.hasNext();) {
            EGLCompletionProposalComputerDescriptor desc = (EGLCompletionProposalComputerDescriptor) it.next();
            EGLCompletionProposalCategory cat = desc.getCategory();
            if (cat.equals(category)) {
                IContributor contributor = desc.getContributor();
                if (contributor != null && !culprit.equals(contributor))
                    affectedPlugins.add(contributor.getName());
            }
        }
        return affectedPlugins;
    }

    private Object toString(Collection collection) {
        // strip brackets off AbstractCollection.toString()
        String string = collection.toString();
        return string.substring(1, string.length() - 1);
    }
}