| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.skywalking.oap.server.core.config.group.openapi; |
| |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Map; |
| import lombok.Getter; |
| import org.apache.skywalking.oap.server.library.util.StringFormatGroup; |
| |
| public class EndpointGroupingRule4Openapi { |
| private final Map<String/*serviceName*/, Map<String/*endpointName*/, String/*endpointGroupName*/>> directLookup = new HashMap<>(); |
| @Getter |
| private final Map<String, Map<String, StringFormatGroup>> groupedRules = new HashMap<>(); |
| |
| void addDirectLookup(String serviceName, String endpointName, String endpointGroupName) { |
| Map<String, String> endpointNameLookup = directLookup.computeIfAbsent(serviceName, name -> new HashMap<>()); |
| endpointNameLookup.put(endpointName, endpointGroupName); |
| } |
| |
| void addGroupedRule(String serviceName, String endpointGroupName, String ruleRegex) { |
| String rulesGroupkey = getGroupedRulesKey(ruleRegex); |
| Map<String, StringFormatGroup> rules = groupedRules.computeIfAbsent(serviceName, name -> new HashMap<>()); |
| StringFormatGroup formatGroup = rules.computeIfAbsent(rulesGroupkey, name -> new StringFormatGroup()); |
| formatGroup.addRule(endpointGroupName, ruleRegex); |
| } |
| |
| public StringFormatGroup.FormatResult format(String service, String endpointName) { |
| Map<String, String> endpointNameLookup = directLookup.get(service); |
| if (endpointNameLookup != null && endpointNameLookup.get(endpointName) != null) { |
| return new StringFormatGroup.FormatResult(true, endpointName, endpointNameLookup.get(endpointName)); |
| } |
| |
| Map<String, StringFormatGroup> rules = groupedRules.get(service); |
| if (rules != null) { |
| final StringFormatGroup stringFormatGroup = rules.get(getGroupedRulesKey(endpointName)); |
| if (stringFormatGroup != null) { |
| return stringFormatGroup.format(endpointName); |
| } |
| } |
| |
| return new StringFormatGroup.FormatResult(false, endpointName, endpointName); |
| } |
| |
| void sortRulesAll() { |
| groupedRules.entrySet().forEach(rules -> { |
| sortRulesByService(rules.getKey()); |
| }); |
| } |
| |
| void sortRulesByService(String serviceName) { |
| Map<String, StringFormatGroup> rules = groupedRules.get(serviceName); |
| if (rules != null) { |
| rules.entrySet().forEach(stringFormatGroup -> { |
| stringFormatGroup.getValue() |
| .sortRules(new EndpointGroupingRule4Openapi.EndpointGroupingRulesComparator()); |
| }); |
| } |
| } |
| |
| String getGroupedRulesKey(String string) { |
| String[] ss = string.split("/"); |
| if (ss.length == 1) { //eg. POST:/ |
| return ss[0] + "/"; |
| } |
| if (ss.length > 1) { |
| return ss[0] + "/" + ss[1]; |
| } |
| return "/"; |
| } |
| |
| static class EndpointGroupingRulesComparator implements Comparator<StringFormatGroup.PatternRule> { |
| private static final String VAR_PATTERN = "\\(\\[\\^\\/\\]\\+\\)"; |
| |
| @Override |
| public int compare(final StringFormatGroup.PatternRule rule1, final StringFormatGroup.PatternRule rule2) { |
| |
| String pattern1 = rule1.getPattern().pattern(); |
| String pattern2 = rule2.getPattern().pattern(); |
| |
| if (getPatternVarsCount(pattern1) < getPatternVarsCount(pattern2)) { |
| return -1; |
| } else if (getPatternVarsCount(pattern1) > getPatternVarsCount(pattern2)) { |
| return 1; |
| } |
| |
| int length1 = getPatternLength(pattern1); |
| int length2 = getPatternLength(pattern2); |
| return length2 - length1; |
| } |
| |
| private int getPatternVarsCount(String pattern) { |
| return ",".concat(pattern).concat(",").split(VAR_PATTERN).length - 1; |
| } |
| |
| private int getPatternLength(String pattern) { |
| return pattern.replaceAll(VAR_PATTERN, "#").length(); |
| } |
| |
| } |
| } |