blob: 4fa1b09cba6dee1b4e5aedc24cdca508c2907ee6 [file] [log] [blame]
/*
* 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();
}
}
}