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.DatabaseRuleConfigurationChecker;
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.ComputeNodeInstanceContext;
29  import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
30  import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
31  import org.apache.shardingsphere.infra.spi.type.ordered.OrderedSPILoader;
32  
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 computeNodeInstanceContext compute node instance context
56       * @param resourceMetaData  resource meta data
57       * @return built rules
58       */
59      @SuppressWarnings({"unchecked", "rawtypes"})
60      public static Collection<ShardingSphereRule> build(final String databaseName, final DatabaseType protocolType, final DatabaseConfiguration databaseConfig,
61                                                         final ComputeNodeInstanceContext computeNodeInstanceContext, final ResourceMetaData resourceMetaData) {
62          Collection<ShardingSphereRule> result = new LinkedList<>();
63          for (Entry<RuleConfiguration, DatabaseRuleBuilder> entry : getRuleBuilderMap(databaseConfig).entrySet()) {
64              DatabaseRuleConfigurationChecker configChecker = OrderedSPILoader.getServicesByClass(
65                      DatabaseRuleConfigurationChecker.class, Collections.singleton(entry.getKey().getClass())).get(entry.getKey().getClass());
66              if (null != configChecker) {
67                  configChecker.check(databaseName, entry.getKey(), resourceMetaData.getDataSourceMap(), result);
68              }
69              result.add(entry.getValue().build(entry.getKey(), databaseName, protocolType, resourceMetaData, result, computeNodeInstanceContext));
70          }
71          return result;
72      }
73      
74      /**
75       * Build database rule.
76       *
77       * @param databaseName database name
78       * @param protocolType protocol type
79       * @param rules rules
80       * @param ruleConfig rule configuration
81       * @param computeNodeInstanceContext compute node instance context
82       * @param resourceMetaData  resource meta data
83       * @return built rule
84       */
85      @SuppressWarnings({"unchecked", "rawtypes"})
86      public static ShardingSphereRule build(final String databaseName, final DatabaseType protocolType, final Collection<ShardingSphereRule> rules, final RuleConfiguration ruleConfig,
87                                             final ComputeNodeInstanceContext computeNodeInstanceContext, final ResourceMetaData resourceMetaData) {
88          DatabaseRuleBuilder databaseRuleBuilder = OrderedSPILoader.getServices(DatabaseRuleBuilder.class, Collections.singleton(ruleConfig)).get(ruleConfig);
89          DatabaseRuleConfigurationChecker configChecker =
90                  OrderedSPILoader.getServicesByClass(DatabaseRuleConfigurationChecker.class, Collections.singleton(ruleConfig.getClass())).get(ruleConfig.getClass());
91          if (null != configChecker) {
92              configChecker.check(databaseName, ruleConfig, resourceMetaData.getDataSourceMap(), rules);
93          }
94          return databaseRuleBuilder.build(ruleConfig, databaseName, protocolType, resourceMetaData, rules, computeNodeInstanceContext);
95      }
96      
97      @SuppressWarnings("rawtypes")
98      private static Map<RuleConfiguration, DatabaseRuleBuilder> getRuleBuilderMap(final DatabaseConfiguration databaseConfig) {
99          Map<RuleConfiguration, DatabaseRuleBuilder> result = new LinkedHashMap<>();
100         result.putAll(getDistributedRuleBuilderMap(databaseConfig.getRuleConfigurations()));
101         result.putAll(getEnhancedRuleBuilderMap(databaseConfig.getRuleConfigurations()));
102         result.putAll(getMissedDefaultRuleBuilderMap(result.values()));
103         return result;
104     }
105     
106     @SuppressWarnings("rawtypes")
107     private static Map<RuleConfiguration, DatabaseRuleBuilder> getDistributedRuleBuilderMap(final Collection<RuleConfiguration> ruleConfigs) {
108         Collection<RuleConfiguration> distributedRuleConfigs = ruleConfigs.stream().filter(each -> isAssignableFrom(each, DistributedRuleConfiguration.class)).collect(Collectors.toList());
109         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class, distributedRuleConfigs, Comparator.reverseOrder());
110     }
111     
112     @SuppressWarnings("rawtypes")
113     private static Map<RuleConfiguration, DatabaseRuleBuilder> getEnhancedRuleBuilderMap(final Collection<RuleConfiguration> ruleConfigs) {
114         Collection<RuleConfiguration> enhancedRuleConfigs = ruleConfigs.stream().filter(each -> isAssignableFrom(each, EnhancedRuleConfiguration.class)).collect(Collectors.toList());
115         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class, enhancedRuleConfigs);
116     }
117     
118     private static boolean isAssignableFrom(final RuleConfiguration ruleConfig, final Class<? extends RuleConfiguration> ruleConfigClass) {
119         return Arrays.stream(ruleConfig.getClass().getInterfaces()).anyMatch(ruleConfigClass::isAssignableFrom);
120     }
121     
122     @SuppressWarnings("rawtypes")
123     private static Map<RuleConfiguration, DatabaseRuleBuilder> getMissedDefaultRuleBuilderMap(final Collection<DatabaseRuleBuilder> configuredBuilders) {
124         Map<RuleConfiguration, DatabaseRuleBuilder> result = new LinkedHashMap<>();
125         Map<DatabaseRuleBuilder, DefaultDatabaseRuleConfigurationBuilder> defaultBuilders =
126                 OrderedSPILoader.getServices(DefaultDatabaseRuleConfigurationBuilder.class, getMissedDefaultRuleBuilders(configuredBuilders));
127         // TODO consider about order for new put items
128         for (Entry<DatabaseRuleBuilder, DefaultDatabaseRuleConfigurationBuilder> entry : defaultBuilders.entrySet()) {
129             result.put(entry.getValue().build(), entry.getKey());
130         }
131         return result;
132     }
133     
134     @SuppressWarnings({"unchecked", "rawtypes"})
135     private static Collection<DatabaseRuleBuilder> getMissedDefaultRuleBuilders(final Collection<DatabaseRuleBuilder> configuredBuilders) {
136         Collection<Class<DatabaseRuleBuilder>> configuredBuilderClasses = configuredBuilders.stream().map(each -> (Class<DatabaseRuleBuilder>) each.getClass()).collect(Collectors.toSet());
137         return OrderedSPILoader.getServices(DatabaseRuleBuilder.class).stream().filter(each -> !configuredBuilderClasses.contains(each.getClass())).collect(Collectors.toList());
138     }
139 }