null safe wildcard matching
[svjatoslav_commons.git] / src / main / java / eu / svjatoslav / commons / string / WildCardMatcher.java
1 /*
2  * Svjatoslav Commons - shared library of common functionality.
3  * Copyright ©2012-2013, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License
7  * as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.commons.string;
11
12 public class WildCardMatcher {
13
14         /**
15          * Allow only for * in wildcards
16          */
17         private static boolean checkWildCardEnd(final String wildcardExpression,
18                         int wildCardPosition) {
19                 for (; wildCardPosition < wildcardExpression.length(); wildCardPosition++) {
20                         final char wildCardChar = wildcardExpression
21                                         .charAt(wildCardPosition);
22                         if (wildCardChar != '*')
23                                 return false;
24                 }
25
26                 return true;
27         }
28
29         /**
30          * <pre>
31          * Test input string against wildcard expression.
32          * * -- corresponds to any amount of characters.
33          * ? -- corresponds to any single character.
34          * </pre>
35          */
36
37         public static boolean match(final String inputString,
38                         final String wildcardExpression) {
39
40                 if (inputString == null)
41                         return false;
42
43                 if (wildcardExpression == null)
44                         return false;
45
46                 int i;
47
48                 for (i = 0; i < inputString.length(); i++) {
49                         if (i >= wildcardExpression.length())
50                                 return false;
51                         final char wildCardChar = wildcardExpression.charAt(i);
52                         if (wildCardChar == '*')
53                                 return matchPiece(inputString, i, wildcardExpression, i + 1);
54                         if (wildCardChar != '?')
55                                 if (inputString.charAt(i) != wildCardChar)
56                                         return false;
57                 }
58
59                 return checkWildCardEnd(wildcardExpression, i);
60         }
61
62         private static boolean matchPiece(final String inputString,
63                         final int inputStringIndex, final String wildcardExpression,
64                         final int wildCardExpressionIndex) {
65
66                 int wildCardPosition = wildCardExpressionIndex;
67
68                 for (int i = inputStringIndex; i < inputString.length(); i++) {
69
70                         wildCardPosition = wildCardExpressionIndex;
71
72                         subMatchAttempt: {
73
74                                 for (int j = i; j < inputString.length(); j++) {
75                                         if (wildCardPosition >= wildcardExpression.length())
76                                                 break subMatchAttempt;
77                                         final char wildCardChar = wildcardExpression
78                                                         .charAt(wildCardPosition);
79
80                                         if (wildCardChar == '*')
81                                                 return matchPiece(inputString, j, wildcardExpression,
82                                                                 wildCardPosition + 1);
83
84                                         if (wildCardChar != '?')
85                                                 if (inputString.charAt(j) != wildCardChar)
86                                                         break subMatchAttempt;
87
88                                         wildCardPosition++;
89                                 }
90
91                                 return checkWildCardEnd(wildcardExpression, wildCardPosition);
92                         }
93
94                 }
95
96                 return checkWildCardEnd(wildcardExpression, wildCardPosition);
97         }
98
99 }