[Bug 401678] Subdestinations selection not preserved
diff --git a/bundles/org.eclipse.platform.discovery.runtime/src/org/eclipse/platform/discovery/runtime/internal/SearchProviderConfigurationFactory.java b/bundles/org.eclipse.platform.discovery.runtime/src/org/eclipse/platform/discovery/runtime/internal/SearchProviderConfigurationFactory.java
index 2e931c5..38cf372 100644
--- a/bundles/org.eclipse.platform.discovery.runtime/src/org/eclipse/platform/discovery/runtime/internal/SearchProviderConfigurationFactory.java
+++ b/bundles/org.eclipse.platform.discovery.runtime/src/org/eclipse/platform/discovery/runtime/internal/SearchProviderConfigurationFactory.java
@@ -8,20 +8,32 @@
  * Contributors:
  *     SAP AG - initial API and implementation
  *******************************************************************************/
-package org.eclipse.platform.discovery.runtime.internal;

-

+package org.eclipse.platform.discovery.runtime.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.core.runtime.IExtensionRegistry;
-import org.eclipse.platform.discovery.runtime.internal.impl.SearchProviderConfiguration;

-import org.eclipse.platform.discovery.runtime.internal.impl.XpParsersFactory;

-import org.eclipse.platform.discovery.runtime.internal.search.activation.SearchProviderActivationConfigDummy;

-

-public class SearchProviderConfigurationFactory

+import org.eclipse.platform.discovery.runtime.internal.impl.SearchProviderConfiguration;
+import org.eclipse.platform.discovery.runtime.internal.impl.XpParsersFactory;
+import org.eclipse.platform.discovery.runtime.internal.search.activation.SearchProviderActivationConfigDummy;
+
+public class SearchProviderConfigurationFactory
 {
-

-	public ISearchProviderConfiguration getSearchProviderConfiguration(IExtensionRegistry registry)

-	{

+	private static final Map<IExtensionRegistry, ISearchProviderConfiguration> configurationsMap = new HashMap<IExtensionRegistry, ISearchProviderConfiguration>();
+
+	public ISearchProviderConfiguration getSearchProviderConfiguration(IExtensionRegistry registry)
+	{
+		if (!configurationsMap.containsKey(registry))
+		{
+			configurationsMap.put(registry, createConfiguration(registry));
+		}
+		return configurationsMap.get(registry);
+	}
+
+	private ISearchProviderConfiguration createConfiguration(IExtensionRegistry registry)
+	{
 		final XpParsersFactory parsersFactory = new XpParsersFactory(registry);
-		return new SearchProviderConfiguration(parsersFactory, new SearchProviderActivationConfigDummy(parsersFactory.createSearchProviderParser()), new SubdestinationsActivationConfig(parsersFactory
-										.createSubdestinationsParser()));
-	}

-}

+		return new SearchProviderConfiguration(parsersFactory, new SearchProviderActivationConfigDummy(parsersFactory.createSearchProviderParser()), new SubdestinationsActivationConfig(parsersFactory.createSubdestinationsParser()));
+	}
+}
diff --git a/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java b/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
index 604accc..ae5ef8b 100644
--- a/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
+++ b/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
@@ -16,6 +16,7 @@
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.platform.discovery.core.api.ISearchContext;
@@ -222,7 +223,12 @@
 	

 	protected ISearchProviderConfiguration getSearchProviderConfiguration()

 	{

-		return new SearchProviderConfigurationFactory().getSearchProviderConfiguration(Platform.getExtensionRegistry());

+		return new SearchProviderConfigurationFactory().getSearchProviderConfiguration(extensionRegistry());

+	}
+	
+	protected IExtensionRegistry extensionRegistry() 
+	{
+	    return Platform.getExtensionRegistry();
 	}

 

 	@Override

