https://github.com/inqwise/inqwise-walker
A convenient and powerful object walker for Java, designed to traverse complex object graphs with ease. It provides a simple, event-driven API for navigating nested structures, making it ideal for data processing, validation, and transformation tasks.
https://github.com/inqwise/inqwise-walker
event-driven java library object-traversal object-walker reactive vertx
Last synced: 5 months ago
JSON representation
A convenient and powerful object walker for Java, designed to traverse complex object graphs with ease. It provides a simple, event-driven API for navigating nested structures, making it ideal for data processing, validation, and transformation tasks.
- Host: GitHub
- URL: https://github.com/inqwise/inqwise-walker
- Owner: inqwise
- License: mit
- Created: 2025-07-30T07:35:01.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-10-15T18:53:57.000Z (5 months ago)
- Last Synced: 2025-10-16T04:10:11.321Z (5 months ago)
- Topics: event-driven, java, library, object-traversal, object-walker, reactive, vertx
- Language: Java
- Homepage:
- Size: 113 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.adoc
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
= Inqwise Walker - Object Traversal Framework
:toc:
:toclevels: 3
:source-highlighter: highlight.js
:icons: font
image:https://github.com/inqwise/inqwise-walker/actions/workflows/ci.yml/badge.svg[CI, link=https://github.com/inqwise/inqwise-walker/actions/workflows/ci.yml]
image:https://github.com/inqwise/inqwise-walker/actions/workflows/release.yml/badge.svg[Release, link=https://github.com/inqwise/inqwise-walker/actions/workflows/release.yml]
image:https://github.com/inqwise/inqwise-walker/actions/workflows/codeql.yml/badge.svg[CodeQL, link=https://github.com/inqwise/inqwise-walker/actions/workflows/codeql.yml]
image:https://codecov.io/gh/inqwise/inqwise-walker/branch/main/graph/badge.svg[Codecov, link=https://codecov.io/gh/inqwise/inqwise-walker]
image:https://snyk.io/test/github/inqwise/inqwise-walker/badge.svg[Snyk Security, link=https://snyk.io/test/github/inqwise/inqwise-walker]
image:https://img.shields.io/maven-central/v/com.inqwise/inqwise-walker.svg?label=Maven%20Central[Maven Central, link=https://search.maven.org/search?q=g:%22com.inqwise%22%20AND%20a:%22inqwise-walker%22]
image:https://img.shields.io/badge/License-MIT-yellow.svg[License: MIT, link=https://opensource.org/licenses/MIT]
image:https://img.shields.io/badge/Java-21%2B-blue.svg[Java Version, link=https://openjdk.java.net/projects/jdk/21/]
A powerful and flexible Java library for traversing complex object hierarchies with event-driven processing.
== Overview
Inqwise Walker provides a framework for walking through object structures with customizable event handlers, flow control, and extensible walker implementations. It's particularly useful for processing JSON data, nested objects, and implementing visitor patterns.
=== Key Features
* ๐ **Event-driven processing** with customizable handlers
* ๐๏ธ **Extensible architecture** - create custom walkers for any object type
* ๐ฎ **Flow control** - pause, resume, and early termination
* ๐ก๏ธ **Error handling** with success/failure callbacks
* ๐ **Path tracking** - know exactly where you are in the object hierarchy
* ๐งต **Thread-safe operations** for concurrent access
* ๐ **Context data sharing** between processing stages
== Quick Start
=== Maven Dependency
[source,xml]
----
com.inqwise
inqwise-walker
${latest.version}
----
=== Basic Usage
[source,java]
----
import com.inqwise.walker.*;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.JsonArray;
// Create a JSON structure
JsonObject person = new JsonObject()
.put("name", "John Doe")
.put("age", 30)
.put("address", new JsonObject()
.put("street", "123 Main St")
.put("city", "New York"))
.put("hobbies", new JsonArray()
.add("reading")
.add("swimming"));
// Create walker with nested support
JsonObjectWalker walker = JsonObjectWalker.instance();
// Add event handler
walker.handler(event -> {
String path = event.meta().get(ObjectWalker.Keys.PATH).toString();
Object value = event.indicatedObject();
System.out.println("Path: " + path + " -> Value: " + value);
});
// Start walking
ObjectWalkingContext context = walker.handle(person);
System.out.println("Success: " + context.success());
----
== Architecture
=== Core Components
==== ObjectWalker (Abstract Base Class)
The foundation of the framework providing:
* Walker registration and delegation
* Event handler management
* Flow control coordination
* Error handling infrastructure
==== Built-in Walkers
[cols="1,3"]
|===
|Walker |Description
|`JsonObjectWalker`
|Traverses Vert.x JsonObject instances with path tracking
|`JsonArrayWalker`
|Processes JsonArray elements with indexed paths
|`DifferencesWalker`
|Handles difference objects from inqwise-difference library
|===
==== Context Management
* **ObjectWalkingContext**: Manages walking state, flow control, and data storage
* **ObjectWalkingEvent**: Provides event information and control methods
* **IndicatedItem**: Wraps objects with metadata during processing
=== Processing Flow
[source]
----
ObjectWalker.handle(object)
โ
Create ObjectWalkingContext
โ
For each object in hierarchy:
โ
Generate ObjectWalkingEvent
โ
Call registered event handlers
โ
Delegate to appropriate walker
โ
Continue until complete or terminated
----
== Advanced Features
=== Custom Walker Implementation
Create walkers for your own data types:
[source,java]
----
public class PersonWalker extends ObjectWalker {
public PersonWalker() {
super(null);
}
@Override
protected Class> type() {
return Person.class;
}
@Override
protected Iterator createObjectIterator(
IndicatedItem item, ObjectWalkingContext context) {
Person person = (Person) item.value();
String basePath = item.meta().getOrDefault(Keys.PATH, ".").toString();
return List.of(
item.newSubItem(person.getName()).put(Keys.PATH, basePath + ".name"),
item.newSubItem(person.getAge()).put(Keys.PATH, basePath + ".age")
).iterator();
}
}
----
=== Flow Control
[source,java]
----
walker.handler(event -> {
String path = event.meta().get(ObjectWalker.Keys.PATH).toString();
// Pause processing
if (path.equals(".metadata")) {
event.context().pause();
// Do some async work...
event.context().resume();
}
// Early termination
if (path.equals(".stop-here")) {
event.end();
}
});
----
=== Context Data Sharing
[source,java]
----
walker.handler(event -> {
String path = event.meta().get(ObjectWalker.Keys.PATH).toString();
Object value = event.indicatedObject();
// Store data in context
if (path.contains("user")) {
event.context().put("userCount",
(Integer) event.context().get("userCount") + 1);
}
});
// Access shared data after walking
Integer userCount = context.get("userCount");
----
=== Error Handling
[source,java]
----
walker.handler(event -> {
// Processing that might throw exceptions
if (someCondition) {
throw new RuntimeException("Processing error");
}
});
walker.errorHandler(context -> {
System.err.println("Error: " + context.cause().getMessage());
System.err.println("Failed at level: " + context.levelIndex());
});
walker.endHandler(context -> {
if (context.success()) {
System.out.println("Walking completed successfully");
}
});
----
== Use Cases
=== Data Validation
Walk through complex objects to validate structure and values:
[source,java]
----
walker.handler(event -> {
String path = event.meta().get(ObjectWalker.Keys.PATH).toString();
Object value = event.indicatedObject();
if (path.endsWith(".email") && !isValidEmail(value.toString())) {
throw new ValidationException("Invalid email at " + path);
}
});
----
=== Data Transformation
Convert objects from one format to another:
[source,java]
----
Map result = new HashMap<>();
walker.handler(event -> {
String path = event.meta().get(ObjectWalker.Keys.PATH).toString();
Object value = event.indicatedObject();
// Transform field names and values
String transformedPath = transformPath(path);
Object transformedValue = transformValue(value);
result.put(transformedPath, transformedValue);
});
----
=== Metrics Collection
Gather statistics about object structures:
[source,java]
----
AtomicInteger fieldCount = new AtomicInteger(0);
AtomicInteger arrayCount = new AtomicInteger(0);
AtomicInteger objectCount = new AtomicInteger(0);
walker.handler(event -> {
fieldCount.incrementAndGet();
if (event.hasWalker()) {
if (event.getWalker() instanceof JsonArrayWalker) {
arrayCount.incrementAndGet();
} else if (event.getWalker() instanceof JsonObjectWalker) {
objectCount.incrementAndGet();
}
}
});
----
== Building and Testing
=== Prerequisites
* Java 21+
* Maven 3.6.3+
=== Build Commands
[source,bash]
----
# Compile the project
mvn compile
# Run tests
mvn test
# Create JAR
mvn package
# Install to local repository
mvn install
----
=== Running Examples
[source,bash]
----
# Compile and run usage examples
mvn exec:java -Dexec.mainClass="com.inqwise.walker.example.WalkerUsageExample"
----
== Dependencies
The library has minimal runtime dependencies:
* **Vert.x Core** (5.0.4) - For JSON processing (provided scope)
* **Google Guava** (33.4.0-jre) - For collections utilities (provided scope)
* **Apache Log4j** (2.25.2) - For logging (api required, core provided)
* **Inqwise Difference** (1.1.6) - For difference processing (provided scope)
Test dependencies include JUnit 5.11.3 and Vert.x test utilities.
== Contributing
We welcome contributions! Please see our link:CONTRIBUTING.md[contributing guidelines] for details on:
* Code style and conventions
* Submitting issues and feature requests
* Creating pull requests
* Running tests locally
== License
This project is licensed under the MIT License - see the link:LICENSE[LICENSE] file for details.
== Support
* **Documentation**: Check this README and the link:WalkerUsageExample.java[usage examples]
* **Issues**: Report bugs and request features on link:https://github.com/inqwise/inqwise-walker/issues[GitHub Issues]
* **Discussions**: Ask questions on link:https://github.com/inqwise/inqwise-walker/discussions[GitHub Discussions]
---
Built with โค๏ธ by the link:https://www.inqwise.com[Inqwise] team.