/******************************************************************************* * Copyright (c) 2010, 2012 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.wst.sse.ui.internal.contentassist; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; 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.core.runtime.content.IContentType; import org.eclipse.wst.sse.ui.internal.Logger; import org.eclipse.wst.sse.ui.internal.SSEUIPlugin; import org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationReader; import org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter; /** * <p>A registry for all extensions to the * <code>org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration</code> * extension point.</p> */ public final class CompletionProposoalCatigoriesConfigurationRegistry { /** The extension schema name of the extension point */ private static final String EXTENSION_POINT = "completionProposalCategoriesConfiguration"; //$NON-NLS-1$ /** The extension schema name of categories properties child elements */ private static final String ELEM_CATEGORIES_PROPERTIES = "categoriesConfiguration"; //$NON-NLS-1$ /** The extension schema name of the content type id attribute */ private static final String ATTR_CONTENT_TYPE_ID = "contentTypeID"; //$NON-NLS-1$ /** The extension schema name of the class attribute */ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ /** The singleton instance. */ private static CompletionProposoalCatigoriesConfigurationRegistry fgSingleton = null; /** <code>true</code> if this registry has been loaded. */ private boolean fLoaded; /** * <code>{@link Map}<{@link String}, {@link ICompletionProposalCategoriesConfigurationReader}></code> * <ul> * <li><b>key:</b> Content Type ID</li> * <li><b>value:</b> Categories Properties</li> */ private Map fPropertiesByContentTypeID; /** * @return the singleton instance of this registry */ public static synchronized CompletionProposoalCatigoriesConfigurationRegistry getDefault() { if (fgSingleton == null) { fgSingleton = new CompletionProposoalCatigoriesConfigurationRegistry(); } return fgSingleton; } /** * Private constructor to create singleton instance */ private CompletionProposoalCatigoriesConfigurationRegistry() { this.fLoaded = false; this.fPropertiesByContentTypeID = new HashMap(); } /** * @param contentTypeID get the {@link ICompletionProposalCategoriesConfigurationReader} associated * with the given content type * @return the {@link ICompletionProposalCategoriesConfigurationReader} associated * with the given content type, or <code>null</code> if one does not exist. */ public ICompletionProposalCategoriesConfigurationReader getReadableConfiguration(String contentTypeID) { this.ensureLoaded(); IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID); // Check if any base types are within the properties map while (contentType != null) { final String id = contentType.getId(); if (fPropertiesByContentTypeID.containsKey(id)) { contentTypeID = id; break; } contentType = contentType.getBaseType(); } return (ICompletionProposalCategoriesConfigurationReader)this.fPropertiesByContentTypeID.get(contentTypeID); } /** * @param contentTypeID get the {@link ICompletionProposalCategoriesConfigurationWriter} associated * with the given content type * @return the {@link ICompletionProposalCategoriesConfigurationWriter} associated * with the given content type, or <code>null</code> if one does not exist. */ public ICompletionProposalCategoriesConfigurationWriter getWritableConfiguration(String contentTypeID) { this.ensureLoaded(); ICompletionProposalCategoriesConfigurationReader reader = getReadableConfiguration(contentTypeID); ICompletionProposalCategoriesConfigurationWriter writer = null; if(reader instanceof ICompletionProposalCategoriesConfigurationWriter) { writer = (ICompletionProposalCategoriesConfigurationWriter)reader; } return writer; } /** * Ensures the <code>org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration</code> * extensions have been loaded */ private void ensureLoaded() { if(!this.fLoaded) { this.load(); this.fLoaded = true; } } /** * Loads the <code>org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration</code> extensions */ private void load() { //get the extensions IExtensionRegistry registry= Platform.getExtensionRegistry(); List extensionElements= new ArrayList(Arrays.asList(registry.getConfigurationElementsFor(SSEUIPlugin.ID, EXTENSION_POINT))); //for each element get its attributes and add it to the map of properties Iterator elementsIter = extensionElements.iterator(); while(elementsIter.hasNext()) { IConfigurationElement element = (IConfigurationElement)elementsIter.next(); try { if(element.getName().equals(ELEM_CATEGORIES_PROPERTIES)) { String contentTypeID = element.getAttribute(ATTR_CONTENT_TYPE_ID); ContentAssistUtils.checkExtensionAttributeNotNull(contentTypeID, ATTR_CONTENT_TYPE_ID, element); String pageClass = element.getAttribute(ATTR_CLASS); ContentAssistUtils.checkExtensionAttributeNotNull(pageClass, ATTR_CLASS, element); ICompletionProposalCategoriesConfigurationReader props = (ICompletionProposalCategoriesConfigurationReader)element.createExecutableExtension(ATTR_CLASS); if(!this.fPropertiesByContentTypeID.containsKey(contentTypeID)){ this.fPropertiesByContentTypeID.put(contentTypeID, props); } else { Logger.log(Logger.ERROR, "Extension " + element.getDeclaringExtension() + //$NON-NLS-1$ " is attempting to to define itself as the proposal cateigories" + //$NON-NLS-1$ " configuration for content type " + contentTypeID + " when another" + //$NON-NLS-1$ //$NON-NLS-2$ " extensions has already done so."); //$NON-NLS-1$ } } else { //extension specified element that is not valid for this extension Logger.log(Logger.WARNING, "The element " + element + " is not valid for the" + //$NON-NLS-1$ //$NON-NLS-2$ "org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration" + //$NON-NLS-1$ " extension point. Only " + ELEM_CATEGORIES_PROPERTIES + //$NON-NLS-1$ " elements are valid."); //$NON-NLS-1$ } } catch (InvalidRegistryObjectException x) { /* * Element is not valid any longer as the contributing plug-in was unloaded * or for some other reason. */ String message = "The extension ''" + element.toString() + "'' has become invalid."; //$NON-NLS-1$ //$NON-NLS-2$ IStatus status= new Status(IStatus.WARNING, SSEUIPlugin.ID, IStatus.OK, message, x); Logger.log(status); } catch (CoreException x) { Logger.log(x.getStatus()); } } } }