/*
 * Copyright 1999-2015 dangdang.com.
 * <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 com.dangdang.ddframe.rdb.sharding.router;

import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.parser.sql.context.GeneratedKeyContext;
import com.dangdang.ddframe.rdb.sharding.parser.sql.context.InsertSQLContext;
import com.dangdang.ddframe.rdb.sharding.parser.sql.context.SQLContext;
import com.google.common.base.Optional;
import lombok.RequiredArgsConstructor;

import java.util.List;

/**
 * 预解析功能的SQL路由器.
 * 
 * @author gaohongtao
 */
@RequiredArgsConstructor
public class PreparedSQLRouter {
    
    private final String logicSql;
    
    private final SQLRouteEngine engine;
    
    private final ShardingRule shardingRule;
    
    private SQLContext sqlContext;
    
    /**
     * 使用参数进行SQL路由.
     * 当第一次路由时进行SQL解析,之后的路由复用第一次的解析结果.
     * 
     * @param parameters SQL中的参数
     * @return 路由结果
     */
    public SQLRouteResult route(final List<Object> parameters) {
        if (null == sqlContext) {
            sqlContext = engine.parseSQL(logicSql, parameters);
        } else {
            generateId(parameters);
            sqlContext.getConditionContext().setNewConditionValue(parameters);
        }
        return engine.routeSQL(sqlContext, parameters);
    }
    
    private void generateId(final List<Object> parameters) {
        if (!(sqlContext instanceof InsertSQLContext)) {
            return;
        }
        Optional<TableRule> tableRuleOptional = shardingRule.tryFindTableRule(sqlContext.getTables().iterator().next().getName());
        if (!tableRuleOptional.isPresent()) {
            return;
        }
        TableRule tableRule = tableRuleOptional.get();
        GeneratedKeyContext generatedKeyContext = ((InsertSQLContext) sqlContext).getGeneratedKeyContext();
        for (String each : generatedKeyContext.getColumns()) {
            Object id = tableRule.generateId(each);
            parameters.add(id);
            generatedKeyContext.putValue(each, id);
        }
    }
}


@@ -1092,24 +1092,82 @@
 nstructor;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Collections;%0A
 import java.
@@ -1177,16 +1177,16 @@
 l.List;%0A
-
 %0A/**%0A * 
@@ -1800,28 +1800,91 @@
     
-generateId(parameter
+List%3CObject%3E generatedIds = generateId();%0A            parameters.addAll(generatedId
 s);%0A
@@ -2055,30 +2055,8 @@
 ate 
-void generateId(final 
 List
@@ -2060,34 +2060,35 @@
 ist%3CObject%3E 
-parameters
+generateId(
 ) %7B%0A        
@@ -2146,32 +2146,56 @@
           return
+ Collections.emptyList()
 ;%0A        %7D%0A    
@@ -2385,16 +2385,40 @@
   return
+ Collections.emptyList()
 ;%0A      
@@ -2580,24 +2580,112 @@
 yContext();%0A
+        List%3CObject%3E result = new ArrayList%3C%3E(generatedKeyContext.getColumns().size());%0A
         for 
@@ -2795,34 +2795,30 @@
             
-parameters
+result
 .add(id);%0A  
@@ -2863,24 +2863,24 @@
 (each, id);%0A
-
         %7D%0A  
@@ -2873,21 +2873,44 @@
 ;%0A        %7D%0A
+        return result;%0A
     %7D%0A%7D%0A%0A

refactor generateId