Wildcard style search in Java Pattern
Tags: java, wildcard, text, search
Published: 2020-11-02 08:51:35

There is huge text data on local computer and server side with developers in these days. Java provide powerful pattern matching method to it's developers. But Java pattern regex is very difficult branch of it to use.  

In this post, We are going to see that text searching function is based on Wildcard keyword.  

Example of the function is that getting all file objects are matched with wildcard keywords in List.

## Let's dive in  

### Scenario
Our concrete scenario is 'Getting all java source file matching with wildcard keyword. we should do being seen matching line number and file path from Standard IO(Terminal)'.  

### Step 1 - Create wildcard pattern.
To create regex, It's needed to customized a wildcard keyword to Java regex pattern.  
```
If wildcard expression is like *static*, 
Java regex should be .*\Qstaic\E.*
And if wildcard expression is like *st*ic ,
Java regex must be .*\Qst\E.*\Qic\E.*
```

To do like this, Java code like below.
```java
String keyword = "...*...*..
String regex = Arrays.asList(keyword.split(Pattern.quote("*"))).stream().map(s -> s.equals("") ? "" : Pattern.quote(s)).collect(Collectors.joining(".*"))+".*"
```

### Step 2 - Design function structure.  
1. Input root directory, filtering extension, and wildcard keyword list.
2. Get all files matching with extension under the specified root directory.
3. Using Java Stream API, Get all line and do compare each line with wildcard regex. if matching text is existing in file, Print line number, matching keyword and file path on STD IO. And then filter the non-matching file and collect matching file on List.
4. And print a returned file to terminal.  

### Step 3 - All code of function.  
All code of the function is down below.

```java
	/**
	 * Search Files from specified directory with file extension and wildcard keywords.
	 * @param rootPath
	 * @param fileExtension
	 * @param wildcardKeywords
	 * @return
	 * @throws IOException
	 */
	public static List<File> search(Path rootPath, String fileExtension, List<String> wildcardKeywords) throws IOException {
		//Get all files under specified path matching with specified file extention list.
		List<File> allFiles = Files.walk(rootPath).sorted().map(Path::toFile).filter(f -> f.getName().endsWith(fileExtension)).collect(Collectors.toList());
		return allFiles.stream().map(f -> {
			try {
				//Read all lines of a file to List.
				List<String> lines = Files.readAllLines(f.toPath());
				//matching flag
				boolean isMatching = false;
				//String line loop.
				for(int i=0; i<lines.size(); i++) {
					String line = lines.get(i);
					for(String keyword : wildcardKeywords) {
						String regex = Arrays.asList(keyword.split(Pattern.quote("*"))).stream().map(s -> s.equals("") ? "" : Pattern.quote(s)).collect(Collectors.joining(".*"))+".*";
						//if a line be matched with pattern regex, print line number and file absolute path.
						if(line.matches(regex)) {
							//Print formatted text on STD IO.
							System.out.println(String.format("%-10s   %-50s   %s", "LINE: "+(i+1), "MATCHING KEYWORD: "+keyword, "PATH: "+f.getAbsolutePath()));
							isMatching = true;
						}	
					}
				}
				if(isMatching) {
					return f;
				}
			} catch(IOException e) {
				e.printStackTrace();
			}
			return null;
			//Filtering null value.						
		}).filter(f -> f != null).collect(Collectors.toList());
	}
```

### Step 4 - Test drive
Create main function and test the function 'search'.  

* main
```java
	public static void main(String[] args) throws IOException {		
        Path rootPath = Paths.get("D:\\Development\\DBController");
        List<String> wildcardKeywords = new ArrayList<String>();
        wildcardKeywords.add("*pu*lic*");
        List<File> resultFiles = search(rootPath, ".java", wildcardKeywords);
        resultFiles.stream().forEach(System.out::println);
	}
```

I checked the function with a arbitrary Java project source directory in my local PC and then Result is like below image.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nesobnpnhlt2yv6fe4vn.png)

You could try to modify or add functionality that replace or change text by your business on a file in huge scale processing.  

Good luck to you!!!