/*
 * Copyright 2016-2018 shardingsphere.io.
 * <p>
 * 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.
 * </p>
 */

package io.shardingsphere.jdbc.orchestration.spring.namespace.parser;

import io.shardingsphere.jdbc.orchestration.config.OrchestrationConfiguration;
import io.shardingsphere.jdbc.orchestration.config.OrchestrationType;
import io.shardingsphere.jdbc.orchestration.spring.datasource.OrchestrationSpringMasterSlaveDataSource;
import io.shardingsphere.jdbc.orchestration.spring.datasource.OrchestrationSpringShardingDataSource;
import io.shardingsphere.jdbc.orchestration.spring.namespace.constants.ShardingDataSourceBeanDefinitionParserTag;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

/**
 * Data source parser for spring namespace.
 * 
 * @author panjuan
 */
public final class DataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser {
    
    private OrchestrationType orchestrationType;
    
    @Override
    protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
        setOrchestrationType(element);
        BeanDefinitionBuilder factory = OrchestrationType.SHARDING == orchestrationType ? BeanDefinitionBuilder.rootBeanDefinition(OrchestrationSpringShardingDataSource.class)
                : BeanDefinitionBuilder.rootBeanDefinition(OrchestrationSpringMasterSlaveDataSource.class);
        
        factory.addConstructorArgReference(element.getAttribute(ShardingDataSourceBeanDefinitionParserTag.DATA_SOURCE_REF_TAG));
        factory.addConstructorArgValue(getOrchestrationConfiguration(element));
        return factory.getBeanDefinition();
    }
    
    private void setOrchestrationType(final Element element) {
        orchestrationType = ShardingDataSourceBeanDefinitionParserTag.ROOT_TAG.equals(element.getLocalName()) ? OrchestrationType.SHARDING : OrchestrationType.MASTER_SLAVE;
    }
    
    private BeanDefinition getOrchestrationConfiguration(final Element element) {
        BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(OrchestrationConfiguration.class);
        factory.addConstructorArgValue(element.getAttribute(ID_ATTRIBUTE));
        factory.addConstructorArgReference(element.getAttribute(ShardingDataSourceBeanDefinitionParserTag.REG_REF_TAG));
        factory.addConstructorArgValue(element.getAttribute(ShardingDataSourceBeanDefinitionParserTag.OVERWRITE_TAG));
        factory.addConstructorArgValue(orchestrationType);
        return factory.getBeanDefinition();
    }
}


@@ -684,16 +684,55 @@
 arser;%0A%0A
+import com.google.common.base.Strings;%0A
 import i
@@ -2239,24 +2239,59 @@
 s);%0A        
+configureFactory(element, factory);
 %0A        fac
@@ -2283,32 +2283,39 @@
 y);%0A        
+return 
 factory.
 addConstruct
@@ -2306,35 +2306,168 @@
 ory.
-addConstructorArgReference(
+getBeanDefinition();%0A    %7D%0A    %0A    private void configureFactory(final Element element, final BeanDefinitionBuilder factory) %7B%0A        String dataSourceName = 
 elem
@@ -2537,33 +2537,32 @@
 _SOURCE_REF_TAG)
-)
 ;%0A        factor
@@ -2547,32 +2547,160 @@
 F_TAG);%0A        
+if (!Strings.isNullOrEmpty(dataSourceName)) %7B%0A            factory.addConstructorArgReference(dataSourceName);%0A        %7D%0A        
 factory.addConst
@@ -2756,52 +2756,8 @@
 ent)
-);%0A        return factory.getBeanDefinition(
 );%0A 

add configureFactory()