Skip to content

Commit 3fef38c

Browse files
authored
Added DotUtils and parsePaths to help build path components list (#7)
1 parent c9f9785 commit 3fef38c

11 files changed

Lines changed: 279 additions & 117 deletions

File tree

README.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,23 @@ System.out.println(compactJson);
233233
{"username": "john_doe", "address": {"street": "123 Main St", "city": "Springfield"}, "orders": [{"products": [{"name": "Laptop"}, {"name": "Mouse"}]}]}
234234
```
235235

236+
## Map objects
237+
Convert any object to a Map representation using the `toMap` method. This is useful for scenarios where you need a visual representation of the entire object structure.
238+
239+
```java
240+
Map<String, Object> userMap = dotPathQL.toMap(userObject);
241+
```
242+
236243
## Helper Utilities
237244

238-
You can also easy access the map result using the `DotPathQL` utility methods:
245+
You can also easy access the map result using the `DotUtils` utility methods:
246+
247+
### Path parsing
248+
249+
```java
250+
List<String> paths = DotUtils.parsePaths("locations[home.street,work.city],contact[email,phone.mobile],age");
251+
// Result: ["locations[home.street,work.city]", "contact[email,phone.mobile]", "age"]
252+
```
239253

240254
### Quick Access Methods
241255

@@ -249,15 +263,9 @@ Map<String, Object> result = dotPathQL.filter(userObject, List.of(
249263
));
250264

251265
// Step 2: Accessing the result
252-
Map<String, Object> address = dotPathQL.mapFrom(result, "address");
253-
List<Map<String, Object>> friendList = dotPathQL.listFrom(result, "friendList");
254-
Object[] games = dotPathQL.arrayFrom(result, "games");
255-
```
256-
257-
### Map objects
258-
259-
```java
260-
Map<String, Object> userMap = dotPathQL.toMap(userObject);
266+
Map<String, Object> address = DotUtils.mapFrom(result, "address");
267+
List<Map<String, Object>> friendList = DotUtils.listFrom(result, "friendList");
268+
Object[] games = DotUtils.arrayFrom(result, "games");
261269
```
262270

263271
## Technical Requirements

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

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* @author petruki
1515
* @since 2025-08-02
1616
*/
17-
@SuppressWarnings("unchecked")
1817
public class DotPathQL {
1918

2019
private final DotPath pathFilter;
@@ -59,65 +58,6 @@ public <T> Map<String, Object> exclude(T source, List<String> excludePaths) {
5958
return pathExclude.run(source, excludePaths);
6059
}
6160

62-
/**
63-
* Converts the source object to a map representation.
64-
*
65-
* @param <T> the type of the source object
66-
* @param source the source object to convert
67-
* @return a map containing all properties of the source object
68-
*/
69-
public <T> Map<String, Object> toMap(T source) {
70-
return exclude(source, Collections.emptyList());
71-
}
72-
73-
/**
74-
* Extracts a map from the source map based on the specified property.
75-
*
76-
* @param source the source map
77-
* @param property the property to extract
78-
* @return the extracted map or an empty map if not found
79-
* @throws ClassCastException if the property is not a map
80-
*/
81-
public Map<String, Object> mapFrom(Map<String, Object> source, String property) {
82-
if (isInvalid(source, property)) {
83-
return Collections.emptyMap();
84-
}
85-
86-
return (Map<String, Object>) source.get(property);
87-
}
88-
89-
/**
90-
* Extracts a list of maps from the source map based on the specified property.
91-
*
92-
* @param source the source map
93-
* @param property the property to extract
94-
* @return the extracted list of maps or an empty list if not found
95-
* @throws ClassCastException if the property is not a list of maps
96-
*/
97-
public List<Map<String, Object>> listFrom(Map<String, Object> source, String property) {
98-
if (isInvalid(source, property)) {
99-
return Collections.emptyList();
100-
}
101-
102-
return (List<Map<String, Object>>) source.get(property);
103-
}
104-
105-
/**
106-
* Extracts a list of objects from the source map based on the specified property.
107-
*
108-
* @param source the source map
109-
* @param property the property to extract
110-
* @return the extracted list of objects or an empty list if not found
111-
* @throws ClassCastException if the property is not a list of objects
112-
*/
113-
public Object[] arrayFrom(Map<String, Object> source, String property) {
114-
if (isInvalid(source, property)) {
115-
return new Object[0];
116-
}
117-
118-
return (Object[]) source.get(property);
119-
}
120-
12161
/**
12262
* Adds default filter paths that will be included in every filtering operation.
12363
*
@@ -136,6 +76,17 @@ public void addDefaultExcludePaths(List<String> paths) {
13676
pathExclude.addDefaultPaths(paths);
13777
}
13878

79+
/**
80+
* Converts the source object to a map representation.
81+
*
82+
* @param <T> the type of the source object
83+
* @param source the source object to convert
84+
* @return a map containing all properties of the source object
85+
*/
86+
public <T> Map<String, Object> toMap(T source) {
87+
return exclude(source, Collections.emptyList());
88+
}
89+
13990
/**
14091
* Converts the given sourceMap to a JSON string representation with optional formatting.
14192
*
@@ -159,7 +110,4 @@ public String toJson(Map<String, Object> sourceMap, boolean prettier) {
159110
return pathPrinter.toJson(sourceMap, prettier);
160111
}
161112

162-
private boolean isInvalid(Map<String, Object> source, String property) {
163-
return source == null || property == null || property.isEmpty() || !source.containsKey(property);
164-
}
165113
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package io.github.trackerforce;
2+
3+
import io.github.trackerforce.path.DotPathFactory;
4+
5+
import java.util.Collections;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
/**
10+
* Utility class to complement the DotPathQL functionalities.
11+
*/
12+
@SuppressWarnings("unchecked")
13+
public class DotUtils {
14+
15+
private DotUtils() { }
16+
17+
/**
18+
* Parses a dot-notated path into its components.
19+
*
20+
* @param path the dot-notated path
21+
* @return a list of path components
22+
*/
23+
public static List<String> parsePaths(String path) {
24+
return DotPathFactory.buildParser().parse(path);
25+
}
26+
27+
/**
28+
* Extracts a map from the source map based on the specified property.
29+
*
30+
* @param source the source map
31+
* @param property the property to extract
32+
* @return the extracted map or an empty map if not found
33+
* @throws ClassCastException if the property is not a map
34+
*/
35+
public static Map<String, Object> mapFrom(Map<String, Object> source, String property) {
36+
if (isInvalid(source, property)) {
37+
return Collections.emptyMap();
38+
}
39+
40+
return (Map<String, Object>) source.get(property);
41+
}
42+
43+
/**
44+
* Extracts a list of maps from the source map based on the specified property.
45+
*
46+
* @param source the source map
47+
* @param property the property to extract
48+
* @return the extracted list of maps or an empty list if not found
49+
* @throws ClassCastException if the property is not a list of maps
50+
*/
51+
public static List<Map<String, Object>> listFrom(Map<String, Object> source, String property) {
52+
if (isInvalid(source, property)) {
53+
return Collections.emptyList();
54+
}
55+
56+
return (List<Map<String, Object>>) source.get(property);
57+
}
58+
59+
/**
60+
* Extracts a list of objects from the source map based on the specified property.
61+
*
62+
* @param source the source map
63+
* @param property the property to extract
64+
* @return the extracted list of objects or an empty list if not found
65+
* @throws ClassCastException if the property is not a list of objects
66+
*/
67+
public static Object[] arrayFrom(Map<String, Object> source, String property) {
68+
if (isInvalid(source, property)) {
69+
return new Object[0];
70+
}
71+
72+
return (Object[]) source.get(property);
73+
}
74+
75+
private static boolean isInvalid(Map<String, Object> source, String property) {
76+
return source == null || property == null || property.isEmpty() || !source.containsKey(property);
77+
}
78+
}
79+
80+

src/main/java/io/github/trackerforce/path/DotPathFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.github.trackerforce.path;
22

3+
import io.github.trackerforce.path.api.DotParse;
34
import io.github.trackerforce.path.api.DotPath;
45
import io.github.trackerforce.path.api.DotPrinter;
56

@@ -37,4 +38,13 @@ public static DotPath buildExclude() {
3738
public static DotPrinter buildPrinter(int indentSize) {
3839
return new PathPrinter(indentSize);
3940
}
41+
42+
/**
43+
* Builds and returns a new instance of PathParser.
44+
*
45+
* @return a new PathParser instance
46+
*/
47+
public static DotParse buildParser() {
48+
return new PathParser();
49+
}
4050
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.github.trackerforce.path;
2+
3+
import io.github.trackerforce.path.api.DotParse;
4+
import java.util.ArrayList;
5+
import java.util.Collections;
6+
import java.util.List;
7+
8+
/**
9+
* Parser for dot notation paths with support for nested bracket expressions.
10+
*/
11+
public class PathParser implements DotParse {
12+
13+
/**
14+
* Parses a dot notation string into a list of paths, handling nested brackets correctly.
15+
*
16+
* @param input the dot notation string to parse
17+
* @return list of parsed paths
18+
*/
19+
@Override
20+
public List<String> parse(String input) {
21+
if (input == null || input.trim().isEmpty()) {
22+
return Collections.emptyList();
23+
}
24+
25+
List<String> paths = new ArrayList<>();
26+
StringBuilder currentPath = new StringBuilder();
27+
int bracketDepth = 0;
28+
29+
for (int i = 0; i < input.length(); i++) {
30+
char c = input.charAt(i);
31+
32+
if (c == '[') {
33+
bracketDepth++;
34+
currentPath.append(c);
35+
} else if (c == ']') {
36+
bracketDepth--;
37+
currentPath.append(c);
38+
} else if (c == ',' && bracketDepth == 0) {
39+
// Only split on comma when not inside brackets
40+
if (!currentPath.isEmpty()) {
41+
paths.add(currentPath.toString().trim());
42+
currentPath = new StringBuilder();
43+
}
44+
} else {
45+
currentPath.append(c);
46+
}
47+
}
48+
49+
// Add the last path if there's content
50+
if (!currentPath.isEmpty()) {
51+
paths.add(currentPath.toString().trim());
52+
}
53+
54+
return paths;
55+
}
56+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.github.trackerforce.path.api;
2+
3+
import java.util.List;
4+
5+
/**
6+
* Interface for parsing dot path strings into a list of path segments.
7+
*/
8+
public interface DotParse {
9+
10+
/**
11+
* Parses a dot path string into a list of path segments.
12+
*
13+
* @param path the dot path string to parse
14+
* @return a list of path segments extracted from the dot path
15+
*/
16+
List<String> parse(String path);
17+
}

0 commit comments

Comments
 (0)