Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug/12065-refac-glob-matching #1

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 33 additions & 30 deletions libs/common/src/main/java/org/opensearch/common/Glob.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,47 +39,50 @@
*/
public class Glob {

private Glob() {}
/**
* Match a String against the given pattern, supporting the following simple
* pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
* arbitrary number of pattern parts), as well as direct equality.
* Match a String against the given pattern, supporting the following simple pattern styles: "xxx*", "*xxx", "*xxx*"
* and "xxx*yyy" matches (with an arbitrary number of pattern parts), as well as direct equality.
*
* @param pattern the pattern to match against
* @param str the String to match
* @param str the String to match
* @return whether the String matches the given pattern
*/
public static boolean globMatch(String pattern, String str) {

if (pattern == null || str == null) {
return false;
}
int firstIndex = pattern.indexOf('*');
if (firstIndex == -1) {
return pattern.equals(str);
}
if (firstIndex == 0) {
if (pattern.length() == 1) {
return true;
}
int nextIndex = pattern.indexOf('*', firstIndex + 1);
if (nextIndex == -1) {
return str.endsWith(pattern.substring(1));
} else if (nextIndex == 1) {
// Double wildcard "**" - skipping the first "*"
return globMatch(pattern.substring(1), str);
}
String part = pattern.substring(1, nextIndex);
int partIndex = str.indexOf(part);
while (partIndex != -1) {
if (globMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
return true;
}
partIndex = str.indexOf(part, partIndex + 1);

int stringIndex=0;
int patternIndex = 0;
int wildcardIndex = -1;

while (stringIndex < str.length()) {
// pattern and string match
if (patternIndex < pattern.length() && str.charAt(stringIndex) == pattern.charAt(patternIndex)) {
stringIndex++;
patternIndex++;
} else if (patternIndex < pattern.length() && pattern.charAt(patternIndex) == '*') {
// wildcard found
wildcardIndex = patternIndex;
patternIndex++;
} else if (wildcardIndex != -1) {
// last pattern pointer was a wildcard
patternIndex = wildcardIndex + 1;
stringIndex++;
} else {
// characters do not match
return false;
}
return false;
}
return (str.length() >= firstIndex
&& pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex))
&& globMatch(pattern.substring(firstIndex), str.substring(firstIndex)));

while (patternIndex < pattern.length() && pattern.charAt(patternIndex) == '*') {
patternIndex++;
}

return patternIndex == pattern.length();
}


}
84 changes: 84 additions & 0 deletions libs/common/src/test/java/org/opensearch/common/GlobTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.common;

import org.opensearch.test.OpenSearchTestCase;

public class GlobTests extends OpenSearchTestCase {


public void testGlobMatchNoWildcard() {
assertTrue(Glob.globMatch("test", "test"));
assertFalse(Glob.globMatch("test", "testing"));
}


public void testGlobMatchWildcardAtBeginning() {
assertTrue(Glob.globMatch("*test", "thisisatest"));
assertFalse(Glob.globMatch("*test", "thisisatesting"));
}


public void testGlobMatchWildcardAtEnd() {
assertTrue(Glob.globMatch("test*", "testthisisa"));
assertFalse(Glob.globMatch("test*", "atestthisis"));
}


public void testGlobMatchWildcardAtMiddle() {
assertTrue(Glob.globMatch("test*ing", "testthisisaing"));
assertFalse(Glob.globMatch("test*ing", "testthisisa"));
}


public void testGlobMatchMultipleWildcards() {
assertTrue(Glob.globMatch("*test*", "thisisatesting"));
assertFalse(Glob.globMatch("*test*", "thisisatesing"));
assertTrue(Glob.globMatch("*test*test", "thisisatestingtest"));
assertFalse(Glob.globMatch("*test*test", "thisisatesting"));
}

public void testGlobMatchMultipleCharactersWithSingleWildcard() {
assertTrue(Glob.globMatch("a*b", "acb"));
assertTrue(Glob.globMatch("a*b", "aab"));
assertTrue(Glob.globMatch("a*b", "aaab"));
assertFalse(Glob.globMatch("a*b", "ac"));
}

public void testGlobMatchWildcardWithEmptyString() {
assertTrue(Glob.globMatch("*", ""));
assertTrue(Glob.globMatch("a*", "a"));
assertFalse(Glob.globMatch("a*", ""));
}

public void testGlobMatchMultipleWildcardsWithMultipleCharacters() {
assertTrue(Glob.globMatch("a*b*c", "abc"));
assertTrue(Glob.globMatch("a*b*c", "axxxbxbc"));
assertTrue(Glob.globMatch("a*b*c", "aabc"));
assertTrue(Glob.globMatch("a*b*c", "abac"));
assertFalse(Glob.globMatch("a*b*c", "abca"));
assertFalse(Glob.globMatch("a*b*c", "ac"));
}


public void testGlobMatchNullPattern() {
assertFalse(Glob.globMatch(null, "test"));
}


public void testGlobMatchNullString() {
assertFalse(Glob.globMatch("test", null));
}


public void testGlobMatchNullPatternAndString() {
assertFalse(Glob.globMatch(null, null));
}
}