From 4e0944872c34c1c757a7a855aee8c6ad4748d6fa Mon Sep 17 00:00:00 2001 From: Jerry Combs Date: Wed, 7 Oct 2026 18:03:12 -0500 Subject: [PATCH] A blank driver starts with templates: a filter, shim settings with examples, configuration values Jerry: a driver made with the blank option lacked required elements, the filter for one. The blank driver now carries a starting filter (User and Group, the usual attributes synchronised both ways), shim settings with one example parameter in each section (driver, Subscriber, Publisher heartbeat interval) in the engine's definition form, and an empty configuration-values document, instead of an empty and bare option groups. Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 8 ++++ .../pointblue/dirxml/dev/edit/DriverOps.java | 46 +++++++++++++++++-- .../dirxml/dev/edit/DriverOpsTest.java | 17 +++++-- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f334284..4338492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html) ## [Unreleased] +### Changed + +- A blank driver (`driver.add --shim-class`) now starts with the documents the engine and + Designer expect, as templates: a filter with User and Group and the usual attributes + synchronised both ways, shim settings with one example parameter per section (driver, + Subscriber, Publisher heartbeat), and an empty configuration-values document — instead of an + empty `` and bare option groups. + ## [0.14.0] - 2026-10-07 ### Added diff --git a/src/main/java/com/pointblue/dirxml/dev/edit/DriverOps.java b/src/main/java/com/pointblue/dirxml/dev/edit/DriverOps.java index da84ebe..904b113 100644 --- a/src/main/java/com/pointblue/dirxml/dev/edit/DriverOps.java +++ b/src/main/java/com/pointblue/dirxml/dev/edit/DriverOps.java @@ -27,7 +27,10 @@ * artifacts the export carries are added to the tree's Library when absent * (matched by name; an existing one is kept as is); *
  • {@code --copy-of D}: a clone of an existing driver, links re-pointed;
  • - *
  • {@code --shim-class C}: a blank driver with an empty filter.
  • + *
  • {@code --shim-class C}: a blank driver with a starting filter (User and Group, the + * usual attributes synchronised both ways), shim settings with one example parameter per + * section, and an empty configuration-values document — every document the engine and + * Designer expect, as templates to edit rather than blanks to invent.
  • * * Package meta travels with the copied artifacts, so the deployer treats them as * packaged and the project writer will refuse a packaged driver. @@ -37,6 +40,41 @@ public final class DriverOps { private DriverOps() { } + /** A starting filter for a blank driver: User and Group, the usual attributes, synchronised both ways. */ + static final String BLANK_FILTER = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + /** Shim settings for a blank driver: the three sections, each with one example parameter in the engine's definition form. */ + static final String BLANK_SHIM_CONFIG = "" + + "" + + "" + + "A driver parameter the shim reads from its init document (replace or remove)." + + "" + + "" + + "" + + "A Subscriber channel parameter (replace or remove)." + + "" + + "" + + "" + + "Minutes of Publisher silence after which the shim sends a status document; 0 disables it.1" + + "" + + ""; + public static final class Add implements Operation { private final String name; private final Path export; @@ -113,10 +151,10 @@ public void apply(DriverSet ds, Transaction tx) throws Refusal, IOException { d.shimClass = shim; d.shimAuthServer = authServer; d.shimAuthId = authId; - d.config.put(Driver.DRIVER_FILTER, CanonicalXml.parse("").getDocumentElement()); + d.config.put(Driver.DRIVER_FILTER, CanonicalXml.parse(BLANK_FILTER).getDocumentElement()); d.config.put(Driver.SHIM_CONFIG_INFO, CanonicalXml.parse( - "") - .getDocumentElement()); + BLANK_SHIM_CONFIG.replace("%NAME%", name.replace("&", "&").replace("\"", """))).getDocumentElement()); + d.config.put(Driver.CONFIG_VALUES, CanonicalXml.parse("").getDocumentElement()); } if (ds.dn != null && !ds.dn.isBlank()) { d.dn = "cn=" + name + "," + ds.dn; diff --git a/src/test/java/com/pointblue/dirxml/dev/edit/DriverOpsTest.java b/src/test/java/com/pointblue/dirxml/dev/edit/DriverOpsTest.java index e17ccf3..9ddacf6 100644 --- a/src/test/java/com/pointblue/dirxml/dev/edit/DriverOpsTest.java +++ b/src/test/java/com/pointblue/dirxml/dev/edit/DriverOpsTest.java @@ -62,9 +62,20 @@ public void blankDriver() throws IOException { Driver d = AsCodeReader.read(tree).driver("Loop"); assertEquals("com.example.Loop", d.shimClass); assertEquals("svc", d.shimAuthId); - assertNotNull(d.config.get(Driver.DRIVER_FILTER)); - assertNotNull(d.config.get(Driver.SHIM_CONFIG_INFO)); - assertTrue(r.report.ok()); + // the templates: a starting filter, shim settings with an example per section, an empty configuration-values + org.w3c.dom.Element filter = d.config.get(Driver.DRIVER_FILTER); + assertNotNull(filter); + assertEquals(2, filter.getElementsByTagName("filter-class").getLength()); + assertEquals("User", ((org.w3c.dom.Element) filter.getElementsByTagName("filter-class").item(0)).getAttribute("class-name")); + assertTrue(filter.getElementsByTagName("filter-attr").getLength() >= 8); + org.w3c.dom.Element shim = d.config.get(Driver.SHIM_CONFIG_INFO); + assertNotNull(shim); + assertEquals("Loop", shim.getAttribute("name")); + assertEquals(3, shim.getElementsByTagName("definition").getLength()); + assertEquals(1, shim.getElementsByTagName("publisher-options").getLength()); + assertNotNull(d.config.get(Driver.CONFIG_VALUES)); + assertEquals("definitions", d.config.get(Driver.CONFIG_VALUES).getElementsByTagName("definitions").item(0).getNodeName()); + assertTrue(r.report.text(), r.report.ok()); assertTrue(run(new DriverOps.Add("Blank2", null, null, false, null, null, null)).refusal.contains("--shim-class")); }