/*******************************************************************************
* Copyright (c) 2000, 2008 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.core.internal.resources;
import java.util.*;
import org.eclipse.core.internal.utils.Policy;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
public class MarkerTypeDefinitionCache {
static class MarkerTypeDefinition {
boolean isPersistent= false;
Set superTypes;
MarkerTypeDefinition(IExtension ext) {
IConfigurationElement[] elements= ext.getConfigurationElements();
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
// supertype
final String elementName= element.getName();
if (elementName.equalsIgnoreCase("super")) { //$NON-NLS-1$
String aType= element.getAttribute("type"); //$NON-NLS-1$
if (aType != null) {
if (superTypes == null)
superTypes= new HashSet(8);
//note that all marker type names will be in the intern table
//already because there is invariably a constant to describe
//the type name
superTypes.add(aType.intern());
}
}
// persistent
if (elementName.equalsIgnoreCase("persistent")) { //$NON-NLS-1$
String bool= element.getAttribute("value"); //$NON-NLS-1$
if (bool != null)
this.isPersistent= Boolean.valueOf(bool).booleanValue();
}
// XXX: legacy code for support of <transient> tag. remove later.
if (elementName.equalsIgnoreCase("transient")) { //$NON-NLS-1$
String bool= element.getAttribute("value"); //$NON-NLS-1$
if (bool != null)
this.isPersistent= !Boolean.valueOf(bool).booleanValue();
}
}
}
}
/**
* The marker type definitions. Maps String (markerId) -> MarkerTypeDefinition
*/
protected HashMap definitions;
/**
* Constructs a new type cache.
*/
public MarkerTypeDefinitionCache() {
loadDefinitions();
HashSet toCompute= new HashSet(definitions.keySet());
for (Iterator i= definitions.keySet().iterator(); i.hasNext();) {
String markerId= (String)i.next();
if (toCompute.contains(markerId))
computeSuperTypes(markerId, toCompute);
}
}
/**
* Computes the transitive set of super types of the given marker type.
*
* @param markerId The type to compute super types for
* @param toCompute The set of types that have not yet had their supertypes computed.
* @return The transitive set of super types for this marker, or null if this marker is not
* defined or has no super types.
*/
private Set computeSuperTypes(String markerId, Set toCompute) {
MarkerTypeDefinition def= (MarkerTypeDefinition)definitions.get(markerId);
if (def == null || def.superTypes == null) {
//nothing to do if there are no supertypes
toCompute.remove(markerId);
return null;
}
Set transitiveSuperTypes= new HashSet(def.superTypes);
for (Iterator it= def.superTypes.iterator(); it.hasNext();) {
String superId= (String)it.next();
Set toAdd= null;
if (toCompute.contains(superId)) {
//this type's super types have not been compute yet. Do recursive call
toAdd= computeSuperTypes(superId, toCompute);
} else {
// we have already computed this super type's super types (or it doesn't exist)
MarkerTypeDefinition parentDef= (MarkerTypeDefinition)definitions.get(superId);
if (parentDef != null)
toAdd= parentDef.superTypes;
}
if (toAdd != null)
transitiveSuperTypes.addAll(toAdd);
}
def.superTypes= transitiveSuperTypes;
toCompute.remove(markerId);
return transitiveSuperTypes;
}
/**
* Returns true if the given marker type is defined to be persistent.
*/
public boolean isPersistent(String type) {
MarkerTypeDefinition def= (MarkerTypeDefinition)definitions.get(type);
return def != null && def.isPersistent;
}
/**
* Returns true if the given target class has the specified type as a super type.
*/
public boolean isSubtype(String type, String superType) {
//types are considered super types of themselves
if (type.equals(superType))
return true;
MarkerTypeDefinition def= (MarkerTypeDefinition)definitions.get(type);
return def != null && def.superTypes != null && def.superTypes.contains(superType);
}
private void loadDefinitions() {
IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MARKERS);
IExtension[] types= point.getExtensions();
definitions= new HashMap(types.length);
for (int i= 0; i < types.length; i++) {
String markerId= types[i].getUniqueIdentifier();
if (markerId != null)
definitions.put(markerId.intern(), new MarkerTypeDefinition(types[i]));
else
Policy.log(IStatus.WARNING, "Missing marker id from plugin: " + types[i].getContributor().getName(), null); //$NON-NLS-1$
}
}
}