001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.filter; 017 018import java.util.List; 019import java.util.regex.Matcher; 020import java.util.regex.Pattern; 021 022import org.kuali.common.util.Assert; 023 024import com.google.common.collect.ImmutableList; 025 026/** 027 * This class provides logic for filtering strings based on regular expressions. 028 */ 029public final class StringFilter { 030 031 /** 032 * List of include regular expressions. 033 */ 034 private final List<String> includes; 035 036 /** 037 * List of exclude regular expressions. 038 */ 039 private final List<String> excludes; 040 041 private final List<Pattern> includePatterns; 042 private final List<Pattern> excludePatterns; 043 044 public List<String> getIncludes() { 045 return includes; 046 } 047 048 public List<String> getExcludes() { 049 return excludes; 050 } 051 052 /** 053 * Return true if the string should be included. 054 */ 055 public boolean include(String s) { 056 if (isMatch(s, excludePatterns)) { 057 // An exclude pattern match always "wins" 058 return false; 059 } else { 060 // If there are no include patterns always return true 061 // Otherwise only return true if the string matches one of the provided patterns 062 return includePatterns.size() == 0 || isMatch(s, includePatterns); 063 } 064 } 065 066 /** 067 * Return true if the string matches any of the patterns 068 */ 069 private boolean isMatch(String s, List<Pattern> patterns) { 070 // Loop through the patterns looking for a match 071 for (Pattern pattern : patterns) { 072 Matcher matcher = pattern.matcher(s); 073 // We found a match, return true 074 if (matcher.matches()) { 075 return true; 076 } 077 } 078 // We cycled through all of the patterns without finding a match 079 return false; 080 } 081 082 public static class Builder { 083 084 private final List<String> includes; 085 private final List<String> excludes; 086 private final List<Pattern> includePatterns; 087 private final List<Pattern> excludePatterns; 088 089 public Builder() { 090 this(ImmutableList.<String> of(), ImmutableList.<String> of()); 091 } 092 093 public Builder(List<String> includes) { 094 this(includes, ImmutableList.<String> of()); 095 } 096 097 public Builder(List<String> includes, List<String> excludes) { 098 this.includes = ImmutableList.copyOf(includes); 099 this.excludes = ImmutableList.copyOf(excludes); 100 this.includePatterns = ImmutableList.copyOf(RegexUtils.getPatterns(includes)); 101 this.excludePatterns = ImmutableList.copyOf(RegexUtils.getPatterns(excludes)); 102 } 103 104 private void validate(StringFilter filter) { 105 Assert.noNulls(filter.includes, filter.excludes, filter.excludePatterns, filter.includePatterns); 106 } 107 108 public StringFilter build() { 109 StringFilter filter = new StringFilter(this); 110 validate(filter); 111 return filter; 112 } 113 114 } 115 116 private StringFilter(Builder builder) { 117 this.includes = builder.includes; 118 this.excludes = builder.excludes; 119 this.includePatterns = builder.includePatterns; 120 this.excludePatterns = builder.excludePatterns; 121 } 122}