1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.shardingsphere.sharding.rule;
19
20 import com.cedarsoftware.util.CaseInsensitiveMap;
21 import lombok.Getter;
22 import lombok.RequiredArgsConstructor;
23 import org.apache.shardingsphere.sharding.exception.metadata.ActualTableNotFoundException;
24 import org.apache.shardingsphere.sharding.exception.metadata.BindingTableNotFoundException;
25
26 import java.util.Collection;
27 import java.util.LinkedHashMap;
28 import java.util.Map;
29 import java.util.Optional;
30
31 /**
32 * Binding table rule.
33 *
34 * <p>Binding table is same sharding rule with different tables, use one of them can deduce other name of actual tables and data sources.</p>
35 */
36 @RequiredArgsConstructor
37 @Getter
38 public final class BindingTableRule {
39
40 private final Map<String, ShardingTable> shardingTables = new CaseInsensitiveMap<>();
41
42 /**
43 * Judge contains this logic table in this rule.
44 *
45 * @param logicTable logic table name
46 * @return contains this logic table or not
47 */
48 public boolean hasLogicTable(final String logicTable) {
49 return shardingTables.containsKey(logicTable);
50 }
51
52 /**
53 * Deduce actual table name from other actual table name in same binding table rule.
54 *
55 * @param dataSource data source name
56 * @param logicTable logic table name
57 * @param otherLogicTable other logic table name in same binding table rule
58 * @param otherActualTable other actual table name in same binding table rule
59 * @return actual table name
60 * @throws ActualTableNotFoundException actual table not found exception
61 * @throws BindingTableNotFoundException binding table not found exception
62 */
63 public String getBindingActualTable(final String dataSource, final String logicTable, final String otherLogicTable, final String otherActualTable) {
64 Optional<ShardingTable> otherShardingTable = Optional.ofNullable(shardingTables.get(otherLogicTable));
65 int index = otherShardingTable.map(optional -> optional.findActualTableIndex(dataSource, otherActualTable)).orElse(-1);
66 if (-1 == index) {
67 throw new ActualTableNotFoundException(dataSource, otherActualTable);
68 }
69 Optional<ShardingTable> shardingTable = Optional.ofNullable(shardingTables.get(logicTable));
70 if (shardingTable.isPresent()) {
71 return shardingTable.get().getActualDataNodes().get(index).getTableName();
72 }
73 throw new BindingTableNotFoundException(dataSource, logicTable, otherActualTable);
74 }
75
76 /**
77 * Get list of logical table.
78 *
79 * @return logical tables.
80 */
81 public Collection<String> getAllLogicTables() {
82 return shardingTables.keySet();
83 }
84
85 /**
86 * Get logic and actual tables.
87 *
88 * @param dataSource data source
89 * @param logicTable logic table
90 * @param actualTable actual table
91 * @param availableLogicBindingTables available logic binding tables
92 * @return logic and actual tables
93 */
94 public Map<String, String> getLogicAndActualTables(final String dataSource, final String logicTable, final String actualTable, final Collection<String> availableLogicBindingTables) {
95 Map<String, String> result = new LinkedHashMap<>(availableLogicBindingTables.size(), 1F);
96 for (String each : availableLogicBindingTables) {
97 if (!each.equalsIgnoreCase(logicTable) && hasLogicTable(each)) {
98 result.put(each, getBindingActualTable(dataSource, each, logicTable, actualTable));
99 }
100 }
101 return result;
102 }
103 }