Skip to content

Commit 3c6447b

Browse files
authored
Added support to defaultPaths for the exclude API (#4)
1 parent 364dc27 commit 3c6447b

File tree

8 files changed

+100
-46
lines changed

8 files changed

+100
-46
lines changed

README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The `DotPathQL` is the core component of this project that allows you to extract
1818
- 📋 **Collection Handling**: Process Lists, Arrays, and other Collections
1919
- 🗺️ **Map Support**: Handle both simple and complex Map structures
2020
- 📝 **Record & POJO Support**: Works with Java Records and traditional classes
21-
- 🔒 **Private Field Access**: Can access private fields when getters aren't available
21+
- 🔒 **Private Field Access**: Can access private fields when getters aren't available (filtering only)
2222
- 🚀 **Performance Optimized**: Efficient reflection-based property access
2323

2424
## Quick Start
@@ -38,10 +38,8 @@ The `DotPathQL` is the core component of this project that allows you to extract
3838
### Filter Usage
3939

4040
```java
41-
DotPathQL filterUtil = new DotPathQL();
42-
4341
// Filter specific properties from an object
44-
Map<String, Object> result = filterUtil.filter(userObject, List.of(
42+
Map<String, Object> result = new DotPathQL().filter(userObject, List.of(
4543
"username",
4644
"address.street",
4745
"address.city"
@@ -51,10 +49,8 @@ Map<String, Object> result = filterUtil.filter(userObject, List.of(
5149
### Exclude Usage
5250

5351
```java
54-
DotPathQL filterUtil = new DotPathQL();
55-
5652
// Exclude specific properties and return everything else
57-
Map<String, Object> result = filterUtil.exclude(userObject, List.of(
53+
Map<String, Object> result = new DotPathQL().exclude(userObject, List.of(
5854
"password",
5955
"ssn",
6056
"address.country"
@@ -63,7 +59,7 @@ Map<String, Object> result = filterUtil.exclude(userObject, List.of(
6359

6460
## Supported Data Structures
6561

66-
- Simple Properties
62+
- Simple Properties (primitive and object types)
6763
- Nested Objects
6864
- Collections and Arrays
6965
- Map Structures
@@ -96,7 +92,7 @@ The utility uses a multi-layered approach to access object properties:
9692

9793
1. **Record Components** (Most Efficient): For Java Records, uses the generated accessor methods
9894
2. **Getter Methods**: Tries standard getter methods (`getName()`, `getAddress()`)
99-
3. **Direct Field Access**: Falls back to direct field access for private fields
95+
3. **Direct Field Access**: Falls back to direct field access for private fields (except for the exclude API)
10096

10197
### Nested Structure Processing
10298

@@ -178,6 +174,25 @@ List<String> reportFields = List.of(
178174
);
179175
```
180176

177+
## Helper Utilities
178+
179+
You can also easy access the map result using the `DotPathQL` utility methods:
180+
181+
```java
182+
// Step 1
183+
var dotPathQL = new DotPathQL();
184+
var result = dotPathQL.filter(userObject, List.of(
185+
"address",
186+
"friendList",
187+
"games"
188+
));
189+
190+
// Step 2: Accessing the result
191+
var address = dotPathQL.mapFrom(result, "address");
192+
var friendList = dotPathQL.listFrom(result, "friendList");
193+
var games = dotPathQL.arrayFrom(result, "games");
194+
```
195+
181196
## Technical Requirements
182197

183198
- **Java**: 17 or higher

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.github.trackerforce</groupId>
88
<artifactId>dot-path-ql</artifactId>
9-
<version>1.0.1-SNAPSHOT</version>
9+
<version>1.1.0-SNAPSHOT</version>
1010

1111
<name>dot-path-ql</name>
1212
<description>dotPathQL allows object attribute filtering</description>

src/main/java/io/github/trackerforce/DotPathQL.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
@SuppressWarnings("unchecked")
1515
public class DotPathQL {
1616

17-
private final PathFilter pathFilter;
18-
private final PathExclude pathExclude;
17+
private final PathCommon pathFilter;
18+
private final PathCommon pathExclude;
1919

2020
/**
2121
* Constructs a DotPathQL instance with an empty list of default filter paths.
@@ -36,7 +36,7 @@ public DotPathQL() {
3636
* @return a map containing the filtered properties
3737
*/
3838
public <T> Map<String, Object> filter(T source, List<String> filterPaths) {
39-
return pathFilter.filter(source, filterPaths);
39+
return pathFilter.run(source, filterPaths);
4040
}
4141

4242
/**
@@ -51,7 +51,7 @@ public <T> Map<String, Object> filter(T source, List<String> filterPaths) {
5151
* @return a map containing all properties except the excluded ones
5252
*/
5353
public <T> Map<String, Object> exclude(T source, List<String> excludePaths) {
54-
return pathExclude.exclude(source, excludePaths);
54+
return pathExclude.run(source, excludePaths);
5555
}
5656

5757
/**
@@ -108,7 +108,16 @@ public Object[] arrayFrom(Map<String, Object> source, String property) {
108108
* @param paths the list of default filter paths to add
109109
*/
110110
public void addDefaultFilterPaths(List<String> paths) {
111-
pathFilter.addDefaultFilterPaths(paths);
111+
pathFilter.addDefaultPaths(paths);
112+
}
113+
114+
/**
115+
* Adds default exclude paths that will be included in every exclusion operation.
116+
*
117+
* @param paths the list of default exclude paths to add
118+
*/
119+
public void addDefaultExcludePaths(List<String> paths) {
120+
pathExclude.addDefaultPaths(paths);
112121
}
113122

114123
private boolean isInvalid(Map<String, Object> source, String property) {

src/main/java/io/github/trackerforce/PathCommon.java

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import java.lang.reflect.InvocationTargetException;
55
import java.lang.reflect.Method;
66
import java.util.ArrayList;
7+
import java.util.Collections;
78
import java.util.List;
9+
import java.util.Map;
810

911
/**
1012
* Common functionality for handling paths in the DotPathQL library.
@@ -14,28 +16,52 @@
1416
abstract class PathCommon {
1517

1618
/**
17-
* Default filter paths that can be used across different implementations.
18-
* This allows for easy configuration of common paths to filter.
19+
* Default paths that can be used across different implementations.
1920
*/
20-
protected final List<String> defaultFilterPaths;
21+
protected final List<String> defaultPaths;
2122

2223
/**
23-
* Constructor to initialize the PathCommon with an empty list of default filter paths.
24+
* Executes the path processing logic for the given source object.
25+
*
26+
* @param <T> the type of the source object
27+
* @param source the source object to process
28+
* @param filterPaths the list of paths to filter or exclude
29+
* @return a map containing the processed properties
30+
*/
31+
abstract <T> Map<String, Object> execute(T source, List<String> filterPaths);
32+
33+
/**
34+
* Runs the path processing logic for the given source object with the specified paths.
35+
*
36+
* @param <T> the type of the source object
37+
* @param source the source object to process
38+
* @param excludePaths the list of paths to exclude
39+
* @return a map containing the processed properties
40+
*/
41+
<T> Map<String, Object> run(T source, List<String> excludePaths) {
42+
if (source == null) {
43+
return Collections.emptyMap();
44+
}
45+
46+
return execute(source, expandGroupedPaths(excludePaths));
47+
}
48+
49+
/**
50+
* Constructor to initialize the PathCommon with an empty list of default paths.
2451
* This allows subclasses to add their own default paths as needed.
2552
*/
2653
protected PathCommon() {
27-
this.defaultFilterPaths = new ArrayList<>();
54+
this.defaultPaths = new ArrayList<>();
2855
}
2956

3057
/**
31-
* Adds default filter paths to the list of paths that can be used
32-
* when filtering objects. This allows for easy configuration of common
33-
* paths that should always be available for filtering.
58+
* Adds default paths to the list of paths that can be used
59+
* when processing objects.
3460
*
35-
* @param paths the list of paths to add as default filter paths
61+
* @param paths the list of paths to add as default paths
3662
*/
37-
public void addDefaultFilterPaths(List<String> paths) {
38-
defaultFilterPaths.addAll(paths);
63+
public void addDefaultPaths(List<String> paths) {
64+
defaultPaths.addAll(paths);
3965
}
4066

4167
/**

src/main/java/io/github/trackerforce/PathExclude.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ private enum SkipValue {
1010
INSTANCE
1111
}
1212

13-
public <T> Map<String, Object> exclude(T source, List<String> excludePaths) {
14-
if (source == null) {
15-
return Collections.emptyMap();
16-
}
17-
18-
ExclusionNode root = buildExclusionTree(expandGroupedPaths(excludePaths));
13+
public <T> Map<String, Object> execute(T source, List<String> excludePaths) {
1914
Map<String, Object> result = new LinkedHashMap<>();
15+
excludePaths.addAll(0, defaultPaths);
16+
17+
ExclusionNode root = buildExclusionTree(excludePaths);
2018
buildExcluding(result, source, "", root);
2119
return result;
2220
}

src/main/java/io/github/trackerforce/PathFilter.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55
@SuppressWarnings("unchecked")
66
class PathFilter extends PathCommon {
77

8-
public <T> Map<String, Object> filter(T source, List<String> filterPaths) {
9-
if (source == null) {
10-
return Collections.emptyMap();
11-
}
12-
8+
public <T> Map<String, Object> execute(T source, List<String> filterPaths) {
139
Map<String, Object> result = new LinkedHashMap<>();
14-
List<String> expandedPaths = expandGroupedPaths(filterPaths);
15-
expandedPaths.addAll(0, defaultFilterPaths);
10+
filterPaths.addAll(0, defaultPaths);
1611

17-
for (String path : expandedPaths) {
12+
for (String path : filterPaths) {
1813
addPathToResult(result, source, path);
1914
}
2015

src/test/java/io/github/trackerforce/ExcludeTypeClassRecordTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ void shouldExcludeGroupedPaths(String implementation, Object userDetail) {
106106
assertFalse(work.containsKey("city"));
107107
}
108108

109+
@ParameterizedTest(name = "{0}")
110+
@MethodSource("userDetailProvider")
111+
void shouldAddDefaultExclusionPaths(String implementation, Object userDetail) {
112+
// When
113+
dotPathQL.addDefaultExcludePaths(List.of("username"));
114+
var result = dotPathQL.exclude(userDetail, List.of("address.city"));
115+
116+
// Then
117+
assertFalse(result.containsKey("username"));
118+
var address = dotPathQL.mapFrom(result, "address");
119+
assertNotNull(address);
120+
assertFalse(address.containsKey("city"));
121+
assertTrue(address.containsKey("street"));
122+
}
123+
109124
@Test
110125
void shouldReturnEmptyMapWhenSourceIsNull() {
111126
// When

src/test/java/io/github/trackerforce/FilterTypeClassRecordTest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,9 @@ void shouldReturnFilteredObjectWithComplexMap(String implementation, Object user
126126
@ParameterizedTest(name = "{0}")
127127
@MethodSource("userDetailProvider")
128128
void shouldAddDefaultFilterPaths(String implementation, Object userDetail) {
129-
// Given
130-
var defaultPaths = List.of("username");
131-
var filterPaths = List.of("address.city");
132-
133129
// When
134-
dotPathQL.addDefaultFilterPaths(defaultPaths);
135-
var result = dotPathQL.filter(userDetail, filterPaths);
130+
dotPathQL.addDefaultFilterPaths(List.of("username"));
131+
var result = dotPathQL.filter(userDetail, List.of("address.city"));
136132

137133
// Then
138134
assertEquals(2, result.size());

0 commit comments

Comments
 (0)