com.firefly.server.http2.router.impl.ParameterPathMatcher Maven / Gradle / Ivy
package com.firefly.server.http2.router.impl;
import com.firefly.server.http2.router.Matcher;
import com.firefly.server.http2.router.Router;
import com.firefly.server.http2.router.utils.PathUtils;
import java.util.*;
/**
* @author Pengtao Qiu
*/
public class ParameterPathMatcher implements Matcher {
private Map>> parameterPath;
private static class ParameterPath {
final String rule;
final List paths;
public ParameterPath(String rule) {
this.rule = rule;
paths = PathUtils.split(rule);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ParameterPath that = (ParameterPath) o;
return Objects.equals(rule, that.rule);
}
@Override
public int hashCode() {
return Objects.hash(rule);
}
Map match(List list) {
Map param = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
String path = paths.get(i);
String value = list.get(i);
if (path.charAt(0) != ':') {
if (!path.equals(value)) {
return null;
}
} else {
param.put(path.substring(1), value);
}
}
return param;
}
}
private Map>> parameterPath() {
if (parameterPath == null) {
parameterPath = new HashMap<>();
}
return parameterPath;
}
@Override
public void add(String rule, Router router) {
ParameterPath parameterPath = new ParameterPath(rule);
parameterPath().computeIfAbsent(parameterPath.paths.size(), k -> new HashMap<>())
.computeIfAbsent(parameterPath, k -> new HashSet<>())
.add(router);
}
@Override
public MatchResult match(String value) {
if (parameterPath == null) {
return null;
}
if (value.length() == 1) {
if (value.charAt(0) == '/') {
return null;
} else {
throw new IllegalArgumentException("the path: [" + value + "] format error");
}
} else {
List list = PathUtils.split(value);
Map> map = parameterPath.get(list.size());
if (map != null && !map.isEmpty()) {
Set routers = new HashSet<>();
Map> parameters = new HashMap<>();
map.forEach((key, regRouter) -> {
Map param = key.match(list);
if (param != null) {
routers.addAll(regRouter);
regRouter.forEach(router -> parameters.put(router, param));
}
});
if (!routers.isEmpty()) {
return new MatchResult(routers, parameters, getMatchType());
} else {
return null;
}
} else {
return null;
}
}
}
@Override
public MatchType getMatchType() {
return MatchType.PATH;
}
}