com.dangdang.ddframe.rdb.sharding.router.mixed.CartesianTablesRouter.java Source code

Java tutorial

Introduction

Here is the source code for com.dangdang.ddframe.rdb.sharding.router.mixed.CartesianTablesRouter.java

Source

/*
 * 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.mixed;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.dangdang.ddframe.rdb.sharding.router.single.SingleRoutingResult;
import com.dangdang.ddframe.rdb.sharding.router.single.SingleRoutingTableFactor;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * ?.
 * 
 * @author zhangliang
 */
@RequiredArgsConstructor
@Slf4j
final class CartesianTablesRouter {

    private final Collection<SingleRoutingResult> routingResults;

    CartesianResult route() {
        CartesianResult result = new CartesianResult();
        for (Entry<String, Set<String>> entry : getDataSourceLogicTablesMap().entrySet()) {
            List<Set<String>> actualTableGroups = getActualTableGroups(entry.getKey(), entry.getValue());
            List<Set<SingleRoutingTableFactor>> routingTableFactorGroups = toRoutingTableFactorGroups(
                    entry.getKey(), actualTableGroups);
            result.merge(entry.getKey(),
                    getCartesianTableReferences(Sets.cartesianProduct(routingTableFactorGroups)));
        }
        log.trace("cartesian tables sharding result: {}", result);
        return result;
    }

    private Map<String, Set<String>> getDataSourceLogicTablesMap() {
        Collection<String> intersectionDataSources = getIntersectionDataSources();
        Map<String, Set<String>> result = new HashMap<>(routingResults.size());
        for (SingleRoutingResult each : routingResults) {
            for (Entry<String, Set<String>> entry : each.getDataSourceLogicTablesMap(intersectionDataSources)
                    .entrySet()) {
                if (result.containsKey(entry.getKey())) {
                    result.get(entry.getKey()).addAll(entry.getValue());
                } else {
                    result.put(entry.getKey(), entry.getValue());
                }
            }
        }
        return result;
    }

    private Collection<String> getIntersectionDataSources() {
        Collection<String> result = new HashSet<>();
        for (SingleRoutingResult each : routingResults) {
            if (result.isEmpty()) {
                result.addAll(each.getDataSources());
            }
            result.retainAll(each.getDataSources());
        }
        return result;
    }

    private List<Set<String>> getActualTableGroups(final String dataSource, final Set<String> logicTables) {
        List<Set<String>> result = new ArrayList<>(logicTables.size());
        for (SingleRoutingResult each : routingResults) {
            result.addAll(each.getActualTableGroups(dataSource, logicTables));
        }
        return result;
    }

    private List<Set<SingleRoutingTableFactor>> toRoutingTableFactorGroups(final String dataSource,
            final List<Set<String>> actualTableGroups) {
        List<Set<SingleRoutingTableFactor>> result = new ArrayList<>(actualTableGroups.size());
        for (Set<String> each : actualTableGroups) {
            result.add(new HashSet<>(
                    Lists.transform(new ArrayList<>(each), new Function<String, SingleRoutingTableFactor>() {

                        @Override
                        public SingleRoutingTableFactor apply(final String input) {
                            return findRoutingTableFactor(dataSource, input);
                        }
                    })));
        }
        return result;
    }

    private SingleRoutingTableFactor findRoutingTableFactor(final String dataSource, final String actualTable) {
        for (SingleRoutingResult each : routingResults) {
            Optional<SingleRoutingTableFactor> result = each.findRoutingTableFactor(dataSource, actualTable);
            if (result.isPresent()) {
                return result.get();
            }
        }
        throw new IllegalStateException(String.format(
                "Cannot found routing table factor, data source: %s, actual table: %s", dataSource, actualTable));
    }

    private List<CartesianTableReference> getCartesianTableReferences(
            final Set<List<SingleRoutingTableFactor>> cartesianRoutingTableFactorGroups) {
        List<CartesianTableReference> result = new ArrayList<>(cartesianRoutingTableFactorGroups.size());
        for (List<SingleRoutingTableFactor> each : cartesianRoutingTableFactorGroups) {
            result.add(new CartesianTableReference(each));
        }
        return result;
    }
}