1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Bug 374442 - Refresh resource by build configuration

This commit is contained in:
David Salinas 2012-03-15 21:11:47 -04:00 committed by Vivian Kong
parent 12d44ec8be
commit d18cb3e07c
7 changed files with 835 additions and 467 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -25,7 +25,6 @@ import org.eclipse.cdt.core.resources.RefreshScopeManager;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.managedbuilder.internal.ui.Messages;
import org.eclipse.cdt.ui.CDTSharedImages;
import org.eclipse.cdt.ui.newui.AbstractCPropertyTab;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
@ -67,7 +66,7 @@ import org.eclipse.ui.model.WorkbenchLabelProvider;
* @since 8.0
*/
@SuppressWarnings("restriction")
public class RefreshPolicyTab extends AbstractCPropertyTab {
public class RefreshPolicyTab extends AbstractCBuildPropertyTab {
private final Image IMG_FOLDER = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_FOLDER);
private final Image IMG_FILE = ManagedBuilderUIImages.get(ManagedBuilderUIImages.IMG_FILE_OBJ);
@ -83,45 +82,82 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
private TreeViewer fTree;
private RefreshScopeManager fManager;
private IProject fProject;
private ArrayList<_Entry> fSrc;
private List<IResource> fResourcesToRefresh;
private HashMap<IResource, List<RefreshExclusion>> fResourceToExclusionsMap = new HashMap<IResource, List<RefreshExclusion>>();
private HashMap<String, HashMap<IResource, List<RefreshExclusion>>> fConfigurationToResourcesToExclusionsMap;
public RefreshPolicyTab() {
fManager = RefreshScopeManager.getInstance();
}
private void loadInfo() {
fResourcesToRefresh = new LinkedList<IResource>(fManager.getResourcesToRefresh(fProject));
if (fResourcesToRefresh != null) {
Iterator<IResource> iterator = fResourcesToRefresh.iterator();
while (iterator.hasNext()) {
IResource resource = iterator.next();
fResourceToExclusionsMap.put(resource, new LinkedList<RefreshExclusion>(fManager.getExclusions(resource)));
}
}
private HashMap<IResource, List<RefreshExclusion>> getResourcesToExclusionsMap(String configName) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = fConfigurationToResourcesToExclusionsMap.get(configName);
if (resourceMap == null) {
resourceMap = new HashMap<IResource, List<RefreshExclusion>>();
fConfigurationToResourcesToExclusionsMap.put(configName, resourceMap);
}
return resourceMap;
}
private List<RefreshExclusion> getExclusions(IResource resource) {
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
private String getConfigName() {
return this.getCfg().getName();
}
private HashMap<String, HashMap<IResource, List<RefreshExclusion>>> copyHashMap(HashMap<String, HashMap<IResource, List<RefreshExclusion>>> source) {
HashMap<String, HashMap<IResource, List<RefreshExclusion>>> target = new HashMap<String, HashMap<IResource, List<RefreshExclusion>>>();
Iterator<String> config_iterator = source.keySet().iterator();
// for each Configuration ...
while (config_iterator.hasNext()) {
String configName = config_iterator.next();
HashMap<IResource, List<RefreshExclusion>> source_resourceMap = source.get(configName);
HashMap<IResource, List<RefreshExclusion>> target_resourceMap = new HashMap<IResource, List<RefreshExclusion>>();
Iterator<IResource> resource_iterator = source_resourceMap.keySet().iterator();
while (resource_iterator.hasNext()) {
IResource source_resource = resource_iterator.next();
List<RefreshExclusion> source_exclusions = source_resourceMap.get(source_resource);
List<RefreshExclusion> target_exclusions = new LinkedList<RefreshExclusion>();
for (RefreshExclusion exclusion : source_exclusions) {
// ADD each exclusion to the target exclusion list.
RefreshExclusion target_exclusion = (RefreshExclusion) exclusion.clone();
target_exclusions.add(target_exclusion);
}
// ADD the exclusion list for this resource
target_resourceMap.put(source_resource, target_exclusions);
}
// ADD each resource.
target.put(configName, target_resourceMap);
}
return target;
}
private void loadInfo() {
HashMap<String, HashMap<IResource, List<RefreshExclusion>>> configMap = fManager.getConfigurationToResourcesMap(fProject);
fConfigurationToResourcesToExclusionsMap = copyHashMap(configMap);
}
private List<RefreshExclusion> getExclusions(String configName, IResource resource) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(configName);
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if(exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
fResourceToExclusionsMap.put(resource, exclusions);
resourceMap.put(resource, exclusions);
}
return fResourceToExclusionsMap.get(resource);
return resourceMap.get(resource);
}
/**
* Wrapper for IResource/RefreshExclusion
*/
class _Entry {
//if this is not a resource to refresh, resourceToRefresh will be null
//if this is a refresh exclusion, resourceToRefresh will be null
IResource resourceToRefresh = null;
//if this is not a refresh exclusion, exclusion will be null
//if this is a resource to refresh, exclusion will be null
RefreshExclusion exclusion = null;
//if this is a refresh exclusion, parent is the Exceptions node this is a child of
@ -135,7 +171,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
_Entry(IResource _ent) {
resourceToRefresh = _ent;
if (getExclusions(resourceToRefresh) != null && getExclusions(resourceToRefresh).size() > 0)
if (getExclusions(getConfigName(),resourceToRefresh) != null && getExclusions(getConfigName(),resourceToRefresh).size() > 0)
exceptions_node = new _Exception_Node(this);
}
@ -206,7 +242,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
if (parentEntry.isExclusion()) {
parentEntry.exclusion.removeNestedExclusion(exclusionToRemove);
} else {
List<RefreshExclusion> exceptions = getExclusions(parentEntry.resourceToRefresh);
List<RefreshExclusion> exceptions = getExclusions(getConfigName(), parentEntry.resourceToRefresh);
exceptions.remove(exclusionToRemove);
}
@ -217,8 +253,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
parentEntry.exceptions_node = null;
}
} else { //this is a resource to refresh
fResourceToExclusionsMap.remove(resourceToRefresh);
fResourcesToRefresh.remove(resourceToRefresh);
getResourcesToExclusionsMap(getConfigName()).remove(resourceToRefresh);
fSrc.remove(this);
}
}
@ -239,8 +274,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
if (parent.exclusion.getNestedExclusions() != null)
iterator = parent.exclusion.getNestedExclusions().iterator();
} else {
if (getExclusions(parent.resourceToRefresh) != null)
iterator = getExclusions(parent.resourceToRefresh).iterator();
if (getExclusions(getConfigName(),parent.resourceToRefresh) != null)
iterator = getExclusions(getConfigName(),parent.resourceToRefresh).iterator();
}
if (iterator != null) {
@ -256,10 +291,10 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
if (parent.isExclusion()) {
parent.exclusion.addNestedExclusion(exclusion);
} else {
List<RefreshExclusion> exclusions = getExclusions(parent.resourceToRefresh);
List<RefreshExclusion> exclusions = getExclusions(getConfigName(),parent.resourceToRefresh);
if (exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
fResourceToExclusionsMap.put(parent.resourceToRefresh, exclusions);
getResourcesToExclusionsMap(getConfigName()).put(parent.resourceToRefresh, exclusions);
}
exclusions.add(exclusion);
}
@ -309,8 +344,6 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#createControls(org.eclipse.swt.widgets.Composite)
*/
@ -332,7 +365,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
Group g1 = setupGroup(usercomp, Messages.RefreshPolicyTab_resourcesGroupLabel, 2, GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
fSrc = new ArrayList<_Entry>();
generateTreeContent(fProject);
generateTreeContent();
fTree = new TreeViewer(g1);
fTree.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
@ -446,14 +479,19 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
}
}
private void generateTreeContent(IProject project) {
Iterator<IResource> iterator = fResourcesToRefresh.iterator();
private void generateTreeContent() {
Iterator<IResource> iterator = getResourcesToExclusionsMap(getConfigName()).keySet().iterator();
while (iterator.hasNext()) {
_Entry top = new _Entry(iterator.next());
fSrc.add(top);
}
}
private void clearTreeContent() {
// Just clear the fSrc.
fSrc.clear();
}
@Override
protected void performApply(ICResourceDescription src, ICResourceDescription dst) {
performOK();
@ -462,13 +500,20 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
@Override
protected void performDefaults() {
// TODO Auto-generated method stub
}
@Override
protected void updateData(ICResourceDescription cfg) {
// TODO Auto-generated method stub
// only expand on first update.
if (page.isMultiCfg()) {
setAllVisible(false, null);
return;
} else {
clearTreeContent();
generateTreeContent();
fTree.refresh();
fTree.expandAll();
}
}
@Override
@ -488,7 +533,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
@Override
public Object[] getChildren(Object element) {
ArrayList<Object> filteredChildren = new ArrayList<Object>(Arrays.asList(super.getChildren(element)));
Iterator<IResource> iterator = fResourcesToRefresh.iterator();
Iterator<IResource> iterator = getResourcesToExclusionsMap(getConfigName()).keySet().iterator(); //fResourcesToRefresh.iterator();
while (iterator.hasNext()) {
filteredChildren.remove(iterator.next());
}
@ -508,7 +554,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
switch (x) {
case IDX_ADD_RESOURCE:
//TODO: Phase one implementation - folders only - need to change this for Phase two
fResourcesToRefresh.size();
CheckedTreeSelectionDialog addResourceDialog = new CheckedTreeSelectionDialog(shell, new WorkbenchLabelProvider(),
new FilteredContainerContentProvider());
addResourceDialog.setInput(ResourcesPlugin.getWorkspace());
@ -520,7 +566,8 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
IResource resource = (IResource) result[i];
_Entry newResource = new _Entry(resource);
//update the model element in this tab
fResourcesToRefresh.add(resource);
getResourcesToExclusionsMap(getConfigName()).put(resource,new LinkedList<RefreshExclusion>());
//update tree
fSrc.add(newResource);
}
@ -537,7 +584,7 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
if (sel.isExclusion()) {
addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.exclusion, true);
} else {
addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.resourceToRefresh, getExclusions(sel.resourceToRefresh), true);
addExceptionDialog = new RefreshPolicyExceptionDialog(shell, sel.resourceToRefresh, getExclusions(getConfigName(),sel.resourceToRefresh), true);
}
if (addExceptionDialog.open() == Window.OK) {
RefreshExclusion newExclusion = addExceptionDialog.getResult();
@ -624,15 +671,13 @@ public class RefreshPolicyTab extends AbstractCPropertyTab {
*/
@Override
protected void performOK() {
fManager.setResourcesToRefresh(fProject, fResourcesToRefresh);
Iterator<IResource> iterator = fResourcesToRefresh.iterator();
while (iterator.hasNext()) {
IResource resource = iterator.next();
fManager.clearExclusions(resource);
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
fManager.setExclusions(resource, exclusions);
Iterator<String> config_iterator = fConfigurationToResourcesToExclusionsMap.keySet().iterator();
while (config_iterator.hasNext()) {
String configName = config_iterator.next();
fManager.setResourcesToExclusionsMap(fProject, configName, getResourcesToExclusionsMap(configName));
}
try {
fManager.persistSettings(getResDesc().getConfiguration().getProjectDescription());
} catch (CoreException e) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -12,6 +12,7 @@ package org.eclipse.cdt.core.resources.tests;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@ -54,6 +55,7 @@ public class RefreshScopeTests extends TestCase {
private IFolder fFolder4;
private IFolder fFolder5;
private IFolder fFolder6;
private String config1,config2;
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
@ -74,6 +76,9 @@ public class RefreshScopeTests extends TestCase {
IWorkspaceRoot root = CTestPlugin.getWorkspace().getRoot();
IProject project = root.getProject("testRefreshScope");
config1 = "Debug";
config2 = "Release";
// create some folders
// structure is:
/*
@ -123,56 +128,80 @@ public class RefreshScopeTests extends TestCase {
}
public void testAddDeleteResource() throws CoreException {
RefreshScopeManager manager = RefreshScopeManager.getInstance();
manager.clearAllData();
manager.addResourceToRefresh(fProject, fFolder1);
// TEST 1:
// add resource "folder1" under config1.
manager.addResourceToRefresh(fProject, config1, fFolder1);
// now, check that it was added.
IResource[] config1_resources = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resources.length, 2);
assertEquals(fFolder1, config1_resources[1]);
IResource[] resources = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resources.length, 1);
assertEquals(fFolder1, resources[0]);
manager.addResourceToRefresh(fProject, fFolder2);
resources = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resources.length, 2);
assertEquals(fFolder1, resources[0]);
assertEquals(fFolder2, resources[1]);
// first try deleting a resource that was never added... the project
manager.deleteResourceToRefresh(fProject, fProject);
IResource[] resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resourcesAfterDelete.length, 2);
assertEquals(fFolder1, resources[0]);
assertEquals(fFolder2, resources[1]);
// TEST 2:
// add resource "folder2" under config1
manager.addResourceToRefresh(fProject, config1, fFolder2);
// now check to see that it and "folder1" are still there.
config1_resources = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resources.length, 3); // 3 because by default the project is always there.
assertEquals(fFolder2, config1_resources[0]);
assertEquals(fFolder1, config1_resources[2]);
// make sure it wasn't added under "Release", which should be empty now.
IResource[] config2_resources = manager.getResourcesToRefresh(fProject, config2).toArray(new IResource[0]);
assertEquals(config2_resources.length,1); // 1 because project is there by default.
assertEquals(fProject,config2_resources[0]);
// and add one under config 2.
manager.addResourceToRefresh(fProject, config2, fFolder1);
config2_resources = manager.getResourcesToRefresh(fProject, config2).toArray(new IResource[0]);
assertEquals(config2_resources.length,2);
assertEquals(fFolder1, config2_resources[1]);
// TEST 3:
// first try deleting a resource that was never added... folder5
manager.deleteResourceToRefresh(fProject, config1, fFolder5);
IResource[] config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resourcesAfterDelete.length, 3);
assertEquals(fFolder2, config1_resources[0]);
assertEquals(fFolder1, config1_resources[2]);
// ditto for config2, but this time we did add the resource, to make sure fFolder1 wasn't added.
manager.deleteResourceToRefresh(fProject, config2, fFolder5);
IResource[] config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2).toArray(new IResource[0]);
assertEquals(config2_resourcesAfterDelete.length, 2);
// TEST 4:
// now delete the resources from the manager one by one
manager.deleteResourceToRefresh(fProject, resources[1]);
resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resourcesAfterDelete.length, 1);
assertEquals(resourcesAfterDelete[0], resources[0]);
manager.deleteResourceToRefresh(fProject, config1, config1_resources[2]);
config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resourcesAfterDelete.length, 2);
assertEquals(config1_resourcesAfterDelete[1], config1_resources[1]);
manager.deleteResourceToRefresh(fProject, resources[0]);
resourcesAfterDelete = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resourcesAfterDelete.length, 0);
manager.deleteResourceToRefresh(fProject, config1, config1_resources[0]);
config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resourcesAfterDelete.length, 1);
// and ditto for config2
manager.deleteResourceToRefresh(fProject, config2, config2_resources[0]);
config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2).toArray(new IResource[0]);
assertEquals(config2_resourcesAfterDelete.length, 1);
}
public void testSetResourcesToRefresh() {
public void testSetResourcesToExclusionsMapRefresh() {
RefreshScopeManager manager = RefreshScopeManager.getInstance();
manager.clearAllData();
List<IResource> resources = new LinkedList<IResource>();
resources.add(fFolder1);
resources.add(fFolder2);
manager.setResourcesToRefresh(fProject, resources);
HashMap<IResource, List<RefreshExclusion>> config1_resourceMap = new HashMap<IResource, List<RefreshExclusion>>();
config1_resourceMap.put(fFolder1,new LinkedList<RefreshExclusion>());
config1_resourceMap.put(fFolder2,new LinkedList<RefreshExclusion>());
manager.setResourcesToExclusionsMap(fProject, config1, config1_resourceMap);
IResource[] resourcesAfterSet = manager.getResourcesToRefresh(fProject).toArray(new IResource[0]);
assertEquals(resourcesAfterSet.length, 2);
assertEquals(fFolder1, resourcesAfterSet[0]);
assertEquals(fFolder2, resourcesAfterSet[1]);
IResource[] config1_resourcesAfterSet = manager.getResourcesToRefresh(fProject, config1).toArray(new IResource[0]);
assertEquals(config1_resourcesAfterSet.length, 2);
assertEquals(fFolder2, config1_resourcesAfterSet[0]);
assertEquals(fFolder1, config1_resourcesAfterSet[1]);
manager.clearResourcesToRefresh(fProject);
@ -182,28 +211,31 @@ public class RefreshScopeTests extends TestCase {
RefreshScopeManager manager = RefreshScopeManager.getInstance();
manager.clearAllData();
manager.addResourceToRefresh(fProject, fProject);
RefreshExclusion exclusion1 = new TestExclusion();
manager.addExclusion(fProject, exclusion1);
RefreshExclusion exclusion2 = new TestExclusion();
manager.addExclusion(fProject, exclusion2);
IResource config1_resource = fProject;
manager.addResourceToRefresh(fProject, config1, config1_resource);
RefreshExclusion config1_exclusion1 = new TestExclusion();
manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1);
RefreshExclusion config1_exclusion2 = new TestExclusion();
manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2);
// make sure the exclusions are there
List<RefreshExclusion> exclusionsList = manager.getExclusions(fProject);
List<RefreshExclusion> exclusionsList = manager.getExclusions(fProject, config1, config1_resource);
RefreshExclusion[] exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
assertEquals(exclusionsArray.length, 2);
assertEquals(exclusionsArray[0], exclusion1);
assertEquals(exclusionsArray[1], exclusion2);
assertEquals(exclusionsArray[0], config1_exclusion1);
assertEquals(exclusionsArray[1], config1_exclusion2);
// remove the exclusions one by one
manager.removeExclusion(fProject, exclusion2);
exclusionsList = manager.getExclusions(fProject);
manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion2);
exclusionsList = manager.getExclusions(fProject,config1,config1_resource);
exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
assertEquals(exclusionsArray.length, 1);
assertEquals(exclusionsArray[0], exclusion1);
assertEquals(exclusionsArray[0], config1_exclusion1);
manager.removeExclusion(fProject, exclusion1);
exclusionsList = manager.getExclusions(fProject);
manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion1);
exclusionsList = manager.getExclusions(fProject, config1,config1_resource);
exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
assertEquals(exclusionsArray.length, 0);
@ -213,24 +245,46 @@ public class RefreshScopeTests extends TestCase {
RefreshScopeManager manager = RefreshScopeManager.getInstance();
manager.clearAllData();
manager.addResourceToRefresh(fProject, fProject);
IResource config1_resource = fProject;
IResource config2_resource = fFolder1;
RefreshExclusion exclusion1 = new TestExclusion();
manager.addExclusion(fProject, exclusion1);
RefreshExclusion exclusion2 = new TestExclusion();
manager.addExclusion(fProject, exclusion2);
//add a resource and two exclusions for config1.
manager.addResourceToRefresh(fProject, config1, config1_resource);
RefreshExclusion config1_exclusion1 = new TestExclusion();
manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1);
RefreshExclusion config1_exclusion2 = new TestExclusion();
manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2);
// add a nested exclusion to the first exclusion
RefreshExclusion exclusion3 = new TestExclusion();
exclusion1.addNestedExclusion(exclusion3);
RefreshExclusion config1_exclusion3 = new TestExclusion();
config1_exclusion1.addNestedExclusion(config1_exclusion3);
// add an instance to the second exclusion
ExclusionInstance instance = new ExclusionInstance();
instance.setDisplayString("foo");
instance.setResource(fFolder2);
instance.setExclusionType(ExclusionType.RESOURCE);
instance.setParentExclusion(exclusion2);
exclusion2.addExclusionInstance(instance);
ExclusionInstance config1_instance = new ExclusionInstance();
config1_instance.setDisplayString("foo");
config1_instance.setResource(fFolder2);
config1_instance.setExclusionType(ExclusionType.RESOURCE);
config1_instance.setParentExclusion(config1_exclusion2);
config1_exclusion2.addExclusionInstance(config1_instance);
//add a resource and two exclusions for config2.
manager.addResourceToRefresh(fProject, config2, config2_resource);
RefreshExclusion config2_exclusion1 = new TestExclusion();
manager.addExclusion(fProject, config2, config2_resource, config2_exclusion1);
RefreshExclusion config2_exclusion2 = new TestExclusion();
manager.addExclusion(fProject, config2, config2_resource, config2_exclusion2);
// add a nested exclusion to the first exclusion
RefreshExclusion config2_exclusion3 = new TestExclusion();
config2_exclusion1.addNestedExclusion(config2_exclusion3);
// add an instance to the second exclusion
ExclusionInstance config2_instance = new ExclusionInstance();
config2_instance.setDisplayString("foo");
config2_instance.setResource(fFolder2);
config2_instance.setExclusionType(ExclusionType.RESOURCE);
config2_instance.setParentExclusion(config2_exclusion2);
config2_exclusion2.addExclusionInstance(config1_instance);
ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject, true);
@ -251,53 +305,96 @@ public class RefreshScopeTests extends TestCase {
fail();
}
// make sure we got the same stuff we saved
// make sure we got the same stuff we saved for config1
// the project should be set to refresh its root
List<IResource> resources = manager.getResourcesToRefresh(fProject);
assertEquals(resources.size(), 1);
assertEquals(resources.toArray(new IResource[0])[0], fProject);
List<IResource> config1_resources = manager.getResourcesToRefresh(fProject,config1);
assertEquals(config1_resources.size(), 1);
assertEquals(config1_resources.toArray(new IResource[0])[0], config1_resource);
// there should be 2 top-level exclusions
List<RefreshExclusion> exclusions = manager.getExclusions(fProject);
assertEquals(2, exclusions.size());
RefreshExclusion[] exclusionsArray = exclusions.toArray(new RefreshExclusion[0]);
List<RefreshExclusion> config1_exclusions = manager.getExclusions(fProject, config1,config1_resource);
assertEquals(2, config1_exclusions.size());
RefreshExclusion[] config1_exclusionsArray = config1_exclusions.toArray(new RefreshExclusion[0]);
// both exclusions should have parent resource set to the project
assertEquals(fProject, exclusionsArray[0].getParentResource());
assertEquals(fProject, exclusionsArray[1].getParentResource());
assertEquals(config1_resource, config1_exclusionsArray[0].getParentResource());
assertEquals(config1_resource, config1_exclusionsArray[1].getParentResource());
// the first exclusion should have one nested exclusion
List<RefreshExclusion> nestedExclusions1 = exclusionsArray[0].getNestedExclusions();
assertEquals(nestedExclusions1.size(), 1);
RefreshExclusion[] nestedExclusionsArray = nestedExclusions1.toArray(new RefreshExclusion[0]);
List<RefreshExclusion> config1_nestedExclusions1 = config1_exclusionsArray[0].getNestedExclusions();
assertEquals(config1_nestedExclusions1.size(), 1);
RefreshExclusion[] config1_nestedExclusionsArray = config1_nestedExclusions1.toArray(new RefreshExclusion[0]);
// the nested exclusion should have its parent exclusion set properly
assertEquals(nestedExclusionsArray[0].getParentExclusion(), exclusionsArray[0]);
assertEquals(config1_nestedExclusionsArray[0].getParentExclusion(), config1_exclusionsArray[0]);
// the second exclusion should have no nested exclusions
List<RefreshExclusion> nestedExclusions2 = exclusionsArray[1].getNestedExclusions();
assertEquals(nestedExclusions2.size(), 0);
List<RefreshExclusion> config1_nestedExclusions2 = config1_exclusionsArray[1].getNestedExclusions();
assertEquals(config1_nestedExclusions2.size(), 0);
// the second exclusion should have an instance
List<ExclusionInstance> instances = exclusionsArray[1].getExclusionInstances();
assertEquals(1, instances.size());
ExclusionInstance[] instancesArray = instances.toArray(new ExclusionInstance[0]);
ExclusionInstance loadedInstance = instancesArray[0];
List<ExclusionInstance> config1_instances = config1_exclusionsArray[1].getExclusionInstances();
assertEquals(1, config1_instances.size());
ExclusionInstance[] config1_instancesArray = config1_instances.toArray(new ExclusionInstance[0]);
ExclusionInstance config1_loadedInstance = config1_instancesArray[0];
// check the contents of the instance
assertEquals("foo", loadedInstance.getDisplayString());
assertEquals(fFolder2, loadedInstance.getResource());
assertEquals(ExclusionType.RESOURCE, loadedInstance.getExclusionType());
assertEquals("foo", config1_loadedInstance.getDisplayString());
assertEquals(fFolder2, config1_loadedInstance.getResource());
assertEquals(ExclusionType.RESOURCE, config1_loadedInstance.getExclusionType());
// clear data for config1
manager.deleteResourceToRefresh(fProject, config1, config1_resource);
// make sure we got the same stuff we saved for config2
// the project should be set to refresh its root
List<IResource> config2_resources = manager.getResourcesToRefresh(fProject,config2);
assertEquals(config2_resources.size(), 2);
assertEquals(config2_resources.toArray(new IResource[0])[1], config2_resource);
// there should be 2 top-level exclusions
List<RefreshExclusion> config2_exclusions = manager.getExclusions(fProject,config2,config2_resource);
assertEquals(2, config2_exclusions.size());
RefreshExclusion[] config2_exclusionsArray = config2_exclusions.toArray(new RefreshExclusion[0]);
// both exclusions should have parent resource set to the project
assertEquals(config2_resource, config2_exclusionsArray[0].getParentResource());
assertEquals(config2_resource, config2_exclusionsArray[1].getParentResource());
// the first exclusion should have one nested exclusion
List<RefreshExclusion> config2_nestedExclusions1 = config2_exclusionsArray[0].getNestedExclusions();
assertEquals(config2_nestedExclusions1.size(), 1);
RefreshExclusion[] config2_nestedExclusionsArray = config2_nestedExclusions1.toArray(new RefreshExclusion[0]);
// the nested exclusion should have its parent exclusion set properly
assertEquals(config2_nestedExclusionsArray[0].getParentExclusion(), config2_exclusionsArray[0]);
// the second exclusion should have no nested exclusions
List<RefreshExclusion> config2_nestedExclusions2 = config2_exclusionsArray[1].getNestedExclusions();
assertEquals(config2_nestedExclusions2.size(), 0);
// the second exclusion should have an instance
List<ExclusionInstance> config2_instances = config2_exclusionsArray[1].getExclusionInstances();
assertEquals(1, config2_instances.size());
ExclusionInstance[] config2_instancesArray = config2_instances.toArray(new ExclusionInstance[0]);
ExclusionInstance config2_loadedInstance = config2_instancesArray[0];
// check the contents of the instance
assertEquals("foo", config2_loadedInstance.getDisplayString());
assertEquals(fFolder2, config2_loadedInstance.getResource());
assertEquals(ExclusionType.RESOURCE, config2_loadedInstance.getExclusionType());
// cleanup
manager.clearAllData();
}
public void testResourceExclusion() {
RefreshScopeManager manager = RefreshScopeManager.getInstance();
manager.clearAllData();
manager.addResourceToRefresh(fProject, fProject);
IResource config1_resource = fProject;
manager.addResourceToRefresh(fProject, config1, config1_resource);
// create a series of nested exclusions that include/exclude certain folders
// will be included/excluded as follows
@ -319,7 +416,7 @@ public class RefreshScopeTests extends TestCase {
ExclusionInstance instance2 = new ExclusionInstance();
instance2.setResource(fFolder2);
exclusion1.addExclusionInstance(instance2);
manager.addExclusion(fProject, exclusion1);
manager.addExclusion(fProject, config1, config1_resource, exclusion1);
ResourceExclusion exclusion2 = new ResourceExclusion();
ExclusionInstance instance3 = new ExclusionInstance();
@ -335,13 +432,13 @@ public class RefreshScopeTests extends TestCase {
// now check and see if the right folders are included/excluded
assertEquals(true, manager.shouldResourceBeRefreshed(fProject));
assertEquals(false, manager.shouldResourceBeRefreshed(fFolder1));
assertEquals(false, manager.shouldResourceBeRefreshed(fFolder2));
assertEquals(true, manager.shouldResourceBeRefreshed(fFolder3));
assertEquals(false, manager.shouldResourceBeRefreshed(fFolder4));
assertEquals(true, manager.shouldResourceBeRefreshed(fFolder5));
assertEquals(false, manager.shouldResourceBeRefreshed(fFolder6));
assertEquals(true, manager.shouldResourceBeRefreshed(config1, config1_resource));
assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder1));
assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder2));
assertEquals(true, manager.shouldResourceBeRefreshed(config1, fFolder3));
assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder4));
assertEquals(true, manager.shouldResourceBeRefreshed(config1, fFolder5));
assertEquals(false, manager.shouldResourceBeRefreshed(config1, fFolder6));
// now let's create a bunch of files in these directories using java.io.File (so that we don't get
// resource deltas happening), and refresh the project according to the policy. We should only see the files
@ -412,13 +509,13 @@ public class RefreshScopeTests extends TestCase {
manager.clearAllData();
// by default, a project should refresh its root
List<IResource> resourcesToRefresh = manager.getResourcesToRefresh(fProject);
List<IResource> resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1);
assertEquals(1, resourcesToRefresh.size());
IResource[] resourceArray = resourcesToRefresh.toArray(new IResource[0]);
assertEquals(fProject, resourceArray[0]);
// there should be no exclusions
List<RefreshExclusion> exclusions = manager.getExclusions(fProject);
List<RefreshExclusion> exclusions = manager.getExclusions(fProject, config1, fProject);
assertEquals(0, exclusions.size());
ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject);
@ -440,12 +537,12 @@ public class RefreshScopeTests extends TestCase {
// test the defaults again
// by default, a project should refresh its root
resourcesToRefresh = manager.getResourcesToRefresh(fProject);
resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1);
assertEquals(1, resourcesToRefresh.size());
resourceArray = resourcesToRefresh.toArray(new IResource[0]);
assertEquals(fProject, resourceArray[0]);
// there should be no exclusions
exclusions = manager.getExclusions(fProject);
exclusions = manager.getExclusions(fProject, config1, fProject);
assertEquals(0, exclusions.size());
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -31,4 +31,11 @@ public class TestExclusion extends RefreshExclusion {
public boolean supportsExclusionInstances() {
return false;
}
@Override
public Object clone() {
TestExclusion clone = new TestExclusion();
copyTo(clone);
return clone;
}
}

View file

@ -1,68 +1,153 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.cdt.core" version="2">
<resource path="model/org/eclipse/cdt/core/settings/model/ICDescriptionDelta.java" type="org.eclipse.cdt.core.settings.model.ICDescriptionDelta">
<filter comment="Temporary filter to ignore added API restictions for interfaces that should be internal to begin with" id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.settings.model.ICDescriptionDelta"/>
</message_arguments>
</filter>
</resource>
<resource path="model/org/eclipse/cdt/core/settings/model/ICSettingEntry.java" type="org.eclipse.cdt.core.settings.model.ICSettingEntry">
<filter comment="Temporary filter to ignore added API restictions for interfaces that should be internal to begin with" id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.settings.model.ICSettingEntry"/>
</message_arguments>
</filter>
</resource>
<resource path="parser/org/eclipse/cdt/core/dom/ast/IASTCopyLocation.java" type="org.eclipse.cdt.core.dom.ast.IASTCopyLocation">
<filter id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTCopyLocation"/>
</message_arguments>
</filter>
<filter id="406052990">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTCopyLocation"/>
<message_argument value="getOriginalNode()"/>
</message_arguments>
</filter>
</resource>
<resource path="parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java" type="org.eclipse.cdt.core.parser.util.ArrayUtil">
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.addAll(Class&lt;?&gt;, Object[], Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.append(Class&lt;?&gt;, Object[], Object)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.prepend(Class&lt;?&gt;, Object[], Object)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.removeNulls(Class&lt;?&gt;, Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.trim(Class&lt;?&gt;, Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.trim(Class&lt;?&gt;, Object[], boolean)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
</resource>
</component>
<?xml version="1.0" encoding="UTF-8"?><component id="org.eclipse.cdt.core" version="2">
<resource path="model/org/eclipse/cdt/core/settings/model/ICDescriptionDelta.java" type="org.eclipse.cdt.core.settings.model.ICDescriptionDelta">
<filter comment="Temporary filter to ignore added API restictions for interfaces that should be internal to begin with" id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.settings.model.ICDescriptionDelta"/>
</message_arguments>
</filter>
</resource>
<resource path="model/org/eclipse/cdt/core/settings/model/ICSettingEntry.java" type="org.eclipse.cdt.core.settings.model.ICSettingEntry">
<filter comment="Temporary filter to ignore added API restictions for interfaces that should be internal to begin with" id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.settings.model.ICSettingEntry"/>
</message_arguments>
</filter>
</resource>
<resource path="parser/org/eclipse/cdt/core/dom/ast/IASTCopyLocation.java" type="org.eclipse.cdt.core.dom.ast.IASTCopyLocation">
<filter id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTCopyLocation"/>
</message_arguments>
</filter>
<filter id="406052990">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.dom.ast.IASTCopyLocation"/>
<message_argument value="getOriginalNode()"/>
</message_arguments>
</filter>
</resource>
<resource path="parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java" type="org.eclipse.cdt.core.parser.util.ArrayUtil">
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.addAll(Class&lt;?&gt;, Object[], Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.append(Class&lt;?&gt;, Object[], Object)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.prepend(Class&lt;?&gt;, Object[], Object)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.removeNulls(Class&lt;?&gt;, Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.trim(Class&lt;?&gt;, Object[])"/>
<message_argument value="T"/>
</message_arguments>
</filter>
<filter id="420679712">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.parser.util.ArrayUtil.trim(Class&lt;?&gt;, Object[], boolean)"/>
<message_argument value="T"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/core/resources/RefreshScopeManager.java" type="org.eclipse.cdt.core.resources.RefreshScopeManager">
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="addExclusion(IResource, RefreshExclusion)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="addResourceToRefresh(IProject, IResource)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="clearAllExclusions()"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="clearAllResourcesToRefresh()"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="clearExclusions(IResource)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="clearExclusionsForProject(IProject)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="deleteResourceToRefresh(IProject, IResource)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="getExclusions(IResource)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="getRefreshSchedulingRule(IProject)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="getResourcesToRefresh(IProject)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="removeExclusion(IResource, RefreshExclusion)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="setExclusions(IResource, List&lt;RefreshExclusion&gt;)"/>
</message_arguments>
</filter>
<filter id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="setResourcesToRefresh(IProject, List&lt;IResource&gt;)"/>
</message_arguments>
</filter>
<filter comment="routines no longer needed for RefreshScopeManager" id="338792546">
<message_arguments>
<message_argument value="org.eclipse.cdt.core.resources.RefreshScopeManager"/>
<message_argument value="shouldResourceBeRefreshed(IResource)"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -11,6 +11,7 @@
package org.eclipse.cdt.core.resources;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -34,7 +35,7 @@ import com.ibm.icu.text.MessageFormat;
* @since 5.3
*
*/
public abstract class RefreshExclusion {
public abstract class RefreshExclusion implements Cloneable{
public static final String CLASS_ATTRIBUTE_NAME = "class"; //$NON-NLS-1$
public static final String CONTRIBUTOR_ID_ATTRIBUTE_NAME = "contributorId"; //$NON-NLS-1$
@ -356,5 +357,42 @@ public abstract class RefreshExclusion {
return currentValue;
}
/**
* Duplicate this refresh exclusion to the given one.
* @param destination - the refresh exclusion to be modified
* @since 5.4
*/
protected void copyTo (RefreshExclusion destination) {
destination.setContributorId(getContributorId());
destination.setExclusionType(getExclusionType());
destination.setParentResource(getParentResource());
Iterator<RefreshExclusion> iterator = getNestedExclusions().iterator();
while (iterator.hasNext()) {
RefreshExclusion nestedExclusion = iterator.next();
RefreshExclusion clone;
clone = (RefreshExclusion) nestedExclusion.clone();
clone.setParentExclusion(destination);
destination.addNestedExclusion(clone);
}
Iterator<ExclusionInstance> exclusionInstances = getExclusionInstances().iterator();
while(exclusionInstances.hasNext()) {
ExclusionInstance next = exclusionInstances.next();
ExclusionInstance newInstance = new ExclusionInstance();
newInstance.setDisplayString(next.getDisplayString());
newInstance.setExclusionType(next.getExclusionType());
newInstance.setParentExclusion(destination);
newInstance.setResource(next.getResource());
destination.addExclusionInstance(newInstance);
}
}
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public abstract Object clone();
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -10,13 +10,15 @@
*******************************************************************************/
package org.eclipse.cdt.core.resources;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CProjectNature;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
@ -74,6 +76,14 @@ public class RefreshScopeManager {
public static final String VERSION_ELEMENT_NAME = "version"; //$NON-NLS-1$
public static final String VERSION_NUMBER_ATTRIBUTE_NAME = "versionNumber"; //$NON-NLS-1$
public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$
/**
* @since 5.4
*/
public static final String CONFIGURATION_ELEMENT = "configuration"; //$NON-NLS-1$
/**
* @since 5.4
*/
public static final String CONFIGURATION_ELEMENT_NAME = "configurationName"; //$NON-NLS-1$
public static synchronized RefreshScopeManager getInstance() {
if (fInstance == null) {
@ -87,10 +97,8 @@ public class RefreshScopeManager {
private boolean fIsLoaded = false;
private boolean fIsLoading = false;
private HashMap<IProject, LinkedHashSet<IResource>> fProjectToResourcesMap;
private HashMap<IResource, List<RefreshExclusion>> fResourceToExclusionsMap;
private int fVersion = 1;
private HashMap<IProject,HashMap<String,HashMap<IResource, List<RefreshExclusion>>>> fProjToConfToResToExcluMap;
private int fVersion = 2;
private RefreshScopeManager() {
fClassnameToExclusionFactoryMap = new HashMap<String, RefreshExclusionFactory>();
@ -145,7 +153,6 @@ public class RefreshScopeManager {
return false;
}
}
else if (delta.getResource() instanceof IWorkspaceRoot) {
@ -161,7 +168,6 @@ public class RefreshScopeManager {
e.printStackTrace();
}
}
}
},
@ -169,95 +175,82 @@ public class RefreshScopeManager {
| IResourceChangeEvent.PRE_DELETE);
}
public synchronized void addExclusion(IResource resource, RefreshExclusion exclusion) {
getResourcesToExclusionsMap();
/**
* @since 5.4
*/
public synchronized void addExclusion(IProject project, String configName, IResource resource, RefreshExclusion exclusion) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project,configName);
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if (exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
fResourceToExclusionsMap.put(resource, exclusions);
resourceMap.put(resource, exclusions);
}
exclusions.add(exclusion);
}
public synchronized void addResourceToRefresh(IProject project, IResource resource) {
getProjectToResourcesMap();
LinkedHashSet<IResource> resourceSet = fProjectToResourcesMap.get(project);
if (resourceSet == null) {
resourceSet = new LinkedHashSet<IResource>();
fProjectToResourcesMap.put(project, resourceSet);
/**
* @since 5.4
*/
// We are adding a new resource.
public synchronized void addResourceToRefresh(IProject project, String configName, IResource resource) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project, configName);
if (!resourceMap.containsKey(resource)) {
// create a new one:
LinkedList<RefreshExclusion> exclusions = new LinkedList<RefreshExclusion>();
resourceMap.put(resource, exclusions);
}
resourceSet.add(resource);
}
public synchronized void clearAllData() {
clearAllResourcesToRefresh();
clearAllExclusions();
getProjectToConfigurationToResourcesMap();
fProjToConfToResToExcluMap.clear();
fIsLoaded = false;
}
public synchronized void clearAllExclusions() {
if (fResourceToExclusionsMap != null)
fResourceToExclusionsMap.clear();
}
public synchronized void clearAllResourcesToRefresh() {
getProjectToResourcesMap();
fProjectToResourcesMap.clear();
}
private synchronized void clearDataForProject(IProject project) {
clearResourcesToRefresh(project);
clearExclusionsForProject(project);
HashMap<String,HashMap<IResource, List<RefreshExclusion>>> configMap = fProjToConfToResToExcluMap.get(project);
if (configMap != null)
configMap.clear();
}
public synchronized void clearExclusions(IResource resource) {
getResourcesToExclusionsMap();
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
/**
* @since 5.4
*/
public synchronized void clearExclusions(IProject project, String configName, IResource resource) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project, configName);
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if (exclusions != null) {
exclusions.clear();
}
}
public synchronized void clearExclusionsForProject(IProject project) {
getResourcesToExclusionsMap();
List<IResource> resourcesToRemove = new LinkedList<IResource>();
for (IResource resource : fResourceToExclusionsMap.keySet()) {
IProject project2 = resource.getProject();
if (project2.equals(project)) {
resourcesToRemove.add(resource);
}
}
for (IResource resource : resourcesToRemove) {
fResourceToExclusionsMap.remove(resource);
}
}
public synchronized void clearResourcesToRefresh(IProject project) {
getProjectToResourcesMap();
LinkedHashSet<IResource> resourceSet = null;
// Clear all resources for the given project.
HashMap<String,HashMap<IResource, List<RefreshExclusion>>> configMap = getConfigurationToResourcesMap(project);
HashMap<IResource, List<RefreshExclusion>> resourceMap = null;
fProjectToResourcesMap.put(project, resourceSet);
}
public synchronized void deleteResourceToRefresh(IProject project, IResource resource) {
getProjectToResourcesMap();
LinkedHashSet<IResource> resourceSet = fProjectToResourcesMap.get(project);
if (resourceSet == null) {
resourceSet = new LinkedHashSet<IResource>();
return;
Iterator<String> it = configMap.keySet().iterator();
while (it.hasNext()) {
String configName = it.next();
resourceMap = configMap.get(configName);
resourceMap.clear();
}
resourceSet.remove(resource);
}
/**
* @since 5.4
*/
public synchronized void deleteResourceToRefresh(IProject project, String configName, IResource resource) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project, configName);
if (resourceMap.containsKey(resource))
resourceMap.remove(resource);
}
public synchronized RefreshExclusion getExclusionForClassName(String className) {
RefreshExclusionFactory factory = getFactoryForClassName(className);
@ -268,17 +261,6 @@ public class RefreshScopeManager {
return factory.createNewExclusion();
}
public synchronized List<RefreshExclusion> getExclusions(IResource resource) {
getResourcesToExclusionsMap();
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
if (exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
fResourceToExclusionsMap.put(resource, exclusions);
}
return exclusions;
}
public synchronized RefreshExclusionFactory getFactoryForClassName(String className) {
RefreshExclusionFactory factory = fClassnameToExclusionFactoryMap.get(className);
@ -295,16 +277,47 @@ public class RefreshScopeManager {
return factory.createNewExclusionInstance();
}
private HashMap<IProject, LinkedHashSet<IResource>> getProjectToResourcesMap() {
if (fProjectToResourcesMap == null) {
fProjectToResourcesMap = new HashMap<IProject, LinkedHashSet<IResource>>();
private HashMap<IResource, List<RefreshExclusion>> getResourcesToExclusionsMap(IProject project, String configName) {
getProjectToConfigurationToResourcesMap();
HashMap<String, HashMap<IResource, List<RefreshExclusion>>> configMap = getConfigurationToResourcesMap(project);
HashMap<IResource, List<RefreshExclusion>> resourceMap = configMap.get(configName);
if (resourceMap == null) {
resourceMap = new HashMap<IResource, List<RefreshExclusion>>();
resourceMap.put(project, new LinkedList<RefreshExclusion>());
configMap.put(configName, resourceMap);
}
return fProjectToResourcesMap;
return resourceMap;
}
/**
* @since 5.4
*/
public synchronized HashMap<String, HashMap<IResource, List<RefreshExclusion>>> getConfigurationToResourcesMap(IProject project)
{
getProjectToConfigurationToResourcesMap();
HashMap<String,HashMap<IResource, List<RefreshExclusion>>> configMap = fProjToConfToResToExcluMap.get(project);
if (configMap == null) {
configMap = new HashMap<String,HashMap<IResource, List<RefreshExclusion>>>();
fProjToConfToResToExcluMap.put(project,configMap);
}
return configMap;
}
private HashMap<IProject,HashMap<String,HashMap<IResource, List<RefreshExclusion>>>> getProjectToConfigurationToResourcesMap() {
if (fProjToConfToResToExcluMap == null) {
fProjToConfToResToExcluMap = new HashMap<IProject,HashMap<String,HashMap<IResource, List<RefreshExclusion>>>>();
}
return fProjToConfToResToExcluMap;
}
public IWorkspaceRunnable getRefreshRunnable(final IProject project) {
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
/**
@ -312,18 +325,18 @@ public class RefreshScopeManager {
* @param resource
* @throws CoreException
*/
private void refreshResources(IResource resource, List<RefreshExclusion> exclusions,
private void refreshResources(String configName, IResource resource, List<RefreshExclusion> exclusions,
IProgressMonitor monitor) throws CoreException {
if (resource instanceof IContainer) {
IContainer container = (IContainer) resource;
if (shouldResourceBeRefreshed(resource)) {
if (shouldResourceBeRefreshed(configName, resource)) {
resource.refreshLocal(IResource.DEPTH_ONE, monitor);
}
for (IResource child : container.members()) {
refreshResources(child, exclusions, monitor);
refreshResources(configName, child, exclusions, monitor);
}
}
}
@ -331,51 +344,40 @@ public class RefreshScopeManager {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
List<IResource> resourcesToRefresh = getResourcesToRefresh(project);
for (IResource resource : resourcesToRefresh) {
List<RefreshExclusion> exclusions = getExclusions(resource);
refreshResources(resource, exclusions, monitor);
}
HashMap<String,HashMap<IResource, List<RefreshExclusion>>> configMap = getConfigurationToResourcesMap(project);
Iterator<String> it = configMap.keySet().iterator();
while (it.hasNext()) {
String configName = it.next();
List<IResource> resourcesToRefresh = getResourcesToRefresh(project,configName);
for (IResource resource : resourcesToRefresh) {
List<RefreshExclusion> exclusions = getExclusions(project,configName,resource);
refreshResources(configName, resource, exclusions, monitor);
}
}
}
};
return runnable;
}
public synchronized ISchedulingRule getRefreshSchedulingRule(IProject project) {
return new MultiRule(getResourcesToRefresh(project).toArray(new ISchedulingRule[0]));
}
private HashMap<IResource, List<RefreshExclusion>> getResourcesToExclusionsMap() {
if (fResourceToExclusionsMap == null) {
fResourceToExclusionsMap = new HashMap<IResource, List<RefreshExclusion>>();
}
return fResourceToExclusionsMap;
/**
* @since 5.4
*/
public synchronized ISchedulingRule getRefreshSchedulingRule(IProject project, String configName) {
return new MultiRule(getResourcesToRefresh(project, configName).toArray(new ISchedulingRule[0]));
}
/**
* Returns the set of resources that should be refreshed for a project. These resources might have
* associated exclusions.
*
* @param project
* @return List<IResource>
* @since 5.4
*/
public synchronized List<IResource> getResourcesToRefresh(IProject project) {
getProjectToResourcesMap();
LinkedHashSet<IResource> resources = fProjectToResourcesMap.get(project);
public synchronized List<IResource> getResourcesToRefresh(IProject project, String configName) {
getProjectToConfigurationToResourcesMap();
if (resources == null) {
// there are no settings yet for the project, setup the defaults
resources = new LinkedHashSet<IResource>();
resources.add(project);
fProjectToResourcesMap.put(project, resources);
}
return new LinkedList<IResource>(resources);
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project,configName);
return new ArrayList<IResource>(resourceMap.keySet());
}
public int getVersion() {
return fVersion;
}
@ -465,79 +467,105 @@ public class RefreshScopeManager {
REFRESH_SCOPE_STORAGE_NAME, true);
// walk the tree and load the settings
// for now ignore the version attribute, as we only have version 1 at this time
String str = storageElement.getAttribute(VERSION_NUMBER_ATTRIBUTE_NAME);
int version = (str != null) ? Integer.valueOf(str) : 2;
// iterate through the child nodes
ICStorageElement[] children = storageElement.getChildren();
for (ICStorageElement child : children) {
if (version == 1) {
ICConfigurationDescription cfgDescs[] = projectDescription.getConfigurations();
for (ICConfigurationDescription cfgDesc : cfgDescs)
loadResourceData(workspaceRoot, project, cfgDesc.getName(), children);
} else {
for (ICStorageElement child : children) {
if (child.getName().equals(CONFIGURATION_ELEMENT) ) {
String configName = child.getAttribute(CONFIGURATION_ELEMENT_NAME);
loadResourceData(workspaceRoot, project, configName, child.getChildren());
}
}
}
}
}
}
if (child.getName().equals(RESOURCE_ELEMENT_NAME)) {
/**
* @since 5.4
*/
public synchronized void loadResourceData(IWorkspaceRoot workspaceRoot, IProject project, String configName, ICStorageElement[] children) {
for (ICStorageElement child : children) {
if (child.getName().equals(RESOURCE_ELEMENT_NAME)) {
// get the resource path
String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME);
if (resourcePath == null) {
// error... skip this resource
continue;
}
else {
String resourceTypeString = child
.getAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME);
if (resourceTypeString == null) {
// we'll do our best, but we won't be able to create handles to non-existent
// resources
resourceTypeString = OTHER_VALUE;
}
// find the resource
IResource resource = null;
if (resourceTypeString.equals(PROJECT_VALUE)) {
resource = workspaceRoot.getProject(resourcePath);
}
else if (resourceTypeString.equals(FILE_VALUE)) {
resource = workspaceRoot.getFile(new Path(resourcePath));
}
else if (resourceTypeString.equals(FOLDER_VALUE)) {
resource = workspaceRoot.getFolder(new Path(resourcePath));
}
else {
// Find arbitrary resource.
// The only way to do this is to ask the workspace root to find
// it, if it exists. If it doesn't exist, we have no way of
// creating a handle to the right type of object, so we must
// give up. In practice, this would likely happen if we had
// a virtual group resource that has been deleted somehow since
// the settings were created, and since the resource is virtual,
// it's impossible to refresh it if it doesn't exist anyway.
resource = workspaceRoot.findMember(resourcePath);
}
if (resource == null) {
// error.. skip this resource
continue;
}
else {
addResourceToRefresh(project,configName, resource);
// load any exclusions
List<RefreshExclusion> exclusions;
try {
exclusions = RefreshExclusion.loadData(
child, null, resource, this);
// get the resource path
String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME);
if (resourcePath == null) {
// error... skip this resource
continue;
}
else {
String resourceTypeString = child
.getAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME);
if (resourceTypeString == null) {
// we'll do our best, but we won't be able to create handles to non-existent
// resources
resourceTypeString = OTHER_VALUE;
}
// find the resource
IResource resource = null;
if (resourceTypeString.equals(PROJECT_VALUE)) {
resource = workspaceRoot.getProject(resourcePath);
}
else if (resourceTypeString.equals(FILE_VALUE)) {
resource = workspaceRoot.getFile(new Path(resourcePath));
}
else if (resourceTypeString.equals(FOLDER_VALUE)) {
resource = workspaceRoot.getFolder(new Path(resourcePath));
}
else {
// Find arbitrary resource.
// The only way to do this is to ask the workspace root to find
// it, if it exists. If it doesn't exist, we have no way of
// creating a handle to the right type of object, so we must
// give up. In practice, this would likely happen if we had
// a virtual group resource that has been deleted somehow since
// the settings were created, and since the resource is virtual,
// it's impossible to refresh it if it doesn't exist anyway.
resource = workspaceRoot.findMember(resourcePath);
}
if (resource == null) {
// error.. skip this resource
continue;
}
else {
addResourceToRefresh(project, resource);
// load any exclusions
List<RefreshExclusion> exclusions = RefreshExclusion.loadData(
child, null, resource, this);
// add them
for (RefreshExclusion exclusion : exclusions) {
addExclusion(resource, exclusion);
}
// add them
for (RefreshExclusion exclusion : exclusions) {
addExclusion(project, configName, resource, exclusion);
}
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@ -547,14 +575,13 @@ public class RefreshScopeManager {
public synchronized void persistSettings(ICProjectDescription projectDescription)
throws CoreException {
getProjectToResourcesMap();
getResourcesToExclusionsMap();
IProject project = projectDescription.getProject();
if (!project.exists()) {
return;
}
// serialize all settings for the project to the C Project Description
if (project.isOpen()) {
if (project.hasNature(CProjectNature.C_NATURE_ID)) {
@ -566,77 +593,139 @@ public class RefreshScopeManager {
storageElement.setAttribute(VERSION_NUMBER_ATTRIBUTE_NAME,
Integer.toString(fVersion));
for (IResource resource : fProjectToResourcesMap.get(project)) {
// create a resource node
ICStorageElement resourceElement = storageElement
.createChild(RESOURCE_ELEMENT_NAME);
resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource
.getFullPath().toString());
String resourceTypeString = null;
if (resource instanceof IFile) {
resourceTypeString = FILE_VALUE;
}
else if (resource instanceof IFolder) {
resourceTypeString = FOLDER_VALUE;
}
else if (resource instanceof IProject) {
resourceTypeString = PROJECT_VALUE;
}
else {
resourceTypeString = OTHER_VALUE;
}
resourceElement.setAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME, resourceTypeString);
// populate the node with any exclusions
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
if (exclusions != null) {
for (RefreshExclusion exclusion : exclusions) {
exclusion.persistData(resourceElement);
HashMap<String,HashMap<IResource, List<RefreshExclusion>>> configMap = getConfigurationToResourcesMap(project);
if (!configMap.isEmpty()) {
Iterator<String> it = configMap.keySet().iterator();
while (it.hasNext()) {
String configName = it.next();
// for the current configuration, create a storage element
ICStorageElement configElement = storageElement.createChild(CONFIGURATION_ELEMENT);
configElement.setAttribute(CONFIGURATION_ELEMENT_NAME, configName);
// set the resource to exclusion map for this config name.
HashMap<IResource, List<RefreshExclusion>> resourceMap = configMap.get(configName);
// for each resource
for (IResource resource : resourceMap.keySet()) {
persistDataResource(configElement, resource,resourceMap);
}
}
}
}
}
}
}
public synchronized void removeExclusion(IResource resource, RefreshExclusion exclusion) {
getResourcesToExclusionsMap();
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
/**
* @since 5.4
*/
public synchronized void persistDataResource(ICStorageElement storageElement, IResource resource, HashMap<IResource, List<RefreshExclusion>> resourceMap) {
// create a resource node
ICStorageElement resourceElement = storageElement
.createChild(RESOURCE_ELEMENT_NAME);
resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource
.getFullPath().toString());
String resourceTypeString = null;
if (resource instanceof IFile) {
resourceTypeString = FILE_VALUE;
}
else if (resource instanceof IFolder) {
resourceTypeString = FOLDER_VALUE;
}
else if (resource instanceof IProject) {
resourceTypeString = PROJECT_VALUE;
}
else {
resourceTypeString = OTHER_VALUE;
}
resourceElement.setAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME, resourceTypeString);
// populate the node with any exclusions
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if (exclusions != null) {
for (RefreshExclusion exclusion : exclusions) {
exclusion.persistData(resourceElement);
}
}
}
/**
* @since 5.4
*/
public synchronized void removeExclusion(IProject project, String configName, IResource resource, RefreshExclusion exclusion) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project,configName);
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if (exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
fResourceToExclusionsMap.put(resource, exclusions);
resourceMap.put(resource, exclusions);
}
exclusions.remove(exclusion);
}
public synchronized void setExclusions(IResource resource, List<RefreshExclusion> newExclusions) {
getResourcesToExclusionsMap();
/**
* @since 5.4
*/
public synchronized void setExclusions(IProject project, String configName, IResource resource, List<RefreshExclusion> newExclusions) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project,configName);
List<RefreshExclusion> exclusions = new LinkedList<RefreshExclusion>(newExclusions);
fResourceToExclusionsMap.put(resource, exclusions);
resourceMap.put(resource, exclusions);
}
public synchronized void setResourcesToRefresh(IProject project, List<IResource> resources) {
getProjectToResourcesMap();
LinkedHashSet<IResource> resourceSet = new LinkedHashSet<IResource>(resources);
fProjectToResourcesMap.put(project, resourceSet);
/**
* @since 5.4
*/
public synchronized List<RefreshExclusion> getExclusions(IProject project, String configName, IResource resource) {
HashMap<IResource, List<RefreshExclusion>> resourceMap = getResourcesToExclusionsMap(project, configName);
List<RefreshExclusion> exclusions = resourceMap.get(resource);
if (exclusions == null) {
exclusions = new LinkedList<RefreshExclusion>();
resourceMap.put(resource, exclusions);
}
return exclusions;
}
public synchronized boolean shouldResourceBeRefreshed(IResource resource) {
/**
* @since 5.4
*/
public synchronized void setResourcesToExclusionsMap(IProject project, String configName, HashMap<IResource, List<RefreshExclusion>> source_resourceMap) { // List<IResource> resources) {
HashMap<IResource, List<RefreshExclusion>> target_resourceMap = getResourcesToExclusionsMap(project,configName);
target_resourceMap.clear();
Iterator<IResource> resource_iterator = source_resourceMap.keySet().iterator();
while (resource_iterator.hasNext()) {
IResource source_resource = resource_iterator.next();
List<RefreshExclusion> source_exclusions = source_resourceMap.get(source_resource);
List<RefreshExclusion> target_exclusions = new LinkedList<RefreshExclusion>();
for (RefreshExclusion exclusion : source_exclusions) {
target_exclusions.add(exclusion);
}
// ADD the exclusion list for this resource
target_resourceMap.put(source_resource, target_exclusions);
}
}
/**
* @since 5.4
*/
public synchronized boolean shouldResourceBeRefreshed(String configName, IResource resource) {
IProject project = resource.getProject();
List<IResource> resourcesToRefresh = getResourcesToRefresh(project);
List<IResource> resourcesToRefresh = getResourcesToRefresh(project,configName);
boolean isInSomeTree = false;
IResource topLevelResource = null;
@ -666,7 +755,7 @@ public class RefreshScopeManager {
// get any exclusions
boolean isExcluded = false;
for (RefreshExclusion exclusion : getExclusions(topLevelResource)) {
for (RefreshExclusion exclusion : getExclusions(project, configName, topLevelResource)) {
if (exclusion.testExclusionChain(resource)) {
isExcluded = true;
break;
@ -674,7 +763,5 @@ public class RefreshScopeManager {
}
return !isExcluded;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation and others.
* Copyright (c) 2011, 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
@ -81,4 +81,13 @@ public class ResourceExclusion extends RefreshExclusion {
return false;
}
@Override
public Object clone() {
ResourceExclusion clone = new ResourceExclusion();
copyTo(clone);
return clone;
}
}