/**
 * ÀÌ ¼Ò½º´Â Spring ÇÁ·¹ÀÓ¿öÅ© ¿öÅ©ºÏ¿¡¼­ »ç¿ëÇÑ ¿¹Á¦ ¼Ò½ºÀÔ´Ï´Ù. 
 * ÀÌ ¼Ò½º´Â ¸ðµç °³¹ßÀÚµéÀÌ ÀÚÀ¯·Ó°Ô ¼öÁ¤ ¹× ¹èÆ÷ÇÒ ¼ö ÀÖ½À´Ï´Ù. 
 * ´Ü, ÀÌ ¼Ò½º¸¦ ±â¹ÝÀ¸·Î »õ·Î¿î ¾ÖÇÃ¸®ÄÉÀÌ¼ÇÀ» °³¹ßÇÒ °æ¿ì ÃâÃ³¸¦ ¸í½ÃÇØ ÁÖ½Ã¸é µË´Ï´Ù. 
 */
package net.javajigi.advice;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

public class AOPFactoryBean implements FactoryBean, BeanFactoryAware, InitializingBean {
	private boolean singleton = true;
	
	private Object instance;
	
	private String[] interceptorNames;
	
	private Object target;
	
	private BeanFactory beanFactory;
	
	public void setBeanFactory(BeanFactory beanFactory){
		this.beanFactory = beanFactory;
	}
	
	public void setInterceptorNames(String[] interceptorNames) {
		this.interceptorNames = interceptorNames;
	}
	
	public void setTarget(Object target) {
		this.target = target;
	}
	
	public void afterPropertiesSet() throws Exception {
		if( target ==  null ) {
			throw new NullPointerException("Target Å¬·¡½º ÀÌ¸§À» ÀÔ·ÂÇØ¾ß ÇÕ´Ï´Ù.");
		}
		
		if ( (interceptorNames == null ) && (interceptorNames.length == 0) ) {
			instance = target;
		} else {
			ProxyFactory pf = new ProxyFactory();
			pf.setTarget(target);
			
			for( int i=0; i < interceptorNames.length; i++ ) {
				Advisor advisor = getAdvisor(interceptorNames[i]);
				if ( advisor != null ) {
					pf.addAdvisor(advisor);
				}
			}
			
			instance = pf.getProxy();
		}		
	}
	
	private Advisor getAdvisor(String interceptorName){
		Object advObject = beanFactory.getBean(interceptorName);
		if( advObject instanceof Advisor) {
			return (Advisor)advObject;
		} else if(advObject instanceof Advice) {
			return new DefaultPointcutAdvisor((Advice)advObject);
		} else {
			return null;
		}
	}
	
	public Object getObject() throws Exception {
		return instance;
	}

	public Class getObjectType() {
		if( instance != null ) {
			return instance.getClass();
		}
		
		return null;
	}

	public boolean isSingleton() {
		return singleton;
	}
}
