/** * Copyright (C) 2013-2015 all@code-story.net * * Licensed 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 net.codestory.http.routes; import java.util.*; import net.codestory.http.*; import net.codestory.http.io.*; public class UriParser implements Comparable<UriParser> { private final String uriPattern; private final String[] patternParts; private final String[] queryParamsParts; private final int paramsCount; public UriParser(String uriPattern) { this.uriPattern = uriPattern; this.patternParts = parts(stripQueryParams(uriPattern)); this.queryParamsParts = queryParamsParts(extractQueryParams(uriPattern)); this.paramsCount = paramsCount(uriPattern); } public String uriPattern() { return uriPattern; } public String[] params(String uri, Query query) { String[] uriParts = parts(uri); String[] params = new String[paramsCount]; int index = 0; for (int i = 0; i < uriParts.length; i++) { if (patternParts[i].startsWith(":")) { params[index++] = uriParts[i]; } } for (int i = 0; i < queryParamsParts.length; i++) { if (queryParamsParts[i].startsWith(":")) { params[index++] = query.get(queryParamsParts[i - 1]); } } return params; } public boolean matches(String uri) { String[] uriParts = parts(stripQueryParams(uri)); if (patternParts.length != uriParts.length) { return false; } for (int i = 0; i < patternParts.length; i++) { if (!patternParts[i].startsWith(":") && !patternParts[i].equals(uriParts[i])) { return false; } } int lastPart = patternParts.length - 1; return !(patternParts[lastPart].startsWith(":") && uriParts[lastPart].isEmpty()); } private static String[] parts(String uri) { return uri.split("/", -1); } private static String[] queryParamsParts(String uri) { return uri.split("[=&]", -1); } static String stripQueryParams(String uri) { int indexSlash = uri.indexOf('?'); return (indexSlash == -1) ? uri : uri.substring(0, indexSlash); } static String extractQueryParams(String uri) { int indexSlash = uri.indexOf('?'); return (indexSlash == -1) ? "" : uri.substring(indexSlash + 1); } public static int paramsCount(String uriPattern) { return Strings.countMatches(uriPattern, ':'); } @Override public boolean equals(Object obj) { if (obj instanceof UriParser) { UriParser other = (UriParser) obj; return Objects.equals(uriPattern, other.uriPattern); } return false; } @Override public int hashCode() { return uriPattern.hashCode(); } @Override public int compareTo(UriParser other) { int compare = Integer.compare(paramsCount, other.paramsCount); if (compare != 0) { return compare; } int index = 0; for (String part : patternParts) { boolean hasPart1ADash = part.startsWith(":"); boolean hasPart2ADash = other.patternParts[index].startsWith(":"); if (hasPart1ADash && !hasPart2ADash) { return 1; } if (hasPart2ADash && !hasPart1ADash) { return -1; } index++; if (other.patternParts.length == index) { return 0; } } return 0; } }