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.infra.rule.builder.database;
19  
20  import lombok.AccessLevel;
21  import lombok.NoArgsConstructor;
22  import org.apache.shardingsphere.infra.config.database.DatabaseConfiguration;
23  import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
24  import org.apache.shardingsphere.infra.config.rule.checker.RuleConfigurationChecker;
25  import org.apache.shardingsphere.infra.config.rule.function.DistributedRuleConfiguration;
26  import org.apache.shardingsphere.infra.config.rule.function.EnhancedRuleConfiguration;
27  import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
28  import org.apache.shardingsphere.infra.instance.InstanceContext;
29  import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
30  import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
31  
32  import javax.sql.DataSource;
33  import java.util.Arrays;
34  import java.util.Collection;
35  import java.util.Collections;
36  import java.util.Comparator;
37  import java.util.LinkedHashMap;
38  import java.util.LinkedList;
39  import java.util.Map;
40  import java.util.Map.Entry;
41  import java.util.stream.Collectors;
42  
43  /**
44   * Database rules builder.
45   */
46  @NoArgsConstructor(access = AccessLevel.PRIVATE)
47  public final class DatabaseRulesBuilder {
48      
49      /**
50       * Build database rules.
51       *
52       * @param databaseName database name
53       * @param protocolType protocol type
54       * @param databaseConfig database configuration
55       * @param instanceContext instance context
56       * @return built rules
57       */
58      @SuppressWarnings({"unchecked", "rawtypes"})
59      public static Collection<ShardingSphereRule> build(final String databaseName, final DatabaseType protocolType, final DatabaseConfiguration databaseConfig, final InstanceContext instanceContext) {
60          Collection<ShardingSphereRule> result = new LinkedList<>();
61          for (Entry<RuleConfiguration, DatabaseRuleBuilder> entry : getRuleBuilderMap(databaseConfig).entrySet()) {
62              Map<String, DataSource> dataSources = databaseConfig.getStorageUnits().entrySet().stream()
63                      .collect(Collectors.toMap(Entry::getKey, storageUnit -> storageUnit.getValue().getDataSource(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
64              RuleConfigurationChecker configChecker = OrderedSPILoader.getServicesByClass(
65                      RuleConfigurationChecker.class, Collections.singleton(entry.getKey().getClass())).get(entry.getKey().getClass());
66              if (null != configChecker) {
67                  configChecker.check(databaseName, entry.getKey(), dataSources, result);
68              }
69              result.add(entry.getValue().build(entry.getKey(), databaseName, protocolType, dataSources, result, instanceContext));
70          }
71          return result;
72      }
73      
74      /**
75       * Build database rules.
76       *
77       * @param databaseName database name
78       * @param protocolType protocol type
79       * @param dataSources data sources
80       * @param rules rules
81       * @param ruleConfig rule configuration
82       * @param instanceContext instance context
83       * @return built rules
84       */
85      @SuppressWarnings({"unchecked", "rawtypes"})
86      public static Collection<ShardingSphereRule> build(final String databaseName, final DatabaseType protocolType, final Map<String, DataSource> dataSources,
87                                                         final Collection<ShardingSphereRule> rules, final RuleConfiguration ruleConfig, final InstanceContext instanceContext) {
88          Collection<ShardingSphereRule> result = new LinkedList<>();
89          for (Entry<RuleConfiguration, DatabaseRuleBuilder> entry : OrderedSPILoader.getServices(DatabaseRuleBuilder.class,
90                  Collections.singletonList(ruleConfig), Comparator.reverseOrder()).entrySet()) {
91              RuleConfigurationChecker configChecker = OrderedSPILoader.getServicesByClass(
92                      RuleConfigurationChecker.class, Collections.singleton(entry.getKey().getClass())).get(entry.getKey().getClass());
93              if (null != configChecker) {
94                  configChecker.check(databaseName, entry.getKey(), dataSources, rules);
95              }
96              result.add(entry.getValue().build(entry.getKey(), databaseName, protocolType, dataSources, rules, instanceContext));
97          }
98          return result;
99      }
100     
101     @SuppressWarnings("rawtypes")
102     private static Map<RuleConfiguration, DatabaseRuleBuilder> getRuleBuilderMap(final DatabaseConfiguration databaseConfig) {
103         Map<RuleConfiguration, DatabaseRuleBuilder> result = new LinkedHashMap<>();
104         result.putAll(getDistributedRuleBuilderMap(databaseConfig.getRuleConfigurations()));
105         result.putAll(getEnhancedRuleBuilderMap(databaseConfig.getRuleConfigurations()));
106         result.putAll(getMissedDefaultRuleBuilderMap(result.values()));
107         return result;
108     }
109     
110     @SuppressWarnings("rawtypes")
111     private static Map<RuleConfiguration, DatabaseRuleBuilder> getDistributedRuleBuilderMap(final Collection<RuleConfiguration> ruleConfigs) {
112         Collection<RuleConfiguration> distributedRuleConfigs = ruleConfigs.stream().filter(each -> isAssignableFrom(each, DistributedRuleConfiguration.class)).collect(Collectors.toList());
113         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class, distributedRuleConfigs, Comparator.reverseOrder());
114     }
115     
116     @SuppressWarnings("rawtypes")
117     private static Map<RuleConfiguration, DatabaseRuleBuilder> getEnhancedRuleBuilderMap(final Collection<RuleConfiguration> ruleConfigs) {
118         Collection<RuleConfiguration> enhancedRuleConfigs = ruleConfigs.stream().filter(each -> isAssignableFrom(each, EnhancedRuleConfiguration.class)).collect(Collectors.toList());
119         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class, enhancedRuleConfigs);
120     }
121     
122     private static boolean isAssignableFrom(final RuleConfiguration ruleConfig, final Class<? extends RuleConfiguration> ruleConfigClass) {
123         return Arrays.stream(ruleConfig.getClass().getInterfaces()).anyMatch(ruleConfigClass::isAssignableFrom);
124     }
125     
126     @SuppressWarnings("rawtypes")
127     private static Map<RuleConfiguration, DatabaseRuleBuilder> getMissedDefaultRuleBuilderMap(final Collection<DatabaseRuleBuilder> configuredBuilders) {
128         Map<RuleConfiguration, DatabaseRuleBuilder> result = new LinkedHashMap<>();
129         Map<DatabaseRuleBuilder, DefaultDatabaseRuleConfigurationBuilder> defaultBuilders =
130                 OrderedSPILoader.getServices(DefaultDatabaseRuleConfigurationBuilder.class, getMissedDefaultRuleBuilders(configuredBuilders));
131         // TODO consider about order for new put items
132         for (Entry<DatabaseRuleBuilder, DefaultDatabaseRuleConfigurationBuilder> entry : defaultBuilders.entrySet()) {
133             result.put(entry.getValue().build(), entry.getKey());
134         }
135         return result;
136     }
137     
138     @SuppressWarnings({"unchecked", "rawtypes"})
139     private static Collection<DatabaseRuleBuilder> getMissedDefaultRuleBuilders(final Collection<DatabaseRuleBuilder> configuredBuilders) {
140         Collection<Class<DatabaseRuleBuilder>> configuredBuilderClasses = configuredBuilders.stream().map(each -> (Class<DatabaseRuleBuilder>) each.getClass()).collect(Collectors.toSet());
141         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class).stream().filter(each -> !configuredBuilderClasses.contains(each.getClass())).collect(Collectors.toList());
142     }
143 }