/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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 com.asakusafw.compiler.bootstrap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Patterns about class names.
* @since 0.8.0
*/
public class ClassNamePattern {
static final Logger LOG = LoggerFactory.getLogger(ClassNamePattern.class);
private final Pattern[] patterns;
private final boolean defaultAccepts;
/**
* Creates a new instance.
* @param patterns the recognizable patterns
* @param defaultAccepts {@code true} to accept if {@code patterns} is empty, or {@code false} to reject
*/
public ClassNamePattern(List<? extends Pattern> patterns, boolean defaultAccepts) {
this.patterns = patterns.toArray(new Pattern[patterns.size()]);
this.defaultAccepts = defaultAccepts;
}
/**
* Parses the pattern list and returns the corresponded class name pattern.
* @param patternList the class name pattern list ({@code "*"} as a wildcard, nullable)
* @param defaultAccepts {@code true} to accept if the pattern list is empty, or {@code false} to reject
* @return the parsed pattern
*/
public static ClassNamePattern parse(String patternList, boolean defaultAccepts) {
List<Pattern> patterns = parseSegments(patternList);
return new ClassNamePattern(patterns, defaultAccepts);
}
private static List<Pattern> parseSegments(String patternList) {
if (patternList == null) {
return Collections.emptyList();
}
List<Pattern> results = new ArrayList<>();
int start = 0;
while (true) {
int index = patternList.indexOf(',', start);
if (index < 0) {
String segment = patternList.substring(start).trim();
if (segment.isEmpty() == false) {
results.add(parseSegment(segment));
}
break;
} else {
String segment = patternList.substring(start, index);
if (segment.isEmpty() == false) {
results.add(parseSegment(segment));
}
start = index + 1;
}
}
return results;
}
private static Pattern parseSegment(String pattern) {
StringBuilder buf = new StringBuilder();
int start = 0;
while (true) {
int next = pattern.indexOf('*', start);
if (next < 0) {
break;
}
if (start < next) {
buf.append(Pattern.quote(pattern.substring(start, next)));
}
buf.append(".*"); //$NON-NLS-1$
start = next + 1;
}
if (start < pattern.length()) {
buf.append(Pattern.quote(pattern.substring(start)));
}
return Pattern.compile(buf.toString());
}
/**
* Returns whether this accepts the target class name or not.
* @param name the target class name
* @return {@code true} if this accepts the target class name, otherwise {@code false}
*/
public boolean accepts(String name) {
if (patterns.length == 0) {
return defaultAccepts;
}
for (Pattern pattern : patterns) {
if (pattern.matcher(name).matches()) {
if (LOG.isDebugEnabled()) {
LOG.debug("matched: {} ({})", name, pattern); //$NON-NLS-1$
}
return true;
}
}
return false;
}
}