1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 133881 - Make refreshing after building optional

Work in progress.
This commit is contained in:
Chris Recoskie 2011-02-24 02:46:01 +00:00
parent 1d85f97705
commit 2d42d08abc
8 changed files with 807 additions and 0 deletions

View file

@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2011 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.cdt.core.resources;
import org.eclipse.osgi.util.NLS;
/**
* @since 5.3
*/
public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.cdt.core.resources.messages"; //$NON-NLS-1$
public static String RefreshScopeManager_0;
public static String RefreshScopeManager_1;
public static String RefreshScopeManager_2;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
}
}

View file

@ -0,0 +1,331 @@
/*******************************************************************************
* Copyright (c) 2011 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.cdt.core.resources;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.resources.IResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* A RefreshExclusion represents a rule for excluding certain resources from being refreshed.
*
* Clients should extend this class to provide support for their own custom exclusions.
*
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
* that it will remain the same. Please do not use this API without consulting
* with the CDT team.
*
* @author crecoskie
* @since 5.3
*
*/
public abstract class RefreshExclusion {
public static final String EXTENSION_DATA_ELEMENT_NAME = "extensionData"; //$NON-NLS-1$
public static final String CONTRIBUTOR_ID_ATTRIBUTE_NAME = "contributorId"; //$NON-NLS-1$
public static final String INSTANCE_ELEMENT_NAME = "instance"; //$NON-NLS-1$
public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$
public static final String EXCLUSION_TYPE_ATTRIBUTE_NAME = "exclusionType"; //$NON-NLS-1$
public static final String EXCLUSION_ELEMENT_NAME = "exclusion"; //$NON-NLS-1$
public static final String RESOURCE_VALUE = "RESOURCE"; //$NON-NLS-1$
public static final String FOLDER_VALUE = "FOLDER"; //$NON-NLS-1$
public static final String FILE_VALUE = "FILE"; //$NON-NLS-1$
public static final String DISPLAY_STRING_ATTRIBUTE_NAME = "displayString"; //$NON-NLS-1$
/**
* Indicates the type of resources that this exclusion can exclude. Used to determine which type of icon is displayed in
* the exclusion UI when this exclusion is present.
*
*/
public enum ExclusionType {
/**
* Constant indicating that this exclusion only excludes folders.
*/
FOLDER,
/**
* Constant indicating that this exclusion only excludes folders.
*/
FILE,
/**
* Constant indicating that this exclusion can exclude any resource.
*/
RESOURCE
}
/**
* Represents a particular instance of an exclusion. E.g., if an exclusion allowed
* for the exclusion of a list individual resources, there would be one exclusion instance
* per resource. Each exclusion instance is presented in the user interface as a child of the exclusion.
*
* Clients may extend this class to provide custom implementations for their exclusion type.
*
*/
public class ExclusionInstance {
private ExclusionType fInstanceExclusionType;
private IResource fResource;
private String fDisplayString;
public ExclusionType getExclusionType() {
return fInstanceExclusionType;
}
public void setExclusionType(ExclusionType type) {
fInstanceExclusionType = type;
}
/**
* If there is a resource directly associated with this exclusion instance, returns the resource.
*
* @return IResource
*/
public IResource getResource() {
return fResource;
}
public void setResource(IResource resource) {
fResource = resource;
}
/**
* @return a String corresponding to the human-readable name for this exclusion instance.
* Examples of this would be the resource name for a resource based exclusion, or the file extension
* excluded by a file extension exclusion.
*/
public String getDisplayString() {
return fDisplayString;
}
public void setDisplayString(String displayString) {
fDisplayString = displayString;
}
public void persistInstanceData(Document doc, Element extensionElement) {
Element instanceElement = doc.createElement(INSTANCE_ELEMENT_NAME);
// persist the exclusion type
String exclusionType = null;
switch(getExclusionType()) {
case FILE:
exclusionType = FILE_VALUE;
break;
case FOLDER:
exclusionType = FOLDER_VALUE;
break;
case RESOURCE:
exclusionType = RESOURCE_VALUE;
break;
}
if(exclusionType != null) {
instanceElement.setAttribute(EXCLUSION_TYPE_ATTRIBUTE_NAME, exclusionType);
}
// persist resource path
if(fResource != null) {
instanceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, fResource.getFullPath().toString());
}
// persist display string
if(fDisplayString != null) {
instanceElement.setAttribute(DISPLAY_STRING_ATTRIBUTE_NAME, fDisplayString);
}
// persist any data from extenders
persistExtendedInstanceData(doc, instanceElement);
}
protected void persistExtendedInstanceData(Document doc, Element instanceElement) {
// override to provide extension specific behaviour if desired
}
public void loadInstanceData(Element extensionElement) {
}
protected void loadExtendedInstanceData(Element instanceElement) {
// override to provide extension specific behaviour if desired
}
}
protected List<ExclusionInstance> fExclusionInstanceList = new LinkedList<ExclusionInstance>();
protected List<RefreshExclusion> fNestedExclusions = new LinkedList<RefreshExclusion>();
protected ExclusionType fExclusionType;
protected RefreshExclusion fParent;
protected String fContributorId;
/**
* @return a String corresponding to the ID of the RefreshExclusionContributor that was used to create
* this exclusion.
*/
public String getContributorId() {
return fContributorId;
}
public void setContributorId(String id) {
fContributorId = id;
}
/**
* If this is a nested exclusion, returns the exclusion which is the direct parent of this one.
*
* @return RefreshExclusion
*/
public RefreshExclusion getParent() {
return fParent;
}
public void setParent(RefreshExclusion parent) {
fParent = parent;
}
public ExclusionType getExclusionType() {
return fExclusionType;
}
public void setExclusionType(ExclusionType exclusionType) {
fExclusionType = exclusionType;
}
/**
* @return a String corresponding to the human-readable name for this exclusion.
*/
public abstract String getName();
/**
* Tests a given resource to see if this exclusion should exclude it from being refreshed.
*
* @param resource the resource to be tested.
* @return true if the resource should be excluded, false otherwise.
*/
public abstract boolean testExclusion(IResource resource);
/**
* @return an unmodifiable list of all the instance of this exclusion
*/
public List<ExclusionInstance> getExclusionInstances() {
return Collections.unmodifiableList(fExclusionInstanceList);
}
/**
* Adds an instance to the list of instances of this exclusion.
*
* @param exclusionInstance
*/
public void addExclusionInstance(ExclusionInstance exclusionInstance) {
fExclusionInstanceList.add(exclusionInstance);
}
/**
* Removes an exclusion instance from the list of instances of this exclusion.
*
* @param exclusionInstance
*/
public void removeExclusionInstance(ExclusionInstance exclusionInstance) {
fExclusionInstanceList.remove(exclusionInstance);
}
/**
*
* @return an unmodifiable list of exclusions to this exclusion.
*/
public List<RefreshExclusion> getNestedExclusions() {
return Collections.unmodifiableList(fNestedExclusions);
}
public void addNestedExclusion(RefreshExclusion exclusion) {
fNestedExclusions.add(exclusion);
exclusion.setParent(this);
}
/**
* Removes the given nested exclusion. The exclusion must be a direct child of this exclusion.
*
* @param exclusion
*/
public void removeNestedExclusion(RefreshExclusion exclusion) {
fNestedExclusions.remove(exclusion);
}
public void persistData(Document doc, Element parentElement) {
// persist the common data that all RefreshExclusions have
Element exclusionElement = doc.createElement(EXCLUSION_ELEMENT_NAME);
// persist the exclusion type
String exclusionType = null;
switch(getExclusionType()) {
case FILE:
exclusionType = FILE_VALUE;
break;
case FOLDER:
exclusionType = FOLDER_VALUE;
break;
case RESOURCE:
exclusionType = RESOURCE_VALUE;
break;
}
if(exclusionType != null) {
exclusionElement.setAttribute(EXCLUSION_TYPE_ATTRIBUTE_NAME, exclusionType);
}
// note: no need to persist parent, the parent relationship will be determined on load by
// the structure of the XML tree
exclusionElement.setAttribute(CONTRIBUTOR_ID_ATTRIBUTE_NAME, getContributorId());
parentElement.appendChild(exclusionElement);
// provide a place for extenders to store their own data
Element extensionElement = doc.createElement(EXTENSION_DATA_ELEMENT_NAME);
exclusionElement.appendChild(extensionElement);
// persist instances
for(ExclusionInstance instance : fExclusionInstanceList) {
instance.persistInstanceData(doc, extensionElement);
}
// call extender to store any extender-specific data
persistExtendedData(doc, extensionElement);
// persist nested exclusions
for(RefreshExclusion exclusion : fNestedExclusions) {
exclusion.persistData(doc, exclusionElement);
}
}
protected void persistExtendedData(Document doc, Element extensionElement) {
// override to provide extension specific behaviour if desired
}
protected void loadExtendedData(Element parentElement) {
// override to provide extension specific behaviour if desired
}
public void loadData(Element parentElement) {
}
}

