Home | History | Annotate | Download | only in gui
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) 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      */
     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      */
     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      */
     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