You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/06/11 12:45:15 UTC

[isis] branch ISIS-2732 updated (630bfc6 -> 96f8a77)

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a change to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git.


 discard 630bfc6  ISIS-2732: updates documentation (refguide index)
 discard 7f0c0b8  ISIS-2732: adds docs on mocking clock and user
 discard e5d451e  ISIS-2732: deletes fixture library's Clock
 discard 473ddaa  ISIS-2732: deletes FixtureClock
 discard 66cdd01  ISIS-2732: renames FixturesLifecycleService to InitialFixtureScriptsInstaller
 discard b9b2f25  ISIS-2732: simplifies FixturesLifecycleService
 discard ee03db1  ISIS-2732: deletes TickingFixtureClock, ClockFixture, TickingClockFixture
 discard fc6fcf6  ISIS-2732: removes methods to set clock from IsisIntegrationTestAbstractWithFixtures
     add 3296777  Merge pull request #602 from apache/ISIS-2726
     new 535548d  ISIS-2732: removes methods to set clock from IsisIntegrationTestAbstractWithFixtures
     new a3d9f70  ISIS-2732: deletes TickingFixtureClock, ClockFixture, TickingClockFixture
     new 5c8e643  ISIS-2732: simplifies FixturesLifecycleService
     new d1a5cf1  ISIS-2732: renames FixturesLifecycleService to InitialFixtureScriptsInstaller
     new 7b1efa1  ISIS-2732: deletes FixtureClock
     new 3f98ae5  ISIS-2732: deletes fixture library's Clock
     new 3974829  ISIS-2732: adds docs on mocking clock and user
     new 96f8a77  ISIS-2732: updates documentation (refguide index)

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (630bfc6)
            \
             N -- N -- N   refs/heads/ISIS-2732 (96f8a77)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:

[isis] 02/08: ISIS-2732: deletes TickingFixtureClock, ClockFixture, TickingClockFixture

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit a3d9f70f50e2401bd862e2db711e4dd8294c605b
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 11:53:22 2021 +0100

    ISIS-2732: deletes TickingFixtureClock, ClockFixture, TickingClockFixture
---
 .../2018/2.0.0-M1/mignotes/legacy-modules.adoc     |   4 +-
 .../fixtures/applib/clock/ClockFixture.java        | 126 --------------
 .../fixtures/applib/clock/TickingClockFixture.java | 142 ----------------
 .../applib/clock/clock/TickingFixtureClock.java    | 184 ---------------------
 4 files changed, 2 insertions(+), 454 deletions(-)