View file

@ -0,0 +1,181 @@
/*******************************************************************************
* Copyright (c) 2011 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.cdt.core.resources;
import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* The RefreshScopeManager provides access to settings pertaining to refreshes performed during
* a build. Each project may have a set of resources associated with it that are the set of resources
* to be refreshed. An exclusion mechanism exists that allows for one to specify arbitrarily complicated,
* nested logic that determines whether or not a given resource is refreshed according to previously
* specified rules.
*
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
* that it will remain the same. Please do not use this API without consulting
* with the CDT team.
*
* @author crecoskie
* @since 5.3
*
*/
public class RefreshScopeManager {
public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$
public static final String RESOURCE_ELEMENT_NAME = "resource"; //$NON-NLS-1$
public static final String VERSION_NUMBER_ATTRIBUTE_NAME = "versionNumber"; //$NON-NLS-1$
public static final String VERSION_ELEMENT_NAME = "version"; //$NON-NLS-1$
public static final QualifiedName REFRESH_SCOPE_PROPERTY_NAME = new QualifiedName(CCorePlugin.PLUGIN_ID, "refreshScope"); //$NON-NLS-1$
private int fVersion = 1;
private RefreshScopeManager(){
}
private TreeMap<IProject, Set<IResource>> fProjectToResourcesMap;
private TreeMap<IResource, List<RefreshExclusion>> fResourceToExclusionsMap;
private static RefreshScopeManager fInstance;
public static synchronized RefreshScopeManager getInstance() {
if(fInstance == null) {
fInstance = new RefreshScopeManager();
}
return fInstance;
}
public int getVersion() {
return fVersion;
}
/**
* Returns the set of resources that should be refreshed for a project.
* These resources might have associated exclusions.
*
* @param project
* @return Set<IResource>
*/
public Set<IResource> getResourcesToRefresh(IProject project) {
Set<IResource> retval = fProjectToResourcesMap.get(project);
if(retval == null) {
return Collections.emptySet();
}
return retval;
}
public List<RefreshExclusion> getExclusions(IResource resource) {
return fResourceToExclusionsMap.get(resource);
}
public void addExclusion(IResource resource, RefreshExclusion exclusion) {
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
exclusions.add(exclusion);
}
public void removeExclusion(IResource resource, RefreshExclusion exclusion) {
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
exclusions.remove(exclusion);
}
public void persistSettings() throws CoreException {
for(IProject project : fProjectToResourcesMap.keySet()) {
// serialize all settings for the project to an XML document which we will use to persist
// the data to a persistent resource property
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = docBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new CoreException(CCorePlugin.createStatus(Messages.RefreshScopeManager_0, e));
}
// create document root
Document doc = docBuilder.newDocument();
Element root = doc.createElement("root"); //$NON-NLS-1$
doc.appendChild(root);
Element versionElement = doc.createElement(VERSION_ELEMENT_NAME);
versionElement.setAttribute(VERSION_NUMBER_ATTRIBUTE_NAME, Integer.toString(fVersion));
root.appendChild(versionElement);
for(IResource resource : fProjectToResourcesMap.get(project)) {
// create a resource node
Element resourceElement = doc.createElement(RESOURCE_ELEMENT_NAME);
resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource.getFullPath().toString());
root.appendChild(resourceElement);
// populate the node with any exclusions
for(RefreshExclusion exclusion : fResourceToExclusionsMap.get(resource)) {
exclusion.persistData(doc, resourceElement);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer;
try {
transformer = transformerFactory.newTransformer();
} catch (TransformerConfigurationException e) {
throw new CoreException(CCorePlugin.createStatus(Messages.RefreshScopeManager_1, e));
}
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
//create a string from xml tree
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
DOMSource source = new DOMSource(doc);
try {
transformer.transform(source, result);
} catch (TransformerException e) {
throw new CoreException(CCorePlugin.createStatus(Messages.RefreshScopeManager_2, e));
}
String xmlString = stringWriter.toString();
// use the string as a value for a persistent resource property on the project
project.setPersistentProperty(REFRESH_SCOPE_PROPERTY_NAME, xmlString);
}
}
public void loadSettings() {
}
}

