/**
* Copyright (C) 2015-2017 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* From PyNDN ndn_regex.py by Adeola Bannis.
* Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
package net.named_data.jndn.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.named_data.jndn.Name;
/**
* An NdnRegexMatcher has static methods to convert an NDN regex
* (http://redmine.named-data.net/projects/ndn-cxx/wiki/Regex) to a Regex that
* can match against URIs.
*/
public class NdnRegexMatcher {
/**
* Determine if the provided NDN regex matches the given Name.
* @param pattern The NDN regex.
* @param name The Name to match against the regex.
* @return The Matcher object from Pattern.matcher after the first find, or
* null if the pattern does not match.
*/
public static Matcher
match(String pattern, Name name)
{
String nameUri = name.toUri();
pattern = sanitizeSets(pattern);
pattern = pattern.replaceAll("<>", "(?:<.+?>)");
pattern = pattern.replaceAll(">", "");
// Explicitly use regex replace for portability.
pattern = Pattern.compile("<(?!!)").matcher(pattern).replaceAll("/");
Matcher match = Pattern.compile(pattern).matcher(nameUri);
if (match.find())
return match;
else
return null;
}
private static String
sanitizeSets(String pattern)
{
String newPattern = pattern;
// Positive sets can be changed to (comp1|comp2).
// Negative sets must be changed to negative lookahead assertions.
Pattern regex1 = Pattern.compile("\\[(\\^?)(.*?)\\]");
Matcher match = regex1.matcher(pattern);
while (match.find()) {
// Insert | between components.
int start = match.start(2);
int end = match.end(2);
if (start - end == 0)
continue;
String oldStr = match.group(2);
String newStr = oldStr.replace("><", ">|<");
newPattern = newPattern.substring(0, start) + newStr + newPattern.substring(end);
}
// Replace [] with (), or (?! ) for negative lookahead.
// If we use negative lookahead, we also have to consume one component.
boolean isNegative = newPattern.contains("[^");
if (isNegative) {
newPattern = newPattern.replace("[^", "(?:(?!");
newPattern = newPattern.replace("]", ")(?:/.*)*)");
}
else {
newPattern = newPattern.replace("[", "(");
newPattern = newPattern.replace("]", ")");
}
return newPattern;
}
}