1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.shadow.rule;
19
20 import lombok.Getter;
21 import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
22 import org.apache.shardingsphere.infra.rule.scope.DatabaseRule;
23 import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
24 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
25 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
26 import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
27 import org.apache.shardingsphere.shadow.api.config.table.ShadowTableConfiguration;
28 import org.apache.shardingsphere.shadow.api.shadow.ShadowOperationType;
29 import org.apache.shardingsphere.shadow.api.shadow.column.ColumnShadowAlgorithm;
30 import org.apache.shardingsphere.shadow.api.shadow.hint.HintShadowAlgorithm;
31 import org.apache.shardingsphere.shadow.rule.attribute.ShadowDataSourceMapperRuleAttribute;
32 import org.apache.shardingsphere.shadow.spi.ShadowAlgorithm;
33
34 import java.util.Collection;
35 import java.util.LinkedHashMap;
36 import java.util.LinkedList;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.Optional;
40
41
42
43
44 @Getter
45 public final class ShadowRule implements DatabaseRule {
46
47 private final ShadowRuleConfiguration configuration;
48
49 private final Collection<String> hintShadowAlgorithmNames = new LinkedList<>();
50
51 private final Map<String, ShadowDataSourceRule> shadowDataSourceMappings = new LinkedHashMap<>();
52
53 private final Map<String, ShadowAlgorithm> shadowAlgorithms = new LinkedHashMap<>();
54
55 private final Map<String, ShadowTableRule> shadowTableRules = new LinkedHashMap<>();
56
57 private final ShadowAlgorithm defaultShadowAlgorithm;
58
59 @Getter
60 private final RuleAttributes attributes;
61
62 public ShadowRule(final ShadowRuleConfiguration ruleConfig) {
63 configuration = ruleConfig;
64 initShadowDataSourceMappings(ruleConfig.getDataSources());
65 initShadowAlgorithmConfigurations(ruleConfig.getShadowAlgorithms());
66 defaultShadowAlgorithm = shadowAlgorithms.get(ruleConfig.getDefaultShadowAlgorithmName());
67 if (defaultShadowAlgorithm instanceof HintShadowAlgorithm<?>) {
68 hintShadowAlgorithmNames.add(ruleConfig.getDefaultShadowAlgorithmName());
69 }
70 initShadowTableRules(ruleConfig.getTables());
71 attributes = new RuleAttributes(new ShadowDataSourceMapperRuleAttribute(shadowDataSourceMappings));
72 }
73
74 private void initShadowDataSourceMappings(final Collection<ShadowDataSourceConfiguration> dataSources) {
75 dataSources.forEach(each -> shadowDataSourceMappings.put(each.getName(), new ShadowDataSourceRule(each.getProductionDataSourceName(), each.getShadowDataSourceName())));
76 }
77
78 private void initShadowAlgorithmConfigurations(final Map<String, AlgorithmConfiguration> shadowAlgorithmConfigs) {
79 shadowAlgorithmConfigs.forEach((key, value) -> {
80 ShadowAlgorithm algorithm = TypedSPILoader.getService(ShadowAlgorithm.class, value.getType(), value.getProps());
81 if (algorithm instanceof HintShadowAlgorithm<?>) {
82 hintShadowAlgorithmNames.add(key);
83 }
84 shadowAlgorithms.put(key, algorithm);
85 });
86 }
87
88 private void initShadowTableRules(final Map<String, ShadowTableConfiguration> tables) {
89 tables.forEach((key, value) -> shadowTableRules.put(key, new ShadowTableRule(key, value.getDataSourceNames(), value.getShadowAlgorithmNames(), shadowAlgorithms)));
90 }
91
92
93
94
95
96
97 public Optional<ShadowAlgorithm> getDefaultShadowAlgorithm() {
98 return null == defaultShadowAlgorithm ? Optional.empty() : Optional.of(defaultShadowAlgorithm);
99 }
100
101
102
103
104
105
106
107 public Collection<String> getRelatedShadowTables(final Collection<String> tableNames) {
108 Collection<String> result = new LinkedList<>();
109 for (String each : tableNames) {
110 if (shadowTableRules.containsKey(each)) {
111 result.add(each);
112 }
113 }
114 return result;
115 }
116
117
118
119
120
121
122 public Collection<String> getAllShadowTableNames() {
123 return shadowTableRules.keySet();
124 }
125
126
127
128
129
130
131 @SuppressWarnings("unchecked")
132 public Collection<HintShadowAlgorithm<Comparable<?>>> getAllHintShadowAlgorithms() {
133 Collection<HintShadowAlgorithm<Comparable<?>>> result = new LinkedList<>();
134 for (String each : hintShadowAlgorithmNames) {
135 result.add((HintShadowAlgorithm<Comparable<?>>) shadowAlgorithms.get(each));
136 }
137 return result;
138 }
139
140
141
142
143
144
145
146 @SuppressWarnings("unchecked")
147 public Collection<HintShadowAlgorithm<Comparable<?>>> getRelatedHintShadowAlgorithms(final String tableName) {
148 Collection<HintShadowAlgorithm<Comparable<?>>> result = new LinkedList<>();
149 Collection<String> hintShadowAlgorithmNames = shadowTableRules.get(tableName).getHintShadowAlgorithmNames();
150 for (String each : hintShadowAlgorithmNames) {
151 result.add((HintShadowAlgorithm<Comparable<?>>) shadowAlgorithms.get(each));
152 }
153 return result;
154 }
155
156
157
158
159
160
161
162
163
164 @SuppressWarnings("unchecked")
165 public Collection<ColumnShadowAlgorithm<Comparable<?>>> getRelatedColumnShadowAlgorithms(final ShadowOperationType shadowOperationType, final String tableName, final String shadowColumn) {
166 Collection<ColumnShadowAlgorithm<Comparable<?>>> result = new LinkedList<>();
167 Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> columnShadowAlgorithmNames = shadowTableRules.get(tableName).getColumnShadowAlgorithmNames();
168 Collection<ShadowAlgorithmNameRule> names = columnShadowAlgorithmNames.get(shadowOperationType);
169 if (null == names) {
170 return result;
171 }
172 for (ShadowAlgorithmNameRule each : names) {
173 if (shadowColumn.equals(each.getShadowColumnName())) {
174 result.add((ColumnShadowAlgorithm<Comparable<?>>) shadowAlgorithms.get(each.getShadowAlgorithmName()));
175 }
176 }
177 return result;
178 }
179
180
181
182
183
184
185
186
187 public Collection<String> getRelatedShadowColumnNames(final ShadowOperationType shadowOperationType, final String tableName) {
188 Collection<String> result = new LinkedList<>();
189 Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> columnShadowAlgorithmNames = shadowTableRules.get(tableName).getColumnShadowAlgorithmNames();
190 Collection<ShadowAlgorithmNameRule> names = columnShadowAlgorithmNames.get(shadowOperationType);
191 if (null == names) {
192 return result;
193 }
194 for (ShadowAlgorithmNameRule each : names) {
195 result.add(each.getShadowColumnName());
196 }
197 return result;
198 }
199
200
201
202
203
204
205
206 public Map<String, String> getRelatedShadowDataSourceMappings(final String tableName) {
207 Map<String, String> result = new LinkedHashMap<>();
208 Collection<String> shadowDataSources = shadowTableRules.get(tableName).getShadowDataSources();
209 for (String each : shadowDataSources) {
210 ShadowDataSourceRule shadowDataSourceRule = shadowDataSourceMappings.get(each);
211 result.put(shadowDataSourceRule.getProductionDataSource(), shadowDataSourceRule.getShadowDataSource());
212 }
213 return result;
214 }
215
216
217
218
219
220
221 public Map<String, String> getAllShadowDataSourceMappings() {
222 Map<String, String> result = new LinkedHashMap<>();
223 for (Entry<String, ShadowDataSourceRule> entry : shadowDataSourceMappings.entrySet()) {
224 ShadowDataSourceRule rule = entry.getValue();
225 result.put(rule.getProductionDataSource(), rule.getShadowDataSource());
226 }
227 return result;
228 }
229
230
231
232
233
234
235
236 public Optional<String> getSourceDataSourceName(final String actualDataSourceName) {
237 ShadowDataSourceRule shadowDataSourceRule = shadowDataSourceMappings.get(actualDataSourceName);
238 return null == shadowDataSourceRule ? Optional.empty() : Optional.of(shadowDataSourceRule.getProductionDataSource());
239 }
240 }