
com.wizzardo.http.mapping.UrlMapping Maven / Gradle / Ivy
package com.wizzardo.http.mapping;
import com.wizzardo.http.Named;
import com.wizzardo.http.request.ByteTree;
import com.wizzardo.http.request.Request;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
/**
* @author: wizzardo
* Date: 25.09.14
*/
public class UrlMapping {
public static final ByteTree SEGMENT_CACHE = new ByteTree();
static final Pattern VARIABLES = Pattern.compile("\\$\\{?([a-zA-Z_]+[\\w]*)\\}?");
static final String OPTIONAL = "(.+)?";
protected static final Pattern END = Pattern.compile("\\*([a-zA-Z_0-9\\.\\-]+)");
protected Map> mapping = new HashMap<>();
protected Map> regexpMapping = new LinkedHashMap<>();
protected T value;
protected UrlMapping parent;
protected UrlMappingEndsWith endsWithMapping;
protected TemplatesHolder urlTemplates = new TemplatesHolder<>();
protected String context;
public UrlMapping() {
}
public UrlMapping(String context) {
this.context = context;
}
public UrlMapping(String host, int port, String context) {
this.context = context;
urlTemplates = new TemplatesHolder<>(host, port, context);
}
protected UrlMapping(UrlMapping parent) {
this.parent = parent;
}
protected boolean checkNextPart() {
return true;
}
protected void prepare(BiConsumer parameterConsumer, Path path) {
if (parent != null)
parent.prepare(parameterConsumer, path);
}
public TemplatesHolder getTemplatesHolder() {
return urlTemplates;
}
public UrlTemplate getUrlTemplate(String name) {
if (urlTemplates == null)
return null;
return urlTemplates.getTemplate(name);
}
public T get(Request request) {
return get(request, request.path());
}
public T get(String path) {
UrlMapping last = findRecursive(Arrays.asList(path.split("/")), 0);
return last == null ? null : last.value;
}
public T get(Request request, Path path) {
if (request != null)
return get((BiConsumer) request::param, path);
else
return get((BiConsumer) null, path);
}
public T get(BiConsumer parameterConsumer, Path path) {
path = adjustPath(path);
if (path == null)
return null;
UrlMapping last = find(path);
T result = last == null ? null : last.value;
if (result != null && parameterConsumer != null)
last.prepare(parameterConsumer, path);
return result;
}
public void each(BiConsumer parameterConsumer, Path path, Consumer consumer) {
path = adjustPath(path);
if (path == null)
return;
Path finalPath = path;
findRecursive(path.parts(), 0, mapping -> {
mapping.prepare(parameterConsumer, finalPath);
consumer.accept(mapping.value);
return true;
});
}
public T get(Function> resultToParameterConsumer, Path path) {
path = adjustPath(path);
if (path == null)
return null;
UrlMapping last = find(path);
T result = last == null ? null : last.value;
if (result != null && resultToParameterConsumer != null)
last.prepare(resultToParameterConsumer.apply(result), path);
return result;
}
public void each(Function> resultToParameterConsumer, Path path, Consumer consumer) {
path = adjustPath(path);
if (path == null)
return;
Path finalPath = path;
findRecursive(path.parts(), 0, mapping -> {
mapping.prepare(resultToParameterConsumer.apply(mapping.value), finalPath);
consumer.accept(mapping.value);
return true;
});
}
protected Path adjustPath(Path path) {
if (context != null) {
if (path.length() == 0 || !path.getPart(0).equals(context))
return null;
return path.subPath(1);
}
return path;
}
protected UrlMapping find(Path path) {
return findRecursive(path.parts(), 0);
}
protected UrlMapping findRecursive(List parts, int index) {
if (index == parts.size())
return this.value != null ? this : null;
String part = parts.get(index);
if (part.isEmpty())
return findRecursive(parts, index + 1);
UrlMapping tree = findStatic(part);
if (tree != null) {
if (!tree.checkNextPart()) {
return tree;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null)
return tree;
}
}
for (Map.Entry> entry : regexpMapping.entrySet()) {
if (entry.getValue().matches(part)) {
tree = entry.getValue();
if (!tree.checkNextPart()) {
return tree;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null)
return tree;
}
}
}
tree = findEndsWith(parts);
if (tree != null) {
if (!tree.checkNextPart()) {
return tree;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null)
return tree;
}
}
return null;
}
public int size() {
return mapping.size() + regexpMapping.size() + (endsWithMapping != null ? endsWithMapping.size() : 0);
}
public boolean isEmpty() {
return size() == 0;
}
protected boolean findRecursive(List parts, int index, Predicate> consumer) {
if (index == parts.size() && value != null) {
return consumer.test(this);
}
String part = parts.get(index);
if (part.isEmpty())
findRecursive(parts, index + 1, consumer);
UrlMapping tree = findStatic(part);
if (tree != null) {
if (!tree.checkNextPart()) {
if (!consumer.test(tree))
return false;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null && !consumer.test(tree))
return false;
}
}
for (Map.Entry> entry : regexpMapping.entrySet()) {
if (entry.getValue().matches(part)) {
tree = entry.getValue();
if (!tree.checkNextPart()) {
if (!consumer.test(tree))
return false;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null && !consumer.test(tree))
return false;
}
}
}
tree = findEndsWith(parts);
if (tree != null) {
if (!tree.checkNextPart()) {
if (!consumer.test(tree))
return false;
} else {
tree = tree.findRecursive(parts, index + 1);
if (tree != null && !consumer.test(tree))
return false;
}
}
return true;
}
protected UrlMapping find(String part, List parts) {
UrlMapping handler = findStatic(part);
if (handler != null)
return handler;
handler = findDynamic(part);
if (handler != null)
return handler;
return findEndsWith(parts);
}
protected UrlMapping findStatic(String part) {
return mapping.get(part);
}
protected UrlMapping findDynamic(String part) {
for (Map.Entry> entry : regexpMapping.entrySet()) {
if (entry.getValue().matches(part))
return entry.getValue();
}
return null;
}
protected UrlMapping findEndsWith(List parts) {
return endsWithMapping != null ? endsWithMapping.find(null, parts) : null;
}
protected UrlMapping findEndsWith(String[] parts) {
return endsWithMapping != null ? endsWithMapping.find(null, parts) : null;
}
protected UrlMapping find(String part, String[] parts) {
UrlMapping handler = findStatic(part);
if (handler != null)
return handler;
handler = findDynamic(part);
if (handler != null)
return handler;
return findEndsWith(parts);
}
public UrlMapping append(String url, T handler) {
return append(url, null, handler);
}
public UrlMapping append(String url, String name, T handler) {
if (name == null)
name = handler.name();
if (name != null)
urlTemplates.append(name, url);
String[] parts = url.split("/");
UrlMapping tree = this;
int counter = 0;
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (part.isEmpty())
continue;
UrlMapping next;
if (part.contains("*")) {
if (i == parts.length - 1 && END.matcher(part).matches()) {
part = part.substring(1);
if (tree.endsWithMapping == null)
tree.endsWithMapping = new UrlMappingEndsWith<>(tree);
next = tree.endsWithMapping.append(part);
} else {
if (part.equals("*")) {
next = tree.regexpMapping.get(".*");
if (next == null) {
UrlMappingMatcher t = new UrlMappingMatcherAny<>(tree);
tree.regexpMapping.put(".*", t);
next = t;
}
} else {
next = tree.regexpMapping.get(part);
if (next == null) {
UrlMappingMatcher t = new UrlMappingMatcherPattern<>(tree, part);
tree.regexpMapping.put(part, t);
next = t;
}
}
}
} else if (part.contains("$")) {
String pattern = convertRegexpVariables(part);
next = tree.regexpMapping.get(part);
if (next == null) {
UrlMappingWithVariables t;
if (pattern.equals("(.+)") || pattern.equals("(.+)?"))
t = new UrlMappingMatcherAnyVariable<>(tree, part, counter);
else
t = new UrlMappingWithVariables<>(tree, part, counter);
tree.regexpMapping.put(part, t);
next = t;
}
} else {
SEGMENT_CACHE.append(part);
next = tree.mapping.get(part);
if (next == null) {
next = new UrlMapping<>(tree);
tree.mapping.put(part, next);
}
}
tree = next;
counter++;
}
tree.setValue(handler);
return this;
}
protected void setValue(T t) {
value = t;
}
protected String convertRegexpVariables(String s) {
return s.replaceAll(VARIABLES.pattern(), "(.+)");
}
public void setContext(String context) {
this.context = context;
urlTemplates.setContext(context);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy