View Javadoc
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.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   * Databases shadow rule.
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       * Get default shadow algorithm.
94       *
95       * @return shadow algorithm
96       */
97      public Optional<ShadowAlgorithm> getDefaultShadowAlgorithm() {
98          return null == defaultShadowAlgorithm ? Optional.empty() : Optional.of(defaultShadowAlgorithm);
99      }
100     
101     /**
102      * Get related shadow tables.
103      *
104      * @param tableNames table names
105      * @return related shadow tables
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      * Get all shadow table names.
119      *
120      * @return shadow table names
121      */
122     public Collection<String> getAllShadowTableNames() {
123         return shadowTableRules.keySet();
124     }
125     
126     /**
127      * Get related hint shadow algorithms.
128      *
129      * @return related hint shadow algorithms
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      * Get related hint shadow algorithms by table name.
142      *
143      * @param tableName table name
144      * @return hint shadow algorithms
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      * Get related column shadow algorithms by table name.
158      *
159      * @param shadowOperationType shadow operation type
160      * @param tableName table name
161      * @param shadowColumn shadow column
162      * @return column shadow algorithms
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      * Get related shadow column names.
182      *
183      * @param shadowOperationType shadow operation type
184      * @param tableName table name
185      * @return related shadow column names
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      * Get shadow data source mappings.
202      *
203      * @param tableName table name
204      * @return shadow data source rules
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      * Get all shadow data source mappings.
218      *
219      * @return all shadow data source mappings
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      * Get source data source name.
232      *
233      * @param actualDataSourceName actual data source name
234      * @return source data source name
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 }