| /*=============================================================================# |
| # Copyright (c) 2007, 2020 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.ltk.core; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.content.IContentType; |
| import org.eclipse.core.runtime.content.IContentTypeManager; |
| |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.lang.Disposable; |
| |
| import org.eclipse.statet.ltk.core.IExtContentTypeManager; |
| |
| |
| public class ExtContentTypeServices implements IExtContentTypeManager, Disposable { |
| |
| |
| private static boolean matches(IContentType type, final String typeId) { |
| while (type != null) { |
| if (typeId.equals(type.getId())) { |
| return true; |
| } |
| type= type.getBaseType(); |
| } |
| return false; |
| } |
| |
| private static boolean matches(final String[] ids, final String typeId) { |
| for (int i= 0; i < ids.length; i++) { |
| if (typeId.equals(ids[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private static void add(final Map<String, Set<String>> map, final String key, final String value) { |
| Set<String> set= map.get(key); |
| if (set == null) { |
| set= new HashSet<>(); |
| map.put(key, set); |
| } |
| set.add(value); |
| } |
| |
| private static Map<String, String[]> copy(final Map<String, Set<String>> from, final Map<String, String[]> to) { |
| for (final Map.Entry<String, Set<String>> entry : from.entrySet()) { |
| final Set<String> set= entry.getValue(); |
| to.put(entry.getKey(), set.toArray(new String[set.size()])); |
| } |
| return to; |
| } |
| |
| |
| private static final String CONFIG_CONTENTTYPEACTIVATION_EXTENSIONPOINT_ID= "org.eclipse.statet.ltk.ContentTypeActivation"; //$NON-NLS-1$ |
| private static final String CONFIG_CONTENTTYPE_ELEMENT_NAME= "contentType"; //$NON-NLS-1$ |
| private static final String CONFIG_ID_ATTRIBUTE_NAME= "id"; //$NON-NLS-1$ |
| private static final String CONFIG_CONTENTTYPE_ID_ATTRIBUTE_NAME= "contentTypeId"; //$NON-NLS-1$ |
| private static final String CONFIG_SECONDARY_ID_ATTRIBUTE_NAME= "secondaryId"; //$NON-NLS-1$ |
| private static final String CONFIG_MODELTYPE_ID_ATTRIBUTE_NAME= "modelTypeId"; //$NON-NLS-1$ |
| |
| |
| private static final String[] NO_TYPES= new String[0]; |
| |
| |
| private Map<String, String[]> primaryToSecondary; |
| private Map<String, String[]> secondaryToPrimary; |
| private Map<String, String> primaryToModel; |
| private Map<String, ModelTypeDescriptor> modelDescriptors; |
| |
| |
| public ExtContentTypeServices() { |
| load(); |
| } |
| |
| |
| private void load() { |
| final IExtensionRegistry extensionRegistry= Platform.getExtensionRegistry(); |
| |
| final Map<String, ModelTypeDescriptor> modelTypes= new HashMap<>(); |
| |
| final Map<String, Set<String>> primaryToSecondary= new HashMap<>(); |
| final Map<String, Set<String>> secondaryToPrimary= new HashMap<>(); |
| final Map<String, String> primaryToModel= new HashMap<>(); |
| |
| { final IConfigurationElement[] elements= extensionRegistry |
| .getConfigurationElementsFor(CONFIG_CONTENTTYPEACTIVATION_EXTENSIONPOINT_ID); |
| for (final IConfigurationElement element : elements) { |
| if (element.getName().equals(CONFIG_CONTENTTYPE_ELEMENT_NAME)) { |
| String primary= element.getAttribute(CONFIG_ID_ATTRIBUTE_NAME); |
| String secondary= element.getAttribute(CONFIG_SECONDARY_ID_ATTRIBUTE_NAME); |
| if (primary != null && secondary != null |
| && primary.length() > 0 && secondary.length() > 0) { |
| primary= primary.intern(); |
| secondary= secondary.intern(); |
| add(primaryToSecondary, primary, secondary); |
| add(secondaryToPrimary, secondary, primary); |
| } |
| } |
| } |
| } |
| { final IConfigurationElement[] elements= extensionRegistry |
| .getConfigurationElementsFor("org.eclipse.statet.ltk.ModelTypes"); //$NON-NLS-1$ |
| for (final IConfigurationElement element : elements) { |
| if (element.getName().equals("modelType")) { //$NON-NLS-1$ |
| String id= element.getAttribute(CONFIG_ID_ATTRIBUTE_NAME); |
| if (id != null && !id.isEmpty()) { |
| id= id.intern(); |
| ModelTypeDescriptor descriptor= modelTypes.get(id); |
| if (descriptor == null) { |
| descriptor= new ModelTypeDescriptor(id); |
| modelTypes.put(id, descriptor); |
| } |
| final IConfigurationElement[] children= element.getChildren(); |
| for (final IConfigurationElement child : children) { |
| if (child.getName().equals("secondaryType")) { //$NON-NLS-1$ |
| String secondaryId= child.getAttribute(CONFIG_MODELTYPE_ID_ATTRIBUTE_NAME); |
| if (secondaryId != null && !secondaryId.isEmpty()) { |
| secondaryId= secondaryId.intern(); |
| if (!descriptor.secondaryTypeIds.contains(secondaryId)) { |
| descriptor.secondaryTypeIds.add(secondaryId); |
| } |
| } |
| } |
| } |
| } |
| } |
| if (element.getName().equals(CONFIG_CONTENTTYPE_ELEMENT_NAME)) { |
| String contentTypeId= element.getAttribute(CONFIG_CONTENTTYPE_ID_ATTRIBUTE_NAME); |
| String modelTypeId= element.getAttribute(CONFIG_MODELTYPE_ID_ATTRIBUTE_NAME); |
| if (contentTypeId != null && !contentTypeId.isEmpty() |
| && modelTypeId != null && !modelTypeId.isEmpty() ) { |
| contentTypeId= contentTypeId.intern(); |
| modelTypeId= modelTypeId.intern(); |
| primaryToModel.put(contentTypeId, modelTypeId); |
| } |
| } |
| } |
| } |
| |
| checkModelTypes(modelTypes); |
| |
| this.primaryToSecondary= copy(primaryToSecondary, new HashMap<String, String[]>()); |
| this.secondaryToPrimary= copy(secondaryToPrimary, new HashMap<String, String[]>()); |
| this.primaryToModel= primaryToModel; |
| this.modelDescriptors= modelTypes; |
| } |
| |
| private static void checkModelTypes(final Map<String, ModelTypeDescriptor> modelTypes) { |
| final List<String> temp= new ArrayList<>(); |
| for (final ModelTypeDescriptor descriptor : modelTypes.values()) { |
| synchronized (descriptor) { |
| temp.clear(); |
| for (final String sId : descriptor.secondaryTypeIds) { |
| if (modelTypes.containsKey(sId)) { |
| temp.add(sId); |
| } |
| } |
| descriptor.checkedSecondaryTypeIds= ImCollections.toList(temp); |
| } |
| } |
| } |
| |
| |
| @Override |
| public String[] getSecondaryContentTypes(final String primaryContentType) { |
| final String[] types= this.primaryToSecondary.get(primaryContentType); |
| return (types != null) ? types : ExtContentTypeServices.NO_TYPES; |
| } |
| |
| @Override |
| public String[] getPrimaryContentTypes(final String secondaryContentType) { |
| final String[] types= this.secondaryToPrimary.get(secondaryContentType); |
| return (types != null) ? types : ExtContentTypeServices.NO_TYPES; |
| } |
| |
| @Override |
| public boolean matchesActivatedContentType(final String primaryContentTypeId, final String activatedContentTypeId, final boolean self) { |
| final IContentTypeManager manager= Platform.getContentTypeManager(); |
| final IContentType primaryContentType= manager.getContentType(primaryContentTypeId); |
| IContentType primary= primaryContentType; |
| if (self && |
| (primary.getId().equals(activatedContentTypeId) |
| || matches(primary, activatedContentTypeId))) { |
| return true; |
| } |
| while (primary != null) { |
| final String[] types= getSecondaryContentTypes(primary.getId()); |
| if (types != null && matches(types, activatedContentTypeId)) { |
| return true; |
| } |
| primary= primary.getBaseType(); |
| } |
| return false; |
| } |
| |
| |
| @Override |
| public ModelTypeDescriptor getModelType(final String modelTypeId) { |
| return (modelTypeId != null) ? this.modelDescriptors.get(modelTypeId) : null; |
| } |
| |
| @Override |
| public ModelTypeDescriptor getModelTypeForContentType(final String contentTypeId) { |
| return getModelType(this.primaryToModel.get(contentTypeId)); |
| } |
| |
| |
| @Override |
| public void dispose() { |
| } |
| |
| } |