package org.camunda.bpm.extension.osgi.blueprint;

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.isA;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Collections;

import org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.camunda.bpm.engine.impl.javax.el.CompositeELResolver;
import org.camunda.bpm.engine.impl.javax.el.ELResolver;
import org.camunda.bpm.engine.impl.scripting.BeansResolverFactory;
import org.camunda.bpm.engine.impl.scripting.ResolverFactory;
import org.camunda.bpm.engine.impl.scripting.VariableScopeResolverFactory;
import org.camunda.bpm.extension.osgi.blueprint.BlueprintELResolver;
import org.camunda.bpm.extension.osgi.blueprint.ProcessEngineFactoryWithELResolver;
import org.camunda.bpm.extension.osgi.blueprint.ProcessEngineFactoryWithELResolver.BlueprintExpressionManager;
import org.camunda.bpm.extension.osgi.scripting.impl.OsgiScriptingEngines;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

public class ProcessEngineFactoryWithELResolverTest {

	private ProcessEngineFactoryWithELResolver factory;

	@Before
	public void setUp() {
		factory = new ProcessEngineFactoryWithELResolver();
	}

	@Test
	public void initWithBlueprintELResolverAndWithoutResolverFactories()
			throws Exception {
		StandaloneProcessEngineConfiguration config = mock(StandaloneProcessEngineConfiguration.class);
		when(config.getResolverFactories()).thenReturn(null);
		factory.setProcessEngineConfiguration(config);
		factory.setBlueprintELResolver(new BlueprintELResolver());
		factory.init();
		// captures
		ArgumentCaptor<BlueprintExpressionManager> elManagerCaptor = ArgumentCaptor
				.forClass(BlueprintExpressionManager.class);
		verify(config).setExpressionManager(elManagerCaptor.capture());
		ArgumentCaptor<OsgiScriptingEngines> scriptCaptor = ArgumentCaptor
				.forClass(OsgiScriptingEngines.class);
		verify(config).setScriptingEngines(scriptCaptor.capture());
		// checks
		checkScriptingEngine(scriptCaptor.getValue());
		checkExpressionManager(elManagerCaptor.getValue());
	}

	private void checkScriptingEngine(OsgiScriptingEngines scriptingEngine) {
		assertThat(scriptingEngine, isA(OsgiScriptingEngines.class));
		assertThat(scriptingEngine.getScriptBindingsFactory()
				.getResolverFactories().size(), is(2));
		assertThat(
				scriptingEngine.getScriptBindingsFactory()
						.getResolverFactories(),
				allOf(hasItem(isA(VariableScopeResolverFactory.class)),
						hasItem(isA(BeansResolverFactory.class))));
	}

	private void checkExpressionManager(BlueprintExpressionManager exprManager) {
		ELResolver elResolver = exprManager.createElResolver(null);
		assertThat(elResolver, is(instanceOf(CompositeELResolver.class)));
		// FIXME gotta find a way to get hold of Resolvers inside
		// compositeResolver to check that the expected ones are set
	}

	@Test(expected = NullPointerException.class)
	public void initWithoutBlueprintELResolverCausesNPEInBlueprintExpressionManager()
			throws Exception {
		StandaloneProcessEngineConfiguration config = mock(StandaloneProcessEngineConfiguration.class);
		factory.setProcessEngineConfiguration(config);
		factory.init();
		// captures
		ArgumentCaptor<BlueprintExpressionManager> elManagerCaptor = ArgumentCaptor
				.forClass(BlueprintExpressionManager.class);
		verify(config).setExpressionManager(elManagerCaptor.capture());
		elManagerCaptor.getValue().createElResolver(null);
	}

	@Test
	public void initWithResolverFactories() throws Exception {
		StandaloneProcessEngineConfiguration config = mock(StandaloneProcessEngineConfiguration.class);
		ResolverFactory resolverFactory = mock(ResolverFactory.class);
		when(config.getResolverFactories()).thenReturn(
				Collections.singletonList(resolverFactory));
		factory.setProcessEngineConfiguration(config);
		factory.init();
		// captures
		ArgumentCaptor<OsgiScriptingEngines> scriptCaptor = ArgumentCaptor
				.forClass(OsgiScriptingEngines.class);
		verify(config).setScriptingEngines(scriptCaptor.capture());
		// checks
		assertThat(scriptCaptor.getValue().getScriptBindingsFactory()
				.getResolverFactories(), hasItem(resolverFactory));
	}
}

@@ -48,55 +48,8 @@
 t;%0A%0A
-import static org.hamcrest.CoreMatchers.allOf;%0A
 impo
@@ -93,16 +93,16 @@
 asItem;%0A
+
 import s
@@ -429,16 +429,39 @@
 ections;
+%0Aimport java.util.List;
 %0A%0Aimport
@@ -860,161 +860,8 @@
 ry;%0A
-import org.camunda.bpm.extension.osgi.blueprint.BlueprintELResolver;%0Aimport org.camunda.bpm.extension.osgi.blueprint.ProcessEngineFactoryWithELResolver;%0A
 impo
@@ -1042,16 +1042,45 @@
 ngines;%0A
+import org.hamcrest.Matcher;%0A
 import o
@@ -2376,27 +2376,58 @@
 ss));%0A%09%09
-assertThat(
+List%3CResolverFactory%3E resolverFactories = 
 scriptin
@@ -2425,32 +2425,37 @@
  scriptingEngine
+%0A%09%09%09%09
 .getScriptBindin
@@ -2457,37 +2457,32 @@
 indingsFactory()
-%0A%09%09%09%09
 .getResolverFact
@@ -2492,97 +2492,189 @@
 es()
-.size(), is(2));%0A%09%09assertThat(%0A%09%09%09%09scriptingEngine.getScriptBindingsFactory()%0A%09%09%09%09%09%09.getR
+;%0A%09%09assertThat(resolverFactories.size(), is(2));%0A%09%09Matcher%3CIterable%3C? super VariableScopeResolverFactory%3E%3E hasItem = hasItem(isA(VariableScopeResolverFactory.class));%0A%09%09assertThat(r
 esol
@@ -2689,119 +2689,167 @@
 ries
-()
 ,%0A%09%09%09%09
-allOf(
 hasItem
-(isA(VariableScopeResolverFactory.class)),%0A%09%09%09%09%09%09hasItem(isA(BeansResolverFactory.class)))
+);%0A%09%09Matcher%3CIterable%3C? super BeansResolverFactory%3E%3E hasItem2 = hasItem(isA(BeansResolverFactory.class));%0A%09%09assertThat(resolverFactories, hasItem2
 );%0A%09

change matchers in test to fix problem on other computers