diff --git a/antora/components/relnotes/modules/ROOT/pages/2018/2.0.0-M1/mignotes/legacy-modules.adoc b/antora/components/relnotes/modules/ROOT/pages/2018/2.0.0-M1/mignotes/legacy-modules.adoc
index b4737e0..120f955 100644
--- a/antora/components/relnotes/modules/ROOT/pages/2018/2.0.0-M1/mignotes/legacy-modules.adoc
+++ b/antora/components/relnotes/modules/ROOT/pages/2018/2.0.0-M1/mignotes/legacy-modules.adoc
@@ -59,11 +59,11 @@ fixtures`
 
 
 |`DateFixture`
-|Use `TickingClockFixture` instead
+|Use `SudoService` instead
 
 
 |`SwitchUserFixture`
-|Use fixture with injected `SudoService` instead
+|Use `SudoService` instead
 
 
 .2+|o.a.i.applib.
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/ClockFixture.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/ClockFixture.java
deleted file mode 100644
index 419b481..0000000
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/ClockFixture.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.testing.fixtures.applib.clock;
-
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScriptWithExecutionStrategy;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
-import org.apache.isis.testing.fixtures.applib.clock.clock.Clock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.FixtureClock;
-
-@Programmatic
-class ClockFixture extends FixtureScript implements FixtureScriptWithExecutionStrategy {
-
-    static ClockFixture setTo(final String date) {
-        return new ClockFixture().setDate(date);
-    }
-
-    ClockFixture() {
-        super(null, "clock");
-    }
-
-    private String date;
-
-    public String getDate() {
-        return date;
-    }
-
-    public ClockFixture setDate(final String date) {
-        this.date = date;
-        return this;
-    }
-
-    @Override
-    protected void execute(ExecutionContext ec) {
-
-        // can only be used in the context of integration tests
-        if (!(Clock.getInstance() instanceof FixtureClock)) {
-            throw new IllegalStateException("Clock has not been initialized as a FixtureClock");
-        }
-        final FixtureClock fixtureClock = (FixtureClock) FixtureClock.getInstance();
-
-        // check that some value has been set
-        checkParam("date", ec, String.class);
-
-        // process if can be parsed as a LocalDateTime
-        LocalDateTime ldt = parseAsLocalDateTime(date);
-        if (ldt != null) {
-            fixtureClock.setDate(ldt.getYear(), ldt.getMonthOfYear(), ldt.getDayOfMonth());
-            fixtureClock.setTime(ldt.getHourOfDay(), ldt.getMinuteOfHour());
-            return;
-        }
-
-        // else process if can be parsed as a LocalDate
-        LocalDate ld = parseAsLocalDate(date);
-        if (ld != null) {
-            fixtureClock.setDate(ld.getYear(), ld.getMonthOfYear(), ld.getDayOfMonth());
-            return;
-        }
-
-        // else
-        throw new IllegalArgumentException(String.format(
-                "'%s' could not be parsed as a local date/time or local date", date));
-    }
-
-    private static LocalDate parseAsLocalDate(String dateStr) {
-        for (DateTimeFormatter formatter : new DateTimeFormatter[] {
-                DateTimeFormat.fullDateTime(),
-                DateTimeFormat.mediumDateTime(),
-                DateTimeFormat.shortDateTime(),
-                DateTimeFormat.forPattern("yyyy-MM-dd"),
-                DateTimeFormat.forPattern("yyyyMMdd"),
-        }) {
-            try {
-                return formatter.parseLocalDate(dateStr);
-            } catch (Exception e) {
-                // continue;
-            }
-        }
-        return null;
-    }
-
-    private static LocalDateTime parseAsLocalDateTime(String dateStr) {
-        for (DateTimeFormatter formatter : new DateTimeFormatter[] {
-                DateTimeFormat.fullDateTime(),
-                DateTimeFormat.mediumDateTime(),
-                DateTimeFormat.shortDateTime(),
-                DateTimeFormat.forPattern("yyyyMMddhhmmss"),
-                DateTimeFormat.forPattern("yyyyMMddhhmm")
-        }) {
-            try {
-                return formatter.parseLocalDateTime(dateStr);
-            } catch (Exception e) {
-                // continue;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public FixtureScripts.MultipleExecutionStrategy getMultipleExecutionStrategy() {
-        return FixtureScripts.MultipleExecutionStrategy.EXECUTE;
-    }
-
-}
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/TickingClockFixture.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/TickingClockFixture.java
deleted file mode 100644
index 80991af..0000000
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/TickingClockFixture.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.testing.fixtures.applib.clock;
-
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.joda.time.format.DateTimeFormat;
-import org.joda.time.format.DateTimeFormatter;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScriptWithExecutionStrategy;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
-import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
-import org.apache.isis.testing.fixtures.applib.clock.clock.Clock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.FixtureClock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.TickingFixtureClock;
-
-/**
- * @since 2.x {@index}
- */
-@Programmatic
-public class TickingClockFixture
-extends FixtureScript
-implements FixtureScriptWithExecutionStrategy {
-
-    // -- date property
-    private String date;
-    public String getDate() {
-        return date;
-    }
-    public TickingClockFixture setDate(final String date) {
-        this.date = date;
-        return this;
-    }
-
-
-    @Override
-    protected void execute(ExecutionContext ec) {
-
-        // check that some value has been set
-        checkParam("date", ec, String.class);
-
-        final Clock instance = Clock.getInstance();
-
-        if(instance instanceof TickingFixtureClock) {
-            try {
-                TickingFixtureClock.reinstateExisting();
-                setTo(date);
-            } finally {
-                TickingFixtureClock.replaceExisting();
-            }
-        }
-
-        if(instance instanceof FixtureClock) {
-            setTo(date);
-        }
-    }
-
-    private void setTo(final String date) {
-
-        if (!(Clock.getInstance() instanceof FixtureClock)) {
-            throw new IllegalStateException("Clock has not been initialized as a FixtureClock");
-        }
-        final FixtureClock fixtureClock = (FixtureClock) FixtureClock.getInstance();
-
-        // process if can be parsed as a LocalDateTime
-        LocalDateTime ldt = parseAsLocalDateTime(date);
-        if (ldt != null) {
-            fixtureClock.setDate(ldt.getYear(), ldt.getMonthOfYear(), ldt.getDayOfMonth());
-            fixtureClock.setTime(ldt.getHourOfDay(), ldt.getMinuteOfHour());
-            return;
-        }
-
-        // else process if can be parsed as a LocalDate
-        LocalDate ld = parseAsLocalDate(date);
-        if (ld != null) {
-            fixtureClock.setDate(ld.getYear(), ld.getMonthOfYear(), ld.getDayOfMonth());
-            return;
-        }
-
-        // else
-        throw new IllegalArgumentException(String.format(
-                "'%s' could not be parsed as a local date/time or local date", date));
-
-    }
-
-    private static LocalDate parseAsLocalDate(String dateStr) {
-        for (DateTimeFormatter formatter : new DateTimeFormatter[] {
-                DateTimeFormat.fullDateTime(),
-                DateTimeFormat.mediumDateTime(),
-                DateTimeFormat.shortDateTime(),
-                DateTimeFormat.forPattern("yyyy-MM-dd"),
-                DateTimeFormat.forPattern("yyyyMMdd"),
-        }) {
-            try {
-                return formatter.parseLocalDate(dateStr);
-            } catch (Exception e) {
-                // continue;
-            }
-        }
-        return null;
-    }
-
-    private static LocalDateTime parseAsLocalDateTime(String dateStr) {
-        for (DateTimeFormatter formatter : new DateTimeFormatter[] {
-                DateTimeFormat.fullDateTime(),
-                DateTimeFormat.mediumDateTime(),
-                DateTimeFormat.shortDateTime(),
-                DateTimeFormat.forPattern("yyyyMMddhhmmss"),
-                DateTimeFormat.forPattern("yyyyMMddhhmm")
-        }) {
-            try {
-                return formatter.parseLocalDateTime(dateStr);
-            } catch (Exception e) {
-                // continue;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public FixtureScripts.MultipleExecutionStrategy getMultipleExecutionStrategy() {
-        return FixtureScripts.MultipleExecutionStrategy.EXECUTE;
-    }
-
-}
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/TickingFixtureClock.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/TickingFixtureClock.java
deleted file mode 100644
index 6e8100d..0000000
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/TickingFixtureClock.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.testing.fixtures.applib.clock.clock;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * @since 2.x {@index}
- */
-public class TickingFixtureClock extends Clock {
-    private static final TimeZone UTC_TIME_ZONE;
-
-    static {
-        TimeZone tempTimeZone = TimeZone.getTimeZone("Etc/UTC");
-        if (tempTimeZone == null) {
-            tempTimeZone = TimeZone.getTimeZone("UTC");
-        }
-        UTC_TIME_ZONE = tempTimeZone;
-    }
-
-
-    static Clock existingInstance;
-
-    /**
-     * Configures the system to use a FixtureClock rather than the in-built
-     * system clock. Can be called multiple times.
-     *
-     * <p>
-     * Must call before any other call to {@link Clock#getInstance()}.
-     *
-     * @throws IllegalStateException
-     *             if Clock singleton already initialized with some other
-     *             implementation.
-     */
-    public synchronized static TickingFixtureClock replaceExisting() {
-        final Clock instance = getInstance();
-        if (instance instanceof TickingFixtureClock) {
-            return (TickingFixtureClock) instance;
-        }
-
-        final long time = Clock.getEpochMillis();
-        existingInstance = Clock.instance;
-
-        // installs as the singleton
-        Clock.remove();
-
-        return new TickingFixtureClock(time);
-    }
-
-    /**
-     * Makes {@link Clock#remove()} visible.
-     */
-    public static boolean reinstateExisting() {
-        Clock.instance = existingInstance;
-        return true;
-    }
-
-
-
-    private final Calendar calendar = Calendar.getInstance();
-    private long t0 = 0L;
-
-    private TickingFixtureClock(final long time) {
-        calendar.setTimeZone(UTC_TIME_ZONE);
-        calendar.setTimeInMillis(time);
-
-        t0 = System.currentTimeMillis();
-    }
-
-    private long getOffset() {
-        return System.currentTimeMillis() - t0;
-    }
-
-
-    /**
-     * Access via {@link Clock#getTime()}.
-     *
-     * <p>
-     * Will just return the system time until {@link #setDate(int, int, int)} or
-     * {@link #setTime(int, int)} (or one of the overloads) has been called.
-     */
-    @Override
-    protected Instant now() {
-        return Instant.ofEpochMilli(calendar.getTime().getTime() + getOffset());
-    }
-
-    // //////////////////////////////////////////////////
-    // setting/adjusting time
-    // //////////////////////////////////////////////////
-
-    /**
-     * Sets the hours and minutes as specified, and sets the seconds and
-     * milliseconds to zero, but the date portion is left unchanged.
-     *
-     * @see #setDate(int, int, int)
-     * @see #addTime(int, int)
-     */
-    public void setTime(final int hour, final int min) {
-        calendar.set(Calendar.HOUR_OF_DAY, hour);
-        calendar.set(Calendar.MINUTE, min);
-        calendar.set(Calendar.SECOND, 0);
-        calendar.set(Calendar.MILLISECOND, 0);
-        t0 = System.currentTimeMillis();
-    }
-
-    public void setTime(final Timestamp timestamp) {
-        setTime(timestamp.getTime());
-    }
-
-    public void setTime(final long millis) {
-        calendar.setTimeInMillis(millis);
-        t0 = System.currentTimeMillis();
-    }
-
-    /**
-     * Sets the date, but the time portion is left unchanged.
-     *
-     * @see #setTime(int, int)
-     * @see #addDate(int, int, int)
-     */
-    public void setDate(final int year, final int month, final int day) {
-        calendar.set(Calendar.YEAR, year);
-        calendar.set(Calendar.MONTH, month - 1);
-        calendar.set(Calendar.DAY_OF_MONTH, day);
-
-        t0 = System.currentTimeMillis();
-    }
-
-    /**
-     * Adjusts the time by the specified number of hours and minutes.
-     *
-     * <p>
-     * Typically called after {@link #setTime(int, int)}, to move the clock
-     * forward or perhaps back.
-     *
-     * @see #addDate(int, int, int)
-     */
-    public void addTime(final int hours, final int minutes) {
-        calendar.add(Calendar.HOUR_OF_DAY, hours);
-        calendar.add(Calendar.MINUTE, minutes);
-    }
-
-    /**
-     * Adjusts the time by the specified number of years, months or days.
-     *
-     * <p>
-     * Typically called after {@link #setDate(int, int, int)}, to move the clock
-     * forward or perhaps back.
-     *
-     * @see #addTime(int, int)
-     */
-    public void addDate(final int years, final int months, final int days) {
-        calendar.add(Calendar.YEAR, years);
-        calendar.add(Calendar.MONTH, months);
-        calendar.add(Calendar.DAY_OF_MONTH, days);
-    }
-
-
-
-    @Override
-    public String toString() {
-        return Clock.getTimeAsOffsetDateTime().toString();
-    }
-
-}

[isis] 08/08: ISIS-2732: updates documentation (refguide index)

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 96f8a77cabba5fb896bfa5c8b3d42de0c4efd37f
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 13:30:46 2021 +0100

    ISIS-2732: updates documentation (refguide index)
---
 .../applib/pages/index/clock/VirtualClock.adoc     |   2 +-
 .../pages/index/services/clock/ClockService.adoc   |   4 +-
 .../services/command/CommandExecutorService.adoc   |  58 ++++++++--
 ...ndExecutorService~InteractionContextPolicy.adoc |  54 ++++++++++
 .../services/command/CommandOutcomeHandler.adoc    |  54 +++++++++-
 .../index/services/iactn/InteractionProvider.adoc  |   3 +-
 .../services/iactnlayer/InteractionContext.adoc    |  82 +++++++++++----
 .../iactnlayer/InteractionLayerTracker.adoc        |  44 ++++++++
 .../services/iactnlayer/InteractionService.adoc    |  34 ++++--
 .../queryresultscache/QueryResultsCache.adoc       |  19 ++--
 .../pages/index/services/sudo/SudoService.adoc     |  10 +-
 .../pages/index/services/user/UserMemento.adoc     |  32 +++---
 .../pages/index/services/user/UserService.adoc     |  96 +++++++++--------
 .../interaction/session/InteractionFactory.adoc    |  60 -----------
 .../transaction/TransactionServiceSpring.adoc      |   2 +-
 .../security/authentication/Authentication.adoc    | 100 ------------------
 .../authentication/AuthenticationRequest.adoc      |   2 +-
 .../security/authentication/Authenticator.adoc     |  20 ++--
 .../manager/AnonymousInteractionFactory.adoc       |  51 ---------
 .../index/security/authorization/Authorizor.adoc   |  26 ++---
 .../manager/AuthorizationManager.adoc              |  16 +--
 .../commandreplay/secondary/SecondaryStatus.adoc   |   2 -
 .../secondary/clock/TickingClockService.adoc       |  48 ---------
 .../executor/CommandExecutorServiceWithTime.adoc   |  21 ----
 .../authenticator/AuthenticatorSecman.adoc         |   4 +-
 .../integration/authorizor/AuthorizorSecman.adoc   |   4 +-
 .../bypass/authorization/AuthorizorBypass.adoc     |   4 +-
 .../authentication/AuthenticatorKeycloak.adoc      |   4 +-
 .../shiro/authentication/AuthenticatorShiro.adoc   |   6 +-
 .../index/shiro/authorization/AuthorizorShiro.adoc |   4 +-
 .../spring/authentication/AuthenticatorSpring.adoc |   4 +-
 .../pages/index/docx/applib/DocxService.adoc       |  10 +-
 ...efinition.adoc => DocxService~MergeParams.adoc} |   6 +-
 .../fixtures/applib/clock/TickingClockFixture.adoc |  15 ---
 .../index/fixtures/applib/clock/clock/Clock.adoc   |  80 --------------
 .../fixtures/applib/clock/clock/FixtureClock.adoc  | 117 ---------------------
 .../applib/clock/clock/TickingFixtureClock.adoc    |  89 ----------------
 ...ce.adoc => InitialFixtureScriptsInstaller.adoc} |   9 +-
 .../restfulobjects/rendering/IResourceContext.adoc |   5 +-
 .../webmodule/auth/AuthenticationStrategy.adoc     |  20 ++--
 .../auth/AuthenticationStrategyBasicAuth.adoc      |   6 +-
 .../auth/AuthenticationStrategyDefault.adoc        |   6 +-
 core/adoc/modules/_overview/pages/about.adoc       |  29 ++---
 43 files changed, 463 insertions(+), 799 deletions(-)

diff --git a/antora/components/refguide-index/modules/applib/pages/index/clock/VirtualClock.adoc b/antora/components/refguide-index/modules/applib/pages/index/clock/VirtualClock.adoc
index 49ce87c..d7f742d 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/clock/VirtualClock.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/clock/VirtualClock.adoc
@@ -1,7 +1,7 @@
 = VirtualClock _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Works in connection with _org.apache.isis.core.interaction.session.InteractionFactory_ , such that it allows an xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] to run with its own simulated (or actual) time.
+Works in connection with xref:refguide:applib:index/services/iactnlayer/InteractionService.adoc[InteractionService] , such that it allows an xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] to run with its own simulated (or actual) time.
 
 == API
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/clock/ClockService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/clock/ClockService.adoc
index 7a60976..ee09f83 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/clock/ClockService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/clock/ClockService.adoc
@@ -1,4 +1,4 @@
-= ClockService _(interface)_
+= ClockService
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 This service allows an application to be decoupled from the system time. The most common use case is in support of testing scenarios, to "mock the clock". Use of this service also opens up the use of centralized co-ordinated time management through a centralized time service.
@@ -8,7 +8,7 @@ This service allows an application to be decoupled from the system time. The mos
 [source,java]
 .ClockService.java
 ----
-interface ClockService {
+class ClockService {
   VirtualClock getClock()
   long getEpochMillis()
 }
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
index cdbdd59..6ed8dc3 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
@@ -1,31 +1,71 @@
 = CommandExecutorService _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
+Provides a mechanism to execute a xref:refguide:applib:index/services/command/Command.adoc[Command] .
+
 == API
 
 [source,java]
 .CommandExecutorService.java
 ----
 interface CommandExecutorService {
-  Bookmark executeCommand(SudoPolicy sudoPolicy, Command command)     // <.>
-  Bookmark executeCommand(SudoPolicy sudoPolicy, CommandDto commandDto, CommandOutcomeHandler outcomeHandler)
-  Bookmark executeCommand(Command command)
-  Bookmark executeCommand(CommandDto commandDto, CommandOutcomeHandler outcomeHandler)
+  Bookmark executeCommand(InteractionContextPolicy interactionContextPolicy, Command command)     // <.>
+  Bookmark executeCommand(InteractionContextPolicy interactionContextPolicy, CommandDto commandDto, CommandOutcomeHandler outcomeHandler)     // <.>
+  Bookmark executeCommand(Command command)     // <.>
+  Bookmark executeCommand(CommandDto commandDto, CommandOutcomeHandler outcomeHandler)     // <.>
 }
 ----
 
-<.> xref:#executeCommand__SudoPolicy_Command[executeCommand(SudoPolicy, Command)]
+<.> xref:#executeCommand__InteractionContextPolicy_Command[executeCommand(InteractionContextPolicy, Command)]
++
+--
+Executes the specified xref:refguide:applib:index/services/command/Command.adoc[Command] using the required _InteractionContextPolicy_ , updating the Command (or its persistent equivalent) afterwards (for example, setting its _Command#getCommandDto() commandDto_ field.
+--
+<.> xref:#executeCommand__InteractionContextPolicy_CommandDto_CommandOutcomeHandler[executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)]
++
+--
+Executes the specified command (represented as a _CommandDto_ using the required _InteractionContextPolicy_ .
+--
+<.> xref:#executeCommand__Command[executeCommand(Command)]
++
+--
+As per _#executeCommand(InteractionContextPolicy, Command)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
+--
+<.> xref:#executeCommand__CommandDto_CommandOutcomeHandler[executeCommand(CommandDto, CommandOutcomeHandler)]
 +
 --
-Executes the specified command.
+As per _#executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
 --
 
 == Members
 
-[#executeCommand__SudoPolicy_Command]
-=== executeCommand(SudoPolicy, Command)
+[#executeCommand__InteractionContextPolicy_Command]
+=== executeCommand(InteractionContextPolicy, Command)
+
+Executes the specified xref:refguide:applib:index/services/command/Command.adoc[Command] using the required _InteractionContextPolicy_ , updating the Command (or its persistent equivalent) afterwards (for example, setting its _Command#getCommandDto() commandDto_ field.
+
+[#executeCommand__InteractionContextPolicy_CommandDto_CommandOutcomeHandler]
+=== executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)
+
+Executes the specified command (represented as a _CommandDto_ using the required _InteractionContextPolicy_ .
+
+IMPORTANT: THIS METHOD HAS SIGNIFICANT SIDE-EFFECTS. Specifically, the xref:refguide:applib:index/services/command/Command.adoc[Command] of the executing thread (obtained using _org.apache.isis.applib.services.iactn.InteractionProvider_ to obtain the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] , and then _Interaction#getCommand()_ to obtain the xref:refguide:applib:index/services/command/Command.adoc[Command] ) will be UPDATED to hold the _CommandDto_ passed in.
+
+Optionally an xref:refguide:applib:index/services/command/CommandOutcomeHandler.adoc[CommandOutcomeHandler] can be provided to process the result. This is used by the persistent implementations to update their respective persistent equivalents of xref:refguide:applib:index/services/command/Command.adoc[Command] .
+
+[#executeCommand__Command]
+=== executeCommand(Command)
+
+As per _#executeCommand(InteractionContextPolicy, Command)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
+
+Note that this method updates the Command as a side-effect.
+
+[#executeCommand__CommandDto_CommandOutcomeHandler]
+=== executeCommand(CommandDto, CommandOutcomeHandler)
+
+As per _#executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
 
-Executes the specified command.
+Note that this method has significant side-effects.
 
 include::hooks/CommandExecutorService_010-implementation.adoc[]
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService~InteractionContextPolicy.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService~InteractionContextPolicy.adoc
new file mode 100644
index 0000000..559ba54
--- /dev/null
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService~InteractionContextPolicy.adoc
@@ -0,0 +1,54 @@
+= CommandExecutorService.InteractionContextPolicy _(enum)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Determines the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] (the "who" "when" and "where") within which the xref:refguide:applib:index/services/command/Command.adoc[Command] should be executed.
+
+== API
+
+[source,java]
+.CommandExecutorService~InteractionContextPolicy.java
+----
+enum InteractionContextPolicy {
+  NO_SWITCH     // <.>
+  SWITCH_USER_ONLY     // <.>
+  SWITCH_USER_AND_TIME     // <.>
+  public final BiFunction<InteractionContext, CommandDto, InteractionContext> mapper;
+}
+----
+
+<.> xref:#NO_SWITCH[NO_SWITCH]
++
+--
+Execute within the same xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] as the thread calling the xref:refguide:applib:index/services/command/CommandExecutorService.adoc[CommandExecutorService] .
+--
+<.> xref:#SWITCH_USER_ONLY[SWITCH_USER_ONLY]
++
+--
+Execute using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , with the apparent user being taken from the xref:refguide:applib:index/services/command/Command.adoc[Command] .
+--
+<.> xref:#SWITCH_USER_AND_TIME[SWITCH_USER_AND_TIME]
++
+--
+Execute using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , with the apparent user and time being taken from the xref:refguide:applib:index/services/command/Command.adoc[Command] .
+--
+
+== Members
+
+[#NO_SWITCH]
+=== NO_SWITCH
+
+Execute within the same xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] as the thread calling the xref:refguide:applib:index/services/command/CommandExecutorService.adoc[CommandExecutorService] .
+
+For example, regular background commands.
+
+[#SWITCH_USER_ONLY]
+=== SWITCH_USER_ONLY
+
+Execute using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , with the apparent user being taken from the xref:refguide:applib:index/services/command/Command.adoc[Command] .
+
+[#SWITCH_USER_AND_TIME]
+=== SWITCH_USER_AND_TIME
+
+Execute using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , with the apparent user and time being taken from the xref:refguide:applib:index/services/command/Command.adoc[Command] .
+
+For example, replayable commands.
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandOutcomeHandler.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandOutcomeHandler.adoc
index f1114c7..76164b6 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandOutcomeHandler.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandOutcomeHandler.adoc
@@ -1,6 +1,8 @@
 = CommandOutcomeHandler _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
+Used by xref:refguide:applib:index/services/command/CommandExecutorService.adoc[CommandExecutorService] , to update a xref:refguide:applib:index/services/command/Command.adoc[Command] after it has been executed.
+
 == API
 
 [source,java]
@@ -8,10 +10,54 @@
 ----
 interface CommandOutcomeHandler {
   CommandOutcomeHandler NULL;
-  Timestamp getStartedAt()
-  void setStartedAt(Timestamp startedAt)
-  void setCompletedAt(Timestamp completedAt)
-  void setResult(Result<Bookmark> resultBookmark)
+  Timestamp getStartedAt()     // <.>
+  void setStartedAt(Timestamp startedAt)     // <.>
+  void setCompletedAt(Timestamp completedAt)     // <.>
+  void setResult(Result<Bookmark> resultBookmark)     // <.>
 }
 ----
 
+<.> xref:#getStartedAt__[getStartedAt()]
++
+--
+Reads the `startedAt` field from the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+--
+<.> xref:#setStartedAt__Timestamp[setStartedAt(Timestamp)]
++
+--
+Sets the `startedAt` field on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+--
+<.> xref:#setCompletedAt__Timestamp[setCompletedAt(Timestamp)]
++
+--
+Sets the `completedAt` field on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+--
+<.> xref:#setResult__Result[setResult(Result)]
++
+--
+Sets the result of the execute, represented as a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark] , on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent).
+--
+
+== Members
+
+[#getStartedAt__]
+=== getStartedAt()
+
+Reads the `startedAt` field from the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+
+This is to ensure that it isn't overwritten by _#setStartedAt(Timestamp)_ .
+
+[#setStartedAt__Timestamp]
+=== setStartedAt(Timestamp)
+
+Sets the `startedAt` field on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+
+[#setCompletedAt__Timestamp]
+=== setCompletedAt(Timestamp)
+
+Sets the `completedAt` field on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent)
+
+[#setResult__Result]
+=== setResult(Result)
+
+Sets the result of the execute, represented as a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark] , on the underlying xref:refguide:applib:index/services/command/Command.adoc[Command] (or persistent equivalent).
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/iactn/InteractionProvider.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/iactn/InteractionProvider.adoc
index 1c6b2ce..3973521 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/iactn/InteractionProvider.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/iactn/InteractionProvider.adoc
@@ -15,8 +15,9 @@ interface InteractionProvider {
   Optional<Interaction> currentInteraction()     // <.>
   Optional<InteractionContext> currentInteractionContext()     // <.>
   Optional<UUID> getInteractionId()     // <.>
-  Interaction currentInteractionElseFail()
   int getInteractionLayerCount()     // <.>
+  Interaction currentInteractionElseFail()
+  InteractionContext currentInteractionContextElseFail()
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionContext.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionContext.adoc
index c2a711d..df05bf1 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionContext.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionContext.adoc
@@ -9,43 +9,87 @@ Provides the user and scenario specific environment for an xref:refguide:applib:
 .InteractionContext.java
 ----
 class InteractionContext {
-  void putAttribute(String key, Serializable value)
-  Optional<T> getAttribute(String key, Class<T> castTo)
-  boolean equals(Object o)     // <.>
-  int hashCode()     // <.>
   InteractionContext ofUserWithSystemDefaults(final UserMemento user)     // <.>
+  UnaryOperator<InteractionContext> switchUser(final UserMemento userMemento)     // <.>
+  UnaryOperator<InteractionContext> switchClock(final VirtualClock clock)     // <.>
+  UnaryOperator<InteractionContext> switchLocale(final Locale locale)     // <.>
+  UnaryOperator<InteractionContext> switchTimeZone(final TimeZone timeZone)     // <.>
+  UnaryOperator<T> combine(UnaryOperator<T>... mappers)     // <.>
+  UnaryOperator<T> combine(Stream<UnaryOperator<T>> mappers)     // <.>
 }
 ----
 
-<.> xref:#equals__Object[equals(Object)]
+<.> xref:#ofUserWithSystemDefaults__UserMemento[ofUserWithSystemDefaults(UserMemento)]
 +
 --
-We exclude _#attributes_ .
+Creates a new xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] with the specified user and system defaults for clock, locale and time-zone.
 --
-<.> xref:#hashCode__[hashCode()]
+<.> xref:#switchUser__UserMemento[switchUser(UserMemento)]
 +
 --
-We exclude _#attributes_ .
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified xref:refguide:applib:index/services/user/UserMemento.adoc[UserMemento] .
 --
-<.> xref:#ofUserWithSystemDefaults__UserMemento[ofUserWithSystemDefaults(UserMemento)]
+<.> xref:#switchClock__VirtualClock[switchClock(VirtualClock)]
 +
 --
-Creates a new xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] with the specified user and system defaults for clock, locale and time-zone.
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified xref:refguide:applib:index/clock/VirtualClock.adoc[VirtualClock] .
+--
+<.> xref:#switchLocale__Locale[switchLocale(Locale)]
++
+--
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified _Locale_ .
+--
+<.> xref:#switchTimeZone__TimeZone[switchTimeZone(TimeZone)]
++
+--
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified _TimeZone_ .
+--
+<.> xref:#combine__UnaryOperator[combine(UnaryOperator)]
++
+--
+Convenience method to combine _UnaryOperator_ s, for example as per _#switchUser(UserMemento)_ and _#switchTimeZone(TimeZone)_ .
+--
+<.> xref:#combine__Stream[combine(Stream)]
++
+--
+Convenience method to combine _UnaryOperator_ s, for example as per _#switchUser(UserMemento)_ and _#switchTimeZone(TimeZone)_ . credit: https://stackoverflow.com/a/51065029/56880
 --
 
 == Members
 
-[#equals__Object]
-=== equals(Object)
+[#ofUserWithSystemDefaults__UserMemento]
+=== ofUserWithSystemDefaults(UserMemento)
 
-We exclude _#attributes_ .
+Creates a new xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] with the specified user and system defaults for clock, locale and time-zone.
 
-[#hashCode__]
-=== hashCode()
+[#switchUser__UserMemento]
+=== switchUser(UserMemento)
 
-We exclude _#attributes_ .
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified xref:refguide:applib:index/services/user/UserMemento.adoc[UserMemento] .
 
-[#ofUserWithSystemDefaults__UserMemento]
-=== ofUserWithSystemDefaults(UserMemento)
+[#switchClock__VirtualClock]
+=== switchClock(VirtualClock)
 
-Creates a new xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] with the specified user and system defaults for clock, locale and time-zone.
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified xref:refguide:applib:index/clock/VirtualClock.adoc[VirtualClock] .
+
+[#switchLocale__Locale]
+=== switchLocale(Locale)
+
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified _Locale_ .
+
+[#switchTimeZone__TimeZone]
+=== switchTimeZone(TimeZone)
+
+Convenience method for use with _org.apache.isis.applib.services.sudo.SudoService_ , returning a _UnaryOperator_ that will act upon the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to return the same but with the specified _TimeZone_ .
+
+[#combine__UnaryOperator]
+=== combine(UnaryOperator)
+
+Convenience method to combine _UnaryOperator_ s, for example as per _#switchUser(UserMemento)_ and _#switchTimeZone(TimeZone)_ .
+
+NOTE: this implementation can result in heap pollution; better to use the _#combine(Stream) overload_ .
+
+[#combine__Stream]
+=== combine(Stream)
+
+Convenience method to combine _UnaryOperator_ s, for example as per _#switchUser(UserMemento)_ and _#switchTimeZone(TimeZone)_ . credit: https://stackoverflow.com/a/51065029/56880
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionLayerTracker.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionLayerTracker.adoc
new file mode 100644
index 0000000..7463995
--- /dev/null
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionLayerTracker.adoc
@@ -0,0 +1,44 @@
+= InteractionLayerTracker _(interface)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Provides access to the current xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] .
+
+== API
+
+[source,java]
+.InteractionLayerTracker.java
+----
+interface InteractionLayerTracker {
+  Optional<InteractionLayer> currentInteractionLayer()     // <.>
+  InteractionLayer currentInteractionLayerElseFail()
+  Optional<InteractionContext> currentInteractionContext()     // <.>
+  Optional<Interaction> currentInteraction()     // <.>
+}
+----
+
+<.> xref:#currentInteractionLayer__[currentInteractionLayer()]
+<.> xref:#currentInteractionContext__[currentInteractionContext()]
++
+--
+Returns the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] wrapped by the _#currentInteractionLayer()_ (if within an xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] ).
+--
+<.> xref:#currentInteraction__[currentInteraction()]
++
+--
+Returns the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] wrapped by the _#currentInteractionLayer()_ (if within an xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] ).
+--
+
+== Members
+
+[#currentInteractionLayer__]
+=== currentInteractionLayer()
+
+[#currentInteractionContext__]
+=== currentInteractionContext()
+
+Returns the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] wrapped by the _#currentInteractionLayer()_ (if within an xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] ).
+
+[#currentInteraction__]
+=== currentInteraction()
+
+Returns the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] wrapped by the _#currentInteractionLayer()_ (if within an xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] ).
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionService.adoc
index fe56da3..06d3e64 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/iactnlayer/InteractionService.adoc
@@ -17,10 +17,12 @@ There are two main APIs exposed. One is to _#openInteraction(InteractionContext)
 interface InteractionService {
   InteractionLayer openInteraction()     // <.>
   InteractionLayer openInteraction(InteractionContext interactionContext)     // <.>
+  void closeInteractionLayers()     // <.>
   boolean isInInteraction()     // <.>
   R call(InteractionContext interactionContext, Callable<R> callable)     // <.>
   void run(InteractionContext interactionContext, ThrowingRunnable runnable)     // <.>
-  void closeInteractionLayers()     // <.>
+  R callAnonymous(Callable<R> callable)     // <.>
+  void runAnonymous(ThrowingRunnable runnable)     // <.>
 }
 ----
 
@@ -34,6 +36,11 @@ If present, reuses the current top level xref:refguide:applib:index/services/iac
 --
 Returns a new or reused xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] that is a holder of the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] on top of the current thread's interaction layer stack.
 --
+<.> xref:#closeInteractionLayers__[closeInteractionLayers()]
++
+--
+closes all open xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] (s) as stacked on the current thread
+--
 <.> xref:#isInInteraction__[isInInteraction()]
 <.> xref:#call__InteractionContext_Callable[call(InteractionContext, Callable)]
 +
@@ -45,10 +52,15 @@ Executes a block of code with a new or reused xref:refguide:applib:index/service
 --
 Variant of _#call(InteractionContext, Callable)_ that takes a runnable.
 --
-<.> xref:#closeInteractionLayers__[closeInteractionLayers()]
+<.> xref:#callAnonymous__Callable[callAnonymous(Callable)]
 +
 --
-closes all open xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] (s) as stacked on the current thread
+As per _#call(InteractionContext, Callable)_ , but using an anonymous xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] .
+--
+<.> xref:#runAnonymous__ThrowingRunnable[runAnonymous(ThrowingRunnable)]
++
+--
+As per _#callAnonymous(Callable)_ , but for a runnable.
 --
 
 == Members
@@ -67,6 +79,11 @@ If available reuses an existing xref:refguide:applib:index/services/iactnlayer/I
 
 The xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] represents a user's span of activities interacting with the application. These can be stacked (usually temporarily), for example for a sudo session or to mock the clock. The stack is later closed using _#closeInteractionLayers()_ .
 
+[#closeInteractionLayers__]
+=== closeInteractionLayers()
+
+closes all open xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] (s) as stacked on the current thread
+
 [#isInInteraction__]
 === isInInteraction()
 
@@ -84,7 +101,12 @@ If there is currently an xref:refguide:applib:index/services/iactnlayer/Interact
 
 Variant of _#call(InteractionContext, Callable)_ that takes a runnable.
 
-[#closeInteractionLayers__]
-=== closeInteractionLayers()
+[#callAnonymous__Callable]
+=== callAnonymous(Callable)
 
-closes all open xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] (s) as stacked on the current thread
+As per _#call(InteractionContext, Callable)_ , but using an anonymous xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] .
+
+[#runAnonymous__ThrowingRunnable]
+=== runAnonymous(ThrowingRunnable)
+
+As per _#callAnonymous(Callable)_ , but for a runnable.
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/queryresultscache/QueryResultsCache.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/queryresultscache/QueryResultsCache.adoc
index 103231e..e267036 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/queryresultscache/QueryResultsCache.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/queryresultscache/QueryResultsCache.adoc
@@ -1,24 +1,27 @@
-= QueryResultsCache _(interface)_
+= QueryResultsCache
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Provides a mechanism by which idempotent query results can be cached for the duration of an interaction.
+This service (API and implementation) provides a mechanism by which idempotent query results can be cached for the duration of an _org.apache.isis.applib.services.iactn.Interaction_ .
 
 Caching such values is useful to improve the response time (for the end user) of code that loops "naively" through a set of items, performing an expensive operation each time. If the data is such that the same expensive operation is made many times, then the query cache is a perfect fit.
 
+For example, code that makes a repository call many times within a loop can be performance tuned using this service. The benefit is that the algorithm of the business logic can remain easy to understand.
+
 == API
 
 [source,java]
 .QueryResultsCache.java
 ----
-interface QueryResultsCache {
-  T execute(Callable<T> callable, Class<?> callingClass, String methodName, Object... keys)     // <.>
-  void onTransactionEnded()     // <.>
+class QueryResultsCache {
+  T execute(final Callable<T> callable, final Class<?> callingClass, final String methodName, final Object... keys)     // <.>
   R execute(MethodReferences.Call0<? extends R> action, Class<?> callingClass, String methodName)
   R execute(MethodReferences.Call1<? extends R, A0> action, Class<?> callingClass, String methodName, A0 arg0)
   R execute(MethodReferences.Call2<? extends R, A0, A1> action, Class<?> callingClass, String methodName, A0 arg0, A1 arg1)
   R execute(MethodReferences.Call3<? extends R, A0, A1, A2> action, Class<?> callingClass, String methodName, A0 arg0, A1 arg1, A2 arg2)
   R execute(MethodReferences.Call4<? extends R, A0, A1, A2, A3> action, Class<?> callingClass, String methodName, A0 arg0, A1 arg1, A2 arg2, A3 arg3)
   R execute(MethodReferences.Call5<? extends R, A0, A1, A2, A3, A4> action, Class<?> callingClass, String methodName, A0 arg0, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
+  void onTransactionEnded()     // <.>
+  void destroy()
 }
 ----
 
@@ -30,7 +33,7 @@ Executes the callable if not already cached for the supplied calling class, meth
 <.> xref:#onTransactionEnded__[onTransactionEnded()]
 +
 --
-Not API, for framework use only.
+Not API: for framework to call at end of transaction, to clear out the cache.
 --
 
 == Members
@@ -43,7 +46,9 @@ Executes the callable if not already cached for the supplied calling class, meth
 [#onTransactionEnded__]
 === onTransactionEnded()
 
-Not API, for framework use only.
+Not API: for framework to call at end of transaction, to clear out the cache.
+
+(This service really ought to be considered a transaction-scoped service; since that isn't yet supported by the framework, we have to manually reset).
 
 include::hooks/QueryResultsCache_010-implementation.adoc[]
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/sudo/SudoService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/sudo/SudoService.adoc
index 126d27e..a287ad6 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/sudo/SudoService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/sudo/SudoService.adoc
@@ -1,9 +1,9 @@
-= SudoService _(interface)_
+= SudoService
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 Allows a block of code to be executed within an arbitrary xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , allowing the who, when and where to be temporarily switched.
 
-Most typically this service is used to temporarily change the &qout;who", that is the user reported by the xref:refguide:applib:index/services/user/UserService.adoc[UserService] 's _UserService#currentUser() getUser()_ - hence the name SudoService. But the user's locale and timezome can also be changed, as well as the time reported by _org.apache.isis.applib.services.clock.ClockService_ .
+Most typically this service is used to temporarily change the "who", that is the user reported by the xref:refguide:applib:index/services/user/UserService.adoc[UserService] 's _UserService#currentUser() getUser()_ - hence the name SudoService. But the user's locale and timezome can also be changed, as well as the time reported by _org.apache.isis.applib.services.clock.ClockService_ .
 
 The primary use case for this service is for fixture scripts and integration tests.
 
@@ -12,9 +12,9 @@ The primary use case for this service is for fixture scripts and integration tes
 [source,java]
 .SudoService.java
 ----
-interface SudoService {
-  RoleMemento ACCESS_ALL_ROLE;     // <.>
-  T call(final UnaryOperator<InteractionContext> sudoMapper, final Callable<T> supplier)     // <.>
+class SudoService {
+  public static RoleMemento ACCESS_ALL_ROLE;     // <.>
+  T call(final UnaryOperator<InteractionContext> sudoMapper, final Callable<T> callable)     // <.>
   void run(final UnaryOperator<InteractionContext> sudoMapper, final ThrowingRunnable runnable)     // <.>
 }
 ----
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/user/UserMemento.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/user/UserMemento.adoc
index 502f872..1d5cc63 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/user/UserMemento.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/user/UserMemento.adoc
@@ -10,7 +10,6 @@ Immutable serializable value holding details about a user and its roles.
 ----
 class UserMemento {
   public static final String LOGICAL_TYPE_NAME;
-  UserMemento(final String name, final Stream<RoleMemento> roles)     // <.>
   UserMemento system()     // <.>
   UserMemento ofName(final String name)     // <.>
   UserMemento ofNameAndRoles(final String name, final RoleMemento... roles)     // <.>
@@ -18,25 +17,15 @@ class UserMemento {
   UserMemento ofNameAndRoleNames(final String name, final List<String> roleNames)     // <.>
   UserMemento ofNameAndRoleNames(final String name, final Stream<String> roleNames)     // <.>
   String title()
-  UserMemento withRealName(final String realName)
-  UserMemento withAvatarUrl(final URL avatarUrl)
-  UserMemento withImpersonating()
-  List<RoleMemento> getRoles()
-  UserMemento withRole(String role)
+  List<RoleMemento> getRoles()     // <.>
+  UserMemento withRoleAdded(String role)
   boolean isCurrentUser(final String userName)     // <.>
   Stream<String> streamRoleNames()
   boolean hasRoleName(final String roleName)
-  String toString()
-  boolean equals(Object obj)
-  int hashCode()
+  UserMementoBuilder asBuilder()
 }
 ----
 
-<.> xref:#UserMemento__String_Stream[UserMemento(String, Stream)]
-+
---
-Creates a new user with the specified name and assigned roles.
---
 <.> xref:#system__[system()]
 +
 --
@@ -67,6 +56,11 @@ Creates a new user with the specified name and assigned role names.
 --
 Creates a new user with the specified name and assigned role names.
 --
+<.> xref:#getRoles__[getRoles()]
++
+--
+The roles associated with this user.
+--
 <.> xref:#isCurrentUser__String[isCurrentUser(String)]
 +
 --
@@ -75,11 +69,6 @@ Determine if the specified name is this user.
 
 == Members
 
-[#UserMemento__String_Stream]
-=== UserMemento(String, Stream)
-
-Creates a new user with the specified name and assigned roles.
-
 [#system__]
 === system()
 
@@ -110,6 +99,11 @@ Creates a new user with the specified name and assigned role names.
 
 Creates a new user with the specified name and assigned role names.
 
+[#getRoles__]
+=== getRoles()
+
+The roles associated with this user.
+
 [#isCurrentUser__String]
 === isCurrentUser(String)
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/user/UserService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/user/UserService.adoc
index a1646b8..b7fbbe6 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/user/UserService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/user/UserService.adoc
@@ -1,135 +1,143 @@
-= UserService _(interface)_
+= UserService
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 Allows the domain object to obtain the identity of the user interacting with said object.
 
-If xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService] has been used to temporarily override the user and/or roles, then this service will report the overridden values instead.
+If xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService] has been used to temporarily override the user and/or roles, then this service will report the overridden values instead. This is within the context of a thread.
+
+In addition, if impersonation has been invoked through the xref:refguide:applib:index/services/user/ImpersonateMenu.adoc[ImpersonateMenu] , then this service will report the impersonated user, with the companion xref:refguide:applib:index/services/user/ImpersonatedUserHolder.adoc[ImpersonatedUserHolder] taking responsibilty for remembering the impersonated user over multiple (http) requests, eg using an http session. It's important to note that under these circumstances the user reported [...]
 
 == API
 
 [source,java]
 .UserService.java
 ----
-interface UserService {
+class UserService {
+  public static final String NOBODY;     // <.>
   Optional<UserMemento> currentUser()     // <.>
   UserMemento getUser()     // <.>
   UserMemento currentUserElseFail()     // <.>
   Optional<String> currentUserName()     // <.>
   String currentUserNameElseNobody()     // <.>
+  boolean isImpersonating()     // <.>
+  boolean supportsImpersonation()     // <.>
   void impersonateUser(final String userName, final List<String> roles)     // <.>
   void stopImpersonating()     // <.>
-  boolean supportsImpersonation()     // <.>
-  Optional<UserMemento> getImpersonatedUser()     // <.>
-  boolean isImpersonating()     // <.>
 }
 ----
 
+<.> xref:#NOBODY[NOBODY]
++
+--
+Default returned from _#currentUserNameElseNobody()_ .
+--
 <.> xref:#currentUser__[currentUser()]
 +
 --
-Optionally gets the details about the current user, based on whether an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can be found with the current thread's context.
+Returns the details about the current user, either the "effective" user (if being _#impersonateUser(String, List) impersonated_ ) otherwise the "real" user (as obtained from the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] of the current thread).
 --
 <.> xref:#getUser__[getUser()]
 +
 --
-Gets the details about the current user.
+Gets the details about the _#currentUser()_ current user, if any (and returning `null` if there is none).
 --
 <.> xref:#currentUserElseFail__[currentUserElseFail()]
 +
 --
-Gets the details about the current user.
+Gets the details about the _#currentUser()_ current user, throwing an exception if there is none.
 --
 <.> xref:#currentUserName__[currentUserName()]
 +
 --
-Optionally gets the the current user's name, based on whether an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can be found with the current thread's context.
+Optionally gets the _#currentUser() current user_ 's name, obtained from xref:refguide:applib:index/services/user/UserMemento.adoc[UserMemento] .
 --
 <.> xref:#currentUserNameElseNobody__[currentUserNameElseNobody()]
 +
 --
-Returns either the current user's name or else _Nobody_ .
---
-<.> xref:#impersonateUser__String_List[impersonateUser(String, List)]
-+
---
-Allows implementations to override the current user with another user.
+Returns either the current user's name or else _#NOBODY_ .
 --
-<.> xref:#stopImpersonating__[stopImpersonating()]
+<.> xref:#isImpersonating__[isImpersonating()]
 +
 --
-For implementations that support impersonation, this is to programmatically stop impersonating a user
+Whether or not the user currently reported (in _#currentUser()_ and similar) is actually an impersonated user.
 --
 <.> xref:#supportsImpersonation__[supportsImpersonation()]
 +
 --
-Whether this implementation supports impersonation.
+Whether impersonation is available for this request.
 --
-<.> xref:#getImpersonatedUser__[getImpersonatedUser()]
+<.> xref:#impersonateUser__String_List[impersonateUser(String, List)]
 +
 --
-The impersonated user, if it has previously been set.
+Allows implementations to override the current user with another user.
 --
-<.> xref:#isImpersonating__[isImpersonating()]
+<.> xref:#stopImpersonating__[stopImpersonating()]
 +
 --
-Whether or not the user currently reported (in _#currentUser()_ and similar) is actually an impersonated user.
+For implementations that support impersonation, this is to programmatically stop impersonating a user
 --
 
 == Members
 
+[#NOBODY]
+=== NOBODY
+
+Default returned from _#currentUserNameElseNobody()_ .
+
 [#currentUser__]
 === currentUser()
 
-Optionally gets the details about the current user, based on whether an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can be found with the current thread's context.
+Returns the details about the current user, either the "effective" user (if being _#impersonateUser(String, List) impersonated_ ) otherwise the "real" user (as obtained from the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] of the current thread).
 
 [#getUser__]
 === getUser()
 
-Gets the details about the current user.
+Gets the details about the _#currentUser()_ current user, if any (and returning `null` if there is none).
 
 [#currentUserElseFail__]
 === currentUserElseFail()
 
-Gets the details about the current user.
+Gets the details about the _#currentUser()_ current user, throwing an exception if there is none.
 
 [#currentUserName__]
 === currentUserName()
 
-Optionally gets the the current user's name, based on whether an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can be found with the current thread's context.
+Optionally gets the _#currentUser() current user_ 's name, obtained from xref:refguide:applib:index/services/user/UserMemento.adoc[UserMemento] .
 
 [#currentUserNameElseNobody__]
 === currentUserNameElseNobody()
 
-Returns either the current user's name or else _Nobody_ .
+Returns either the current user's name or else _#NOBODY_ .
+
+[#isImpersonating__]
+=== isImpersonating()
+
+Whether or not the user currently reported (in _#currentUser()_ and similar) is actually an impersonated user.
+
+[#supportsImpersonation__]
+=== supportsImpersonation()
+
+Whether impersonation is available for this request.
+
+The typical implementation uses an HTTP session, which is not guaranteed to be available for all viewers. Specifically, the Wicket viewer _does_ use HTTP sessions and therefore supports impersonation, but the RestfulObjects viewer does _not_ . This means that the result of this call varies on a request-by-request basis.
 
 [#impersonateUser__String_List]
 === impersonateUser(String, List)
 
 Allows implementations to override the current user with another user.
 
-This is intended for non-production environments only, where it can be invaluable (from a support perspective) to be able to quickly use the application "as if" logged in as another user.
+If this service (for this request) does not _#supportsImpersonation() support impersonation_ , then the request is just ignored.
+
+IMPORTANT: this is intended for non-production environments only, where it can be invaluable (from a support perspective) to be able to quickly use the application "as if" logged in as another user.
 
 [#stopImpersonating__]
 === stopImpersonating()
 
 For implementations that support impersonation, this is to programmatically stop impersonating a user
 
-Intended to be called at some point after _#impersonateUser(String, List)_ would have been called.
-
-[#supportsImpersonation__]
-=== supportsImpersonation()
-
-Whether this implementation supports impersonation.
-
-[#getImpersonatedUser__]
-=== getImpersonatedUser()
+If this service (for this request) does not _#supportsImpersonation() support impersonation_ , then the request is just ignored.
 
-The impersonated user, if it has previously been set.
-
-[#isImpersonating__]
-=== isImpersonating()
-
-Whether or not the user currently reported (in _#currentUser()_ and similar) is actually an impersonated user.
+Intended to be called at some point after _#impersonateUser(String, List)_ would have been called.
 
 include::hooks/UserService_010-implementation.adoc[]
 
diff --git a/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc b/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc
deleted file mode 100644
index 2204047..0000000
--- a/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc
+++ /dev/null
@@ -1,60 +0,0 @@
-= InteractionFactory _(interface)_
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-The factory of xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] (s) and xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] (s), holding a reference to the current xref:refguide:applib:index/services/iactnlayer/InteractionLayer.adoc[InteractionLayer] stack using a thread-local.
-
-== API
-
-[source,java]
-.InteractionFactory.java
-----
-interface InteractionFactory {
-  R callAuthenticated(Authentication authentication, Callable<R> callable)     // <.>
-  R callAnonymous(Callable<R> callable)     // <.>
-  void runAuthenticated(Authentication authentication, ThrowingRunnable runnable)     // <.>
-  void runAnonymous(ThrowingRunnable runnable)     // <.>
-}
-----
-
-<.> xref:#callAuthenticated__Authentication_Callable[callAuthenticated(Authentication, Callable)]
-+
---
-As per _#call(InteractionContext, Callable)_ , using the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] _Authentication#getInteractionContext() obtained_ from the provided xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] .
---
-<.> xref:#callAnonymous__Callable[callAnonymous(Callable)]
-+
---
-As per _#call(InteractionContext, Callable)_ , but using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] _Authentication#getInteractionContext() obtained_ from an anonymous xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] .
---
-<.> xref:#runAuthenticated__Authentication_ThrowingRunnable[runAuthenticated(Authentication, ThrowingRunnable)]
-+
---
-As per _#callAuthenticated(Authentication, Callable)_ , but for a runnable.
---
-<.> xref:#runAnonymous__ThrowingRunnable[runAnonymous(ThrowingRunnable)]
-+
---
-As per _#callAnonymous(Callable)_ , but for a runnable.
---
-
-== Members
-
-[#callAuthenticated__Authentication_Callable]
-=== callAuthenticated(Authentication, Callable)
-
-As per _#call(InteractionContext, Callable)_ , using the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] _Authentication#getInteractionContext() obtained_ from the provided xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] .
-
-[#callAnonymous__Callable]
-=== callAnonymous(Callable)
-
-As per _#call(InteractionContext, Callable)_ , but using an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] _Authentication#getInteractionContext() obtained_ from an anonymous xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] .
-
-[#runAuthenticated__Authentication_ThrowingRunnable]
-=== runAuthenticated(Authentication, ThrowingRunnable)
-
-As per _#callAuthenticated(Authentication, Callable)_ , but for a runnable.
-
-[#runAnonymous__ThrowingRunnable]
-=== runAnonymous(ThrowingRunnable)
-
-As per _#callAnonymous(Callable)_ , but for a runnable.
diff --git a/antora/components/refguide-index/modules/core/pages/index/runtimeservices/transaction/TransactionServiceSpring.adoc b/antora/components/refguide-index/modules/core/pages/index/runtimeservices/transaction/TransactionServiceSpring.adoc
index 17827f1..41be497 100644
--- a/antora/components/refguide-index/modules/core/pages/index/runtimeservices/transaction/TransactionServiceSpring.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/runtimeservices/transaction/TransactionServiceSpring.adoc
@@ -7,7 +7,7 @@
 .TransactionServiceSpring.java
 ----
 class TransactionServiceSpring {
-  TransactionServiceSpring(final List<PlatformTransactionManager> platformTransactionManagers, final List<PersistenceExceptionTranslator> persistenceExceptionTranslators, final InteractionTracker interactionLayerTracker)
+  TransactionServiceSpring(final List<PlatformTransactionManager> platformTransactionManagers, final List<PersistenceExceptionTranslator> persistenceExceptionTranslators, final InteractionLayerTracker interactionLayerTracker)
   Result<T> callTransactional(TransactionDefinition def, Callable<T> callable)
   void nextTransaction()
   void flushTransaction()
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc
deleted file mode 100644
index bdddcfc..0000000
--- a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc
+++ /dev/null
@@ -1,100 +0,0 @@
-= Authentication _(interface)_
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-An immutable, serializable value type, that holds details about a user's authentication.
-
-This is really little more than a thin wrapper around xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , surfaces a number of the security-specific attributes of that field.
-
-== API
-
-[source,java]
-.Authentication.java
-----
-interface Authentication {
-  String INTERACTION_CONTEXT_KEY;
-  String getUserName()     // <.>
-  String getValidationCode()     // <.>
-  UserMemento getUser()     // <.>
-  InteractionContext getInteractionContext()     // <.>
-  Type getType()     // <.>
-  Authentication withInteractionContext(InteractionContext interactionContext)     // <.>
-  Optional<Authentication> authenticationFrom(final InteractionContext interactionContext)     // <.>
-}
-----
-
-<.> xref:#getUserName__[getUserName()]
-+
---
-The name of the authenticated user; for display purposes only.
---
-<.> xref:#getValidationCode__[getValidationCode()]
-+
---
-A unique code given to this session during authentication.
---
-<.> xref:#getUser__[getUser()]
-+
---
-The (programmatically) simulated (or actual) user, belonging to this session.
---
-<.> xref:#getInteractionContext__[getInteractionContext()]
-+
---
-The xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] (programmatically) simulated (or actual), belonging to this session.
---
-<.> xref:#getType__[getType()]
-+
---
-To support external security mechanisms such as keycloak, where the validity of the session is defined by headers in the request.
---
-<.> xref:#withInteractionContext__InteractionContext[withInteractionContext(InteractionContext)]
-+
---
-Returns a copy with given _interactionContext_ .
---
-<.> xref:#authenticationFrom__InteractionContext[authenticationFrom(InteractionContext)]
-+
---
-Looks up an xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] from the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] .
---
-
-== Members
-
-[#getUserName__]
-=== getUserName()
-
-The name of the authenticated user; for display purposes only.
-
-[#getValidationCode__]
-=== getValidationCode()
-
-A unique code given to this session during authentication.
-
-This can be used to confirm that this session has been properly created and the user has been authenticated. It should return an empty string ( `""` ) if this is unauthenticated user
-
-[#getUser__]
-=== getUser()
-
-The (programmatically) simulated (or actual) user, belonging to this session.
-
-[#getInteractionContext__]
-=== getInteractionContext()
-
-The xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] (programmatically) simulated (or actual), belonging to this session.
-
-[#getType__]
-=== getType()
-
-To support external security mechanisms such as keycloak, where the validity of the session is defined by headers in the request.
-
-[#withInteractionContext__InteractionContext]
-=== withInteractionContext(InteractionContext)
-
-Returns a copy with given _interactionContext_ .
-
-[#authenticationFrom__InteractionContext]
-=== authenticationFrom(InteractionContext)
-
-Looks up an xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] from the provided xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] .
-
-If the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] was created as the result of an authentication process (as opposed to programmatically) then there will be an attached xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] object.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc
index 4f6eefd..416d489 100644
--- a/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc
@@ -3,7 +3,7 @@
 
 Represents a request to authenticate the user identified by _AuthenticationRequest#getName()_ .
 
-If successful, then the authentication mechanism is expected to add the _AuthenticationRequest#streamRoles() roles_ to the resultant xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] (obtained from the _org.apache.isis.applib.services.user.UserMemento_ returned by _Authentication#getUser()_ ).
+If successful, then the authentication mechanism is expected to add the _AuthenticationRequest#streamRoles() roles_ to the resultant xref:refguide:applib:index/services/user/UserMemento.adoc[UserMemento] (obtained from _InteractionContext#getUser()_ ).
 
 == API
 
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc
index 4c6f070..5aade79 100644
--- a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc
@@ -1,7 +1,7 @@
 = Authenticator _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Represents an authentication mechanism capable of authenticating certain types of xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] and returning an xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if the credentials are valid.
+Represents an authentication mechanism capable of authenticating certain types of xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] and returning an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] if the credentials are valid.
 
 There can be multiple xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] s registered. If so, all Authenticators that can authenticate any given xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] must
 
@@ -12,8 +12,8 @@ There can be multiple xref:refguide:core:index/security/authentication/Authentic
 ----
 interface Authenticator {
   boolean canAuthenticate(Class<? extends AuthenticationRequest> authenticationRequestClass)     // <.>
-  Authentication authenticate(AuthenticationRequest request, String code)     // <.>
-  void logout(Authentication authentication)     // <.>
+  InteractionContext authenticate(AuthenticationRequest request, String code)     // <.>
+  void logout(InteractionContext context)     // <.>
 }
 ----
 
@@ -25,12 +25,12 @@ Whether the provided xref:refguide:core:index/security/authentication/Authentica
 <.> xref:#authenticate__AuthenticationRequest_String[authenticate(AuthenticationRequest, String)]
 +
 --
-Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if valid.
+Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] if valid.
 --
-<.> xref:#logout__Authentication[logout(Authentication)]
+<.> xref:#logout__InteractionContext[logout(InteractionContext)]
 +
 --
-Invalidates this xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] , meaning that the user will need to log in again to use the application.
+Invalidates this xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , meaning that the user will need to log in again to use the application.
 --
 
 == Members
@@ -43,9 +43,9 @@ Whether the provided xref:refguide:core:index/security/authentication/Authentica
 [#authenticate__AuthenticationRequest_String]
 === authenticate(AuthenticationRequest, String)
 
-Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if valid.
+Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] if valid.
 
-[#logout__Authentication]
-=== logout(Authentication)
+[#logout__InteractionContext]
+=== logout(InteractionContext)
 
-Invalidates this xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] , meaning that the user will need to log in again to use the application.
+Invalidates this xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] , meaning that the user will need to log in again to use the application.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/manager/AnonymousInteractionFactory.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/manager/AnonymousInteractionFactory.adoc
deleted file mode 100644
index 917cf63..0000000
--- a/antora/components/refguide-index/modules/core/pages/index/security/authentication/manager/AnonymousInteractionFactory.adoc
+++ /dev/null
@@ -1,51 +0,0 @@
-= AnonymousInteractionFactory _(interface)_
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-Inversion of dependency pattern.
-
-Introduced to allow the AuthenticationManager (module: security) access to the InteractionFactory service (module: interaction), which otherwise was not possible, due to Maven module dependencies (preventing circles).
-
-== API
-
-[source,java]
-.AnonymousInteractionFactory.java
-----
-interface AnonymousInteractionFactory {
-  void runAnonymous(ThrowingRunnable runnable)     // <.>
-  R callAnonymous(Callable<R> callable)     // <.>
-  AnonymousInteractionFactory forTesting()     // <.>
-}
-----
-
-<.> xref:#runAnonymous__ThrowingRunnable[runAnonymous(ThrowingRunnable)]
-+
---
-Executes a block of code with anonymous credentials.
---
-<.> xref:#callAnonymous__Callable[callAnonymous(Callable)]
-+
---
-Executes a block of code with anonymous credentials.
---
-<.> xref:#forTesting__[forTesting()]
-+
---
-Returns a pass-through implementation, free of side-effects, in support of simple JUnit tests.
---
-
-== Members
-
-[#runAnonymous__ThrowingRunnable]
-=== runAnonymous(ThrowingRunnable)
-
-Executes a block of code with anonymous credentials.
-
-[#callAnonymous__Callable]
-=== callAnonymous(Callable)
-
-Executes a block of code with anonymous credentials.
-
-[#forTesting__]
-=== forTesting()
-
-Returns a pass-through implementation, free of side-effects, in support of simple JUnit tests.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc
index b2bf14d..81cb9f5 100644
--- a/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc
@@ -1,7 +1,7 @@
 = Authorizor _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Represents a mechanism to evaluate whether the current user (as represented by xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can either view or invoke the domain object feature (as represented by xref:refguide:applib:index/Identifier.adoc[Identifier] .
+Represents a mechanism to evaluate whether the current user (as represented by xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can either view or invoke the domain object feature (as represented by xref:refguide:applib:index/Identifier.adoc[Identifier] .
 
 == API
 
@@ -9,32 +9,32 @@ Represents a mechanism to evaluate whether the current user (as represented by x
 .Authorizor.java
 ----
 interface Authorizor {
-  boolean isVisible(Authentication authentication, Identifier identifier)     // <.>
-  boolean isUsable(Authentication authentication, Identifier identifier)     // <.>
+  boolean isVisible(InteractionContext authentication, Identifier identifier)     // <.>
+  boolean isUsable(InteractionContext authentication, Identifier identifier)     // <.>
 }
 ----
 
-<.> xref:#isVisible__Authentication_Identifier[isVisible(Authentication, Identifier)]
+<.> xref:#isVisible__InteractionContext_Identifier[isVisible(InteractionContext, Identifier)]
 +
 --
-Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+Whether the current xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
 --
-<.> xref:#isUsable__Authentication_Identifier[isUsable(Authentication, Identifier)]
+<.> xref:#isUsable__InteractionContext_Identifier[isUsable(InteractionContext, Identifier)]
 +
 --
-Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+Whether the current xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
 --
 
 == Members
 
-[#isVisible__Authentication_Identifier]
-=== isVisible(Authentication, Identifier)
+[#isVisible__InteractionContext_Identifier]
+=== isVisible(InteractionContext, Identifier)
 
-Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+Whether the current xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
 
-[#isUsable__Authentication_Identifier]
-=== isUsable(Authentication, Identifier)
+[#isUsable__InteractionContext_Identifier]
+=== isUsable(InteractionContext, Identifier)
 
-Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+Whether the current xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
 
 If this methods returns `false` then the feature will be greyed out/disabled.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authorization/manager/AuthorizationManager.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authorization/manager/AuthorizationManager.adoc
index 6f5346a..931a460 100644
--- a/antora/components/refguide-index/modules/core/pages/index/security/authorization/manager/AuthorizationManager.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authorization/manager/AuthorizationManager.adoc
@@ -10,17 +10,17 @@ Authorizes the user in the current session view and use members of an object.
 ----
 class AuthorizationManager {
   AuthorizationManager(final List<Authorizor> authorizors, final AuthorizorChooser authorizorChooser)
-  boolean isUsable(final Authentication authentication, final Identifier identifier)     // <.>
-  boolean isVisible(final Authentication authentication, final Identifier identifier)     // <.>
+  boolean isUsable(final InteractionContext authentication, final Identifier identifier)     // <.>
+  boolean isVisible(final InteractionContext authentication, final Identifier identifier)     // <.>
 }
 ----
 
-<.> xref:#isUsable__Authentication_Identifier[isUsable(Authentication, Identifier)]
+<.> xref:#isUsable__InteractionContext_Identifier[isUsable(InteractionContext, Identifier)]
 +
 --
 Whether the user represented by the specified session is authorized to view the member of the class/object represented by the member identifier.
 --
-<.> xref:#isVisible__Authentication_Identifier[isVisible(Authentication, Identifier)]
+<.> xref:#isVisible__InteractionContext_Identifier[isVisible(InteractionContext, Identifier)]
 +
 --
 Whether the user represented by the specified session is authorized to change the field represented by the member identifier.
@@ -28,15 +28,15 @@ Whether the user represented by the specified session is authorized to change th
 
 == Members
 
-[#isUsable__Authentication_Identifier]
-=== isUsable(Authentication, Identifier)
+[#isUsable__InteractionContext_Identifier]
+=== isUsable(InteractionContext, Identifier)
 
 Whether the user represented by the specified session is authorized to view the member of the class/object represented by the member identifier.
 
 Normally the view of the specified field, or the display of the action will be suppress if this returns false.
 
-[#isVisible__Authentication_Identifier]
-=== isVisible(Authentication, Identifier)
+[#isVisible__InteractionContext_Identifier]
+=== isVisible(InteractionContext, Identifier)
 
 Whether the user represented by the specified session is authorized to change the field represented by the member identifier.
 
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/SecondaryStatus.adoc b/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/SecondaryStatus.adoc
index c7d42d6..ecc885c 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/SecondaryStatus.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/SecondaryStatus.adoc
@@ -7,8 +7,6 @@
 .SecondaryStatus.java
 ----
 enum SecondaryStatus {
-  TICKING_CLOCK_STATUS_UNKNOWN
-  TICKING_CLOCK_NOT_YET_INITIALIZED
   OK
   REST_CALL_FAILING
   FAILED_TO_UNMARSHALL_RESPONSE
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/clock/TickingClockService.adoc b/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/clock/TickingClockService.adoc
deleted file mode 100644
index ff62de7..0000000
--- a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/clock/TickingClockService.adoc
+++ /dev/null
@@ -1,48 +0,0 @@
-= TickingClockService
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-Only enabled for the `secondary` profile, where it sets up the framework to use xref:refguide:testing:index/fixtures/applib/clock/clock/TickingFixtureClock.adoc[TickingFixtureClock] so that time can be changed dynamically when running.
-
-As an additional safeguard, if the configuration keys to access the primary are not provided, then the service will not initialize.
-
-IMPORTANT: the methods provided by this service are not thread-safe, because the clock is a globally-scoped singleton rather than a thread-local. These methods should therefore only be used in single-user systems, eg a replay secondary.
-
-== API
-
-[source,java]
-.TickingClockService.java
-----
-class TickingClockService {
-  void init()
-  boolean isInitialized()
-  void at(Timestamp timestamp, Runnable runnable)     // <.>
-  T at(Timestamp timestamp, Supplier<T> supplier)     // <.>
-}
-----
-
-<.> xref:#at__Timestamp_Runnable[at(Timestamp, Runnable)]
-+
---
-Executes the runnable, setting the clock to be the specified time beforehand (and reinstating it to its original time afterwards).
---
-<.> xref:#at__Timestamp_Supplier[at(Timestamp, Supplier)]
-+
---
-Executes the callable, setting the clock to be the specified time beforehand (and reinstating it to its original time afterwards).
---
-
-== Members
-
-[#at__Timestamp_Runnable]
-=== at(Timestamp, Runnable)
-
-Executes the runnable, setting the clock to be the specified time beforehand (and reinstating it to its original time afterwards).
-
-IMPORTANT: this method is not thread-safe, because the clock is a globally-scoped singleton rather than a thread-local. This method should therefore only be used in single-user systems, eg a replay secondary.
-
-[#at__Timestamp_Supplier]
-=== at(Timestamp, Supplier)
-
-Executes the callable, setting the clock to be the specified time beforehand (and reinstating it to its original time afterwards).
-
-IMPORTANT: this method is not thread-safe, because the clock is a globally-scoped singleton rather than a thread-local. This method should therefore only be used in single-user systems, eg a replay secondary.
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/executor/CommandExecutorServiceWithTime.adoc b/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/executor/CommandExecutorServiceWithTime.adoc
deleted file mode 100644
index c9c2a13..0000000
--- a/antora/components/refguide-index/modules/extensions/pages/index/commandreplay/secondary/executor/CommandExecutorServiceWithTime.adoc
+++ /dev/null
@@ -1,21 +0,0 @@
-= CommandExecutorServiceWithTime
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-Override of xref:refguide:applib:index/services/command/CommandExecutorService.adoc[CommandExecutorService] that also sets the time (using the xref:refguide:extensions:index/commandreplay/secondary/clock/TickingClockService.adoc[TickingClockService] ) to that of the xref:refguide:applib:index/services/command/Command.adoc[Command] 's _Command#getTimestamp() timestamp_ before executing the command.
-
-It then delegates down to the default implementation.
-
-== API
-
-[source,java]
-.CommandExecutorServiceWithTime.java
-----
-class CommandExecutorServiceWithTime {
-  CommandExecutorServiceWithTime(final CommandExecutorService delegate, final TickingClockService tickingClockService)
-  Bookmark executeCommand(final Command command)
-  Bookmark executeCommand(final SudoPolicy sudoPolicy, final Command command)
-  Bookmark executeCommand(final CommandDto dto, final CommandOutcomeHandler outcomeHandler)
-  Bookmark executeCommand(final SudoPolicy sudoPolicy, final CommandDto dto, final CommandOutcomeHandler outcomeHandler)
-}
-----
-
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authenticator/AuthenticatorSecman.adoc b/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authenticator/AuthenticatorSecman.adoc
index 7bf365b..d2e96ca 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authenticator/AuthenticatorSecman.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authenticator/AuthenticatorSecman.adoc
@@ -12,8 +12,8 @@ This Authenticator is a fallback and is only used if there is no other implement
 ----
 class AuthenticatorSecman {
   boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass)
-  Authentication authenticate(final AuthenticationRequest request, final String code)
-  void logout(final Authentication session)
+  InteractionContext authenticate(final AuthenticationRequest request, final String code)
+  void logout(final InteractionContext context)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authorizor/AuthorizorSecman.adoc b/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authorizor/AuthorizorSecman.adoc
index 195e80f..8012e6f 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authorizor/AuthorizorSecman.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/secman/integration/authorizor/AuthorizorSecman.adoc
@@ -7,8 +7,8 @@
 .AuthorizorSecman.java
 ----
 class AuthorizorSecman {
-  boolean isVisible(final Authentication authentication, final Identifier identifier)
-  boolean isUsable(final Authentication authentication, final Identifier identifier)
+  boolean isVisible(final InteractionContext authentication, final Identifier identifier)
+  boolean isUsable(final InteractionContext authentication, final Identifier identifier)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/bypass/authorization/AuthorizorBypass.adoc b/antora/components/refguide-index/modules/security/pages/index/bypass/authorization/AuthorizorBypass.adoc
index e10ef64..926fc19 100644
--- a/antora/components/refguide-index/modules/security/pages/index/bypass/authorization/AuthorizorBypass.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/bypass/authorization/AuthorizorBypass.adoc
@@ -7,8 +7,8 @@
 .AuthorizorBypass.java
 ----
 class AuthorizorBypass {
-  boolean isVisible(final Authentication authentication, final Identifier identifier)
-  boolean isUsable(final Authentication authentication, final Identifier identifier)
+  boolean isVisible(final InteractionContext authentication, final Identifier identifier)
+  boolean isUsable(final InteractionContext authentication, final Identifier identifier)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/keycloak/authentication/AuthenticatorKeycloak.adoc b/antora/components/refguide-index/modules/security/pages/index/keycloak/authentication/AuthenticatorKeycloak.adoc
index d6833dc..9123b36 100644
--- a/antora/components/refguide-index/modules/security/pages/index/keycloak/authentication/AuthenticatorKeycloak.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/keycloak/authentication/AuthenticatorKeycloak.adoc
@@ -8,8 +8,8 @@
 ----
 class AuthenticatorKeycloak {
   boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass)
-  Authentication authenticate(final AuthenticationRequest request, final String code)
-  void logout(final Authentication session)
+  InteractionContext authenticate(final AuthenticationRequest request, final String code)
+  void logout(final InteractionContext session)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc b/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
index 3292fc9..39f6a80 100644
--- a/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
@@ -13,9 +13,9 @@ However, although there are two objects, they are set up to share the same _Secu
 class AuthenticatorShiro {
   AuthenticatorShiro(IsisConfiguration configuration)
   boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass)
-  Authentication authenticate(final AuthenticationRequest request, final String code)
-  void logout(final Authentication session)
-  Authentication authenticationFor(AuthenticationRequest request, String validationCode, AuthenticationToken token, Subject currentSubject)
+  InteractionContext authenticate(final AuthenticationRequest request, final String code)
+  void logout(final InteractionContext context)
+  InteractionContext authenticationFor(AuthenticationRequest request, String validationCode, AuthenticationToken token, Subject currentSubject)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc b/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
index f33bbde..36f7c12 100644
--- a/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
@@ -11,8 +11,8 @@ However, although there are two objects, they are set up to share the same _Secu
 .AuthorizorShiro.java
 ----
 class AuthorizorShiro {
-  boolean isVisible(final Authentication authentication, final Identifier identifier)
-  boolean isUsable(final Authentication authentication, final Identifier identifier)
+  boolean isVisible(final InteractionContext authentication, final Identifier identifier)
+  boolean isUsable(final InteractionContext authentication, final Identifier identifier)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/spring/authentication/AuthenticatorSpring.adoc b/antora/components/refguide-index/modules/security/pages/index/spring/authentication/AuthenticatorSpring.adoc
index 57e42e1..0b2756b 100644
--- a/antora/components/refguide-index/modules/security/pages/index/spring/authentication/AuthenticatorSpring.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/spring/authentication/AuthenticatorSpring.adoc
@@ -8,8 +8,8 @@
 ----
 class AuthenticatorSpring {
   boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass)
-  Authentication authenticate(final AuthenticationRequest request, final String code)
-  void logout(final Authentication session)
+  InteractionContext authenticate(final AuthenticationRequest request, final String code)
+  void logout(final InteractionContext session)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService.adoc b/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService.adoc
index fd7bbbc..d9dcaea 100644
--- a/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService.adoc
+++ b/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService.adoc
@@ -10,7 +10,7 @@ Provides a mail-merge capability.
 ----
 class DocxService {
   WordprocessingMLPackage loadPackage(final InputStream docxTemplate)     // <.>
-  void merge(final MergeDefinition mergeDefn)     // <.>
+  void merge(final MergeParams mergeDefn)     // <.>
 }
 ----
 
@@ -19,7 +19,7 @@ class DocxService {
 --
 Load and return an in-memory representation of a docx.
 --
-<.> xref:#merge__MergeDefinition[merge(MergeDefinition)]
+<.> xref:#merge__MergeParams[merge(MergeParams)]
 +
 --
 Merge the input arguments (as HTML) against the Docx template, writing out as a Word docx..
@@ -32,9 +32,9 @@ Merge the input arguments (as HTML) against the Docx template, writing out as a
 
 Load and return an in-memory representation of a docx.
 
-This is public API because building the in-memory structure can be quite slow. Thus, clients can use this method to cache the in-memory structure, and pass it in the _MergeDefinition_ (through the _MergeDefinition.Builder#docxTemplateAsWpMlPackage(WordprocessingMLPackage) builder method_ )
+This is public API because building the in-memory structure can be quite slow. Thus, clients can use this method to cache the in-memory structure, and pass it in the _MergeParams_ (through the _MergeParams.Builder#docxTemplateAsWpMlPackage(WordprocessingMLPackage) builder method_ )
 
-[#merge__MergeDefinition]
-=== merge(MergeDefinition)
+[#merge__MergeParams]
+=== merge(MergeParams)
 
 Merge the input arguments (as HTML) against the Docx template, writing out as a Word docx..
diff --git a/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeDefinition.adoc b/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeParams.adoc
similarity index 90%
rename from antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeDefinition.adoc
rename to antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeParams.adoc
index 2e98e0c..eed5beb 100644
--- a/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeDefinition.adoc
+++ b/antora/components/refguide-index/modules/subdomains/pages/index/docx/applib/DocxService~MergeParams.adoc
@@ -1,12 +1,12 @@
-= DocxService.MergeDefinition
+= DocxService.MergeParams
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 == API
 
 [source,java]
-.DocxService~MergeDefinition.java
+.DocxService~MergeParams.java
 ----
-class MergeDefinition {
+class MergeParams {
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/TickingClockFixture.adoc b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/TickingClockFixture.adoc
deleted file mode 100644
index 4bf657c..0000000
--- a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/TickingClockFixture.adoc
+++ /dev/null
@@ -1,15 +0,0 @@
-= TickingClockFixture
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-== API
-
-[source,java]
-.TickingClockFixture.java
-----
-class TickingClockFixture {
-  String getDate()
-  TickingClockFixture setDate(final String date)
-  FixtureScripts.MultipleExecutionStrategy getMultipleExecutionStrategy()
-}
-----
-
diff --git a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/Clock.adoc b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/Clock.adoc
deleted file mode 100644
index 87a42a5..0000000
--- a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/Clock.adoc
+++ /dev/null
@@ -1,80 +0,0 @@
-= Clock
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-Provides a mechanism to get (and possible to set) the current time.
-
-The clock is used primarily by the temporal value classes, and is accessed by the framework as a singleton. The actual implementation used can be configured at startup, but once specified the clock instance cannot be changed.
-
-Unless another xref:refguide:testing:index/fixtures/applib/clock/clock/Clock.adoc[Clock] implementation has been installed, the first call to _#getInstance()_ will instantiate an implementation that just uses the system's own clock. Alternate implementations can be created via suitable subclasses, but this must be done * _before_ * the first call to _#getInstance()_ .
-
-== API
-
-[source,java]
-.Clock.java
-----
-class Clock {
-  Clock getInstance()     // <.>
-  boolean isInitialized()     // <.>
-  long getEpochMillis()     // <.>
-  LocalDate getTimeAsLocalDate()
-  LocalDateTime getTimeAsLocalDateTime()
-  OffsetDateTime getTimeAsOffsetDateTime()     // <.>
-  Timestamp getTimeAsJavaSqlTimestamp()
-  DateTime getTimeAsJodaDateTime()     // <.>
-}
-----
-
-<.> xref:#getInstance__[getInstance()]
-+
---
-Returns the (singleton) instance of xref:refguide:testing:index/fixtures/applib/clock/clock/Clock.adoc[Clock] .
---
-<.> xref:#isInitialized__[isInitialized()]
-+
---
-Whether has been initialized or not.
---
-<.> xref:#getEpochMillis__[getEpochMillis()]
-+
---
-The time as the number of milliseconds since the epoch start. (UTC)
---
-<.> xref:#getTimeAsOffsetDateTime__[getTimeAsOffsetDateTime()]
-+
---
-Returns the time as _OffsetDateTime_ , using the _ZoneId#systemDefault() system default_ timezone.
---
-<.> xref:#getTimeAsJodaDateTime__[getTimeAsJodaDateTime()]
-+
---
-Returns the time as a Joda _DateTime_ , using the _ZoneId#systemDefault() system default_ timezone.
---
-
-== Members
-
-[#getInstance__]
-=== getInstance()
-
-Returns the (singleton) instance of xref:refguide:testing:index/fixtures/applib/clock/clock/Clock.adoc[Clock] .
-
-Unless it has been otherwise created, will lazily instantiate an implementation that just delegate to the computer's own system clock (as per _System#currentTimeMillis()_ .
-
-[#isInitialized__]
-=== isInitialized()
-
-Whether has been initialized or not.
-
-[#getEpochMillis__]
-=== getEpochMillis()
-
-The time as the number of milliseconds since the epoch start. (UTC)
-
-[#getTimeAsOffsetDateTime__]
-=== getTimeAsOffsetDateTime()
-
-Returns the time as _OffsetDateTime_ , using the _ZoneId#systemDefault() system default_ timezone.
-
-[#getTimeAsJodaDateTime__]
-=== getTimeAsJodaDateTime()
-
-Returns the time as a Joda _DateTime_ , using the _ZoneId#systemDefault() system default_ timezone.
diff --git a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/FixtureClock.adoc b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/FixtureClock.adoc
deleted file mode 100644
index 374e692..0000000
--- a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/FixtureClock.adoc
+++ /dev/null
@@ -1,117 +0,0 @@
-= FixtureClock
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-This clock, for use by fixtures, can be set to specific time.
-
-If not set it will provide the time provided by the system clock.
-
-Note that - by design - it does not provide any mechanism to advance the time (eg automatic ticking of the clock). That is, the time returned is always explicitly under the control of the programmer (it can be moved forward or back as required).
-
-== API
-
-[source,java]
-.FixtureClock.java
-----
-class FixtureClock {
-  FixtureClock initialize()     // <.>
-  boolean remove()     // <.>
-  void clear()     // <.>
-  void setTime(final int hour, final int min)     // <.>
-  void setDate(final int year, final int month, final int day)     // <.>
-  void addTime(final int hours, final int minutes)     // <.>
-  void addDate(final int years, final int months, final int days)     // <.>
-  void reset()     // <.>
-  String toString()
-}
-----
-
-<.> xref:#initialize__[initialize()]
-+
---
-Configures the system to use a FixtureClock rather than the in-built system clock. Can be called multiple times.
---
-<.> xref:#remove__[remove()]
-+
---
-Makes _Clock#remove()_ visible.
---
-<.> xref:#clear__[clear()]
-+
---
-Sets the clock to epoch, that is midnight, 1 Jan 1970 UTC.
---
-<.> xref:#setTime__int_int[setTime(int, int)]
-+
---
-Sets the hours and minutes as specified, and sets the seconds and milliseconds to zero, but the date portion is left unchanged.
---
-<.> xref:#setDate__int_int_int[setDate(int, int, int)]
-+
---
-Sets the date, but the time portion is left unchanged.
---
-<.> xref:#addTime__int_int[addTime(int, int)]
-+
---
-Adjusts the time by the specified number of hours and minutes.
---
-<.> xref:#addDate__int_int_int[addDate(int, int, int)]
-+
---
-Adjusts the time by the specified number of years, months or days.
---
-<.> xref:#reset__[reset()]
-+
---
-Go back to just returning the system's time.
---
-
-== Members
-
-[#initialize__]
-=== initialize()
-
-Configures the system to use a FixtureClock rather than the in-built system clock. Can be called multiple times.
-
-Must call before any other call to _Clock#getInstance()_ .
-
-[#remove__]
-=== remove()
-
-Makes _Clock#remove()_ visible.
-
-[#clear__]
-=== clear()
-
-Sets the clock to epoch, that is midnight, 1 Jan 1970 UTC.
-
-This is typically called before either _#setDate(int, int, int)_ (so that time is set to midnight) and/or _#setTime(int, int)_ (so that date is set to a well known value).
-
-[#setTime__int_int]
-=== setTime(int, int)
-
-Sets the hours and minutes as specified, and sets the seconds and milliseconds to zero, but the date portion is left unchanged.
-
-[#setDate__int_int_int]
-=== setDate(int, int, int)
-
-Sets the date, but the time portion is left unchanged.
-
-[#addTime__int_int]
-=== addTime(int, int)
-
-Adjusts the time by the specified number of hours and minutes.
-
-Typically called after _#setTime(int, int)_ , to move the clock forward or perhaps back.
-
-[#addDate__int_int_int]
-=== addDate(int, int, int)
-
-Adjusts the time by the specified number of years, months or days.
-
-Typically called after _#setDate(int, int, int)_ , to move the clock forward or perhaps back.
-
-[#reset__]
-=== reset()
-
-Go back to just returning the system's time.
diff --git a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/TickingFixtureClock.adoc b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/TickingFixtureClock.adoc
deleted file mode 100644
index c834f82..0000000
--- a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/clock/clock/TickingFixtureClock.adoc
+++ /dev/null
@@ -1,89 +0,0 @@
-= TickingFixtureClock
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-== API
-
-[source,java]
-.TickingFixtureClock.java
-----
-class TickingFixtureClock {
-  TickingFixtureClock replaceExisting()     // <.>
-  boolean reinstateExisting()     // <.>
-  void setTime(final int hour, final int min)     // <.>
-  void setTime(final Timestamp timestamp)
-  void setTime(final long millis)
-  void setDate(final int year, final int month, final int day)     // <.>
-  void addTime(final int hours, final int minutes)     // <.>
-  void addDate(final int years, final int months, final int days)     // <.>
-  String toString()
-}
-----
-
-<.> xref:#replaceExisting__[replaceExisting()]
-+
---
-Configures the system to use a FixtureClock rather than the in-built system clock. Can be called multiple times.
---
-<.> xref:#reinstateExisting__[reinstateExisting()]
-+
---
-Makes _Clock#remove()_ visible.
---
-<.> xref:#setTime__int_int[setTime(int, int)]
-+
---
-Sets the hours and minutes as specified, and sets the seconds and milliseconds to zero, but the date portion is left unchanged.
---
-<.> xref:#setDate__int_int_int[setDate(int, int, int)]
-+
---
-Sets the date, but the time portion is left unchanged.
---
-<.> xref:#addTime__int_int[addTime(int, int)]
-+
---
-Adjusts the time by the specified number of hours and minutes.
---
-<.> xref:#addDate__int_int_int[addDate(int, int, int)]
-+
---
-Adjusts the time by the specified number of years, months or days.
---
-
-== Members
-
-[#replaceExisting__]
-=== replaceExisting()
-
-Configures the system to use a FixtureClock rather than the in-built system clock. Can be called multiple times.
-
-Must call before any other call to _Clock#getInstance()_ .
-
-[#reinstateExisting__]
-=== reinstateExisting()
-
-Makes _Clock#remove()_ visible.
-
-[#setTime__int_int]
-=== setTime(int, int)
-
-Sets the hours and minutes as specified, and sets the seconds and milliseconds to zero, but the date portion is left unchanged.
-
-[#setDate__int_int_int]
-=== setDate(int, int, int)
-
-Sets the date, but the time portion is left unchanged.
-
-[#addTime__int_int]
-=== addTime(int, int)
-
-Adjusts the time by the specified number of hours and minutes.
-
-Typically called after _#setTime(int, int)_ , to move the clock forward or perhaps back.
-
-[#addDate__int_int_int]
-=== addDate(int, int, int)
-
-Adjusts the time by the specified number of years, months or days.
-
-Typically called after _#setDate(int, int, int)_ , to move the clock forward or perhaps back.
diff --git a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/FixturesLifecycleService.adoc b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/InitialFixtureScriptsInstaller.adoc
similarity index 79%
rename from antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/FixturesLifecycleService.adoc
rename to antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/InitialFixtureScriptsInstaller.adoc
index 27d2d8f..dd62022 100644
--- a/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/FixturesLifecycleService.adoc
+++ b/antora/components/refguide-index/modules/testing/pages/index/fixtures/applib/services/InitialFixtureScriptsInstaller.adoc
@@ -1,15 +1,14 @@
-= FixturesLifecycleService
+= InitialFixtureScriptsInstaller
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 == API
 
 [source,java]
-.FixturesLifecycleService.java
+.InitialFixtureScriptsInstaller.java
 ----
-class FixturesLifecycleService {
-  void postConstruct()
+class InitialFixtureScriptsInstaller {
+  InitialFixtureScriptsInstaller(final IsisConfiguration isisConfiguration, final FixtureScripts fixtureScripts)
   void onMetamodelEvent(final MetamodelEvent event)
-  void preDestroy()
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/IResourceContext.adoc b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/IResourceContext.adoc
index 46b4f7c..0282f14 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/IResourceContext.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/IResourceContext.adoc
@@ -26,11 +26,8 @@ interface IResourceContext {
   boolean suppressMemberDisabledReason()
   boolean canEagerlyRender(ManagedObject objectAdapter)     // <.>
   RepresentationService.Intent getIntent()     // <.>
-  AuthenticationProvider getAuthenticationContext()
-  SpecificationLoader getSpecificationLoader()
+  InteractionProvider getInteractionProvider()
   MetaModelContext getMetaModelContext()
-  ServiceRegistry getServiceRegistry()
-  IsisConfiguration getConfiguration()
   Optional<ManagedObject> getObjectAdapterForOidFromHref(String oidFromHref)
 }
 ----
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.adoc b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.adoc
index c405390..a5fe61e 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.adoc
@@ -1,7 +1,7 @@
 = AuthenticationStrategy _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Decouples the `IsisRestfulObjectsInteractionFilter` from the mechanism of obtaining the xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] .
+Decouples the `IsisRestfulObjectsInteractionFilter` from the mechanism of obtaining the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] .
 
 == API
 
@@ -9,8 +9,8 @@ Decouples the `IsisRestfulObjectsInteractionFilter` from the mechanism of obtain
 .AuthenticationStrategy.java
 ----
 interface AuthenticationStrategy {
-  Authentication lookupValid(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)     // <.>
-  void bind(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication auth)     // <.>
+  InteractionContext lookupValid(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)     // <.>
+  void bind(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, InteractionContext auth)     // <.>
   void invalidate(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
 }
 ----
@@ -18,12 +18,12 @@ interface AuthenticationStrategy {
 <.> xref:#lookupValid__HttpServletRequest_HttpServletResponse[lookupValid(HttpServletRequest, HttpServletResponse)]
 +
 --
-Returns a still-valid xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] or _null_
+Returns a still-valid xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] or _null_
 --
-<.> xref:#bind__HttpServletRequest_HttpServletResponse_Authentication[bind(HttpServletRequest, HttpServletResponse, Authentication)]
+<.> xref:#bind__HttpServletRequest_HttpServletResponse_InteractionContext[bind(HttpServletRequest, HttpServletResponse, InteractionContext)]
 +
 --
-Binds the request to a still-valid xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if applicable
+Binds the request to a still-valid xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] if applicable
 --
 
 == Members
@@ -31,9 +31,9 @@ Binds the request to a still-valid xref:refguide:core:index/security/authenticat
 [#lookupValid__HttpServletRequest_HttpServletResponse]
 === lookupValid(HttpServletRequest, HttpServletResponse)
 
-Returns a still-valid xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] or _null_
+Returns a still-valid xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] or _null_
 
-[#bind__HttpServletRequest_HttpServletResponse_Authentication]
-=== bind(HttpServletRequest, HttpServletResponse, Authentication)
+[#bind__HttpServletRequest_HttpServletResponse_InteractionContext]
+=== bind(HttpServletRequest, HttpServletResponse, InteractionContext)
 
-Binds the request to a still-valid xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if applicable
+Binds the request to a still-valid xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] if applicable
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.adoc b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.adoc
index bce49b1..0953d1f 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.adoc
@@ -1,7 +1,7 @@
 = AuthenticationStrategyBasicAuth
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Implements the HTTP Basic Auth protocol; does not bind the xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] onto the _HttpSession_ .
+Implements the HTTP Basic Auth protocol; does not bind the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] onto the _HttpSession_ .
 
 == API
 
@@ -11,8 +11,8 @@ Implements the HTTP Basic Auth protocol; does not bind the xref:refguide:core:in
 class AuthenticationStrategyBasicAuth {
   public static final String HEADER_AUTHORIZATION;
   public static final String BASIC_AUTH_PREFIX;
-  Authentication lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
-  void bind(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication auth)
+  InteractionContext lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
+  void bind(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, InteractionContext auth)
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.adoc b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.adoc
index 6b334ee..6c3cff9 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.adoc
@@ -1,7 +1,7 @@
 = AuthenticationStrategyDefault
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-Returns a valid xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] through a number of mechanisms; supports caching of the xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] onto the _HttpSession_ .
+Returns a valid xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] through a number of mechanisms; supports caching of the xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] onto the _HttpSession_ .
 
 The session is looked-up as follows:
 
@@ -14,8 +14,8 @@ The session is looked-up as follows:
 ----
 class AuthenticationStrategyDefault {
   public static final String HTTP_SESSION_AUTHENTICATION_SESSION_KEY;
-  Authentication lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
-  void bind(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse, final Authentication authentication)
+  InteractionContext lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
+  void bind(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse, final InteractionContext authentication)
 }
 ----
 
diff --git a/core/adoc/modules/_overview/pages/about.adoc b/core/adoc/modules/_overview/pages/about.adoc
index 1ddb743..95e7a1f 100644
--- a/core/adoc/modules/_overview/pages/about.adoc
+++ b/core/adoc/modules/_overview/pages/about.adoc
@@ -511,7 +511,7 @@ Directory: /testing/fixtures/applib
 |.Components
 ****
 o.a.i.testing.fixtures.applib.modules.ModuleWithFixturesService +
-o.a.i.testing.fixtures.applib.queryresultscache.QueryResultsCacheControlDefault +
+o.a.i.testing.fixtures.applib.queryresultscache.QueryResultsCacheControlForFixtures +
 o.a.i.testing.fixtures.applib.services.FixturesLifecycleService +
 ****
 
@@ -527,7 +527,7 @@ org.apache.isis.testing:isis-testing-integtestsupport-applib:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:testing:index/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.adoc[IsisIntegrationTestAbstractWithFixtures], xref:refguide:testing:index/fixtures/applib/clock/TickingClockFixture.adoc[TickingClockFixture], xref:refguide:testing:index/fixtures/applib/clock/clock/Clock.adoc[Clock], xref:refguide:testing:index/fixtures/applib/clock/clock/FixtureClock.adoc[FixtureClock], xref:refguide:testing:index/fixtures/applib/clock/clock/TickingFixtureClock.adoc[TickingFixtureClock [...]
+xref:refguide:testing:index/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.adoc[IsisIntegrationTestAbstractWithFixtures], xref:refguide:testing:index/fixtures/applib/events/FixturesInstalledEvent.adoc[FixturesInstalledEvent], xref:refguide:testing:index/fixtures/applib/events/FixturesInstallingEvent.adoc[FixturesInstallingEvent], xref:refguide:testing:index/fixtures/applib/fixturescripts/ExecutionParameters.adoc[ExecutionParameters], xref:refguide:testing:index/fixtures/applib/f [...]
 ****
 
 |Apache Isis Tst - H2 Console (parent)
@@ -1504,6 +1504,7 @@ default (Java) programming model.
 o.a.i.applib.annotation.DomainObject +
 o.a.i.applib.annotation.DomainService +
 o.a.i.applib.annotation.Value +
+o.a.i.applib.services.clock.ClockService +
 o.a.i.applib.services.commanddto.conmap.ContentMappingServiceForCommandDto +
 o.a.i.applib.services.commanddto.conmap.ContentMappingServiceForCommandsDto +
 o.a.i.applib.services.commanddto.processor.spi.CommandDtoProcessorServiceIdentity +
@@ -1511,7 +1512,10 @@ o.a.i.applib.services.publishing.log.CommandLogger +
 o.a.i.applib.services.publishing.log.EntityChangesLogger +
 o.a.i.applib.services.publishing.log.EntityPropertyChangeLogger +
 o.a.i.applib.services.publishing.log.ExecutionLogger +
+o.a.i.applib.services.queryresultscache.QueryResultsCache +
 o.a.i.applib.services.session.SessionLoggingServiceLogging +
+o.a.i.applib.services.sudo.SudoService +
+o.a.i.applib.services.user.UserService +
 ****
 
 .Dependencies
@@ -1526,7 +1530,7 @@ org.jmock:jmock:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:applib:index/AbstractViewModel.adoc[AbstractViewModel], xref:refguide:applib:index/Identifier.adoc[Identifier], xref:refguide:applib:index/IsisModuleApplib.adoc[IsisModuleApplib], xref:refguide:applib:index/RecreatableDomainObject.adoc[RecreatableDomainObject], xref:refguide:applib:index/ViewModel.adoc[ViewModel], xref:refguide:applib:index/adapters/AbstractValueSemanticsProvider.adoc[AbstractValueSemanticsProvider], xref:refguide:applib:index/adapters/DefaultsProvider.adoc [...]
+xref:refguide:applib:index/AbstractViewModel.adoc[AbstractViewModel], xref:refguide:applib:index/Identifier.adoc[Identifier], xref:refguide:applib:index/IsisModuleApplib.adoc[IsisModuleApplib], xref:refguide:applib:index/RecreatableDomainObject.adoc[RecreatableDomainObject], xref:refguide:applib:index/ViewModel.adoc[ViewModel], xref:refguide:applib:index/adapters/AbstractValueSemanticsProvider.adoc[AbstractValueSemanticsProvider], xref:refguide:applib:index/adapters/DefaultsProvider.adoc [...]
 ****
 
 |Apache Isis Core - Code Gen (ByteBuddy)
@@ -1613,11 +1617,6 @@ org.apache.isis.core:isis-core-internaltestsupport:jar:<managed> +
 org.apache.isis.core:isis-core-metamodel:jar:<managed> +
 ****
 
-.Document Index Entries
-****
-xref:refguide:core:index/interaction/session/InteractionFactory.adoc[InteractionFactory]
-****
-
 |Apache Isis Core - Unit Test Support
 [source,yaml]
 ----
@@ -1740,7 +1739,6 @@ Directory: /core/runtimeservices
 .Components
 ****
 o.a.i.core.runtimeservices.bookmarks.BookmarkServiceDefault +
-o.a.i.core.runtimeservices.clock.ClockServiceDefault +
 o.a.i.core.runtimeservices.command.CommandDtoFactoryDefault +
 o.a.i.core.runtimeservices.command.CommandExecutorServiceDefault +
 o.a.i.core.runtimeservices.email.EmailServiceDefault +
@@ -1758,19 +1756,16 @@ o.a.i.core.runtimeservices.publish.CommandPublisherDefault +
 o.a.i.core.runtimeservices.publish.EntityChangesPublisherDefault +
 o.a.i.core.runtimeservices.publish.EntityPropertyChangePublisherDefault +
 o.a.i.core.runtimeservices.publish.ExecutionPublisherDefault +
-o.a.i.core.runtimeservices.queryresultscache.QueryResultsCacheDefault +
 o.a.i.core.runtimeservices.recognizer.ExceptionRecognizerServiceDefault +
 o.a.i.core.runtimeservices.recognizer.dae.ExceptionRecognizerForDataAccessException +
 o.a.i.core.runtimeservices.repository.RepositoryServiceDefault +
 o.a.i.core.runtimeservices.routing.RoutingServiceDefault +
 o.a.i.core.runtimeservices.scratchpad.ScratchpadDefault +
-o.a.i.core.runtimeservices.session.InteractionFactoryDefault +
-o.a.i.core.runtimeservices.sudo.SudoServiceDefault +
+o.a.i.core.runtimeservices.session.InteractionServiceDefault +
 o.a.i.core.runtimeservices.transaction.TransactionServiceSpring +
 o.a.i.core.runtimeservices.urlencoding.UrlEncodingServiceWithCompression +
 o.a.i.core.runtimeservices.user.ImpersonateMenuAdvisorDefault +
 o.a.i.core.runtimeservices.user.ImpersonatedUserHolderDefault +
-o.a.i.core.runtimeservices.user.UserServiceDefault +
 o.a.i.core.runtimeservices.userreg.EmailNotificationServiceDefault +
 o.a.i.core.runtimeservices.wrapper.WrapperFactoryDefault +
 o.a.i.core.runtimeservices.xml.XmlServiceDefault +
@@ -1817,7 +1812,7 @@ org.junit.vintage:junit-vintage-engine:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication], xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest], xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator], xref:refguide:core:index/security/authentication/manager/AnonymousInteractionFactory.adoc[AnonymousInteractionFactory], xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor], xref:refguide:core:index/ [...]
+xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest], xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator], xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor], xref:refguide:core:index/security/authorization/manager/AuthorizationManager.adoc[AuthorizationManager], xref:refguide:core:index/security/authorization/manager/AuthorizorChooser.adoc[AuthorizorChooser]
 ****
 
 |Apache Isis Core - Transaction
@@ -4831,9 +4826,7 @@ for obtaining commands from a primary and saving them so that they are replayed.
 o.a.i.extensions.commandreplay.secondary.analyser.CommandReplayAnalyserException +
 o.a.i.extensions.commandreplay.secondary.analyser.CommandReplayAnalyserResult +
 o.a.i.extensions.commandreplay.secondary.analysis.CommandReplayAnalysisService +
-o.a.i.extensions.commandreplay.secondary.clock.TickingClockService +
 o.a.i.extensions.commandreplay.secondary.config.SecondaryConfig +
-o.a.i.extensions.commandreplay.secondary.executor.CommandExecutorServiceWithTime +
 o.a.i.extensions.commandreplay.secondary.fetch.CommandFetcher +
 ****
 
@@ -4852,7 +4845,7 @@ org.apache.isis.testing:isis-testing-fixtures-applib:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:extensions:index/commandreplay/secondary/IsisModuleExtCommandReplaySecondary.adoc[IsisModuleExtCommandReplaySecondary], xref:refguide:extensions:index/commandreplay/secondary/SecondaryStatus.adoc[SecondaryStatus], xref:refguide:extensions:index/commandreplay/secondary/analyser/CommandReplayAnalyser.adoc[CommandReplayAnalyser], xref:refguide:extensions:index/commandreplay/secondary/analyser/CommandReplayAnalyserException.adoc[CommandReplayAnalyserException], xref:refguide:ex [...]
+xref:refguide:extensions:index/commandreplay/secondary/IsisModuleExtCommandReplaySecondary.adoc[IsisModuleExtCommandReplaySecondary], xref:refguide:extensions:index/commandreplay/secondary/SecondaryStatus.adoc[SecondaryStatus], xref:refguide:extensions:index/commandreplay/secondary/analyser/CommandReplayAnalyser.adoc[CommandReplayAnalyser], xref:refguide:extensions:index/commandreplay/secondary/analyser/CommandReplayAnalyserException.adoc[CommandReplayAnalyserException], xref:refguide:ex [...]
 ****
 |===
 
@@ -5091,7 +5084,7 @@ org.jdom:jdom2:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:subdomains:index/docx/applib/DocxService.adoc[DocxService], xref:refguide:subdomains:index/docx/applib/DocxService~MergeDefinition.adoc[DocxService.MergeDefinition]
+xref:refguide:subdomains:index/docx/applib/DocxService.adoc[DocxService], xref:refguide:subdomains:index/docx/applib/DocxService~MergeParams.adoc[DocxService.MergeParams]
 ****
 
 |Apache Isis Sub - Freemarker (parent)

[isis] 06/08: ISIS-2732: deletes fixture library's Clock

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 3f98ae56d0149921b2512f32f0ab28ff78e23b01
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 12:04:42 2021 +0100

    ISIS-2732: deletes fixture library's Clock
    
    Not to be confused with the applib's VirtualClock
---
 .../testing/fixtures/applib/clock/clock/Clock.java | 154 ---------------------
 1 file changed, 154 deletions(-)

diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/Clock.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/Clock.java
deleted file mode 100644
index 4637916..0000000
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/Clock.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.testing.fixtures.applib.clock.clock;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.OffsetDateTime;
-import java.time.ZoneId;
-import java.util.Date;
-
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-
-import lombok.val;
-
-/**
- * Provides a mechanism to get (and possible to set) the current time.
- *
- * <p>
- * The clock is used primarily by the temporal value classes, and is accessed by
- * the framework as a singleton. The actual implementation used can be configured at
- * startup, but once specified the clock instance cannot be changed.
- *
- * <p>
- * Unless another {@link Clock} implementation has been installed, the first
- * call to {@link #getInstance()} will instantiate an implementation that just
- * uses the system's own clock. Alternate implementations can be created via
- * suitable subclasses, but this must be done <b><i>before</i></b> the first
- * call to {@link #getInstance()}.
- *
- * @since 2.x {@index}
- */
-public abstract class Clock {
-
-    protected static Clock instance;
-
-    /**
-     * Returns the (singleton) instance of {@link Clock}.
-     *
-     * <p>
-     * Unless it has been otherwise created, will lazily instantiate an
-     * implementation that just delegate to the computer's own system clock (as
-     * per {@link System#currentTimeMillis()}.
-     */
-    public static final Clock getInstance() {
-        if (!isInitialized()) {
-            instance = new SystemClock();
-        }
-        return instance;
-    }
-
-    /**
-     * Whether has been initialized or not.
-     */
-    public static boolean isInitialized() {
-        return instance != null;
-    }
-
-    /**
-     * The time as the number of milliseconds since the epoch start. (UTC)
-     *
-     * @see Date#getTime()
-     */
-    public static long getEpochMillis() {
-        return getInstance().now().toEpochMilli();
-    }
-
-    public static LocalDate getTimeAsLocalDate() {
-        return getTimeAsLocalDateTime().toLocalDate();
-    }
-
-    public static LocalDateTime getTimeAsLocalDateTime() {
-        val zoneId = ZoneId.systemDefault();
-        return LocalDateTime.ofInstant(getInstance().now(), zoneId);
-    }
-
-    /**
-     * Returns the time as {@link OffsetDateTime},
-     * using the {@link ZoneId#systemDefault() system default} timezone.
-     */
-    public static OffsetDateTime getTimeAsOffsetDateTime() {
-        val zoneId = ZoneId.systemDefault();
-        return OffsetDateTime.ofInstant(getInstance().now(), zoneId);
-    }
-
-
-    public static Timestamp getTimeAsJavaSqlTimestamp() {
-        return new java.sql.Timestamp(getEpochMillis());
-    }
-
-    /**
-     * Returns the time as a Joda {@link DateTime},
-     * using the {@link ZoneId#systemDefault() system default} timezone.
-     */
-    public static DateTime getTimeAsJodaDateTime() {
-        final ZoneId zoneId = ZoneId.systemDefault();
-        return new DateTime(getInstance().now().toEpochMilli(), DateTimeZone.forID(zoneId.getId()));
-    }
-
-    /**
-     * Allows subclasses to remove their implementation.
-     *
-     * @return whether a clock was removed.
-     */
-    protected static boolean remove() {
-        if (instance == null) {
-            return false;
-        }
-        instance = null;
-        return true;
-    }
-
-    protected Clock() {
-        instance = this;
-    }
-
-
-    /**
-     * The current time represented by an instant, either measured or simulated.
-     */
-    protected abstract Instant now();
-
-
-}
-
-final class SystemClock extends Clock {
-
-    SystemClock() {}
-
-    @Override
-    protected Instant now() {
-        return Instant.now();
-    }
-
-}
-

[isis] 01/08: ISIS-2732: removes methods to set clock from IsisIntegrationTestAbstractWithFixtures

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 535548d262b1dc977b0434c526515f75fe71200c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 11:48:30 2021 +0100

    ISIS-2732: removes methods to set clock from IsisIntegrationTestAbstractWithFixtures
---
 .../IsisIntegrationTestAbstractWithFixtures.java   | 44 +---------------------
 1 file changed, 2 insertions(+), 42 deletions(-)

diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.java
index d6b3826..7ad0d6f 100644
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.java
+++ b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisIntegrationTestAbstractWithFixtures.java
@@ -20,19 +20,14 @@ package org.apache.isis.testing.fixtures.applib;
 
 import javax.inject.Inject;
 
-import org.joda.time.LocalDate;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 
-import org.apache.isis.applib.services.clock.ClockService;
-import org.apache.isis.testing.fixtures.applib.personas.PersonaWithBuilderScript;
-import org.apache.isis.testing.fixtures.applib.clock.clock.Clock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.FixtureClock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.TickingFixtureClock;
-import org.apache.isis.testing.fixtures.applib.personas.BuilderScriptAbstract;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
 import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixturesService;
+import org.apache.isis.testing.fixtures.applib.personas.BuilderScriptAbstract;
+import org.apache.isis.testing.fixtures.applib.personas.PersonaWithBuilderScript;
 import org.apache.isis.testing.integtestsupport.applib.IsisIntegrationTestAbstract;
 
 /**
@@ -56,41 +51,6 @@ public abstract class IsisIntegrationTestAbstractWithFixtures extends IsisIntegr
         return this.fixtureScripts.runPersona(personaScript);
     }
 
-    /**
-     * To use instead of {@link #getFixtureClock()}'s {@link FixtureClock#setDate(int, int, int)} ()}.
-     */
-    protected void setFixtureClockDate(final LocalDate date) {
-        if(date == null) {
-            return;
-        }
-        setFixtureClockDate(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth());
-    }
-
-    /**
-     * To use instead of {@link #getFixtureClock()}'s {@link FixtureClock#setDate(int, int, int)} ()}.
-     */
-    protected void setFixtureClockDate(final int year, final int month, final int day) {
-
-        final Clock instance = Clock.getInstance();
-
-        if(instance instanceof TickingFixtureClock) {
-            TickingFixtureClock.reinstateExisting();
-            getFixtureClock().setDate(year, month, day);
-            TickingFixtureClock.replaceExisting();
-        }
-
-        if(instance instanceof FixtureClock) {
-            getFixtureClock().setDate(year, month, day);
-        }
-    }
-
-    /**
-     * If just require the current time, use {@link ClockService}
-     */
-    private FixtureClock getFixtureClock() {
-        return ((FixtureClock)FixtureClock.getInstance());
-    }
-
     // -- DEPENDENCIES
 
     @BeforeEach

[isis] 05/08: ISIS-2732: deletes FixtureClock

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 7b1efa1673409b46f2217233b50dc79a89f07648
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 12:03:52 2021 +0100

    ISIS-2732: deletes FixtureClock
---
 .../fixtures/applib/clock/clock/FixtureClock.java  | 214 ---------------------
 .../legacy/FixtureClockInstantiationTest.java      |  60 ------
 2 files changed, 274 deletions(-)

diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/FixtureClock.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/FixtureClock.java
deleted file mode 100644
index 4ab3aa7..0000000
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/clock/clock/FixtureClock.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.testing.fixtures.applib.clock.clock;
-
-import java.time.Instant;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-
-/**
- * This clock, for use by fixtures, can be set to specific time.
- *
- * <p>
- * If not set it will provide the time provided by the system clock.
- *
- * <p>
- * Note that - by design - it does not provide any mechanism to advance the time
- * (eg automatic ticking of the clock). That is, the time returned is always
- * explicitly under the control of the programmer (it can be moved forward or
- * back as required).
- *
- * @since 2.x {@index}
- */
-public class FixtureClock extends Clock {
-    private static final TimeZone UTC_TIME_ZONE;
-
-    static {
-        TimeZone tempTimeZone = TimeZone.getTimeZone("Etc/UTC");
-        if (tempTimeZone == null) {
-            tempTimeZone = TimeZone.getTimeZone("UTC");
-        }
-        UTC_TIME_ZONE = tempTimeZone;
-    }
-
-    /**
-     * Configures the system to use a FixtureClock rather than the in-built
-     * system clock. Can be called multiple times.
-     *
-     * <p>
-     * Must call before any other call to {@link Clock#getInstance()}.
-     *
-     * @throws IllegalStateException
-     *             if Clock singleton already initialized with some other
-     *             implementation.
-     */
-    public synchronized static FixtureClock initialize() {
-        if (!isInitialized() || !(getInstance() instanceof FixtureClock)) {
-            // installs the FixtureClock as the Clock singleton via the Clock's
-            // constructor
-            // if was initialized, then will replace.
-            // (if non-replaceable, then superclass will throw exception for us.
-            new FixtureClock();
-        }
-        return (FixtureClock) getInstance();
-    }
-
-    /**
-     * Makes {@link Clock#remove()} visible.
-     */
-    public static boolean remove() {
-        return Clock.remove();
-    }
-
-    // //////////////////////////////////////////////////
-    // Constructor
-    // //////////////////////////////////////////////////
-
-    // if non-null, then indicates that the time has been explicitly set.
-    // Otherwise returns the system time.
-    private Calendar calendar = null;
-
-    private FixtureClock() {
-    }
-
-    // //////////////////////////////////////////////////
-    // hook
-    // //////////////////////////////////////////////////
-
-    /**
-     * Access via {@link Clock#getInstance()}.
-     *
-     * <p>
-     * Will just return the system time until {@link #setDate(int, int, int)} or
-     * {@link #setTime(int, int)} (or one of the overloads) has been called.
-     */
-    @Override
-    protected Instant now() {
-        if (calendar == null) {
-            return Instant.now();
-        }
-        return calendar.toInstant();
-    }
-
-    // //////////////////////////////////////////////////
-    // setting/adjusting time
-    // //////////////////////////////////////////////////
-
-    /**
-     * Sets the clock to epoch, that is midnight, 1 Jan 1970 UTC.
-     *
-     * <p>
-     * This is typically called before either {@link #setDate(int, int, int)}
-     * (so that time is set to midnight) and/or {@link #setTime(int, int)} (so
-     * that date is set to a well known value).
-     */
-    public void clear() {
-        setupCalendarIfRequired();
-        calendar.clear();
-    }
-
-    /**
-     * Sets the hours and minutes as specified, and sets the seconds and
-     * milliseconds to zero, but the date portion is left unchanged.
-     *
-     * @see #setDate(int, int, int)
-     * @see #addTime(int, int)
-     */
-    public void setTime(final int hour, final int min) {
-        setupCalendarIfRequired();
-        calendar.set(Calendar.HOUR_OF_DAY, hour);
-        calendar.set(Calendar.MINUTE, min);
-        calendar.set(Calendar.SECOND, 0);
-        calendar.set(Calendar.MILLISECOND, 0);
-    }
-
-    /**
-     * Sets the date, but the time portion is left unchanged.
-     *
-     * @see #setTime(int, int)
-     * @see #addDate(int, int, int)
-     */
-    public void setDate(final int year, final int month, final int day) {
-        setupCalendarIfRequired();
-        calendar.set(Calendar.YEAR, year);
-        calendar.set(Calendar.MONTH, month - 1);
-        calendar.set(Calendar.DAY_OF_MONTH, day);
-    }
-
-    /**
-     * Adjusts the time by the specified number of hours and minutes.
-     *
-     * <p>
-     * Typically called after {@link #setTime(int, int)}, to move the clock
-     * forward or perhaps back.
-     *
-     * @see #addDate(int, int, int)
-     */
-    public void addTime(final int hours, final int minutes) {
-        setupCalendarIfRequired();
-        calendar.add(Calendar.HOUR_OF_DAY, hours);
-        calendar.add(Calendar.MINUTE, minutes);
-    }
-
-    /**
-     * Adjusts the time by the specified number of years, months or days.
-     *
-     * <p>
-     * Typically called after {@link #setDate(int, int, int)}, to move the clock
-     * forward or perhaps back.
-     *
-     * @see #addTime(int, int)
-     */
-    public void addDate(final int years, final int months, final int days) {
-        setupCalendarIfRequired();
-        calendar.add(Calendar.YEAR, years);
-        calendar.add(Calendar.MONTH, months);
-        calendar.add(Calendar.DAY_OF_MONTH, days);
-    }
-
-    private void setupCalendarIfRequired() {
-        if (calendar != null) {
-            return;
-        }
-        calendar = Calendar.getInstance();
-        calendar.setTimeZone(UTC_TIME_ZONE);
-    }
-
-    // //////////////////////////////////////////////////
-    // reset
-    // //////////////////////////////////////////////////
-
-    /**
-     * Go back to just returning the system's time.
-     */
-    public void reset() {
-        calendar = null;
-    }
-
-    // //////////////////////////////////////////////////
-    // toString
-    // //////////////////////////////////////////////////
-
-    @Override
-    public String toString() {
-        return (calendar == null ? "System" : "Explicitly set") + ": " + Clock.getTimeAsOffsetDateTime().toString();
-    }
-
-}
diff --git a/testing/fixtures/applib/src/test/java/org/apache/isis/testing/fixtures/applib/legacy/FixtureClockInstantiationTest.java b/testing/fixtures/applib/src/test/java/org/apache/isis/testing/fixtures/applib/legacy/FixtureClockInstantiationTest.java
deleted file mode 100644
index 5d82271..0000000
--- a/testing/fixtures/applib/src/test/java/org/apache/isis/testing/fixtures/applib/legacy/FixtureClockInstantiationTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.testing.fixtures.applib.legacy;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import org.apache.isis.testing.fixtures.applib.clock.clock.Clock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.FixtureClock;
-
-public class FixtureClockInstantiationTest {
-
-    @BeforeEach
-    public void setUp() {
-
-    }
-
-    @Test
-    public void shouldSetupClockSingletonWithFixtureClockWhenInitialize() {
-        FixtureClock.initialize();
-        assertThat(Clock.getInstance(), is(instanceOf(FixtureClock.class)));
-    }
-
-    @Test
-    public void canInitializeFixtureClockMultipleTimesButAlwaysGetTheSameFixtureClock() {
-        final FixtureClock fixtureClock1 = FixtureClock.initialize();
-        final FixtureClock fixtureClock2 = FixtureClock.initialize();
-        assertThat(fixtureClock1, CoreMatchers.is(fixtureClock2));
-    }
-
-    @Test
-    public void canRemoveFixtureClock() {
-        FixtureClock.initialize();
-        assertThat(FixtureClock.remove(), is(true));
-        assertThat(FixtureClock.remove(), is(false)); // already removed.
-    }
-
-}

[isis] 04/08: ISIS-2732: renames FixturesLifecycleService to InitialFixtureScriptsInstaller

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit d1a5cf1483c8c86c6375ccab95888eb8d4bfb6a1
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 12:00:12 2021 +0100

    ISIS-2732: renames FixturesLifecycleService to InitialFixtureScriptsInstaller
    
    to reflect its actual responsibilities
---
 .../modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc | 2 +-
 .../testing/fixtures/applib/IsisModuleTestingFixturesApplib.java  | 4 ++--
 ...sLifecycleService.java => InitialFixtureScriptsInstaller.java} | 8 +++-----
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc
index 05d3187..fbfdc5f 100644
--- a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc
+++ b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc
@@ -20,7 +20,7 @@ It is not recommended that your code use the `Clock` directly, but it's worth un
 This is a read-only clock that reads from the system time.
 The instance registers itself as the singleton and cannot be replaced.
 
-* If running in xref:refguide:config:about.adoc#deployment-types[prototype] mode, though, then the framework (using `FixturesLifecycleService`) will instead instantiate `FixtureClock`.
+* If running in xref:refguide:config:about.adoc#deployment-types[prototype] mode, though, then the framework (using `InitialFixtureScriptsInstaller`) will instead instantiate `FixtureClock`.
 This is a read-write clock that will behave as the system clock, unless it is explicitly set using eg, `FixtureClock#setDate(...)` or `FixtureClock#setTime(...)` etc.
 
 Moreover, the `FixtureClock` singleton can be replaced with another implementation.
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisModuleTestingFixturesApplib.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisModuleTestingFixturesApplib.java
index 7e65b79..d6e128a 100644
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisModuleTestingFixturesApplib.java
+++ b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/IsisModuleTestingFixturesApplib.java
@@ -25,7 +25,7 @@ import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
 import org.apache.isis.testing.fixtures.applib.queryresultscache.QueryResultsCacheControlForFixtures;
 import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixturesService;
 import org.apache.isis.subdomains.spring.applib.IsisModuleSubdomainsSpringApplib;