View file

@ -0,0 +1,13 @@
###############################################################################
# Copyright (c) 2011 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
###############################################################################
RefreshScopeManager_0=Error instantiating XML document builder.
RefreshScopeManager_1=Error instantiating XML transformer.
RefreshScopeManager_2=Error transforming XML.

View file

@ -26,6 +26,7 @@
<extension-point id="quickAssistProcessors" name="%quickAssistProcessorExtensionPoint" schema="schema/quickAssistProcessors.exsd"/>
<extension-point id="DocCommentOwner" name="%DocCommentOwner.name" schema="schema/DocCommentOwner.exsd"/>
<extension-point id="workingSetConfigurations" name="%workingSetConfigurationsExtensionPoint" schema="schema/workingSetConfigurations.exsd"/>
<extension-point id="RefreshExclusionContributor" name="Refresh Exclusion Contributor" schema="schema/RefreshExclusionContributor.exsd"/>
<extension
point="org.eclipse.core.runtime.adapters">

View file

@ -0,0 +1,126 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.ui" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.ui" id="RefreshExclusionContributor" name="Refresh Exclusion Contributor"/>
</appInfo>
<documentation>
This extension point allows for contribution of new types of refresh exclusions to CDT&apos;s refresh exclusion system. A refresh exclusion is essentially some arbitrary rule that can be tested against a given resource and evaluates to true or false. The exclusion returns true if it should be applied (i.e. the tested resource should be excluded). Rules can be nested, so it is possible to have exclusions to exclusions.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="exclusionContributor"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="exclusionContributor">
<annotation>
<documentation>
A contribution of a new type of refresh exclusion.
</documentation>
</annotation>
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
Java class corresponding to the contribution, responsible both for acting as a factory that creates concrete instances of the exclusion, as well as providing a UI for modifying properties specific to the exclusion.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.ui.resources.RefreshExclusionContribution:"/>
</appInfo>
</annotation>
</attribute>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
A unique string that identifies this contribution.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
5.3
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
There is a supplied implementation for Resource Exclusions.
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
Copyright (c) 2011 IBM Corporation and others.&lt;br&gt;
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 &lt;a
href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
</documentation>
</annotation>
</schema>

