1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.gui; 22 23 import javax.swing.*; 24 25 /** 26 * This class builds filters corresponding to the selections and names of a 27 * given list of check boxes. 28 */ 29 public class FilterBuilder 30 { 31 private JCheckBox[] checkBoxes; 32 private char separator; 33 34 35 /** 36 * Creates a new FilterBuilder. 37 * @param checkBoxes the check boxes with names and selections that should 38 * be reflected in the output filter. 39 * @param separator the separator for the names in the check boxes. 40 */ FilterBuilder(JCheckBox[] checkBoxes, char separator)41 public FilterBuilder(JCheckBox[] checkBoxes, char separator) 42 { 43 this.checkBoxes = checkBoxes; 44 this.separator = separator; 45 } 46 47 48 /** 49 * Builds a filter for the current names and selections of the check boxes. 50 */ buildFilter()51 public String buildFilter() 52 { 53 StringBuffer positive = new StringBuffer(); 54 StringBuffer negative = new StringBuffer(); 55 56 buildFilter("", positive, negative); 57 58 return positive.length() <= negative.length() ? 59 positive.toString() : 60 negative.toString(); 61 } 62 63 64 /** 65 * Builds two versions of the filter for the given prefix. 66 * @param prefix the prefix. 67 * @param positive the filter to be extended, assuming the matching 68 * strings are accepted. 69 * @param negative the filter to be extended, assuming the matching 70 * strings are rejected. 71 */ buildFilter(String prefix, StringBuffer positive, StringBuffer negative)72 private void buildFilter(String prefix, 73 StringBuffer positive, 74 StringBuffer negative) 75 { 76 int positiveCount = 0; 77 int negativeCount = 0; 78 79 // Count all selected and unselected check boxes with the prefix. 80 for (int index = 0; index < checkBoxes.length; index++) 81 { 82 JCheckBox checkBox = checkBoxes[index]; 83 String name = checkBox.getText(); 84 85 if (name.startsWith(prefix)) 86 { 87 if (checkBox.isSelected()) 88 { 89 positiveCount++; 90 } 91 else 92 { 93 negativeCount++; 94 } 95 } 96 } 97 98 // Are there only unselected check boxes? 99 if (positiveCount == 0) 100 { 101 // Extend the positive filter with exceptions and return. 102 if (positive.length() > 0) 103 { 104 positive.append(','); 105 } 106 positive.append('!').append(prefix); 107 if (prefix.length() == 0 || 108 prefix.charAt(prefix.length()-1) == separator) 109 { 110 positive.append('*'); 111 } 112 113 return; 114 } 115 116 // Are there only selected check boxes? 117 if (negativeCount == 0) 118 { 119 // Extend the negative filter with exceptions and return. 120 if (negative.length() > 0) 121 { 122 negative.append(','); 123 } 124 negative.append(prefix); 125 if (prefix.length() == 0 || 126 prefix.charAt(prefix.length()-1) == separator) 127 { 128 negative.append('*'); 129 } 130 131 return; 132 } 133 134 // Create new positive and negative filters for names starting with the 135 // prefix only. 136 StringBuffer positiveFilter = new StringBuffer(); 137 StringBuffer negativeFilter = new StringBuffer(); 138 139 String newPrefix = null; 140 141 for (int index = 0; index < checkBoxes.length; index++) 142 { 143 String name = checkBoxes[index].getText(); 144 145 if (name.startsWith(prefix)) 146 { 147 if (newPrefix == null || 148 !name.startsWith(newPrefix)) 149 { 150 int prefixIndex = 151 name.indexOf(separator, prefix.length()+1); 152 153 newPrefix = prefixIndex >= 0 ? 154 name.substring(0, prefixIndex+1) : 155 name; 156 157 buildFilter(newPrefix, 158 positiveFilter, 159 negativeFilter); 160 } 161 } 162 } 163 164 // Extend the positive filter. 165 if (positiveFilter.length() <= negativeFilter.length() + prefix.length() + 3) 166 { 167 if (positive.length() > 0 && 168 positiveFilter.length() > 0) 169 { 170 positive.append(','); 171 } 172 173 positive.append(positiveFilter); 174 } 175 else 176 { 177 if (positive.length() > 0 && 178 negativeFilter.length() > 0) 179 { 180 positive.append(','); 181 } 182 183 positive.append(negativeFilter).append(",!").append(prefix).append('*'); 184 } 185 186 // Extend the negative filter. 187 if (negativeFilter.length() <= positiveFilter.length() + prefix.length() + 4) 188 { 189 if (negative.length() > 0 && 190 negativeFilter.length() > 0) 191 { 192 negative.append(','); 193 } 194 195 negative.append(negativeFilter); 196 } 197 else 198 { 199 if (negative.length() > 0 && 200 positiveFilter.length() > 0) 201 { 202 negative.append(','); 203 } 204 205 negative.append(positiveFilter).append(',').append(prefix).append('*'); 206 } 207 } 208 } 209