/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
 */
package org.ocelotds.spring;

import org.ocelotds.spi.DataServiceException;
import org.ocelotds.spi.DataServiceResolver;
import org.ocelotds.spi.IDataServiceResolver;
import org.ocelotds.spi.Scope;
import java.util.Map;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import org.ocelotds.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * Resolver of SPRING
 *
 * @author hhfrancois
 */
@DataServiceResolver(Constants.Resolver.SPRING)
@ApplicationScoped
public class SpringResolver implements IDataServiceResolver{

	private static final Logger logger = LoggerFactory.getLogger(SpringResolver.class);
	
	@Inject
	@Any
	@OcelotSpringConfiguration		  
	Instance<Object> ocelotSpringConfigs;

	private AnnotationConfigApplicationContext applicationContext;
	
	public AnnotationConfigApplicationContext getApplicationContext() {
		logger.debug("Initialisation du context Spring");
		if(applicationContext == null) {
			applicationContext =  new AnnotationConfigApplicationContext();
			for (Object ocelotSpringConfig : ocelotSpringConfigs) {
				logger.debug("Find 1 context Spring that implements OcelotSpringConfig");
				applicationContext.register(ocelotSpringConfig.getClass());
			}
			applicationContext.refresh();
		}
		return applicationContext;
	}

	@Override
	public <T> T resolveDataService(Class<T> clazz) throws DataServiceException {
		Map<String, ?> beansOfType = getApplicationContext().getBeansOfType(clazz);
		if (beansOfType == null || beansOfType.isEmpty()) {
			throw new DataServiceException("Unable to find any Spring bean of type : " + clazz.getName());
		}
		if (beansOfType.size() > 1) {
			throw new DataServiceException("Multiple (" + beansOfType.size() + ") Spring beans of type : '" + clazz.getName() + "' founded. Unable to choose one.");
		}
		return clazz.cast(beansOfType.values().iterator().next());
	}

	@Override
	public Scope getScope(Class clazz) {
		AnnotationConfigApplicationContext applicationCtx = this.getApplicationContext();
		Map<String, ?> beansOfType = applicationCtx.getBeansOfType(clazz);
		if(beansOfType != null) {
			String next = beansOfType.keySet().iterator().next();
			if(next!=null) {
				if (!applicationCtx.isPrototype(next) && !applicationCtx.isSingleton(next)) {
					return Scope.SESSION;
				}
			}
		}
		return Scope.MANAGED;
	}
}

@@ -614,30 +614,51 @@
 %0Aimport org.
-slf4j.
+ocelotds.annotations.Ocelot
 Logger;%0Aimpo
@@ -676,23 +676,16 @@
 j.Logger
-Factory
 ;%0Aimport
@@ -946,97 +946,52 @@
 lver
+ 
 %7B%0A%0A%09
-private static final Logger logger = LoggerFactory.getLogger(SpringResolver.class)
+@Inject%0A%09@OcelotLogger%0A%09Logger logger
 ;%0A
-%09
 %0A%09@I
@@ -1033,12 +1033,8 @@
 tion
-%09%09  
 %0A%09In
@@ -1075,16 +1075,8 @@
 ;%0A%0A%09
-private 
 Anno
@@ -1126,17 +1126,16 @@
 ontext;%0A
-%09
 %0A%09public
@@ -1220,29 +1220,23 @@
 Init
-ialisation du
+ Spring
  context
  Spr
@@ -1235,23 +1235,16 @@
 text
- Spring
 %22);%0A%09%09if
 (app
@@ -1239,16 +1239,17 @@
 %22);%0A%09%09if
+ 
 (applica
@@ -1294,17 +1294,16 @@
 ontext =
- 
  new Ann
@@ -1337,16 +1337,164 @@
 text();%0A
+%09%09%09ClientScope clientScope = new ClientScope();%0A%09%09%09applicationContext.getBeanFactory().registerScope(clientScope.getConversationId(), clientScope);%0A
 %09%09%09for (
@@ -1559,22 +1559,19 @@
 ger.
-debug
+info
 (%22Find 
-1 
 cont
@@ -1585,25 +1585,14 @@
 ing 
-that implements O
+%7B%7D%22, o
 celo
@@ -1604,17 +1604,27 @@
 ngConfig
-%22
+.getClass()
 );%0A%09%09%09%09a
@@ -2387,16 +2387,71 @@
 lazz) %7B%0A
+%09%09logger.debug(%22Try to get scope of class %7B%7D%22, clazz);%0A
 %09%09Annota
@@ -2599,16 +2599,17 @@
 z);%0A%09%09if
+ 
 (beansOf
@@ -2624,16 +2624,83 @@
 null) %7B%0A
+%09%09%09logger.debug(%22Try to get scope of class %7B%7D from beans%22, clazz);%0A
 %09%09%09Strin
@@ -2701,20 +2701,20 @@
 %09String 
-next
+bean
  = beans
@@ -2755,17 +2755,95 @@
 %0A%09%09%09
-if(next
+logger.debug(%22Try to get scope of class %7B%7D from bean %7B%7D%22, clazz, bean);%0A%09%09%09if (bean 
 !=
+ 
 null
@@ -2854,13 +2854,28 @@
 %09%09%09%09
-if (!
+boolean prototype = 
 appl
@@ -2901,50 +2901,215 @@
 ype(
-next) && !applicationCtx.isSingleton(next)
+bean);%0A%09%09%09%09boolean singleton = applicationCtx.isSingleton(bean);%0A%09%09%09%09logger.debug(%22Try to get scope of class %7B%7D prototype : %7B%7D, singleton : %7B%7D%22, clazz, prototype, singleton);%0A%09%09%09%09if (!prototype && !singleton
 ) %7B%0A

create client scope