View file

@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2011 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.cdt.ui.resources;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
* that it will remain the same. Please do not use this API without consulting
* with the CDT team.
*
* @author crecoskie
*
*/
public class RefreshExclusionContributionManager {
public static final String EXCLUSION_CONTRIBUTOR = "exclusionContributor"; //$NON-NLS-1$
public static final String EXTENSION_ID = "RefreshExclusionContributor"; //$NON-NLS-1$
private Map<String, RefreshExclusionContributor> fIDtoContributorsMap;
private static RefreshExclusionContributionManager fInstance;
private RefreshExclusionContributionManager() {
fIDtoContributorsMap = new HashMap<String, RefreshExclusionContributor>();
loadExtensions();
}
public static synchronized RefreshExclusionContributionManager getInstance() {
if(fInstance == null) {
fInstance = new RefreshExclusionContributionManager();
}
return fInstance;
}
public synchronized void loadExtensions() {
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CUIPlugin.PLUGIN_ID,
EXTENSION_ID);
if (extension != null) {
IExtension[] extensions = extension.getExtensions();
for (IExtension extension2 : extensions) {
IConfigurationElement[] configElements = extension2.getConfigurationElements();
for (IConfigurationElement configElement : configElements) {
if (configElement.getName().equals(EXCLUSION_CONTRIBUTOR)) {
String id = configElement.getAttribute("id"); //$NON-NLS-1$
String utility = configElement.getAttribute("class"); //$NON-NLS-1$
if (utility != null) {
try {
Object execExt = configElement.createExecutableExtension("class"); //$NON-NLS-1$
if ((execExt instanceof RefreshExclusionContributor) && id != null) {
fIDtoContributorsMap.put(id, (RefreshExclusionContributor) execExt);
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2011 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.cdt.ui.resources;
import org.eclipse.swt.widgets.Composite;
import org.w3c.dom.Element;
import org.eclipse.cdt.core.resources.RefreshExclusion;
/**
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as
* part of a work in progress. There is no guarantee that this API will work or
* that it will remain the same. Please do not use this API without consulting
* with the CDT team.
*
* @author crecoskie
*
*/
public abstract class RefreshExclusionContributor {
protected String fID;
public String getID() {
return fID;
}
public void setID(String id) {
fID = id;
}
abstract public RefreshExclusion createExclusion();
abstract public void createProperiesUI(Composite parent);
abstract public RefreshExclusion createExclusionFromXML(Element exclusionElement);
}