Thanks for your interest in contributing! This document explains how to build, test, and submit changes, and — most importantly — the one design rule that makes this project different from a typical library.
This project is a deliberate, class-for-class port of Mercedes-Benz's Python
odxtools. The upstream Python
implementation is the behavior oracle: when the question is "what should this
do?", the answer is "whatever Python odxtools does."
Concretely, this means:
- Don't redesign the API to taste. Class names, method names, and the resolution/inheritance/encode-decode semantics intentionally track upstream. A "more idiomatic Java" change that diverges from Python behavior will usually be rejected, even if it looks cleaner.
- Cite the Python origin. Most types carry javadoc like "Java counterpart of
Python's
HierarchyElement". When you add or change a type, keep those references accurate and add them for new code. - When fixing a behavior bug, check Python first. The fix is almost always "make it match upstream," and the PR description should say what upstream does.
- If you believe upstream itself is wrong, say so explicitly in the issue/PR — intentional divergence is possible but must be a conscious, documented decision, not an accident.
This repository is the odxtools-core module only — PDX/ODX reading, the data
model, ODXLINK/SNREF resolution, value inheritance, and the bit-level
encode/decode loop. The CLI, the model-based writer, and the CAN/ISO-TP layer
are out of scope here. Please open an issue before starting large new surface
area so we can confirm it fits.
Requires JDK 25 (the Gradle toolchain is pinned to 25). If your default JDK is older, point at a JDK 25 install — on macOS:
export JAVA_HOME="$(/usr/libexec/java_home -v 25)"The Gradle wrapper is committed, so use it directly:
./gradlew :odxtools-core:test # run the test suite (JUnit 5 + AssertJ)
./gradlew :odxtools-core:check # test + checkstyle + jacoco coverage gate
./gradlew :odxtools-core:jar # build the library jar
# run a single test class or method:
./gradlew :odxtools-core:test --tests 'dev.opendota.odxtools.codec.ParameterCodecTest'
./gradlew :odxtools-core:test --tests '*ParameterCodecTest.someMethodName'Before opening a PR, ./gradlew :odxtools-core:check must pass. CI runs the
same command. Note the two gates that fail the build:
- Checkstyle (
config/checkstyle/checkstyle.xml) — style violations fail. - Coverage — jacoco enforces a line/branch minimum (85% / 75%) scoped to the
dev.opendota.odxtools.codecpackage. Adding codec code without tests will fail the build.
- Public types carry full javadoc; match the density of the surrounding code.
- Keep the "Java counterpart of Python's
X" references accurate (see above). - Shared Gradle config lives in the convention plugin
buildSrc/src/main/kotlin/odxtools.java-conventions.gradle.kts— edit build config there or inodxtools-core/build.gradle.kts, not the (intentionally empty) root build.
examples/somersault.pdx is the only sample fixture, and it is the public
synthetic database from upstream — it contains no real vehicle data.
⚠️ Never commit real vehicle PDX/ODX data..gitignoreactively guards against it (examples/*.pdxexcept somersault, and deflated*.odx-d/*.odx-c/index.xmlartifacts). Do not work around those guards.
- Fork and create a feature branch off
main. - Make your change with tests; run
./gradlew :odxtools-core:check. - Write a clear PR description. For behavior changes, state what upstream
Python
odxtoolsdoes and link the relevant upstream code if you can. - Keep PRs focused — one logical change per PR is much easier to review.
By contributing, you agree that your contributions are licensed under the project's MIT License.
- Regular bugs: open a GitHub issue using the provided template.
- Security vulnerabilities: please follow SECURITY.md instead of filing a public issue.