XApi is a modular Java toolkit for source parsing and generation, functional utilities, models and collections, service abstractions, and schema-driven build tooling. The repository is also its own largest integration test: its main Gradle build is described by XApi source files and generated by the XApi settings plugin.
This is a large, partially migrated codebase—not a uniformly supported library release. The actively used core and modern Gradle tooling coexist with historical GWT, PlayN, and custom-Gradle code. Presence in the repository does not by itself mean that a module is current or independently buildable.
The current development coordinate is 0.5.1. Local Maven artifacts under repo/ are
intentionally mutable and are consumed directly by sibling projects such as Kukunochi and
/opt/wti-ui.
Many of the repository's *.xapi files use a language that looks superficially like XML
or HTML but is better understood as a structured DSL embedded into a Java expression
parser.
For example, the root schema.xapi begins with a structure like this:
<xapi-schema
name = "xapi"
group = "net.wetheinter"
version = "0.5.1"
defaultRepoUrl = mavenCentral()
platforms = [
<main />,
<jre replace = "main" published = true />,
<gwt replace = main published = true />
]
projects = {
multiplatform: ["util"],
virtual: [<dev multiplatform = true /dev>]
}
/xapi-schema>
This is not XML:
- attribute values are AST expressions, not XML strings;
- names, strings, booleans, method calls, lambdas, type expressions, and other Java-shaped expressions can remain structurally distinct;
[...]and{key: value}become ordered array/map expression trees;- nested tags are expressions too, so a map, list, call, or tag can contain another tag;
- comments, templates, JSON-like containers, and CSS-oriented nodes share the same AST and visitor infrastructure;
- XApi's closing-tag forms include compact forms such as
/xapi-schema>in addition to more familiar tag syntax.
The implementation starts from an older JavaParser grammar. XApi extends that grammar in
xapi.jj with lexical
states and productions for UI/container, JSON-like, CSS, template, and dynamic syntax.
JavaCC generates one ASTParser containing both Java entry points such as
CompilationUnit and XApi entry points such as RootUiContainer.
JavaParser is the
public facade: its normal parse(...) methods return a Java CompilationUnit, while
parseXapi(...) and parseUiContainer(...) select RootUiContainer and return a
UiContainerExpr.
The resulting syntax tree preserves structure rather than flattening values into text:
| Source form | Representative AST shape |
|---|---|
<project ... /> |
UiContainerExpr |
name = value |
UiAttrExpr containing an Expression |
[main, <jre />] |
array-like JsonContainerExpr with distinct child expressions |
{ api: "xapi-api" } |
map-like JsonContainerExpr / JsonPairExpr |
mavenCentral() |
MethodCallExpr |
item -> item.getName() |
LambdaExpr and ordinary Java expression nodes |
| backtick templates | TemplateLiteralExpr and related dynamic nodes |
Parsing establishes syntax, source locations, and AST shape; it does not assign one global meaning to every tag or execute arbitrary expressions. Domain-specific visitors interpret the tree:
- XapiSchemaParser
interprets
<xapi-schema>documents as projects, platforms, modules, dependencies, versions, and publication settings. - DslParser and the
net.wti.core/dslmodel/compiler interpret<xapi-dsl>documents as definitions for other DSLs. - Source generators and older UI/server tooling consume the same expression and visitor model for their own domains.
That separation is the main design idea: an XML-shaped surface provides readable nesting,
the Java-derived expression grammar provides rich structured values, and a domain visitor
supplies semantics. A .xapi file is therefore closer to a typed syntax tree literal than
to an XML configuration document, JSON file, or Groovy script.
Useful examples and deeper references include:
- schema.xapi: the main build topology;
- xapi-dsl.xapi: a DSL schema written in the language it describes;
- simple-valid.xapi: a compact DSL instance;
- xapi-dsl.md: the DSL layer's roadmap and normalization model;
- In.xapi: richer generator-oriented expressions, templates, loops, and lambdas.
The xapi-dsl meta-model is still evolving. Some comments and declarations describe the
target design rather than fully implemented behavior; its tests and implementation are
the authority for what currently works.
XApi is composed of several related Gradle builds:
| Build family | Role | Current constraint |
|---|---|---|
net.wti.core |
Functional utilities, annotations, source generation, the language parser, and DSL tooling | Routine bootstrap stage; Java 8 target |
net.wti.gradle.modern |
Gradle 8.11.1 plugins, schema/settings parser, and migration bridge | Routine bootstrap stage; main build consumes its settings plugin |
| Repository root | Schema-generated XApi libraries such as base, collect, model, util, ui, and server |
Generated project scripts are tracked |
net.wti.gradle.tools |
Legacy Gradle plugins and tools | Still consumed; requires customized Gradle and Java 8 |
net.wti.gradle |
Legacy loader/plugin/API family | Still consumed; requires customized Gradle and Java 8 |
The old description of XApi as primarily a dependency-injection framework for GWT and
PlayN is historical. The injection modules still exist, but they are one subsystem rather
than an accurate description of the whole repository. Current migration work prioritizes
the core used by desktop and Android consumers. Fork-dependent GWT and Gradle code is
expected eventually to move behind a net.wti.legacy boundary; preserving every GWT
module during that split is not a requirement.
See Repository Map for the maintained topology and Modern Core and Legacy Boundary for the accepted migration direction.
The primary development environment is Ubuntu with Bash. Routine builds require Java 17 to launch Gradle 8.11.1. The two legacy Gradle build families additionally require a Java 8 JDK. Public dependencies still require network access.
./liteBuild.shThis is the normal broad development path. It builds and publishes net.wti.core, then
net.wti.gradle.modern, then the main schema-generated build. It compiles test classes
but deliberately excludes actual test, check, and Javadoc execution.
When the prerequisite 0.5.1 artifacts in repo/ are already current:
./liteBuild.sh --fast
# or: ./liteBuild.sh -fFast mode runs only the main build.
A clean checkout needs the private bootstrap seed because legacy code still depends on a customized Gradle distribution, customized GWT/compiler artifacts, and other local Maven inputs. The seed is produced by:
./bootstrap/create-bundle.shThe resulting ignored archive is
build/bootstrap/xapi-bootstrap-seed-0.5.1.zip. Extract it into the root of a clean
checkout, verify it, then run the complete build:
./bootstrap/verify-bundle.sh
./fullBuild.sh --shadowSet XAPI_JAVA8_HOME if Java 8 is not discovered automatically. The PowerShell
equivalents are bootstrap/verify-bundle.ps1 and fullBuild.ps1 -Shadow, but native
Windows execution is not yet verified.
The bootstrap archive is not an offline dependency cache and should remain private while the provenance of all legacy binaries is incomplete. See bootstrap/README.md and Build and Bootstrap Reality before changing or redistributing it.
Broad scripts optimize for fast consumer feedback and do not run the complete test suite.
Run focused tests from the Gradle build that owns the project. For example, parser and DSL
projects belong to net.wti.core, while settings-plugin tests belong to
net.wti.gradle.modern.
cd net.wti.gradle.modern
./gradlew :xapi-gradle-settings-plugin:test --console=plainPublication goes to the repository-local repo/ Maven filesystem. In the modern build,
leaf xapiPublish tasks publish every publication targeting xapiLocal, while root
publishRequired aggregates the leaves. Version 0.5.1 is intentionally republished in
place during local development.
The root schema.xapi, nested schemas, source layout, and handwritten
fragments such as src/gradle/<key>/body.end are generator inputs. The settings plugin
produces tracked *.gradle project scripts and an ignored build/xindex.
- Do not hand-edit content between
// GenStart ...XapiSettingsPluginand// GenEnd .... - Put custom Gradle logic in the supported fragment files.
- Expect ordinary Gradle invocations to regenerate project scripts.
- Review generated diffs for topology, dependencies, coordinates, and portable paths.
- The schema version becomes the default Gradle project version and is emitted into normal and synthetic-source project scripts.
- Logical dependency keys that are unsafe as Windows filenames are stored in
build/xindexusing the reversibleSchemaPathCodec; the encoded disk name is not a Gradle path or Maven coordinate.
See Schema-Generated Build Rules before changing schemas, generator logic, fragments, or generated output.
The most relevant compatibility boundaries are:
/opt/wti: the original XApi consumer;- Kukunochi: consumes selected XApi artifacts and the modern settings plugin from
repo/; /opt/wti-ui: consumes the modern settings generator and locally published artifacts;/opt/collide: a low-priority historical consumer that may no longer build.
Changes should be driven by a concrete module and consumer rather than a repository-wide assumption that similarly named legacy modules are live.
Start with AGENTS.md and the routed agent knowledge index.
They document build ownership, generated-file rules, current decisions, deferred tasks,
and the required knowledge-distillation process. Nested AGENTS.md files add guidance for
individual build families.
Preserve unrelated worktree changes, do not casually delete deprecated-looking Gradle code that remains on the build classpath, and use focused consumer evidence before expanding a modernization task.
See LICENSE.txt. The language parser contains code derived from JavaParser; the applicable original notices and license terms are retained in its sources.