/*=============================================================================#
# Copyright (c) 2007-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.ecommons.ltk.internal.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 de.walware.jcommons.collections.ImCollections;
import de.walware.ecommons.IDisposable;
import de.walware.ecommons.ltk.IExtContentTypeManager;
public class ExtContentTypeServices implements IExtContentTypeManager, IDisposable {
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 = "de.walware.ecommons.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 Map<String, String[]> fPrimaryToSecondary;
private Map<String, String[]> fSecondaryToPrimary;
private Map<String, String> primaryToModel;
private Map<String, ModelTypeDescriptor> modelDescriptors;
private final String[] NO_TYPES = new String[0];
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("de.walware.ecommons.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.fPrimaryToSecondary = copy(primaryToSecondary, new HashMap<String, String[]>());
this.fSecondaryToPrimary = 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.fPrimaryToSecondary.get(primaryContentType);
return (types != null) ? types : this.NO_TYPES;
}
@Override
public String[] getPrimaryContentTypes(final String secondaryContentType) {
final String[] types = this.fSecondaryToPrimary.get(secondaryContentType);
return (types != null) ? types : this.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() {
}
}