/*
 * Copyright 2002-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.config.java.plugin.tx;

import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.config.java.plugin.ProxyTargetClass;
import org.springframework.config.java.plugin.ProxyTargetClassDeclaration;


/**
 * TODO: JAVADOC
 * Utility class for handling registration of auto-proxy creators used internally
 * by the '{@code aop}' namespace tags.
 *
 * <p>Only a single auto-proxy creator can be registered and multiple tags may wish
 * to register different concrete implementations. As such this class delegates to
 * {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
 * may request a particular auto-proxy creator and know that class, <i>or a subclass
 * thereof</i>, will eventually be resident in the application context.
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 2.0
 * @see AopConfigUtils
 */
abstract class GeneralizedAopNamespaceUtils {

    /**
     * The {@code proxy-target-class} attribute as found on AOP-related XML tags.
     */
    public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";


    public static void registerAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, ProxyTargetClassDeclaration declaration) {

        BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
                registry, null /*parserContext.extractSource(sourceElement) */);
        useClassProxyingIfNecessary(registry, declaration);
        registerComponentIfNecessary(beanDefinition, registry);
    }

    public static void registerAspectJAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, ProxyTargetClassDeclaration declaration) {

        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
                registry, null /*parserContext.extractSource(sourceElement)*/);
        useClassProxyingIfNecessary(registry, declaration);
        registerComponentIfNecessary(beanDefinition, registry);
    }

    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, ProxyTargetClassDeclaration declaration) {

        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                registry, null /*parserContext.extractSource(declaration)*/);
        useClassProxyingIfNecessary(registry, declaration);
        registerComponentIfNecessary(beanDefinition, registry);
    }

    /**
     * @deprecated since Spring 2.5, in favor of
     * {@link #registerAutoProxyCreatorIfNecessary(ParserContext, Element)} and
     * {@link AopConfigUtils#registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)}
     */
    @Deprecated
    public static void registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
                registry, source);
        registerComponentIfNecessary(beanDefinition, registry);
    }

    /**
     * @deprecated since Spring 2.5, in favor of
     * {@link AopConfigUtils#forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry)}
     */
    @Deprecated
    public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }


    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, ProxyTargetClassDeclaration declaration) {
        if (declaration != null) {
            /*
            boolean proxyTargetClass = Boolean.valueOf(
                    sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)).booleanValue();
                    */
            if (declaration.getProxyTargetClass() == ProxyTargetClass.TRUE) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
        }
    }

    private static void registerComponentIfNecessary(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
        if (beanDefinition != null) {
            /*
            BeanComponentDefinition componentDefinition =
                    new BeanComponentDefinition(beanDefinition, );
            parserContext.registerComponent(componentDefinition);
            */
            registry.registerBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        }
    }

}
