Java tutorial
/******************************************************************************* * Copyright (c) 2015 VDS Rail and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Enrico De Fent - initial API and implementation (see bug 459214) *******************************************************************************/ package org.eclipse.tycho.extras.docbundle; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.commons.lang3.StringUtils; /** * An utility class for filtering package names. */ public class PackageNameMatcher { /** * Compiles the given list of package name specification strings into a matching object. * * <p> * If the list is empty, the resulting object will never match any package name, which means * that {@link #matches(String)} will always return <code>false</code>. * </p> * * @param specs * The list of package name specifications. For details on specification syntax see * {@link #compile(String)}. * @return A new matching object. * @throws IllegalArgumentException * Thrown if the given argument is <code>null</code> or if any of the strings in the * list is an invalid package name specification. */ public static PackageNameMatcher compile(final List<String> specs) { if (specs == null) { throw new IllegalArgumentException("null package name specifications"); } final List<Pattern> list = new ArrayList<Pattern>(); for (String part : specs) { list.add(buildPattern(part)); } return new PackageNameMatcher(list); } private static Pattern buildPattern(final String spec) { if (StringUtils.isEmpty(spec)) { throw new IllegalArgumentException("empty package name"); } final StringBuilder regex = new StringBuilder(); for (int idx = 0; idx < spec.length(); idx++) { char ch = spec.charAt(idx); if (ch == '*') { regex.append(".*"); } else if (ch == '.') { regex.append("\\."); } else if (idx == 0 && !Character.isJavaIdentifierStart(ch)) { throw new IllegalArgumentException("invalid package name: " + spec); } else if (!Character.isJavaIdentifierPart(ch)) { throw new IllegalArgumentException("invalid package name: " + spec); } else { regex.append(ch); } } try { return Pattern.compile(regex.toString()); } catch (PatternSyntaxException e) { throw new IllegalArgumentException("invalid package specification: " + spec, e); } } private final List<Pattern> patterns; private final String description; /** * Constructs a new object which matches against the given patterns. * * @param patterns */ private PackageNameMatcher(List<Pattern> patterns) { this.patterns = patterns; this.description = buildDescription(); } private String buildDescription() { final StringBuilder sb = new StringBuilder(); for (int idx = 0; idx < patterns.size(); idx++) { sb.append('"').append(patterns.get(idx).pattern()).append('"'); if (idx < patterns.size() - 1) { sb.append(", "); } } return sb.toString(); } /** * Returns true if the given package name matches against any of the patterns in this matcher. * * @return Always <code>false</code> if the given package name is <code>null</code> or an empty * string. */ public boolean matches(String packageName) { if (StringUtils.isEmpty(packageName)) { return false; } for (Pattern pattern : patterns) { if (pattern.matcher(packageName).matches()) { return true; } } return false; } @Override public String toString() { return String.format("%s[%s]", getClass().getSimpleName(), description); } }