package jp.bne.deno.ordermaid.common;

import java.lang.reflect.Method;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import jp.bne.deno.ordermaid.service.PrinterService;
import jp.bne.deno.ordermaid.service.PrinterServiceImpl;

import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.matcher.AbstractMatcher;

/**
 * DIコンテナを設定するためのモジュール構成.
 * 
 * @author hasegawt
 * 
 */
public class CommonModule extends AbstractModule {

	/**
	 * インターフェイス-実装の関連付けを行う.
	 */
	public void configure() {

		// ロギングの設定.
		bindInterceptor(new LoggingClassMatcher(), new AllMethodMatcher(),
				new LoggingIntercepter());

		// サービス層の設定.
		bind(PrinterService.class).to(PrinterServiceImpl.class);

		// EJB3の設定.
		EntityManagerFactory factory = Persistence
				.createEntityManagerFactory("order");
		bind(EntityManagerFactory.class).toInstance(factory);
		bind(EntityManager.class).toProvider(EntityManagerProvider.class);
		bindInterceptor(new DaoClassMatcher(), new AllMethodMatcher(),
				new DaoInterceptor(factory));

	}

	/**
	 * ログ出力するクラスの絞込.
	 * 
	 * @author hasegawt
	 * 
	 */
	class LoggingClassMatcher extends AbstractMatcher<Class<?>> {
		public boolean matches(Class<?> clazz) {
			String prefix = "jp.bne.deno.ordermaid";
			if (clazz.getPackage().getName().startsWith(prefix)) {
				return true;
			}
			return false;
		}
	}

	/**
	 * DAOクラスの絞込.
	 * 
	 * @author hasegawt
	 * 
	 */
	class DaoClassMatcher extends AbstractMatcher<Class<?>> {
		public boolean matches(Class<?> clazz) {
			String prefix = "jp.bne.deno.ordermaid.dao";
			if (clazz.getPackage().getName().startsWith(prefix)) {
				return true;
			}
			return false;
		}
	}

	/**
	 * 全メソッドを対象とするMatcher.
	 * 
	 * @author hasegawt
	 * 
	 */
	class AllMethodMatcher extends AbstractMatcher<Method> {
		public boolean matches(Method t) {
			return true;
		}
	}

	/**
	 * EntityManagerを返すプロバイダ。
	 * 
	 * @author hasegawt
	 * 
	 */
	static class EntityManagerProvider implements Provider<EntityManager> {

		@Inject
		EntityManagerFactory factory;

		@Override
		public EntityManager get() {
			return factory.createEntityManager();
		}
	}
}
