Compare your string with the wild card pattern

Discussion in 'Java' started by Debadatta Mishra, Jul 16, 2008.

  1. Debadatta Mishra

    Debadatta Mishra New Member

    Joined:
    Jul 16, 2008
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0

    Introduction



    Have you ever searched for files and folders in Windows operating system? Generally most of the users try to search various .doc files, .pdf files etc. We generally search by giving *.doc or *.pdf in the text box of the search window of the windows OS. Of course windows OS provides some other more specific search utilities. However this kind of search is used in many applications. If an application provides this kind of facility it is considered as the best feature of that application.

    Technicalities



    It is always important for an application how the user is going to provide a search condition. All kinds of search conditions are not always feasible. Generally It has been universally endorsed that a user can search based upon certain specifications. As far this specification is concerned, we generally search by providing wild card characters. The wild card characters are * and ? . There is a concept behind these characters. I hope you know about it. This kind of search specification is recurrent in various applications. If you are working on an application, there will be a text field where user has to search the name of the persons by giving * or ? or a combination both and alphanumeric characters. For example I have to search a name, I can give J* so that my out may be “John”, “Johnson” or anything that starts with “J”. There is another case that I have to search exactly four characters, so I can give my search condition as ???? . However user can give any kind of combinations to search the String pattern. In case of Java based application you can achieve this feature by using regular expression. But the formation of regular expression depends upon you. Sometimes we may find it difficult to form the exact regular expression to meet the expectation. However if the requirement is only to find out the match a String based upon the wild card pattern, I have provided an example below. You can use anywhere where you want to search a name based upon the wild card pattern.

    Complete Example

    The following class is a utility class where you can use as string finder for wild card pattern. For example you have your original String as “John” and you want to find whether the original string matches with the wild pattern as “J*”. You can do it easily. I have provided the test harness class to test the functionality. You can test in various ways.

    Code:
    
    package com.ddlabs.core.util;
    import java.util.Vector;
    
    
    /**This class is a utility for finding
     * the String based upon the wild card
     * pattern. For example if the actual
     * String "John" and your wild card pattern
     * is "J*", it will return true.
     * @author Debadatta Mishra(PIKU)
     *
     */
    public class WildCardStringFinder 
    {
    	/**
    	 * String variable for wild card pattern 
    	 */
    	private String wildCardPatternString;
    	/**
    	 * Variable for the length of the wild card pattern
    	 */
    	private int wildCardPatternLength;
    	/**
    	 * Boolean variable to for checking wild cards,
    	 * It is false by default.
    	 */
    	private boolean ignoreWildCards;
    	/**
    	 * Boolean variable to know whether the pattern
    	 * has leading * or not.
    	 */
    	private boolean hasLeadingStar;
    	/**
    	 * Boolean variable to know whether the pattern
    	 * has * at the end.
    	 */
    	private boolean hasTrailingStar;
    	/**
    	 * A String array to contain chars
    	 */
    	private String charSegments[];
    	/**
    	 * Variable to maintain the boundary of the String.
    	 */
    	private int charBound;
    	
    	/**
    	 * Default constructor
    	 */
    	public WildCardStringFinder()
    	{
    		super();
    		ignoreWildCards = false;
    	}
    	
    	/**This is the public method which will be called to match a String
    	 * with the wild card pattern.
    	 * @param actualString of type String indicating the String to be matched
    	 * @param wildCardString of type String indicating the wild card String
    	 * @return true if matches
    	 */
    	public boolean isStringMatching( String actualString , String wildCardString )
    	{
    		wildCardPatternString = wildCardString;
    		wildCardPatternLength = wildCardString.length();
    		setWildCards();
    		return doesMatch( actualString, 0, actualString.length() );
    	}
    	
    	/**
    	 * This method is used to set the wild cards.
    	 * The pattern for the wild card may be *, ? or 
    	 * a combination of *,? and alphanumeric character.
    	 */
    	private void setWildCards()
    	{
    		if(wildCardPatternString.startsWith("*"))
    		{
    			hasLeadingStar = true;
    		}
    		if (wildCardPatternString.endsWith("*") && wildCardPatternLength > 1 )
    		{
    			hasTrailingStar = true;
    		}
    		Vector<String> temp = new Vector<String>();
    		int pos = 0;
    		StringBuffer buf = new StringBuffer();
    		while(pos < wildCardPatternLength) 
    		{
    			char c = wildCardPatternString.charAt(pos++);
    			switch(c)
    			{
    			case 42: // It refers to *
    				if(buf.length() > 0)
    				{
    					temp.addElement(buf.toString());
    					charBound += buf.length();
    					buf.setLength(0);
    				}
    				break;
    			case 63: // It refers to ? 
    				buf.append('\0');
    				break;
    
    			default:
    				buf.append(c);
    			break;
    			}
    		}
    		if(buf.length() > 0)
    		{
    			temp.addElement(buf.toString());
    			charBound += buf.length();
    		}
    		charSegments = new String[temp.size()];
    		temp.copyInto(charSegments);
    	}
    	
    	/**This is the actual method which makes comaparision
    	 * the with the wild card pattern.
    	 * @param text of type String indicating the actual String
    	 * @param startPoint of type int indicating the start index
    	 * of the String
    	 * @param endPoint of type int indicating the end index of
    	 * the String
    	 * @return true if matches.
    	 */
    	private final boolean doesMatch(String text, int startPoint, int endPoint)
    	{
    		int textLength = text.length();
    		
    		if(startPoint > endPoint)
    		{
    			return false;
    		}
    		if(ignoreWildCards)
    		{
    			return endPoint - startPoint == wildCardPatternLength
    					&& wildCardPatternString.regionMatches(false, 0, text,
    							startPoint, wildCardPatternLength);
    		}
    		int charCount = charSegments.length;
    		if(charCount == 0 && ( hasLeadingStar || hasTrailingStar ) )
    		{
    			return true;
    		}
    		if(startPoint == endPoint)
    		{
    			return wildCardPatternLength == 0;
    		}
    		if(wildCardPatternLength == 0)
    		{
    			return startPoint == endPoint;
    		}
    		if(startPoint < 0)
    		{
    			startPoint = 0;
    		}
    		if(endPoint > textLength)
    		{
    			endPoint = textLength;
    		}
    		int currPosition = startPoint;
    		int bound = endPoint - charBound;
    		if(bound < 0)
    		{
    			return false;
    		}
    		int i = 0;
    		String currString = charSegments[i];
    		int currStringLength = currString.length();
    		if( !hasLeadingStar )
    		{
    			if(!isExpressionMatching(text, startPoint, currString, 0, currStringLength))
    			{
    				return false;
    			}
    			i++;
    			currPosition += currStringLength;
    		}
    		if(charSegments.length == 1 && !hasLeadingStar && !hasTrailingStar)
    		{
    			return currPosition == endPoint;
    		}
    		for(; i < charCount; i++)
    		{
    			currString = charSegments[i];
    			int k = currString.indexOf('\0');
    			int currentMatch;
    			currentMatch = getTextPosition(text, currPosition, endPoint, currString);
    			if(k < 0)
    			{
    				if(currentMatch < 0)
    				{
    					return false;
    				}
    			}
    			currPosition = currentMatch + currString.length();
    		}
    		if(!hasTrailingStar && currPosition != endPoint)
    		{
    			int clen = currString.length();
    			return isExpressionMatching(text, endPoint - clen, currString, 0, clen);
    		}
    		return i == charCount;
    	}
    	
    	/**This method finds the position of the String based upon the
    	 * wild card pattern. It also considers some special case
    	 * like *.* and ???.? and their combination.
    	 * @param textString of type String indicating the String
    	 * @param start of type int indicating the start index of the String
    	 * @param end of type int indicating the end index of the String
    	 * @param posString of type indicating the position after wild card
    	 * @return the position of the String
    	 */
    	private final int getTextPosition(String textString, int start, int end, String posString)
    	{
    		/*
    		 * String after *
    		 */
    		int plen = posString.length();
    		int max = end - plen;
    		int position = -1;
    		int i = textString.indexOf(posString, start);
    		/*
    		 * The following conditions are met for the
    		 * special case where user give *.* 
    		 */
    		if( posString.equals("."))
    		{
    			position = 1;
    		}
    		if(i == -1 || i > max)
    		{
    			position = -1;
    		}
    		else
    		{
    			position = i;
    		}
    		return position;
    	}
    
    	/**This method is used to match the wild card with the String
    	 * based upon the start and end index.
    	 * @param textString of type String indicating the String
    	 * @param stringStartIndex of type int indicating the start
    	 * index of the String.
    	 * @param patternString of type String indicating the pattern
    	 * @param patternStartIndex of type int indicating the start index
    	 * @param length of type int indicating the length of pattern
    	 * @return true if matches otherwise false
    	 */
    	private boolean isExpressionMatching(String textString, int stringStartIndex,
    			String patternString, int patternStartIndex, int length)
    	{
    		while(length-- > 0) 
    		{
    			char textChar = textString.charAt(stringStartIndex++);
    			char patternChar = patternString.charAt(patternStartIndex++);
    			if ((ignoreWildCards || patternChar != 0)
    					&& patternChar != textChar
    					&& (textChar != patternChar && textChar != patternChar))
    			{
    				return false;
    			}
    		}
    		return true;
    	}
    
    }
    
    The following class is a test harness class for the above class.

    Code:
    package com.ddlabs.core.util;
    
    /**This is a test harness class to test
     * the wild card patter on a particular
     * String.
     * @author Debadatta Mishra(PIKU)
     *
     */
    public class WildCardTestharness
    {
    	public static void main(String[] args) 
    	{
    		String name = "John";
    		String searchString = "John";
    		
    		WildCardStringFinder finder = new WildCardStringFinder();
    		boolean flag = finder.isStringMatching(name, searchString);
    		System.out.println(flag);
    	}
    }
    
    To test the above programs, please create the appropriate package as mentioned in the program. You can also create your own package and modify the package name in the above programs. You can all the code in your favorable java editor. However I attach the code , you can download and test in your favourite editor.

    Conclusion



    I hope that you will enjoy my article. If you find any problems or errors, please feel free to send me a mail in the address debadattamishra at aol.com . This article is only meant for those who are new to java development. This article does not bear any commercial significance. Please provide me the feedback about this article.
     

    Attached Files:

  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
  4. akash2008

    akash2008 New Member

    Joined:
    Jan 20, 2009
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    files and folders in Windows operating system? Generally most of the users try to search various .doc files, .pdf files etc.
     
  5. devunion

    devunion New Member

    Joined:
    Sep 26, 2008
    Messages:
    19
    Likes Received:
    2
    Trophy Points:
    0
    I have few comments:

    1. It will be good to improve codestyle of the class.
    2. As I remember, Commons Lang utilities also contains such functionality. FilenameUtilities.wildcardMatch methods.
     
  6. JVposter

    JVposter New Member

    Joined:
    Feb 26, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    java programmer
    Location:
    Romania
    Home Page:
    http://www.marblehost.com
    hello!

    Thanks for the pattern!
    may be you will post an article about how to write a doc file with java using a template

    regards,
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice