Skip to content

chore: refactor to use same glob as Go #23

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

Merged
merged 1 commit into from
Aug 9, 2023
Merged
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
42 changes: 42 additions & 0 deletions lib/src/main/java/io/cloudquery/glob/Glob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.cloudquery.glob;

public class Glob {
public static final String GLOB = "*";

public static boolean match(String pattern, String subject) {
if (pattern.isEmpty()) {
return subject.equals(pattern);
}

if (pattern.equals(GLOB)) {
return true;
}

String[] parts = pattern.split("\\" + GLOB, -1);
if (parts.length == 1) {
return subject.equals(pattern);
}

boolean leadingGlob = pattern.startsWith(GLOB);
boolean trailingGlob = pattern.endsWith(GLOB);
int end = parts.length - 1;

for (int i = 0; i < end; i++) {
int idx = subject.indexOf(parts[i]);

if (i == 0) {
if (!leadingGlob && idx != 0) {
return false;
}
} else {
if (idx < 0) {
return false;
}
}

subject = subject.substring(idx + parts[i].length());
}

return trailingGlob || subject.endsWith(parts[end]);
}
}
21 changes: 21 additions & 0 deletions lib/src/main/java/io/cloudquery/glob/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2014 Ryan Uber

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3 changes: 3 additions & 0 deletions lib/src/main/java/io/cloudquery/glob/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Glob Matching Library

This glob-matching library was copied from [ryanuber/go-glob](https://github.com/ryanuber/go-glob) and therefore falls under its [license](LICENSE).
23 changes: 0 additions & 23 deletions lib/src/main/java/io/cloudquery/helper/GlobMatcher.java

This file was deleted.

25 changes: 11 additions & 14 deletions lib/src/main/java/io/cloudquery/schema/Table.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.cloudquery.schema;

import io.cloudquery.helper.GlobMatcher;
import io.cloudquery.glob.Glob;
import lombok.Builder;
import lombok.Getter;

Expand Down Expand Up @@ -28,47 +28,44 @@ public static List<Table> flattenTables(List<Table> tables) {
}

public static List<Table> filterDFS(List<Table> tables, List<String> includeConfiguration, List<String> skipConfiguration, boolean skipDependentTables) throws SchemaException {
List<GlobMatcher> includes = includeConfiguration.stream().map(GlobMatcher::new).toList();
List<GlobMatcher> excludes = skipConfiguration.stream().map(GlobMatcher::new).toList();

List<Table> flattenedTables = flattenTables(tables);
for (GlobMatcher includeMatcher : includes) {
for (String includePattern : includeConfiguration) {
boolean includeMatch = false;
for (Table table : flattenedTables) {
if (includeMatcher.matches(table.getName())) {
if (Glob.match(includePattern, table.getName())) {
includeMatch = true;
break;
}
}
if (!includeMatch) {
throw new SchemaException("table configuration includes a pattern \"" + includeMatcher.getStringMatch() + "\" with no matches");
throw new SchemaException("table configuration includes a pattern \"" + includePattern + "\" with no matches");
}
}
for (GlobMatcher excludeMatcher : excludes) {
for (String excludePattern : skipConfiguration) {
boolean excludeMatch = false;
for (Table table : flattenedTables) {
if (excludeMatcher.matches(table.getName())) {
if (Glob.match(excludePattern, table.getName())) {
excludeMatch = true;
break;
}
}
if (!excludeMatch) {
throw new SchemaException("skip configuration includes a pattern \"" + excludeMatcher.getStringMatch() + "\" with no matches");
throw new SchemaException("skip configuration includes a pattern \"" + excludePattern + "\" with no matches");
}
}

Predicate<Table> include = table -> {
for (GlobMatcher matcher : includes) {
if (matcher.matches(table.getName())) {
for (String includePattern : includeConfiguration) {
if (Glob.match(includePattern, table.getName())) {
return true;
}
}
return false;
};

Predicate<Table> exclude = table -> {
for (GlobMatcher matcher : excludes) {
if (matcher.matches(table.getName())) {
for (String excludePattern : skipConfiguration) {
if (Glob.match(excludePattern, table.getName())) {
return true;
}
}
Expand Down
100 changes: 100 additions & 0 deletions lib/src/test/java/io/cloudquery/glob/GlobTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package io.cloudquery.glob;

import org.junit.Test;

import java.util.List;

import static io.cloudquery.glob.Glob.GLOB;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class GlobTest {
@Test
public void testEmptyPattern() {
assertGlobMatch("", "");
assertNotGlobMatch("", "test");
}

@Test
public void testEmptySubject() {
for (String s : List.of("",
"*",
"**",
"***",
"****************",
GLOB.repeat(1000000)
)) {
assertGlobMatch(s, "");
}

for (String pattern : List.of(
// No globs/non-glob characters
"test",
"*test*",

// Trailing characters
"*x",
"*****************x",
GLOB.repeat(1000000) + "x",

// Leading characters
"x*",
"x*****************",
"x" + GLOB.repeat(1000000),

// Mixed leading/trailing characters
"x*x",
"x****************x",
"x" + GLOB.repeat(1000000) + "x"
)) {
assertNotGlobMatch(pattern, "");
}
}

@Test
public void testPatternWithoutGlobs() {
assertGlobMatch("test", "test");
}

@Test
public void testGlobs() {
for (String pattern : List.of(
"*test", // Leading glob
"this*", // Trailing glob
"this*test", // Middle glob
"*is *", // String in between two globs
"*is*a*", // Lots of globs
"**test**", // Double glob characters
"**is**a***test*", // Varying number of globs
"* *", // White space between globs
"*", // Lone glob
"**********", // Nothing but globs
"*Ѿ*", // Unicode with globs
"*is a ϗѾ *" // Mixed ASCII/unicode
)) {
assertGlobMatch(pattern, "this is a ϗѾ test");
}

for(String pattern:List.of(
"test*", // Implicit substring match
"*is", // Partial match
"*no*", // Globs without a match between them
" ", // Plain white space
"* ", // Trailing white space
" *", // Leading white space
"*ʤ*", // Non-matching unicode
"this*this is a test" // Repeated prefix
)) {
assertNotGlobMatch(pattern, "this is a test");
}
}

public void assertGlobMatch(String pattern, String subject) {
assertTrue(String.format("\"%s\" should match \"%s\"", pattern, subject), Glob.match(pattern, subject));
}

public void assertNotGlobMatch(String pattern, String subject) {
assertFalse(String.format("\"%s\" should not match \"%s\"", pattern, subject), Glob.match(pattern, subject));
}

}
41 changes: 0 additions & 41 deletions lib/src/test/java/io/cloudquery/helper/GlobMatcherTest.java

This file was deleted.