Changeset 5156


Ignore:
Timestamp:
2003-08-18T13:58:40+12:00 (21 years ago)
Author:
jmt12
Message:

Fix 203B096

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java

    r4366 r5156  
    66 * University of Waikato, New Zealand.
    77 *
    8  * <BR><BR>
    9  *
    108 * Author: John Thompson, Greenstone Digital Library, University of Waikato
    119 *
    12  * <BR><BR>
    13  *
    1410 * Copyright (C) 1999 New Zealand Digital Library Project
    15  *
    16  * <BR><BR>
    1711 *
    1812 * This program is free software; you can redistribute it and/or modify
     
    2115 * (at your option) any later version.
    2216 *
    23  * <BR><BR>
    24  *
    2517 * This program is distributed in the hope that it will be useful,
    2618 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2719 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2820 * GNU General Public License for more details.
    29  *
    30  * <BR><BR>
    3121 *
    3222 * You should have received a copy of the GNU General Public License
     
    3525 *########################################################################
    3626 */
    37 
    38  
    39 
    40 
    41 
    42 
    43 /* GPL_HEADER */
    4427package org.greenstone.gatherer.gui.metaaudit;
    4528/**************************************************************************************
     
    5033 * Written:        /05/02
    5134 * Revised:      22/08/02 Revamped, Optimized and Commented.
     35 *               13-08-03 Extended matching functionality to correctly handle the wildcard character
    5236 **************************************************************************************/
    5337
    5438import java.util.ArrayList;
     39import org.greenstone.gatherer.util.StaticStrings;
    5540/** An Autofilter object stores the filters set on a single column, and provides a method for determining if a certain value passes the filter.
    5641 * @author John Thompson
     
    5843 */
    5944public class Autofilter {
     45
     46    static public void main(String[] args) {
     47    if(args.length != 2) {
     48        System.err.println("Usage: java Autofilter <string> <pattern>");
     49    }
     50    else {
     51        switch(compareToPattern(args[0], args[1])) {
     52        case LESS_THAN:
     53        System.err.print(args[0] + " is less than");
     54        break;
     55        case GREATER_THAN:
     56        System.err.print(args[0] + " is greater than");
     57        break;
     58        case EQUAL:
     59        System.err.print(args[0] + " is equal to");
     60        break;
     61        default:
     62        System.err.print(args[0] + " is something to");
     63        }
     64        System.err.println(" " + args[1]);
     65    }
     66    }
     67
     68    /** A String comparison which also recognises the WildCard character. The basic idea is that '*' matches zero or more of any characters, and if we limited patterns to be like "a*" then as soon as we hit the star we could return a match. The problem is that we want patterns like "b*y" which would match "boy" but not "bee" nor "bus" (but should return less than or greater than for each of these respectively). Thus our testing has to become non-deterministic so the matches are conducted like so:
     69     * Given p = [ b * y ]
     70     * Test  s = [ b e e ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2>s2=>LESS_THAN)})} => LESS_THAN
     71     * Test  s = [ b o y ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2=s2=>EQUAL)})} => EQUAL
     72     * Test  s = [ b u s ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2<s2=>GREATER_THAN)})} => GREATER_THAN
     73     * where the two () phrases within a {} represent two different 'threads' of processing. Errors are generated when one string runs out of characters before the other. Only non-error results are propogated. I've decided to implement this non-deterministic matching as a recursive function call.
     74     * If you analyse it you can see there are three possible actions when a '*' is detected.
     75     * 1. * is an empty string, ignore it in pattern and try to compare the next character in p with the current character in s. This case only occurs if there are more characters in p (otherwise apple would be greater than a*)
     76     * 2. * matches exactly the current character in s, try to match the next character in p with the next character in s
     77     * 3. * matches some string of characters including the current character in s, try to match '*' against the next character in s
     78     * @param  s the String being matched
     79     * @param  p the Pattern to match it against
     80     * @return -1 if s is less than p, 0 if they are equal, 1 if s is greater than p
     81     */
     82    static public int compareToPattern(String s, String p) {
     83    if(p.indexOf(StaticStrings.STAR_CHAR) == -1) {
     84        return compareToPattern(s, p, 0, 0, false);
     85    }
     86    else {
     87        return compareToPattern(s, p, 0, 0, true);
     88    }
     89    }
     90
     91    static final private int LESS_THAN = -1;
     92    static final private int EQUAL = 0;
     93    static final private int GREATER_THAN = 1;
     94    static final private int ERROR = 42;
     95
     96    static private int compareToPattern(String s, String p, int s_index, int p_index, boolean wildcard_matching) {
     97    // Lets do the simple cases first.
     98    // Both out of characters at the same time
     99    if(s_index >= s.length() && p_index >= p.length()) {
     100        ///ystem.err.println("Both out of characters. Equal.");
     101        return EQUAL;
     102    }
     103    // s out of characters first
     104    if(s_index >= s.length()) {
     105        // Not allowed to run out if matching wildcard
     106        if(wildcard_matching) {
     107        return ERROR;
     108        }
     109        // Remember that wildcard matches the empty string too, so as long as there are only '*' characters left in the pattern we can say they are equal as well.
     110        else {
     111        while(p_index < p.length()) {
     112            if(p.charAt(p_index) == StaticStrings.STAR_CHAR) {
     113            p_index++;
     114            }
     115            else {
     116            ///ystem.err.println("S out of characters. Less Than.");
     117            return LESS_THAN;
     118            }
     119        }
     120        // We've run out of pattern and it only contained '*' so we're still equal
     121        ///ystem.err.println("Both out of characters. Equal.");
     122        return EQUAL;
     123        }
     124    }
     125    // p out of characters first
     126    if(p_index >= p.length()) {
     127        // Not allowed to run out if matching wildcard
     128        if(wildcard_matching) {
     129        return ERROR;
     130        }
     131        // so it is greater than
     132        else {
     133        ///ystem.err.println("P out of characters. Greater Than.");
     134        return GREATER_THAN;
     135        }
     136    }
     137    char s_char = s.charAt(s_index);
     138    char p_char = p.charAt(p_index);
     139    ///ystem.err.println("Comparing " + s_char + " against pattern character " + p_char);
     140    // Equivelent characters
     141    // Now the tricky-dicky bit - WildCard matching.
     142    if(p_char == StaticStrings.STAR_CHAR) {
     143        int result;
     144        // Case 1
     145        ///ystem.err.println("WildCard Case 1");
     146        if(p_index + 1 < p.length()) {
     147        if((result = compareToPattern(s, p, s_index, p_index + 1, wildcard_matching)) != ERROR) {
     148            return result;
     149        }
     150        }
     151        // Case 2
     152        ///ystem.err.println("WildCard Case 2");
     153        if((result = compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching)) != ERROR) {
     154        return result;
     155        }
     156        // Case 3
     157        ///ystem.err.println("WildCard Case 3");
     158        if((result = compareToPattern(s, p, s_index + 1, p_index, wildcard_matching)) != ERROR) {
     159        return result;
     160        }
     161    }
     162    if(s_char == p_char) {
     163        return compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching);
     164    }
     165    // A preceeding character
     166    if(s_char < p_char) {
     167        ///ystem.err.println("s char is less than p char");
     168        if(wildcard_matching) {
     169        ///ystem.err.println("Because we are wildcard matching we still have to match the rest of s incase of errors.");
     170        if(compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching) != ERROR) {
     171            ///ystem.err.println("No error. Less than.");
     172            return LESS_THAN;
     173        }
     174        else {
     175            ///ystem.err.println("Error detected.");
     176            return ERROR;
     177        }
     178        }
     179        else {
     180        ///ystem.err.println("Less than.");
     181        return LESS_THAN;
     182        }
     183    }
     184    // A succeeding character
     185    if(s_char > p_char) {
     186        ///ystem.err.println("s char is greater than p char");
     187        if(wildcard_matching) {
     188        ///ystem.err.println("Because we are wildcard matching we still have to match the rest of s incase of errors.");
     189        if(compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching) != ERROR) {
     190            ///ystem.err.println("No error. Greater than.");
     191            return GREATER_THAN;
     192        }
     193        else {
     194            ///ystem.err.println("Error detected.");
     195            return ERROR;
     196        }
     197        }
     198        else {
     199        ///ystem.err.println("Greater than.");
     200        return GREATER_THAN;
     201        }
     202    }
     203    // Oh-No. Well, we'll just assume that string is less than pattern
     204    return LESS_THAN;
     205    }
     206
    60207    /** <i>true</i> if the filter should be applied, <i>false</i> to indicate the filter is turned off. */
    61208    public boolean active;
     
    169316    }
    170317    else {
    171                 // For each value in the list...
     318        // For each value in the list...
    172319        for(int i = 0; i < values.size(); i++) {
    173320        boolean pass;
     
    180327            source = values.get(i).toString().toLowerCase();
    181328        }
     329        System.err.println("Testing " + source + " against pattern " + target);
    182330        // Perform the match, based on the selected method.
    183331        switch(method) {
    184332        case 1: // !EQ
    185             pass = !(source.equals(target));
     333            pass = (compareToPattern(source, target) != 0);
    186334            break;
    187335        case 2: // <
    188             pass = (source.compareTo(target) < 0);
     336            pass = (compareToPattern(source, target) < 0);
    189337            break;
    190338        case 3: // <eq
    191             pass = (source.compareTo(target) <= 0);
     339            pass = (compareToPattern(source, target) <= 0);
    192340            break;
    193341        case 4: // >
    194             pass = (source.compareTo(target) > 0);
     342            pass = (compareToPattern(source, target) > 0);
    195343            break;
    196344        case 5: // >eq
    197             pass = (source.compareTo(target) >= 0);
     345            pass = (compareToPattern(source, target) >= 0);
    198346            break;
    199347        case 6: // ^
     
    216364            break;
    217365        default: // EQEQ
    218             pass = source.equals(target);
     366            pass = (compareToPattern(source, target) == 0);
    219367            break;
    220368        }
Note: See TracChangeset for help on using the changeset viewer.