alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*****************************************************************************
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version
 * 1.0 (the "License"). You may not use this file except in compliance with
 * the License. A copy of the License is available at http://www.sun.com/
 *
 * The Original Code is the CVS Client Library.
 * The Initial Developer of the Original Code is Thomas Singer.
 * Portions created by Thomas Singer Copyright (C) 2001.
 * All Rights Reserved.
 *
 * Contributor(s): Thomas Singer, Milos Kleint
 *****************************************************************************/
package org.netbeans.lib.cvsclient.util;

import java.util.*;

/**
 * @author  Thomas Singer
 */
public class SimpleStringPattern
        implements StringPattern {

    private static final char MATCH_EACH = '*';
    private static final char MATCH_ONE = '?';

    private final List subPatterns = new LinkedList();

    /**
     * Creates a SimpleStringPattern for the specified definition.
     * The definition might contain two special characters ('*' and '?').
     */
    public SimpleStringPattern(String definition) {
        splitInSubPattern(definition);
    }

    /**
     * Returns whether the specified string matches thiz pattern.
     */
    public boolean doesMatch(String string) {
        int index = 0;
        SubPattern subPattern = null;
        for (Iterator it = subPatterns.iterator(); it.hasNext();) {
            subPattern = (SubPattern)it.next();
            index = subPattern.doesMatch(string, index);
            if (index < 0) {
                return false;
            }
        }

        if (index == string.length()) {
            return true;
        }
        if (subPattern == null) {
            return false;
        }
        return subPattern.checkEnding(string, index);
    }

    private void splitInSubPattern(String definition) {
        char prevSubPattern = ' ';

        int prevIndex = 0;
        for (int index = 0; index >= 0;) {
            prevIndex = index;

            index = definition.indexOf(MATCH_EACH, prevIndex);
            if (index >= 0) {
                String match = definition.substring(prevIndex, index);
                addSubPattern(match, prevSubPattern);
                prevSubPattern = MATCH_EACH;
                index++;
                continue;
            }
            index = definition.indexOf(MATCH_ONE, prevIndex);
            if (index >= 0) {
                String match = definition.substring(prevIndex, index);
                addSubPattern(match, prevSubPattern);
                prevSubPattern = MATCH_ONE;
                index++;
                continue;
            }
        }
        String match = definition.substring(prevIndex);
        addSubPattern(match, prevSubPattern);
    }

    private void addSubPattern(String match, char subPatternMode) {
        SubPattern subPattern = null;
        switch (subPatternMode) {
        case MATCH_EACH:
            subPattern = new MatchEachCharPattern(match);
            break;
        case MATCH_ONE:
            subPattern = new MatchOneCharPattern(match);
            break;
        default:
            subPattern = new MatchExactSubPattern(match);
            break;
        }

        subPatterns.add(subPattern);
    }

    public String toString() {
        StringBuffer buffer = new StringBuffer();
        for (Iterator it = subPatterns.iterator(); it.hasNext();) {
            SubPattern subPattern = (SubPattern)it.next();
            buffer.append(subPattern.toString());
        }
        return buffer.toString();
    }
    
    public boolean equals(Object obj) {
        if (!(obj instanceof SimpleStringPattern)) return false;
        return subPatterns.equals(((SimpleStringPattern) obj).subPatterns);
    }
    
    public int hashCode() {
        return -subPatterns.hashCode();
    }

    public static void main(String[] arguments) {
        StringPattern sp = new SimpleStringPattern("a*b"); //NOI18N

        test(sp, "ab", true); //NOI18N
        test(sp, "aab", true); //NOI18N
        test(sp, "ba", false); //NOI18N
        test(sp, "abc", false); //NOI18N

        sp = new SimpleStringPattern("*.txt"); //NOI18N

        test(sp, "datei.txt", true); //NOI18N
        test(sp, ".txt", true); //NOI18N
        test(sp, "datei.tx", false); //NOI18N
        test(sp, "datei.txt.txt", true); //NOI18N

        sp = new SimpleStringPattern("datei*1*"); //NOI18N

        test(sp, "datei0.txt", false); //NOI18N
        test(sp, "datei1.txt", true); //NOI18N
        test(sp, "datei.tx", false); //NOI18N
        test(sp, "datei1.txt.txt", true); //NOI18N

        sp = new SimpleStringPattern("Makefile"); //NOI18N

        test(sp, "Makefile", true); //NOI18N
        test(sp, "Makefile.mak", false); //NOI18N
        test(sp, "Makefile1", false); //NOI18N
        test(sp, ".Makefile", false); //NOI18N
        test(sp, ".Makefile.", false); //NOI18N

        sp = new SimpleStringPattern("*~"); //NOI18N

        test(sp, "datei~", true); //NOI18N
        test(sp, "datei~1", false); //NOI18N
        test(sp, "datei~1~", true); //NOI18N
        
        // Equality:
        SimpleStringPattern pattern1 = new SimpleStringPattern("*.class");
        SimpleStringPattern pattern2 = new SimpleStringPattern("*.class");
        System.err.println(pattern1+".equals("+pattern2+") = "+pattern1.equals(pattern2));
        
        pattern1 = new SimpleStringPattern("?.class");
        pattern2 = new SimpleStringPattern("*.class");
        System.err.println(pattern1+".equals("+pattern2+") = "+pattern1.equals(pattern2));
        
        pattern1 = new SimpleStringPattern("*.clazz");
        pattern2 = new SimpleStringPattern("*.class");
        System.err.println(pattern1+".equals("+pattern2+") = "+pattern1.equals(pattern2));
    }

    private static void test(StringPattern sp, String testString, boolean shouldResult) {
        System.err.print('"' + sp.toString() + '"' + ": " + testString + " " + shouldResult); //NOI18N

        boolean doesMatch = sp.doesMatch(testString);

        if (doesMatch == shouldResult) {
            System.err.println(" proved"); //NOI18N
        }
        else {
            System.err.println(" **denied**"); //NOI18N
        }
    }

    private static abstract class SubPattern {
        protected final String match;

        protected SubPattern(String match) {
            this.match = match;
        }

        /**
         * @parameter string ... the whole string to test for matching
         * @parameter index  ... the index in string where this' test should begin
         * @returns          ... if successful the next test-position, if not -1
         */
        public abstract int doesMatch(String string, int index);

        public boolean checkEnding(String string, int index) {
            return false;
        }
        
        public boolean equals(Object obj) {
            if (!(this.getClass().isInstance(obj))) return false;
            return match.equals(((SubPattern) obj).match);
        }
        
        public int hashCode() {
            return -match.hashCode();
        }
    }

    private static class MatchExactSubPattern extends SubPattern {
        public MatchExactSubPattern(String match) {
            super(match);
        }

        public int doesMatch(String string, int index) {
            if (!string.startsWith(match, index)) {
                return -1;
            }
            return index + match.length();
        }

        public String toString() {
            return match;
        }
    }

    private static class MatchEachCharPattern extends SubPattern {
        public MatchEachCharPattern(String match) {
            super(match);
        }

        public int doesMatch(String string, int index) {
            int matchIndex = string.indexOf(match, index);
            if (matchIndex < 0) {
                return -1;
            }
            return matchIndex + match.length();
        }

        public boolean checkEnding(String string, int index) {
            return string.endsWith(match);
        }

        public String toString() {
            return MATCH_EACH + match;
        }
    }

    private static class MatchOneCharPattern extends MatchExactSubPattern {
        public MatchOneCharPattern(String match) {
            super(match);
        }

        public int doesMatch(String string, int index) {
            index++;
            if (string.length() < index) {
                return -1;
            }
            return super.doesMatch(string, index);
        }

        public String toString() {
            return MATCH_ONE + match;
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.