-import org.apache.isis.testing.fixtures.applib.services.FixturesLifecycleService;
+import org.apache.isis.testing.fixtures.applib.services.InitialFixtureScriptsInstaller;
 
 @Configuration
 @Import({
@@ -33,7 +33,7 @@ import org.apache.isis.testing.fixtures.applib.services.FixturesLifecycleService
         IsisModuleSubdomainsSpringApplib.class,
 
         // @Service's
-        FixturesLifecycleService.class,
+        InitialFixtureScriptsInstaller.class,
         ModuleWithFixturesService.class,
         QueryResultsCacheControlForFixtures.class,
 
diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/InitialFixtureScriptsInstaller.java
similarity index 93%
rename from testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java
rename to testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/InitialFixtureScriptsInstaller.java
index 94f9add..c090602 100644
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java
+++ b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/InitialFixtureScriptsInstaller.java
@@ -30,25 +30,23 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.events.MetamodelEvent;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
 
-import lombok.SneakyThrows;
 import lombok.extern.log4j.Log4j2;
 
 /**
  * @since 2.0 {@index}
  */
 @Service
-@Named("isis.testing.fixtures.FixturesLifecycleService")
+@Named("isis.testing.fixtures.InitialFixtureScriptsInstaller")
 @Order(OrderPrecedence.MIDPOINT)
 @Primary
 @Qualifier("Default")
 @Log4j2
-public class FixturesLifecycleService {
+public class InitialFixtureScriptsInstaller {
 
     @SuppressWarnings("unused")
 
@@ -57,7 +55,7 @@ public class FixturesLifecycleService {
     private FixtureScript initialFixtureScript;
 
     @Inject
-    public FixturesLifecycleService(
+    public InitialFixtureScriptsInstaller(
             final IsisConfiguration isisConfiguration,
             final FixtureScripts fixtureScripts) {
 

[isis] 07/08: ISIS-2732: adds docs on mocking clock and user

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 39748295bf0f064cccc5e64ba7318274d3ebf88e
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 13:12:57 2021 +0100

    ISIS-2732: adds docs on mocking clock and user
---
 .../services/command/CommandExecutorService.java   | 24 +++----
 .../services/iactnlayer/InteractionContext.java    | 59 ++++++++++++++++
 .../InteractionContext_combine_Test.java           | 25 +++++++
 .../command/CommandExecutorServiceDefault.java     | 18 ++---
 .../jobcallables/ReplicateAndRunCommands.java      |  2 +-
 .../adoc/modules/fixtures/pages/about.adoc         |  6 +-
 .../fixture-scripts/mocking-the-clock-or-user.adoc | 79 ++++++++++++++++++++++
 .../pages/fixture-scripts/mocking-the-clock.adoc   | 49 --------------
 .../pages/fixture-scripts/sudo-service.adoc        | 55 ---------------
 9 files changed, 187 insertions(+), 130 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/command/CommandExecutorService.java b/api/applib/src/main/java/org/apache/isis/applib/services/command/CommandExecutorService.java
index fceb8f2..bae583d 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/command/CommandExecutorService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/command/CommandExecutorService.java
@@ -47,7 +47,7 @@ public interface CommandExecutorService {
      *
      * @since 1.x {@index}
      */
-    enum SudoPolicy {
+    enum InteractionContextPolicy {
 
         /**
          * Execute within the same {@link org.apache.isis.applib.services.iactnlayer.InteractionContext} as the
@@ -89,26 +89,26 @@ public interface CommandExecutorService {
 
         public final BiFunction<InteractionContext, CommandDto, InteractionContext> mapper;
 
-        private SudoPolicy(BiFunction<InteractionContext, CommandDto, InteractionContext> mapper) {
+        private InteractionContextPolicy(BiFunction<InteractionContext, CommandDto, InteractionContext> mapper) {
             this.mapper = mapper;
         }
     }
 
     /**
-     * Executes the specified {@link Command} using the required {@link SudoPolicy}, updating the Command (or its
+     * Executes the specified {@link Command} using the required {@link InteractionContextPolicy}, updating the Command (or its
      * persistent equivalent) afterwards (for example, setting its {@link Command#getCommandDto() commandDto} field.
      *
-     * @param sudoPolicy - policy to use
+     * @param interactionContextPolicy - policy to use
      * @param command - the {@link Command} to be executed
      * @return - a bookmark representing the result of executing the command (could be null)
      */
     Bookmark executeCommand(
-            SudoPolicy sudoPolicy,
+            InteractionContextPolicy interactionContextPolicy,
             Command command
     );
 
     /**
-     * Executes the specified command (represented as a {@link CommandDto} using the required {@link SudoPolicy}.
+     * Executes the specified command (represented as a {@link CommandDto} using the required {@link InteractionContextPolicy}.
      *
      * <p>
      *     IMPORTANT: THIS METHOD HAS SIGNIFICANT SIDE-EFFECTS.  Specifically, the {@link Command} of the executing
@@ -122,38 +122,38 @@ public interface CommandExecutorService {
      * used by the persistent implementations to update their respective persistent equivalents of {@link Command}.
      * </p>
      *
-     * @param sudoPolicy - policy to use
+     * @param interactionContextPolicy - policy to use
      * @param commandDto - the {@link CommandDto} to be executed
      * @param outcomeHandler - callback to handle the result
      *
      * @return - a bookmark representing the result of executing the command (could be null)
      */
     Bookmark executeCommand(
-            SudoPolicy sudoPolicy,
+            InteractionContextPolicy interactionContextPolicy,
             CommandDto commandDto,
             CommandOutcomeHandler outcomeHandler);
 
     /**
-     * As per {@link #executeCommand(SudoPolicy, Command)}, with a policy of {@link SudoPolicy#NO_SWITCH no switch}.
+     * As per {@link #executeCommand(InteractionContextPolicy, Command)}, with a policy of {@link InteractionContextPolicy#NO_SWITCH no switch}.
      *
      * <p>
      *     Note that this method updates the Command as a side-effect.
      * </p>
      *
-     * @see #executeCommand(SudoPolicy, Command)
+     * @see #executeCommand(InteractionContextPolicy, Command)
      */
     Bookmark executeCommand(
             Command command
     );
 
     /**
-     * As per {@link #executeCommand(SudoPolicy, CommandDto, CommandOutcomeHandler)}, with a policy of {@link SudoPolicy#NO_SWITCH no switch}.
+     * As per {@link #executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)}, with a policy of {@link InteractionContextPolicy#NO_SWITCH no switch}.
      *
      * <p>
      *     Note that this method has significant side-effects.
      * </p>
      *
-     * @see #executeCommand(SudoPolicy, CommandDto, CommandOutcomeHandler)
+     * @see #executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)
      *
      * @param commandDto
      * @param outcomeHandler
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
index 394de8f..1d75cb7 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactnlayer/InteractionContext.java
@@ -21,6 +21,8 @@ package org.apache.isis.applib.services.iactnlayer;
 import java.io.Serializable;
 import java.util.Locale;
 import java.util.TimeZone;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
 
 import org.apache.isis.applib.clock.VirtualClock;
 import org.apache.isis.applib.services.iactn.Interaction;
@@ -86,6 +88,63 @@ public class InteractionContext implements Serializable {
     @NonNull TimeZone timeZone = TimeZone.getDefault();
 
 
+    /**
+     * Convenience method for use with {@link org.apache.isis.applib.services.sudo.SudoService}, returning a
+     * {@link UnaryOperator} that will act upon the provided {@link InteractionContext} to return the same but with
+     * the specified {@link UserMemento}.
+     */
+    public static UnaryOperator<InteractionContext> switchUser(@NonNull final UserMemento userMemento) {
+        return interactionContext -> interactionContext.withUser(userMemento);
+    }
+
+    /**
+     * Convenience method for use with {@link org.apache.isis.applib.services.sudo.SudoService}, returning a
+     * {@link UnaryOperator} that will act upon the provided {@link InteractionContext} to return the same but with
+     * the specified {@link VirtualClock}.
+     */
+    public static UnaryOperator<InteractionContext> switchClock(@NonNull final VirtualClock clock) {
+        return interactionContext -> interactionContext.withClock(clock);
+    }
+
+    /**
+     * Convenience method for use with {@link org.apache.isis.applib.services.sudo.SudoService}, returning a
+     * {@link UnaryOperator} that will act upon the provided {@link InteractionContext} to return the same but with
+     * the specified {@link Locale}.
+     */
+    public static UnaryOperator<InteractionContext> switchLocale(@NonNull final Locale locale) {
+        return interactionContext -> interactionContext.withLocale(locale);
+    }
+
+    /**
+     * Convenience method for use with {@link org.apache.isis.applib.services.sudo.SudoService}, returning a
+     * {@link UnaryOperator} that will act upon the provided {@link InteractionContext} to return the same but with
+     * the specified {@link TimeZone}.
+     */
+    public static UnaryOperator<InteractionContext> switchTimeZone(@NonNull final TimeZone timeZone) {
+        return interactionContext -> interactionContext.withTimeZone(timeZone);
+    }
+
+    /**
+     * Convenience method to combine {@link UnaryOperator}s, for example as per {@link #switchUser(UserMemento)} and {@link #switchTimeZone(TimeZone)}.
+     *
+     * <p>
+     * NOTE: this implementation can result in heap pollution; better to use the {@link #combine(Stream) overload}.
+     * </p>
+     *
+     * @see #combine(Stream)
+     */
+    public static <T> UnaryOperator<T> combine(UnaryOperator<T>... mappers) {
+        return combine(Stream.of(mappers));
+    }
+
+    /**
+     * Convenience method to combine {@link UnaryOperator}s, for example as per {@link #switchUser(UserMemento)} and {@link #switchTimeZone(TimeZone)}.
+     *
+     * credit: https://stackoverflow.com/a/51065029/56880
+     */
+    public static <T> UnaryOperator<T> combine(Stream<UnaryOperator<T>> mappers) {
+        return mappers.reduce(t -> t, (a,b) -> a.andThen(b)::apply);
+    }
 
 
 }
diff --git a/api/applib/src/test/java/org/apache/isis/applib/services/iactnlayer/InteractionContext_combine_Test.java b/api/applib/src/test/java/org/apache/isis/applib/services/iactnlayer/InteractionContext_combine_Test.java
new file mode 100644
index 0000000..2cb9675
--- /dev/null
+++ b/api/applib/src/test/java/org/apache/isis/applib/services/iactnlayer/InteractionContext_combine_Test.java
@@ -0,0 +1,25 @@
+package org.apache.isis.applib.services.iactnlayer;
+
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import lombok.val;
+
+class InteractionContext_combine_Test {
+
+    @Test
+    void happy_case() {
+
+        val mappers = Stream.<UnaryOperator<String>>of(
+                s -> s + "bar",
+                s -> "[" + s + "]",
+                s -> s + s);
+        val result = InteractionContext.combine(mappers).apply("foo");
+
+        Assertions.assertThat(result).isEqualTo("[foobar][foobar]");
+    }
+
+}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
index 13b11d3..d452737 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
@@ -102,15 +102,15 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
 
     @Override
     public Bookmark executeCommand(final Command command) {
-        return executeCommand(SudoPolicy.NO_SWITCH, command);
+        return executeCommand(InteractionContextPolicy.NO_SWITCH, command);
     }
 
     @Override
     public Bookmark executeCommand(
-            final SudoPolicy sudoPolicy,
+            final InteractionContextPolicy interactionContextPolicy,
             final Command command) {
 
-        return doExecute(sudoPolicy, command.getCommandDto(), command.updater());
+        return doExecute(interactionContextPolicy, command.getCommandDto(), command.updater());
     }
 
     @Override
@@ -118,20 +118,20 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
             final CommandDto dto,
             final CommandOutcomeHandler outcomeHandler) {
 
-        return executeCommand(SudoPolicy.NO_SWITCH, dto, outcomeHandler);
+        return executeCommand(InteractionContextPolicy.NO_SWITCH, dto, outcomeHandler);
     }
 
     @Override
     public Bookmark executeCommand(
-            final SudoPolicy sudoPolicy,
+            final InteractionContextPolicy interactionContextPolicy,
             final CommandDto dto,
             final CommandOutcomeHandler outcomeHandler) {
 
-        return doExecute(sudoPolicy, dto, outcomeHandler);
+        return doExecute(interactionContextPolicy, dto, outcomeHandler);
     }
 
     private Bookmark doExecute(
-            final SudoPolicy sudoPolicy,
+            final InteractionContextPolicy interactionContextPolicy,
             final CommandDto dto,
             final CommandOutcomeHandler commandUpdater) {
 
@@ -145,12 +145,12 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
 
         val result = transactionService.callWithinCurrentTransactionElseCreateNew(
             () -> {
-                if (sudoPolicy == SudoPolicy.NO_SWITCH) {
+                if (interactionContextPolicy == InteractionContextPolicy.NO_SWITCH) {
                     // short-circuit
                     return doExecuteCommand(dto);
                 }
                 return sudoService.call(
-                        context -> sudoPolicy.mapper.apply(context, dto),
+                        context -> interactionContextPolicy.mapper.apply(context, dto),
                         () -> doExecuteCommand(dto));
             });
 
diff --git a/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/jobcallables/ReplicateAndRunCommands.java b/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/jobcallables/ReplicateAndRunCommands.java
index 78d6f24..2d36807 100644
--- a/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/jobcallables/ReplicateAndRunCommands.java
+++ b/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/jobcallables/ReplicateAndRunCommands.java
@@ -174,7 +174,7 @@ public class ReplicateAndRunCommands implements Callable<SecondaryStatus> {
         transactionService.runWithinCurrentTransactionElseCreateNew(
                 () -> {
                     commandExecutorService.executeCommand(
-                        CommandExecutorService.SudoPolicy.SWITCH_USER_AND_TIME, commandJdo.getCommandDto(), commandJdo.outcomeHandler());
+                        CommandExecutorService.InteractionContextPolicy.SWITCH_USER_AND_TIME, commandJdo.getCommandDto(), commandJdo.outcomeHandler());
                 });
 
         transactionService.runWithinCurrentTransactionElseCreateNew(() -> {
diff --git a/testing/fixtures/adoc/modules/fixtures/pages/about.adoc b/testing/fixtures/adoc/modules/fixtures/pages/about.adoc
index 1b0823e..0f428c6 100644
--- a/testing/fixtures/adoc/modules/fixtures/pages/about.adoc
+++ b/testing/fixtures/adoc/modules/fixtures/pages/about.adoc
@@ -17,7 +17,6 @@ The solution that Apache Isis provides is a small library called *_fixture scrip
 A fixture script is basically a command object for executing arbitrary work, where the work in question is almost always invoking one or more business actions.
 In other words, the database is populating through the functionality of the domain object model itself.
 
-
 There is another benefit to Apache Isis' fixture script approach; the fixtures can be (in prototyping mode) run from your application.
 This means that fixture scripts can actually help all the way through the development lifecycle:
 
@@ -36,13 +35,12 @@ And if you can't write a fixture script for the story, it probably means that th
 * when you want to roll out training to your users, you can write fixture scripts as part of their training exercises
 
 
-The following  sections explain the API and how to go about using the API.
+The following sections explain the API and how to go about using the API.
 
 
 
 include::fixture-scripts/api-and-usage.adoc[leveloffset=+1]
-include::fixture-scripts/mocking-the-clock.adoc[leveloffset=+1]
-include::fixture-scripts/sudo-service.adoc[leveloffset=+1]
+include::fixture-scripts/mocking-the-clock-or-user.adoc[leveloffset=+1]
 
 
 
diff --git a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock-or-user.adoc b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock-or-user.adoc
new file mode 100644
index 0000000..53dbda0
--- /dev/null
+++ b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock-or-user.adoc
@@ -0,0 +1,79 @@
+= Mocking the Clock or User
+
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+
+The xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService] provides the mechanism to run an arbitrary block of code, but changing the effective user executing the block, or the effective time that the block was run.
+
+This is a general purpose capability, but is especially useful for fixtures.
+
+== Mocking the Clock
+
+It's sometimes necessary to change the effective time that a fixture or test runs.
+This can be done by calling xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService] with an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] that has switched the clock.
+
+For example:
+
+[source,java]
+----
+val when = VirtualClock.nowAt(Instant.parse("2017-02-03T09:00:00.00Z")); // <.>
+
+simpleObject =
+    sudoService.call(
+        InteractionContext.switchClock(when),                            // <.>
+        ()-> fixtureScripts.runPersona(SimpleObject_persona.FOO)         // <.>
+    );
+----
+
+<.> the effective time, in other words the date/time we want the xref:refguide:applib:index/services/clock/ClockService.adoc[ClockService] to report
+<.> Unary operator on xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to switch the effective time
+<.> the block of code to run within this modified xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext].
+
+
+== Switching the User ("Sudo")
+
+Sometimes in our fixture scripts we want to perform a business action running as a particular user.
+This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
+Either way, this can be done by calling xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService] with an xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] that has switched the effective user.
+
+
+For example:
+
+[source,java]
+----
+val who = UserMemento.ofName("fred");                            // <.>
+
+simpleObject =
+    sudoService.call(
+        InteractionContext.switchUser(who),                      // <.>
+        ()-> fixtureScripts.runPersona(SimpleObject_persona.FOO) // <.>
+    );
+----
+
+<.> the effective user, in other words the user that we want xref:refguide:applib:index/services/user/UserService.adoc[UserService] to report
+<.> Unary operator on xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] to switch the effective user
+<.> the block of code to run within this modified xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext].
+
+
+
+== Mocking the Clock and the User
+
+If we want to change both the effective time _and_ the effective user, then we just need to combine the ``UnaryOperator``s passed into xref:refguide:applib:index/services/sudo/SudoService.adoc[SudoService].
+
+As a convenience, xref:refguide:applib:index/services/iactnlayer/InteractionContext.adoc[InteractionContext] provides a helper method for just this purpose:
+
+For example:
+
+[source,java]
+----
+val who = UserMemento.ofName("fred");
+val when = VirtualClock.nowAt(Instant.parse("2017-02-03T09:00:00.00Z"));
+
+val switchWhoAndWhen =
+        InteractionContext.combine(
+            InteractionContext.switchUser(who),
+            InteractionContext.switchClock(when)
+        );
+----
+
+This can then be passed in as the first argument to `SudoService`'s xref:refguide:applib:index/services/sudo/SudoService.adoc#call__UnaryOperator_Callable[call(...)] or xref:refguide:applib:index/services/sudo/SudoService.adoc#run__UnaryOperator_ThrowingRunnable[run(...)] methods.
diff --git a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc
deleted file mode 100644
index fbfdc5f..0000000
--- a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/mocking-the-clock.adoc
+++ /dev/null
@@ -1,49 +0,0 @@
-= Mocking the Clock
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-
-WARNING: TODO: v2 - this documentation has not yet been updated.
-In particular, the `Clock` singleton has been removed, the `ClockService` has been refactored.
-
-It's often useful to be able to change the effective time that a test runs.
-The framework itself uses the xref:refguide:applib:index/services/clock/ClockService.adoc[ClockService] to obtain the current time, and applications should also use this domain service for a consistent view of the current time.
-
-This page describes how to change the current time, and how to set up tests using fixture scripts with a mocked time.
-
-== FixtureClock
-
-The default xref:refguide:applib:index/services/clock/ClockService.adoc[ClockService] implementation in fact simply delegates to another class defined in the API, namely the `o.a.i.applib.clock.Clock`, an abstract singleton class.
-It is not recommended that your code use the `Clock` directly, but it's worth understanding how this all works.
-
-* If running in xref:refguide:config:about.adoc#deployment-types[production] (server) mode, then the framework will (lazily) instantiate the ``SystemClock` when first required.
-This is a read-only clock that reads from the system time.
-The instance registers itself as the singleton and cannot be replaced.
-
-* If running in xref:refguide:config:about.adoc#deployment-types[prototype] mode, though, then the framework (using `InitialFixtureScriptsInstaller`) will instead instantiate `FixtureClock`.
-This is a read-write clock that will behave as the system clock, unless it is explicitly set using eg, `FixtureClock#setDate(...)` or `FixtureClock#setTime(...)` etc.
-
-Moreover, the `FixtureClock` singleton can be replaced with another implementation.
-And, it is sometimes useful to replace it using `TickingFixtureClock`, a subclass that is very similar to `FixtureClock` (in that the time can be changed) but which will continue to tick once set.
-
-
-== TickingClockFixture
-
-The `TickingClockFixture` is a pre-built fixture script that resets the date/time returned by the xref:refguide:applib:index/services/clock/ClockService.adoc[ClockService] to a known value.
-
-Thereafter the time returned continues to tick forward (as would the real clock) until reset once more.
-
-For example, to set the clock to return "3 Sept 2014", use:
-
-[source,java]
-----
-executionContext.executeChild(this, new TickingClockFixture().setTo("2014-09-03"));
-----
-
-A variety of format strings are supported; the format "YYYY-MM-DD" (as shown above) will work in every locale.
-
-NOTE: This fixture script requires that a `TickingFixtureClock` is initialized during bootstrapping.
-
-
-
-
diff --git a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/sudo-service.adoc b/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/sudo-service.adoc
deleted file mode 100644
index c8fd420..0000000
--- a/testing/fixtures/adoc/modules/fixtures/pages/fixture-scripts/sudo-service.adoc
+++ /dev/null
@@ -1,55 +0,0 @@
-= `SudoService`
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-
-
-
-Sometimes in our fixture scripts we want to perform a business action running as a particular user.
-This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
-
-For example, consider this code that creates a todo item:
-
-[source,java]
-.Production code that depends on current user
-----
-// annotations omitted for clarity
-public ToDoItem newToDo(
-        final String description,
-        final Category category,
-        final Subcategory subcategory,
-        final LocalDate dueBy,
-        final BigDecimal cost) {
-    return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
-}
-private String currentUserName() {
-    return container.getUser().getName();       // <1>
-}
-----
-<1> is the current user.
-
-The fixture for this can use the `SudoService` to run a block of code as a specified user:
-
-[source,java]
-.Fixture Script
-----
-final String description = ...
-final Category category = ...
-final Subcategory subcategory = ...
-final LocalDate dueBy = ...
-final BigDecimal cost = ...
-final Location location = ...
-
-toDoItem = sudoService.sudo(username,
-        new Callable<ToDoItem>() {
-            @Override
-            public ToDoItem call() {
-                final ToDoItem toDoItem = wrap(toDoItems).newToDo(
-                        description, category, subcategory, dueBy, cost);
-                wrap(toDoItem).setLocation(location);
-                return toDoItem;
-            }
-        });
-----
-
-Behind the scenes the `SudoService` simply talks to the `UserService` to override the user returned by the `getUser()` API.
-It is possible to override both users and roles.

[isis] 03/08: ISIS-2732: simplifies FixturesLifecycleService

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2732
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 5c8e643fa21249434bcf7dae85e0c5dd5343cee1
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 11 11:59:18 2021 +0100

    ISIS-2732: simplifies FixturesLifecycleService
---
 .../applib/services/FixturesLifecycleService.java  | 47 +++++-----------------
 1 file changed, 11 insertions(+), 36 deletions(-)

diff --git a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java
index 782c49d..94f9add 100644
--- a/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java
+++ b/testing/fixtures/applib/src/main/java/org/apache/isis/testing/fixtures/applib/services/FixturesLifecycleService.java
@@ -18,8 +18,8 @@
  */
 package org.apache.isis.testing.fixtures.applib.services;
 
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
+import java.lang.reflect.InvocationTargetException;
+
 import javax.inject.Inject;
 import javax.inject.Named;
 
@@ -32,14 +32,11 @@ import org.springframework.stereotype.Service;
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.core.config.IsisConfiguration;
-import org.apache.isis.core.config.environment.IsisSystemEnvironment;
-import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.core.metamodel.events.MetamodelEvent;
-import org.apache.isis.testing.fixtures.applib.clock.clock.Clock;
-import org.apache.isis.testing.fixtures.applib.clock.clock.FixtureClock;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScripts;
 
+import lombok.SneakyThrows;
 import lombok.extern.log4j.Log4j2;
 
 /**
@@ -55,37 +52,22 @@ public class FixturesLifecycleService {
 
     @SuppressWarnings("unused")
 
-    @Inject
-    private InteractionService interactionService; // depends on relationship
-    @Inject
-    private IsisSystemEnvironment isisSystemEnvironment;
-    @Inject
-    private IsisConfiguration isisConfiguration;
-    @Inject
-    private ServiceInjector serviceInjector;
-    @Inject
-    private FixtureScripts fixtureScripts;
+    private final FixtureScripts fixtureScripts;
 
     private FixtureScript initialFixtureScript;
 
+    @Inject
+    public FixturesLifecycleService(
+            final IsisConfiguration isisConfiguration,
+            final FixtureScripts fixtureScripts) {
 
-    @PostConstruct
-    public void postConstruct() {
-
-        // a bit of a workaround, but required if anything in the metamodel (for example, a
-        // ValueSemanticsProvider for a date value type) needs to use the Clock singleton
-        // we do this after loading the services to allow a service to prime a different clock
-        // implementation (eg to use an NTP time service).
-        if (isisSystemEnvironment.isPrototyping() && !Clock.isInitialized()) {
-            FixtureClock.initialize();
-        }
+        this.fixtureScripts = fixtureScripts;
 
         final Class<?> initialScript = isisConfiguration.getTesting().getFixtures().getInitialScript();
         if (initialScript != null && FixtureScript.class.isAssignableFrom(initialScript)) {
             try {
-                initialFixtureScript = (FixtureScript) initialScript.newInstance();
-                serviceInjector.injectServicesInto(initialFixtureScript);
-            } catch (InstantiationException | IllegalAccessException e) {
+                initialFixtureScript = (FixtureScript) initialScript.getDeclaredConstructor().newInstance();
+            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                 initialFixtureScript = null;
             }
         }
@@ -102,13 +84,6 @@ public class FixturesLifecycleService {
             log.info("install initial fixtures from script {}", initialFixtureScript.getFriendlyName());
             fixtureScripts.run(initialFixtureScript);
         }
-
-    }
-
-
-    @PreDestroy
-    public void preDestroy() {
-
     }
 
 }