001package fi.jyu.mit.ohj2;
002 
003/**
004 * Luokka wildmat-vertailuun, jossa jokereita ovat * ja ?
005 * @author Vesa Lappalainen, Markku Vire
006 * @version 1.0, 23.03.2002
007 */
008public class WildChars { // NOPMD
009
010  /**
011   * Palauttaa sisältääkö jono str jokerimekrkkejä * tai ?
012   * @param str jono jota tutkitaan
013   * @return sisältääkö jono (true) jokerimerkkejä vai ei (false)
014   * @example
015   * <pre name="test">
016   *  containsWildChars(null) === false;
017   *  containsWildChars("*")  === true;
018   *  containsWildChars("?")  === true;
019   *  containsWildChars("a*b?c")  === true;
020   * </pre>
021   */
022  public static boolean containsWildChars(String str)
023  {
024    if (str == null)  return false;
025    return (str.indexOf('*') >= 0 || str.indexOf('?') >= 0);
026  }
027
028  /**
029   * Apumetodi wildmat-aliohjelman toteuttamiseksi
030   * @param str  tutkittava jono
031   * @param mask maski johon verrataan
032   * @param strIndex   indeksi jonossa, josta aloitetaan vertailu
033   * @param maskIndex  indeksi maskissa, josta aloitetaan vertailu
034   * @return ovatko samat (true) vai ei (false) jokeri-mielessä
035   * @example
036   */
037  private static boolean wildmat(String str, String mask, int strIndex, int maskIndex) { // NOPMD
038    if ( str == null || mask == null ) return ( str == null && mask == null );
039    int mi = maskIndex;
040    int si = strIndex;
041    
042    while ( mi < mask.length() ) {
043      char m = mask.charAt(mi);
044
045      if ( m == '?' ) {
046        if (si >= str.length()) return false;
047      }
048      else if ( m == '*' ) {
049        mi++;
050        if ( mi < mask.length() )
051          while ( !wildmat(str, mask,si,mi) ) {
052            si++;
053            if ( si >= str.length() ) return false;
054          }
055        return true;
056      }
057      else if ( ( si >= str.length() ) || ( m != str.charAt(si) ) )
058        return false;
059
060      si++; mi++;
061    }
062
063    return ( si == str.length() );
064  }
065
066  /**
067   *<pre>
068   * Funktiolla tutkitaan täsmääkö annettu jono verrattavaan maskiin.
069   * Maski saa sisältää seuraavia erikoismerkkejä:
070   *   * vastaa 0-n merkkiä
071   *   ? vastaa mitä tahansa yhtä merkkiä
072   *
073   * Algoritmi: Kysymysmerkki ja tavallinen kirjain normaalisti
074   *            Jos tulee vastaan tähti joka ei ole jonon lopussa,
075   *            niin ongelmahan on oikeastaan
076   *            (koska tähän asti kaikki on ollut oikein)
077   *            "Onko loppujono sama kuin toisen jonon loppu JOSTAKIN
078   *             kohdasta alkaen"?
079   *            Siis kokeillaan sovittaa loppujonoa aliohjelman itsensä
080   *            (rekursio) avulla kaikkiin mahdollisiin loppupaikkoihin.
081   * Esimerkki: str = "Kissa" maski = "*ss*" -> true
082   *                                = "*ss"  -> false
083   * </pre>
084   *
085   * @param str   jono jota tutkitaan
086   * @param mask  maski johon verrataan
087   * @return      onko samat (true) vai ei (false) maskin mielessä.
088   * 
089   * @example
090   * <pre name="test">
091   *    wildmat("kissa","kissa")           === true;
092   *    wildmat("kissa","kiss*")           === true;
093   *    wildmat("kissa","kss*")            === false;
094   *    wildmat("kissa","k*ss*")           === true;
095   *    wildmat("kissa","k***********ss*") === true;
096   *    wildmat("kissa","*iss*")           === true;
097   *    wildmat("kissa","*kiss*")          === true;
098   *    wildmat("kissa","*kissa*")         === true;
099   *    wildmat("kissa","*k?ss*")          === true;
100   *    wildmat("kissa","kass*")           === false;
101   *    wildmat("","*a")                   === false;
102   *    wildmat("","*")                    === true;
103   *    wildmat("","")                     === true;
104   *    wildmat("a","")                    === false;
105   *    wildmat("kissa","KISSA")           === false;
106   *    wildmat("k","k?")                  === false;
107   *    wildmat(null,null)                 === true;
108   *    wildmat("",null)                   === false;
109   *    wildmat(null,"")                   === false;
110   * 
111   * </pre>
112   */
113  public static boolean wildmat(String str, String mask) {
114    return wildmat(str,mask,0,0);
115  }
116
117  /**
118   * Testaa ovatko kaksi merkkijonoa samat maskin mielessä 
119   * jos ne muutetaan isoille kirjaimille.
120   * @param str  tutkittava jono
121   * @param mask maski 
122   * @return true jos samat
123   * 
124   * @example
125   * <pre name="test">
126   *   onkoSamat("kissa","KISSA") === true;
127   *   onkoSamat("KISSA","kissa") === true;
128   *   onkoSamat("kissa","kiss") === false;
129   *   onkoSamat("KISSA","ki*") === true;
130   *    
131   * </pre>
132   */
133  public static boolean onkoSamat(String str, String mask) {
134    return wildmat(str.toUpperCase(),mask.toUpperCase()); // NOPMD
135  }
136
137/*
138  static int wilderr = 0;
139
140  private static  void wildtest(String s, String maski, boolean result) {
141    boolean ret = onkoSamat(s,maski);
142    System.out.print("\"" + s + "\"  \"" + maski + "\"  => " + ret);
143    if ( ret != result ) {
144      System.out.print("  VÄÄRIN!");
145      wilderr++;
146    }
147    System.out.println();
148  }
149
150  public static void main(String[] args) {
151    wildtest("kissa","kissa",true);
152    wildtest("kissa","kiss*",true);
153    wildtest("kissa","kss*",false);
154    wildtest("kissa","k*ss*",true);
155    wildtest("kissa","k***********ss*",true);
156    wildtest("kissa","*iss*",true);
157    wildtest("kissa","*kiss*",true);
158    wildtest("kissa","*kissa*",true);
159    wildtest("kissa","*k?ss*",true);
160    wildtest("kissa","kass*",false);
161    wildtest("","*a",false);
162    wildtest("","*",true);
163    wildtest("","",true);
164    wildtest("a","",false);
165    wildtest("kissa","KISSA",true);
166    if ( wilderr == 0 ) System.out.println("Kaikki oikein :-)");
167    else  System.out.println(" VIRHEITÄ: " + wilderr);
168  }
169*/  
170}