Skip to content

Add an NRW Abitur version of the library - #36

Merged
mikebarkmin merged 1 commit into
mainfrom
ccr-3eca7a1f-ofkc4j
Sep 30, 2026
Merged

mikebarkmin merged 1 commit into
mainfrom
ccr-3eca7a1f-ofkc4j

Conversation

@mikebarkmin

@mikebarkmin mikebarkmin commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Courses in North Rhine-Westphalia use the classes of the Zentralabitur (List, Queue, Stack, Graph, …). They sit in the default package of the student's project, which a library can't reference by name. So find, getAll and getTouchingSprites could only return java.util.List, and this didn't compile:

List<Gegner> gegner = find(Gegner.class);
// error: incompatible types: java.util.List<Gegner> cannot be converted to List<Gegner>

What changes

There's now a second JAR. A course picks one by picking the JAR:

JAR find, getAll, getTouchingSprites return
scratch-<version>-all.jar java.util.List (unchanged)
scratch-<version>-nrw-all.jar the Abitur's List

The rest of the API is the same in both, and the normal JAR's API doesn't change.

How it works

  • Both versions in one source file: Java can't overload on return type, so Stage.java and Sprite.java hold both versions of each of the three methods. The NRW one sits in // nrw: comments between // nrw-standard-begin / // nrw-standard-end markers.
  • Building the NRW JAR: src/tools/java/variants/NrwVariant.java copies the sources and swaps the two versions. The new nrw Maven profile compiles that copy instead of src/main/java, so mvn clean package -Pall,nrw produces scratch-<version>-nrw-all.jar and -nrw-sources.jar. That build skips tests, examples and the reference docs, which are written for java.util.List.
  • At runtime: internal/NrwList looks up the class called List through the student's class loader. It creates one, fills it with append, and returns it as whatever type the student wrote on the left.
  • The Abiturklassen aren't bundled. The official files carry no licence. A bundled List would also clash with the copy teachers already put in the project, since a class in the project takes priority over an import. The student's own copy is always the one used.

Other changes

  • Release: release.yml builds the NRW JARs and attaches them to the GitHub release. Maven Central still gets only the normal version.

  • Docs: a new Abiturklassen NRW page covers:

    • which JAR to use;
    • project setup, including where to get the Abiturklassen;
    • examples for all three methods, plus a Queue example;
    • how it works;
    • common errors.

    It's linked from Setup and Download.

  • Build: pom.xml gets the nrw profile, and the shaded JAR's classifier is now configurable so the two fat JARs get different names.

  • CLAUDE.md: documents the new build command.

  • Changeset: minor.

Testing

  • mvn test: 184 tests pass. 2 are skipped because they need Java 25; they're unrelated to this change.
  • New NrwListTest covers the runtime lookup, including a missing List and a List without append.
  • New NrwVariantTest checks the rewrite. It also builds the NRW sources and compiles a student program against them, so a change that breaks the NRW version fails the normal test run.
  • Ran by hand under Xvfb with the unchanged official Abiturklassen and the NRW fat JAR:
    • find, getAll and getTouchingSprites returned the official List with the right sprites.
    • Queue, Stack and Graph work alongside the library with every extension package imported, with no name clashes.
  • Against the normal JAR, the same project fails only on those three lines, as expected.
  • Every code example on the new docs page compiles against the JAR it's written for.

Not tested: the release workflow change, which first runs on the next release, and running inside BlueJ itself.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KLR5H7eqDSncYYkosKf8r5

Courses in North Rhine-Westphalia work with the classes of the Zentralabitur,
whose List sits in the default package of the student's project. A library
cannot name that class, so find, getAll and getTouchingSprites could only ever
hand out java.util.List, and List<Gegner> gegner = find(Gegner.class) did not
compile.

There is now a second JAR for these courses. mvn clean package -Pall,nrw builds
scratch-<version>-nrw-all.jar, in which those three methods return the
Abitur's List:

  List<Gegner> gegner = find(Gegner.class);

The normal JAR is unchanged.

Java cannot overload on the return type, so both versions of each method live
in Stage.java and Sprite.java, the NRW one in "// nrw:" comments.
src/tools/java/variants/NrwVariant.java swaps them into a copy of the sources,
which the nrw profile compiles in place of src/main/java. At run time,
internal/NrwList looks up the student's List through their class loader, fills
it with append, and returns it as whatever type the assignment asks for. The
Abiturklassen themselves are not bundled: they carry no licence, and a bundled
List would clash with the copy teachers already put into the project.

The release workflow attaches the NRW JARs to the GitHub release. The docs gain
an Abiturklassen NRW page (setup, usage, how it works, troubleshooting), with
links from Setup and Download. A test builds the NRW sources and compiles a
student program against them, so the NRW JAR cannot break unnoticed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLR5H7eqDSncYYkosKf8r5
@mikebarkmin mikebarkmin changed the title Return the NRW Abitur List from find, getAll and getTouchingSprites Add an NRW Abitur version of the library Sep 30, 2026

@mikebarkmin mikebarkmin left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mikebarkmin
mikebarkmin merged commit b7a13e0 into main Sep 30, 2026
2 checks passed
mikebarkmin added a commit that referenced this pull request Sep 30, 2026
Fix the release workflow broken by #36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants