Skip to content
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
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,23 @@ System.out.println(compactJson);
{"username": "john_doe", "address": {"street": "123 Main St", "city": "Springfield"}, "orders": [{"products": [{"name": "Laptop"}, {"name": "Mouse"}]}]}
```

## Map objects
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.

```java
Map<String, Object> userMap = dotPathQL.toMap(userObject);
```

## Helper Utilities

You can also easy access the map result using the `DotPathQL` utility methods:
You can also easy access the map result using the `DotUtils` utility methods:

### Path parsing

```java
List<String> paths = DotUtils.parsePaths("locations[home.street,work.city],contact[email,phone.mobile],age");
// Result: ["locations[home.street,work.city]", "contact[email,phone.mobile]", "age"]
```

### Quick Access Methods

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

// Step 2: Accessing the result
Map<String, Object> address = dotPathQL.mapFrom(result, "address");
List<Map<String, Object>> friendList = dotPathQL.listFrom(result, "friendList");
Object[] games = dotPathQL.arrayFrom(result, "games");
```

### Map objects

```java
Map<String, Object> userMap = dotPathQL.toMap(userObject);
Map<String, Object> address = DotUtils.mapFrom(result, "address");
List<Map<String, Object>> friendList = DotUtils.listFrom(result, "friendList");
Object[] games = DotUtils.arrayFrom(result, "games");
```

## Technical Requirements
Expand Down
74 changes: 11 additions & 63 deletions src/main/java/io/github/trackerforce/DotPathQL.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* @author petruki
* @since 2025-08-02
*/
@SuppressWarnings("unchecked")
public class DotPathQL {

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

/**
* Converts the source object to a map representation.
*
* @param <T> the type of the source object
* @param source the source object to convert
* @return a map containing all properties of the source object
*/
public <T> Map<String, Object> toMap(T source) {
return exclude(source, Collections.emptyList());
}

/**
* Extracts a map from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted map or an empty map if not found
* @throws ClassCastException if the property is not a map
*/
public Map<String, Object> mapFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return Collections.emptyMap();
}

return (Map<String, Object>) source.get(property);
}

/**
* Extracts a list of maps from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted list of maps or an empty list if not found
* @throws ClassCastException if the property is not a list of maps
*/
public List<Map<String, Object>> listFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return Collections.emptyList();
}

return (List<Map<String, Object>>) source.get(property);
}

/**
* Extracts a list of objects from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted list of objects or an empty list if not found
* @throws ClassCastException if the property is not a list of objects
*/
public Object[] arrayFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return new Object[0];
}

return (Object[]) source.get(property);
}

/**
* Adds default filter paths that will be included in every filtering operation.
*
Expand All @@ -136,6 +76,17 @@ public void addDefaultExcludePaths(List<String> paths) {
pathExclude.addDefaultPaths(paths);
}

/**
* Converts the source object to a map representation.
*
* @param <T> the type of the source object
* @param source the source object to convert
* @return a map containing all properties of the source object
*/
public <T> Map<String, Object> toMap(T source) {
return exclude(source, Collections.emptyList());
}

/**
* Converts the given sourceMap to a JSON string representation with optional formatting.
*
Expand All @@ -159,7 +110,4 @@ public String toJson(Map<String, Object> sourceMap, boolean prettier) {
return pathPrinter.toJson(sourceMap, prettier);
}

private boolean isInvalid(Map<String, Object> source, String property) {
return source == null || property == null || property.isEmpty() || !source.containsKey(property);
}
}
80 changes: 80 additions & 0 deletions src/main/java/io/github/trackerforce/DotUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.github.trackerforce;

import io.github.trackerforce.path.DotPathFactory;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* Utility class to complement the DotPathQL functionalities.
*/
@SuppressWarnings("unchecked")
public class DotUtils {

private DotUtils() { }

/**
* Parses a dot-notated path into its components.
*
* @param path the dot-notated path
* @return a list of path components
*/
public static List<String> parsePaths(String path) {
return DotPathFactory.buildParser().parse(path);
}

/**
* Extracts a map from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted map or an empty map if not found
* @throws ClassCastException if the property is not a map
*/
public static Map<String, Object> mapFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return Collections.emptyMap();
}

return (Map<String, Object>) source.get(property);
}

/**
* Extracts a list of maps from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted list of maps or an empty list if not found
* @throws ClassCastException if the property is not a list of maps
*/
public static List<Map<String, Object>> listFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return Collections.emptyList();
}

return (List<Map<String, Object>>) source.get(property);
}

/**
* Extracts a list of objects from the source map based on the specified property.
*
* @param source the source map
* @param property the property to extract
* @return the extracted list of objects or an empty list if not found
* @throws ClassCastException if the property is not a list of objects
*/
public static Object[] arrayFrom(Map<String, Object> source, String property) {
if (isInvalid(source, property)) {
return new Object[0];
}

return (Object[]) source.get(property);
}

private static boolean isInvalid(Map<String, Object> source, String property) {
return source == null || property == null || property.isEmpty() || !source.containsKey(property);
}
}


10 changes: 10 additions & 0 deletions src/main/java/io/github/trackerforce/path/DotPathFactory.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.trackerforce.path;

import io.github.trackerforce.path.api.DotParse;
import io.github.trackerforce.path.api.DotPath;
import io.github.trackerforce.path.api.DotPrinter;

Expand Down Expand Up @@ -37,4 +38,13 @@ public static DotPath buildExclude() {
public static DotPrinter buildPrinter(int indentSize) {
return new PathPrinter(indentSize);
}

/**
* Builds and returns a new instance of PathParser.
*
* @return a new PathParser instance
*/
public static DotParse buildParser() {
return new PathParser();
}
}
56 changes: 56 additions & 0 deletions src/main/java/io/github/trackerforce/path/PathParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.github.trackerforce.path;

import io.github.trackerforce.path.api.DotParse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Parser for dot notation paths with support for nested bracket expressions.
*/
public class PathParser implements DotParse {

/**
* Parses a dot notation string into a list of paths, handling nested brackets correctly.
*
* @param input the dot notation string to parse
* @return list of parsed paths
*/
@Override
public List<String> parse(String input) {
if (input == null || input.trim().isEmpty()) {
return Collections.emptyList();
}

List<String> paths = new ArrayList<>();
StringBuilder currentPath = new StringBuilder();
int bracketDepth = 0;

for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);

if (c == '[') {
bracketDepth++;
currentPath.append(c);
} else if (c == ']') {
bracketDepth--;
currentPath.append(c);
} else if (c == ',' && bracketDepth == 0) {
// Only split on comma when not inside brackets
if (!currentPath.isEmpty()) {
paths.add(currentPath.toString().trim());
currentPath = new StringBuilder();
}
} else {
currentPath.append(c);
}
}

// Add the last path if there's content
if (!currentPath.isEmpty()) {
paths.add(currentPath.toString().trim());
}

return paths;
}
}
17 changes: 17 additions & 0 deletions src/main/java/io/github/trackerforce/path/api/DotParse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.github.trackerforce.path.api;

import java.util.List;

/**
* Interface for parsing dot path strings into a list of path segments.
*/
public interface DotParse {

/**
* Parses a dot path string into a list of path segments.
*
* @param path the dot path string to parse
* @return a list of path segments extracted from the dot path
*/
List<String> parse(String path);
}
Loading
Loading