diff --git a/tests/org.eclipse.platform.discovery.runtime.test.unit/src/org/eclipse/platform/discovery/runtime/test/unit/internal/SearchProviderConfigurationFactoryTest.java b/tests/org.eclipse.platform.discovery.runtime.test.unit/src/org/eclipse/platform/discovery/runtime/test/unit/internal/SearchProviderConfigurationFactoryTest.java
new file mode 100644
index 0000000..9e07faa
--- /dev/null
+++ b/tests/org.eclipse.platform.discovery.runtime.test.unit/src/org/eclipse/platform/discovery/runtime/test/unit/internal/SearchProviderConfigurationFactoryTest.java
@@ -0,0 +1,40 @@
+package org.eclipse.platform.discovery.runtime.test.unit.internal;
+
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.platform.discovery.runtime.internal.SearchProviderConfigurationFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class SearchProviderConfigurationFactoryTest
+{
+	@Mock
+	private IExtensionRegistry registry_1;
+	@Mock
+	private IExtensionRegistry registry_2;
+
+	private SearchProviderConfigurationFactory factory;
+
+	@Before
+	public void setUp()
+	{
+		MockitoAnnotations.initMocks(this);
+		factory = new SearchProviderConfigurationFactory();
+	}
+
+	@Test
+	public void testSameConfigurationReturnedForRegistry()
+	{
+		assertSame("Different configuration instances returned for different registries", factory.getSearchProviderConfiguration(registry_1), factory.getSearchProviderConfiguration(registry_1));
+	}
+
+	@Test
+	public void testDifferentConfigurationsReturnedForDifferentRegistries()
+	{
+		assertNotSame("Same configuration instances returned for different registries", factory.getSearchProviderConfiguration(registry_1), factory.getSearchProviderConfiguration(registry_2));
+	}
+}
diff --git a/tests/org.eclipse.platform.discovery.ui.test.unit/src/org/eclipse/platform/discovery/ui/test/unit/internal/SubdestinationsSelectionPersistedTest.java b/tests/org.eclipse.platform.discovery.ui.test.unit/src/org/eclipse/platform/discovery/ui/test/unit/internal/SubdestinationsSelectionPersistedTest.java
new file mode 100644
index 0000000..f8c373a
--- /dev/null
+++ b/tests/org.eclipse.platform.discovery.ui.test.unit/src/org/eclipse/platform/discovery/ui/test/unit/internal/SubdestinationsSelectionPersistedTest.java
@@ -0,0 +1,121 @@
+package org.eclipse.platform.discovery.ui.test.unit.internal;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.platform.discovery.runtime.api.IDestinationsProvider;
+import org.eclipse.platform.discovery.runtime.api.ISearchDestination;
+import org.eclipse.platform.discovery.runtime.api.ISearchProvider;
+import org.eclipse.platform.discovery.runtime.api.ISearchSubdestination;
+import org.eclipse.platform.discovery.runtime.internal.ISearchProviderConfiguration;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationCategoryDescription;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IObjectTypeDescription;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.ISearchProviderDescription;
+import org.eclipse.platform.discovery.testutils.utils.registry.ExtensionRegistryBuilder;
+import org.eclipse.platform.discovery.ui.internal.view.SearchConsoleView;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+public class SubdestinationsSelectionPersistedTest
+{
+	private SearchConsoleViewExtended consoleView;
+	private IExtensionRegistry extensionRegistry;
+
+	@Mock
+	private IDestinationsProvider destinationsProvider;
+	@Mock
+	private ISearchDestination searchDestination;
+	@Mock
+	private ISearchProviderDescription searchProviderDescr;
+	@Mock
+	private IObjectTypeDescription objectType;
+	@Mock
+	private IDestinationCategoryDescription destCategory;
+	@Mock
+	private ISearchProviderDescription searchProvider;
+	@Mock
+	private ISearchSubdestination subdestination;
+
+	@Before
+	public void setUp()
+	{
+		MockitoAnnotations.initMocks(this);
+		consoleView = new SearchConsoleViewExtended();
+
+		stubObjectType();
+		stubDestinationCategory();
+		stubDestinationsProvider();
+		stubSearchProvider();
+		stubSubdestination();
+
+		extensionRegistry = stubExtensionsRegistry();
+	}
+
+	private void stubDestinationsProvider()
+	{
+		Mockito.stub(destinationsProvider.getSearchDestinations()).toReturn(new HashSet<ISearchDestination>(Arrays.asList(new ISearchDestination[] { searchDestination })));
+	}
+
+	private void stubSubdestination()
+	{
+		Mockito.stub(subdestination.getId()).toReturn("my.subdestination");
+		final String destCategoryId = destCategory.getId();
+		Mockito.stub(subdestination.getDestinationCategoryId()).toReturn(destCategoryId);
+	}
+
+	private void stubSearchProvider()
+	{
+		Mockito.stub(searchProvider.getId()).toReturn("my.search.provider.id");
+		Mockito.stub(searchProvider.getObjectType()).toReturn(objectType);
+	}
+
+	private void stubDestinationCategory()
+	{
+		Mockito.stub(destCategory.getId()).toReturn("my.category.id");
+		Mockito.stub(destCategory.getDestinationProviderIds()).toReturn(Arrays.asList(new String[] { "my.dest.provider.id" }));
+		Mockito.stub(destCategory.getDestinationsClass()).toReturn(ISearchDestination.class);
+	}
+
+	private void stubObjectType()
+	{
+		Mockito.stub(objectType.getId()).toReturn("my.object.id");
+	}
+
+	private IExtensionRegistry stubExtensionsRegistry()
+	{
+		final ExtensionRegistryBuilder registryBuilder = new ExtensionRegistryBuilder();
+		registryBuilder.addObjectType(objectType.getId(), objectType.getDisplayName());
+		registryBuilder.addDestinationCategory(destCategory.getId(), destCategory.getDisplayName());
+		registryBuilder.addSearchProvider(searchProvider.getId(), "foo", Mockito.mock(ISearchProvider.class), objectType.getId(), "true", destCategory.getId());
+		registryBuilder.addSearchSubdestination(subdestination.getId(), subdestination.getDisplayName(), subdestination.getDestinationCategoryId(), objectType.getId(), "false");
+		return registryBuilder.getRegistry();
+	}
+
+	@Test
+	public void testSubdestinationsSelectionPersisted()
+	{
+		consoleView.getSearchProviderConfiguration().activateSubdestination(objectType, destCategory, searchProvider, subdestination, true);
+		assertTrue("Subdestination is still inactive", consoleView.getSearchProviderConfiguration().isSubdestinationActive(subdestination, objectType, destCategory, searchProvider));
+	}
+
+	private class SearchConsoleViewExtended extends SearchConsoleView
+	{
+		@Override
+		protected IExtensionRegistry extensionRegistry()
+		{
+			return extensionRegistry;
+		}
+
+		@Override
+		protected ISearchProviderConfiguration getSearchProviderConfiguration()
+		{
+			return super.getSearchProviderConfiguration();
+		}
+	}
+}