Coverage Report - org.xmlhammer.gui.util.WildcardFileFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
WildcardFileFilter
61% 
70% 
0
 
 1  
 /*
 2  
  * $Id: WildcardFileFilter.java,v 1.4 2006/09/06 17:48:19 edankert Exp $
 3  
  *
 4  
  * The contents of this file are subject to the Mozilla Public License 
 5  
  * Version 1.1 (the "License"); you may not use this file except in 
 6  
  * compliance with the License. You may obtain a copy of the License at 
 7  
  * http://www.mozilla.org/MPL/ 
 8  
  *
 9  
  * Software distributed under the License is distributed on an "AS IS" basis, 
 10  
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 11  
  * for the specific language governing rights and limitations under the License.
 12  
  *
 13  
  * The Original Code is XML Hammer code. (org.xmlhammer.*)
 14  
  *
 15  
  * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
 16  
  * by the Initial Developer are Copyright (C) 2002 - 2006 the Initial Developer. 
 17  
  * All Rights Reserved.
 18  
  *
 19  
  * Contributor(s): Edwin Dankert <edankert@gmail.com>
 20  
  */
 21  
 
 22  
 
 23  
 package org.xmlhammer.gui.util;
 24  
 
 25  
 import java.io.File;
 26  
 import java.util.ArrayList;
 27  
 import java.util.List;
 28  
 
 29  
 import org.apache.commons.io.filefilter.AbstractFileFilter;
 30  
 
 31  
 /**
 32  
  * Filters files using supplied wildcard(s).
 33  
  * <p/>
 34  
  * See org.apache.commons.io.find.FilenameUtils.wildcardMatch() for wildcard matching rules
 35  
  * <p/>
 36  
  *
 37  
  * <p/>
 38  
  * e.g.
 39  
  * <pre>
 40  
  * File dir = new File(".");
 41  
  * FileFilter fileFilter = new WildcardFilter("*test*.java~*~");
 42  
  * File[] files = dir.listFiles(fileFilter);
 43  
  * for (int i = 0; i < files.length; i++) {
 44  
  *   System.out.println(files[i]);
 45  
  * }
 46  
  * </pre>
 47  
  *
 48  
  * @author Jason Anderson
 49  
  * @version $Revision: 1.4 $ $Date: 2006/09/06 17:48:19 $
 50  
  * @since Commons IO 1.1
 51  
  */
 52  
 public class WildcardFileFilter extends AbstractFileFilter {
 53  
 
 54  
     /** The patterns that will be used to match filenames */
 55  44
     private String[] patterns = null;
 56  
 
 57  
     /**
 58  
      * Construct a new wildcard filter for a single wildcard
 59  
      *
 60  
      * @param wildcard wildcard to match
 61  
      * @throws IllegalArgumentException if the pattern is null
 62  
      */
 63  44
     public WildcardFileFilter( String pattern) {
 64  44
         if (pattern == null) {
 65  0
             throw new java.lang.IllegalArgumentException();
 66  
         }
 67  
     
 68  44
         patterns = new String[] { pattern };
 69  44
     }
 70  
 
 71  
     /**
 72  
      * Construct a new wildcard filter for an array of wildcards
 73  
      *
 74  
      * @param wildcards wildcards to match
 75  
      * @throws IllegalArgumentException if the pattern array is null
 76  
      */
 77  0
     public WildcardFileFilter(String[] pattern) {
 78  0
         if (pattern == null) {
 79  0
             throw new java.lang.IllegalArgumentException();
 80  
         }
 81  
     
 82  0
         this.patterns = pattern;
 83  0
     }
 84  
 
 85  
     /**
 86  
      * Construct a new wildcard filter for a list of wildcards
 87  
      *
 88  
      * @param wildcards list of wildcards to match
 89  
      * @throws IllegalArgumentException if the pattern list is null
 90  
      * @throws ClassCastException if the list does not contain Strings
 91  
      */
 92  0
     public WildcardFileFilter( List<String> patterns) {
 93  0
         if ( patterns == null) {
 94  0
             throw new java.lang.IllegalArgumentException();
 95  
         }
 96  
     
 97  0
         this.patterns = patterns.toArray(new String[patterns.size()]);
 98  0
     }
 99  
 
 100  
     /**
 101  
      * Checks to see if the filename matches one of the wildcards.
 102  
      *
 103  
      * @param dir   the file directory
 104  
      * @param name  the filename
 105  
      * @return true if the filename matches one of the wildcards
 106  
      */
 107  
     public boolean accept(File dir, String name) {
 108  0
         if (dir != null && new File(dir, name).isDirectory()) {
 109  0
             return false;
 110  
         }
 111  
     
 112  0
         for (int i = 0; i < patterns.length; i++) {
 113  0
             if ( WildcardFileFilter.wildcardMatch(name, patterns[i])) {
 114  0
                 return true;
 115  
             }
 116  
         }
 117  
     
 118  0
         return false;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Checks to see if the filename matches one of the wildcards.
 123  
      *
 124  
      * @param file the file to check
 125  
      * @return true if the filename matches one of the wildcards
 126  
      */
 127  
     public boolean accept(File file) {
 128  352
         if (file.isDirectory()) {
 129  132
             return false;
 130  
         }
 131  
     
 132  308
         for (int i = 0; i < patterns.length; i++) {
 133  220
             if ( wildcardMatch(file.getName(), patterns[i])) {
 134  132
                 return true;
 135  
             }
 136  
         }
 137  
     
 138  88
         return false;
 139  
     }
 140  
     
 141  
     //-----------------------------------------------------------------------
 142  
     /**
 143  
      * Checks a filename to see if it matches the specified wildcard matcher.
 144  
      * <p>
 145  
      * The wildcard matcher uses the characters '?' and '*' to represent a
 146  
      * single or multiple wildcard characters.
 147  
      * This is the same as often found on Dos/Unix command lines.
 148  
      * The extension check is case sensitive on Unix and case insensitive on Windows.
 149  
      * <pre>
 150  
      * wildcardMatch("c.txt", "*.txt")      --> true
 151  
      * wildcardMatch("c.txt", "*.jpg")      --> false
 152  
      * wildcardMatch("a/b/c.txt", "a/b/*")  --> true
 153  
      * wildcardMatch("c.txt", "*.???")      --> true
 154  
      * wildcardMatch("c.txt", "*.????")     --> false
 155  
      * </pre>
 156  
      * 
 157  
      * @param filename  the filename to match on
 158  
      * @param wildcardMatcher  the wildcard string to match against
 159  
      * @return true if the filename matches the wilcard string
 160  
      */
 161  
     public static boolean wildcardMatch(String filename, String wildcardMatcher) {
 162  220
         if (filename == null && wildcardMatcher == null) {
 163  0
             return true;
 164  
         }
 165  220
         if (filename == null || wildcardMatcher == null) {
 166  0
             return false;
 167  
         }
 168  220
         if ( File.separatorChar == '\\') {
 169  220
             filename = filename.toLowerCase();
 170  220
             wildcardMatcher = wildcardMatcher.toLowerCase();
 171  
         }
 172  220
         String[] wcs = splitOnTokens(wildcardMatcher);
 173  220
         boolean anyChars = false;
 174  220
         int textIdx = 0;
 175  220
         int wcsIdx = 0;
 176  
   
 177  
         // loop whilst tokens and text left to process
 178  572
         while (wcsIdx < wcs.length && textIdx < filename.length()) {
 179  
   
 180  440
             if (wcs[wcsIdx].equals("?")) {
 181  
                 // ? so move to next text char
 182  0
                 textIdx++;
 183  0
                 anyChars = false;
 184  
                 
 185  0
             } else if (wcs[wcsIdx].equals("*")) {
 186  
                 // set any chars status
 187  220
                 anyChars = true;
 188  
                 
 189  220
             } else {
 190  
                 // matching text token
 191  220
                 if (anyChars) {
 192  
                     // any chars then try to locate text token
 193  220
                     textIdx = filename.indexOf(wcs[wcsIdx], textIdx);
 194  220
                     if (textIdx == -1) {
 195  
                         // token not found
 196  88
                         return false;
 197  
                     }
 198  
                 } else {
 199  
                     // matching from current position
 200  0
                     if (!filename.startsWith(wcs[wcsIdx], textIdx)) {
 201  
                         // couldnt match token
 202  0
                         return false;
 203  
                     }
 204  
                 }
 205  
   
 206  
                 // matched text token, move text index to end of matched token
 207  132
                 textIdx += wcs[wcsIdx].length();
 208  132
                 anyChars = false;
 209  
             }
 210  
   
 211  352
             wcsIdx++;
 212  352
         }
 213  
 
 214  
         // didnt match all wildcards
 215  132
         if (wcsIdx < wcs.length) {
 216  
             // ok if one remaining and wildcard or empty
 217  0
             if (wcsIdx + 1 != wcs.length || !(wcs[wcsIdx].equals("*") || wcs[wcsIdx].equals("")) ) {
 218  0
                 return false;
 219  
             }
 220  
         }
 221  
   
 222  
         // ran out of text chars
 223  132
         if (textIdx > filename.length()) {
 224  0
            return false;
 225  
         }
 226  
   
 227  
         // didnt match all text chars, only ok if any chars set
 228  132
         if (textIdx < filename.length() && !anyChars) {
 229  0
             return false;
 230  
         }
 231  
   
 232  132
         return true;
 233  
     }
 234  
 
 235  
     // used by wildcardMatch
 236  
     // package level so a unit test may run on this
 237  
     static String[] splitOnTokens(String text) {
 238  220
         if (text.indexOf("?") == -1 && text.indexOf("*") == -1) {
 239  0
             return new String[] { text };
 240  
         }
 241  
 
 242  220
         char[] array = text.toCharArray();
 243  220
         ArrayList<String> list = new ArrayList<String>();
 244  220
         StringBuffer buffer = new StringBuffer();
 245  1320
         for (int i = 0; i < array.length; i++) {
 246  1100
                         if (array[i] == '?' || array[i] == '*') {
 247  220
                                 if (buffer.length() != 0) {
 248  0
                                         list.add(buffer.toString());
 249  0
                                         buffer.setLength(0);
 250  
                                 }
 251  220
                                 list.add(new String(new char[] { array[i] }));
 252  220
                         } else {
 253  880
                                 buffer.append(array[i]);
 254  
                         }
 255  
                 }
 256  220
         if (buffer.length() != 0) {
 257  220
             list.add(buffer.toString());
 258  
         }
 259  
 
 260  220
         return list.toArray(new String[0]);
 261  
     }
 262  
 }