You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2023/10/19 08:32:06 UTC

[causeway] branch master updated (0807100dc6 -> 72c92e0f8f)

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

ahuber pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/causeway.git


    from 0807100dc6 CAUSEWAY-3637: [Commons] flatMap and filter for Try<T>
     new 7773222924 CAUSEWAY-3637: adds (flat)mapSuccessWhenPresent(..) for Try<T>
     new 72c92e0f8f CAUSEWAY-3637: updates doc index

The 2 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:
 .../commons/pages/index/functional/Try.adoc        |  66 +++++++++++---
 .../services/grid/GridLoaderServiceDefault.adoc}   |  19 ++--
 .../services/grid/spi/LayoutResourceLoader.adoc    |  40 +++++++++
 .../CausewayModuleExtLayoutGithubLoader.adoc       |  70 +++++++++++++++
 .../loader/menu/LayoutLoaderMenu.adoc}             |   9 +-
 ...CausewayExtLayoutGithubRoleAndPermissions.adoc} |  10 +--
 .../tabular/CollectionContentsExporter.adoc        |  13 +--
 .../apache/causeway/commons/functional/Try.java    |  44 ++++++++-
 core/adoc/modules/_overview/pages/about.adoc       | 100 +++++++++++++++++++--
 .../grid/spi/LayoutResourceLoaderDefault.java      |  12 ++-
 10 files changed, 328 insertions(+), 55 deletions(-)
 copy antora/components/refguide-index/modules/{applib/pages/index/CausewayModuleApplib.adoc => core/pages/index/metamodel/services/grid/GridLoaderServiceDefault.adoc} (57%)
 create mode 100644 antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/spi/LayoutResourceLoader.adoc
 create mode 100644 antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/CausewayModuleExtLayoutGithubLoader.adoc
 copy antora/components/refguide-index/modules/extensions/pages/index/{commandreplay/primary/config/PrimaryConfig.adoc => layoutgithub/loader/menu/LayoutLoaderMenu.adoc} (83%)
 copy antora/components/refguide-index/modules/extensions/pages/index/secman/applib/role/seed/{CausewayExtCommandLogRoleAndPermissions.adoc => CausewayExtLayoutGithubRoleAndPermissions.adoc} (81%)


[causeway] 01/02: CAUSEWAY-3637: adds (flat)mapSuccessWhenPresent(..) for Try

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 7773222924757bc411da5113136b953cf670377a
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Oct 19 10:31:41 2023 +0200

    CAUSEWAY-3637: adds (flat)mapSuccessWhenPresent(..) for Try<T>
---
 .../apache/causeway/commons/functional/Try.java    | 44 +++++++++++++++++++++-
 .../grid/spi/LayoutResourceLoaderDefault.java      | 12 +++---
 2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/commons/src/main/java/org/apache/causeway/commons/functional/Try.java b/commons/src/main/java/org/apache/causeway/commons/functional/Try.java
index 539f053e80..ae7c239266 100644
--- a/commons/src/main/java/org/apache/causeway/commons/functional/Try.java
+++ b/commons/src/main/java/org/apache/causeway/commons/functional/Try.java
@@ -148,6 +148,17 @@ public interface Try<T> {
      *      the success value - as passed over to the successMapper - is guaranteed non-null.
      */
     <R> Try<R> mapSuccessAsNullable(@NonNull ThrowingFunction<T, R> successMapper);
+    /**
+     * If this {@link Try} holds a non-null {@code value} (and hence is also a {@link Success}),
+     * maps this {@link Try} to another,
+     * by calling the successMapper with the {@code value} (which is non-null).
+     * Otherwise acts as identity operator, that is,
+     * either stay an empty {@link Success} or stay a {@link Failure},
+     * though implementations may return a new instance.
+     * <p>
+     * If given successMapper throws an exception, a failed {@link Try} is returned.
+     */
+    <R> Try<R> mapSuccessWhenPresent(@NonNull ThrowingFunction<T, R> successMapper);
     /**
      * If this is a {@link Failure}, maps this {@link Try} to another.
      * Otherwise if this is a {@link Success} acts as identity operator,
@@ -182,7 +193,7 @@ public interface Try<T> {
             final @NonNull ThrowingFunction<Throwable, L> failureMapper,
             final @NonNull ThrowingFunction<Optional<T>, R> successMapper);
 
-    // -- FLAT MAPPING
+    // -- FLAT MAPPING / FUNCTION COMPOSITION
 
     /**
      * Variant of {@link #mapSuccess(ThrowingFunction)},
@@ -198,6 +209,13 @@ public interface Try<T> {
      */
     <R> Try<R> flatMapSuccessAsNullable(@NonNull ThrowingFunction<T, Try<R>> successMapper);
 
+    /**
+     * Variant of {@link #mapSuccessWhenPresent(ThrowingFunction)},
+     * utilizing a different successMapper, one that returns a {@link Try}.
+     * @see #mapSuccessWhenPresent(ThrowingFunction)
+     */
+    <R> Try<R> flatMapSuccessWhenPresent(@NonNull ThrowingFunction<T, Try<R>> successMapper);
+
     // -- ACCEPT
 
     /**
@@ -329,6 +347,12 @@ public interface Try<T> {
             return Try.call(()->successMapper.apply(getValue().orElse(null)));
         }
         @Override
+        public <R> Try<R> mapSuccessWhenPresent(final @NonNull ThrowingFunction<T, R> successMapper) {
+            return getValue()
+                    .map(value->Try.call(()->successMapper.apply(value)))
+                    .orElseGet(Try::empty);
+        }
+        @Override
         public <R> Try<R> flatMapSuccess(final @NonNull ThrowingFunction<Optional<T>, Try<R>> successMapper) {
             try {
                 return successMapper.apply(getValue());
@@ -344,6 +368,16 @@ public interface Try<T> {
                 return Try.failure(ex);
             }
         }
+        @Override
+        public <R> Try<R> flatMapSuccessWhenPresent(final @NonNull ThrowingFunction<T, Try<R>> successMapper) {
+            var value = getValue().orElse(null);
+            if(value==null) return Try.empty();
+            try {
+                return successMapper.apply(value);
+            } catch (Throwable ex) {
+                return Try.failure(ex);
+            }
+        }
 
         @Override
         public Success<T> mapFailure(final @NonNull ThrowingFunction<Throwable, Throwable> failureMapper){
@@ -466,6 +500,10 @@ public interface Try<T> {
             return new Failure<>(throwable); // railway pattern:  once failed, stays failed
         }
         @Override
+        public <R> Failure<R> mapSuccessWhenPresent(final @NonNull ThrowingFunction<T, R> successMapper) {
+            return new Failure<>(throwable); // railway pattern:  once failed, stays failed
+        }
+        @Override
         public <R> Failure<R> flatMapSuccess(final @NonNull ThrowingFunction<Optional<T>, Try<R>> successMapper) {
             return new Failure<>(throwable); // railway pattern:  once failed, stays failed
         }
@@ -473,6 +511,10 @@ public interface Try<T> {
         public <R> Failure<R> flatMapSuccessAsNullable(final @NonNull ThrowingFunction<T, Try<R>> successMapper) {
             return new Failure<>(throwable); // railway pattern:  once failed, stays failed
         }
+        @Override
+        public <R> Failure<R> flatMapSuccessWhenPresent(final @NonNull ThrowingFunction<T, Try<R>> successMapper) {
+            return new Failure<>(throwable); // railway pattern:  once failed, stays failed
+        }
 
         @Override
         public Failure<T> mapFailure(final @NonNull ThrowingFunction<Throwable, Throwable> failureMapper){
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/grid/spi/LayoutResourceLoaderDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/grid/spi/LayoutResourceLoaderDefault.java
index 839db05dea..feb737ffbe 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/grid/spi/LayoutResourceLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/grid/spi/LayoutResourceLoaderDefault.java
@@ -35,13 +35,11 @@ public class LayoutResourceLoaderDefault implements LayoutResourceLoader {
 
         return DataSource.ofResource(type, candidateResourceName)
             .tryReadAsStringUtf8()
-            .mapSuccess(fileContent->fileContent
-                .map(layoutSource->
-                    new LayoutResource(
-                            candidateResourceName,
-                            NamedWithMimeType.CommonMimeType.valueOfFileName(candidateResourceName).orElseThrow(),
-                            layoutSource))
-                .orElse(null));
+            .mapSuccessWhenPresent(fileContent->
+                new LayoutResource(
+                        candidateResourceName,
+                        NamedWithMimeType.CommonMimeType.valueOfFileName(candidateResourceName).orElseThrow(),
+                        fileContent));
     }
 
 }


[causeway] 02/02: CAUSEWAY-3637: updates doc index

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 72c92e0f8f3e190902d0811722a3ee86d88eae0b
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Oct 19 10:32:01 2023 +0200

    CAUSEWAY-3637: updates doc index
---
 .../commons/pages/index/functional/Try.adoc        |  66 +++++++++++---
 .../services/grid/GridLoaderServiceDefault.adoc    |  17 ++++
 .../services/grid/spi/LayoutResourceLoader.adoc    |  40 +++++++++
 .../CausewayModuleExtLayoutGithubLoader.adoc       |  70 +++++++++++++++
 .../layoutgithub/loader/menu/LayoutLoaderMenu.adoc |  15 ++++
 .../CausewayExtLayoutGithubRoleAndPermissions.adoc |  17 ++++
 .../tabular/CollectionContentsExporter.adoc        |  13 +--
 core/adoc/modules/_overview/pages/about.adoc       | 100 +++++++++++++++++++--
 8 files changed, 311 insertions(+), 27 deletions(-)

diff --git a/antora/components/refguide-index/modules/commons/pages/index/functional/Try.adoc b/antora/components/refguide-index/modules/commons/pages/index/functional/Try.adoc
index 0190d74975..d71c0e12d8 100644
--- a/antora/components/refguide-index/modules/commons/pages/index/functional/Try.adoc
+++ b/antora/components/refguide-index/modules/commons/pages/index/functional/Try.adoc
@@ -29,10 +29,14 @@ interface Try<T> {
   Try<T> ifAbsentFail()     // <.>
   Try<R> mapSuccess(ThrowingFunction<Optional<T>, R> successMapper)     // <.>
   Try<R> mapSuccessAsNullable(ThrowingFunction<T, R> successMapper)     // <.>
+  Try<R> mapSuccessWhenPresent(ThrowingFunction<T, R> successMapper)     // <.>
   Try<T> mapFailure(ThrowingFunction<Throwable, Throwable> failureMapper)     // <.>
   Try<T> mapFailureToSuccess(ThrowingFunction<Throwable, T> recoveryMapper)     // <.>
   Try<T> mapEmptyToFailure()     // <.>
   Either<L, R> mapToEither(ThrowingFunction<Throwable, L> failureMapper, ThrowingFunction<Optional<T>, R> successMapper)     // <.>
+  Try<R> flatMapSuccess(ThrowingFunction<Optional<T>, Try<R>> successMapper)     // <.>
+  Try<R> flatMapSuccessAsNullable(ThrowingFunction<T, Try<R>> successMapper)     // <.>
+  Try<R> flatMapSuccessWhenPresent(ThrowingFunction<T, Try<R>> successMapper)     // <.>
   Try<T> accept(ThrowingConsumer<Throwable> failureConsumer, ThrowingConsumer<Optional<T>> successConsumer)     // <.>
   R fold(ThrowingFunction<Throwable, R> failureMapper, ThrowingFunction<Optional<T>, R> successMapper)     // <.>
   Try<R> thenCall(Callable<R> callable)     // <.>
@@ -87,33 +91,53 @@ Throws _NoSuchElementException_ if _value_ is _null_ .
 <.> xref:#mapSuccess_ThrowingFunction[mapSuccess(ThrowingFunction)]
 +
 --
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Success_ , passing the _value_ wrapped in an _Optional_ . Otherwise if this is a _Failure_ acts as identity operator.
+If this is a _Success_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ wrapped by an _Optional_ . Otherwise if this is a _Failure_ , acts as identity operator, though implementations may return a new instance.
 --
 <.> xref:#mapSuccessAsNullable_ThrowingFunction[mapSuccessAsNullable(ThrowingFunction)]
 +
 --
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Success_ . Otherwise if this is a _Failure_ acts as identity operator.
+If this is a _Success_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ (which may be null). Otherwise if this is a _Failure_ , acts as identity operator, though implementations may return a new instance.
+--
+<.> xref:#mapSuccessWhenPresent_ThrowingFunction[mapSuccessWhenPresent(ThrowingFunction)]
++
+--
+If this xref:refguide:commons:index/functional/Try.adoc[Try] holds a non-null _value_ (and hence is also a _Success_ ), maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ (which is non-null). Otherwise acts as identity operator, that is, either stay an empty _Success_ or stay a _Failure_ , though implementations may return a new instance.
 --
 <.> xref:#mapFailure_ThrowingFunction[mapFailure(ThrowingFunction)]
 +
 --
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Failure_ . Otherwise if this is a _Success_ acts as identity operator.
+If this is a _Failure_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another. Otherwise if this is a _Success_ acts as identity operator, though implementations may return a new instance.
 --
 <.> xref:#mapFailureToSuccess_ThrowingFunction[mapFailureToSuccess(ThrowingFunction)]
 +
 --
-Recovers from a failed xref:refguide:commons:index/functional/Try.adoc[Try] if its a _Failure_ . Otherwise if this is a _Success_ acts as identity operator.
+If this is a _Failure_ , recovers to a _Success_ . Otherwise if this is a _Success_ acts as identity operator, though implementations may return a new instance.
 --
 <.> xref:#mapEmptyToFailure_[mapEmptyToFailure()]
 +
 --
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to _Failure_ if this is a _Success_ with an empty _value_ . Otherwise acts as identity operator.
+Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to _Failure_ if this is a _Success_ with an empty _value_ . Otherwise acts as identity operator, though implementations may return a new instance.
 --
 <.> xref:#mapToEither_ThrowingFunction_ThrowingFunction[mapToEither(ThrowingFunction, ThrowingFunction)]
 +
 --
 Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to xref:refguide:commons:index/functional/Either.adoc[Either] using according mapping function _successMapper_ or _failureMapper_ .
 --
+<.> xref:#flatMapSuccess_ThrowingFunction[flatMapSuccess(ThrowingFunction)]
++
+--
+Variant of _#mapSuccess(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+--
+<.> xref:#flatMapSuccessAsNullable_ThrowingFunction[flatMapSuccessAsNullable(ThrowingFunction)]
++
+--
+Variant of _#mapSuccessAsNullable(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+--
+<.> xref:#flatMapSuccessWhenPresent_ThrowingFunction[flatMapSuccessWhenPresent(ThrowingFunction)]
++
+--
+Variant of _#mapSuccessWhenPresent(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+--
 <.> xref:#accept_ThrowingConsumer_ThrowingConsumer[accept(ThrowingConsumer, ThrowingConsumer)]
 +
 --
@@ -206,35 +230,42 @@ Throws _NoSuchElementException_ if _value_ is _null_ .
 [#mapSuccess_ThrowingFunction]
 === mapSuccess(ThrowingFunction)
 
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Success_ , passing the _value_ wrapped in an _Optional_ . Otherwise if this is a _Failure_ acts as identity operator.
+If this is a _Success_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ wrapped by an _Optional_ . Otherwise if this is a _Failure_ , acts as identity operator, though implementations may return a new instance.
 
 If given successMapper throws an exception, a failed xref:refguide:commons:index/functional/Try.adoc[Try] is returned.
 
 [#mapSuccessAsNullable_ThrowingFunction]
 === mapSuccessAsNullable(ThrowingFunction)
 
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Success_ . Otherwise if this is a _Failure_ acts as identity operator.
+If this is a _Success_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ (which may be null). Otherwise if this is a _Failure_ , acts as identity operator, though implementations may return a new instance.
+
+If given successMapper throws an exception, a failed xref:refguide:commons:index/functional/Try.adoc[Try] is returned.
+
+[#mapSuccessWhenPresent_ThrowingFunction]
+=== mapSuccessWhenPresent(ThrowingFunction)
+
+If this xref:refguide:commons:index/functional/Try.adoc[Try] holds a non-null _value_ (and hence is also a _Success_ ), maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another, by calling the successMapper with the _value_ (which is non-null). Otherwise acts as identity operator, that is, either stay an empty _Success_ or stay a _Failure_ , though implementations may return a new instance.
 
 If given successMapper throws an exception, a failed xref:refguide:commons:index/functional/Try.adoc[Try] is returned.
 
 [#mapFailure_ThrowingFunction]
 === mapFailure(ThrowingFunction)
 
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another if this is a _Failure_ . Otherwise if this is a _Success_ acts as identity operator.
+If this is a _Failure_ , maps this xref:refguide:commons:index/functional/Try.adoc[Try] to another. Otherwise if this is a _Success_ acts as identity operator, though implementations may return a new instance.
 
 If given failureMapper throws an exception, a failed xref:refguide:commons:index/functional/Try.adoc[Try] is returned (hiding the original failure).
 
 [#mapFailureToSuccess_ThrowingFunction]
 === mapFailureToSuccess(ThrowingFunction)
 
-Recovers from a failed xref:refguide:commons:index/functional/Try.adoc[Try] if its a _Failure_ . Otherwise if this is a _Success_ acts as identity operator.
+If this is a _Failure_ , recovers to a _Success_ . Otherwise if this is a _Success_ acts as identity operator, though implementations may return a new instance.
 
 If given recoveryMapper throws an exception, a failed xref:refguide:commons:index/functional/Try.adoc[Try] is returned.
 
 [#mapEmptyToFailure_]
 === mapEmptyToFailure()
 
-Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to _Failure_ if this is a _Success_ with an empty _value_ . Otherwise acts as identity operator.
+Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to _Failure_ if this is a _Success_ with an empty _value_ . Otherwise acts as identity operator, though implementations may return a new instance.
 
 [#mapToEither_ThrowingFunction_ThrowingFunction]
 === mapToEither(ThrowingFunction, ThrowingFunction)
@@ -243,6 +274,21 @@ Maps this xref:refguide:commons:index/functional/Try.adoc[Try] to xref:refguide:
 
 Any exceptions thrown by given failureMapper or successMapper are propagated without catching.
 
+[#flatMapSuccess_ThrowingFunction]
+=== flatMapSuccess(ThrowingFunction)
+
+Variant of _#mapSuccess(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+
+[#flatMapSuccessAsNullable_ThrowingFunction]
+=== flatMapSuccessAsNullable(ThrowingFunction)
+
+Variant of _#mapSuccessAsNullable(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+
+[#flatMapSuccessWhenPresent_ThrowingFunction]
+=== flatMapSuccessWhenPresent(ThrowingFunction)
+
+Variant of _#mapSuccessWhenPresent(ThrowingFunction)_ , utilizing a different successMapper, one that returns a xref:refguide:commons:index/functional/Try.adoc[Try] .
+
 [#accept_ThrowingConsumer_ThrowingConsumer]
 === accept(ThrowingConsumer, ThrowingConsumer)
 
diff --git a/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/GridLoaderServiceDefault.adoc b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/GridLoaderServiceDefault.adoc
new file mode 100644
index 0000000000..011559e4d8
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/GridLoaderServiceDefault.adoc
@@ -0,0 +1,17 @@
+= GridLoaderServiceDefault
+: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]
+.GridLoaderServiceDefault.java
+----
+class GridLoaderServiceDefault {
+  GridLoaderServiceDefault(MessageService messageService, CausewaySystemEnvironment causewaySystemEnvironment, List<LayoutResourceLoader> layoutResourceLoaders)
+  void remove(Class<?> domainClass)
+  boolean existsFor(Class<?> domainClass, EnumSet<CommonMimeType> supportedFormats)
+  Optional<T> load(Class<?> domainClass, String layoutIfAny, GridMarshallerService<T> marshaller)
+  Optional<LayoutResource> loadLayoutResource(LayoutKey layoutKey, EnumSet<CommonMimeType> supportedFormats)
+}
+----
+
diff --git a/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/spi/LayoutResourceLoader.adoc b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/spi/LayoutResourceLoader.adoc
new file mode 100644
index 0000000000..8166ee60f0
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/grid/spi/LayoutResourceLoader.adoc
@@ -0,0 +1,40 @@
+= LayoutResourceLoader
+: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 [...]
+
+A simpler SPI for xref:refguide:core:index/metamodel/services/grid/GridLoaderServiceDefault.adoc[GridLoaderServiceDefault] .
+
+== API
+
+[source,java]
+.LayoutResourceLoader.java
+----
+interface LayoutResourceLoader {
+  Try<LayoutResource> tryLoadLayoutResource(Class<?> type, String candidateResourceName)     // <.>
+  Optional<LayoutResource> lookupLayoutResource(Class<?> type, String candidateResourceName)     // <.>
+}
+----
+
+<.> xref:#tryLoadLayoutResource_Class_String[tryLoadLayoutResource(Class, String)]
++
+--
+Try to locate and load a _LayoutResource_ by type and name.
+--
+<.> xref:#lookupLayoutResource_Class_String[lookupLayoutResource(Class, String)]
++
+--
+Optionally returns a _LayoutResource_ based on whether it could be resolved by type and name and successfully read.
+--
+
+== Members
+
+[#tryLoadLayoutResource_Class_String]
+=== tryLoadLayoutResource(Class, String)
+
+Try to locate and load a _LayoutResource_ by type and name.
+
+[#lookupLayoutResource_Class_String]
+=== lookupLayoutResource(Class, String)
+
+Optionally returns a _LayoutResource_ based on whether it could be resolved by type and name and successfully read.
+
+Silently ignores exceptions underneath, if any.
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/CausewayModuleExtLayoutGithubLoader.adoc b/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/CausewayModuleExtLayoutGithubLoader.adoc
new file mode 100644
index 0000000000..e4127c2ca2
--- /dev/null
+++ b/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/CausewayModuleExtLayoutGithubLoader.adoc
@@ -0,0 +1,70 @@
+= CausewayModuleExtLayoutGithubLoader
+: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 [...]
+
+Adds the xref:refguide:applib:index/layout/menubars/Menu.adoc[Menu] with its auto-configured menu entries.
+
+== API
+
+[source,java]
+.CausewayModuleExtLayoutGithubLoader.java
+----
+class CausewayModuleExtLayoutGithubLoader {
+  public static final String NAMESPACE;
+  RestTemplate restTemplateForGithubSearch(CausewayConfiguration causewayConfiguration)     // <.>
+  RestTemplate restTemplateForGithubContent(CausewayConfiguration causewayConfiguration)     // <.>
+}
+----
+
+<.> xref:#restTemplateForGithubSearch_CausewayConfiguration[restTemplateForGithubSearch(CausewayConfiguration)]
++
+--
+Returns a template configured to search for a file in the git repo.
+--
+<.> xref:#restTemplateForGithubContent_CausewayConfiguration[restTemplateForGithubContent(CausewayConfiguration)]
++
+--
+Returns a template configured to obtain the content of a file in a repo (from the default branch).
+--
+
+== Members
+
+[#restTemplateForGithubSearch_CausewayConfiguration]
+=== restTemplateForGithubSearch(CausewayConfiguration)
+
+Returns a template configured to search for a file in the git repo.
+
+Append for example:
+
+----
+/search/code?q=SimpleObject.layout.xml+in:path+repo:apache/causeway-app-simpleapp
+----
+
+Returns for example:
+
+----
+
+{
+  "total_count": 1,
+  "incomplete_results": false,
+  "items": [
+    {
+      "name": "SimpleObject.layout.xml",
+      "path": "module-simple/src/main/java/domainapp/modules/simple/dom/so/SimpleObject.layout.xml",
+      ...
+    },
+     ...
+   ]
+   ...
+}
+----
+
+[#restTemplateForGithubContent_CausewayConfiguration]
+=== restTemplateForGithubContent(CausewayConfiguration)
+
+Returns a template configured to obtain the content of a file in a repo (from the default branch).
+
+Append for example:
+
+----
+/contents/module-simple/src/main/java/domainapp/modules/simple/dom/so/SimpleObject.layout.xml
+----
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/menu/LayoutLoaderMenu.adoc b/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/menu/LayoutLoaderMenu.adoc
new file mode 100644
index 0000000000..04a3b45741
--- /dev/null
+++ b/antora/components/refguide-index/modules/extensions/pages/index/layoutgithub/loader/menu/LayoutLoaderMenu.adoc
@@ -0,0 +1,15 @@
+= LayoutLoaderMenu
+: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 actions to managed the dynamic loading of layouts from a github source code repository.
+
+== API
+
+[source,java]
+.LayoutLoaderMenu.java
+----
+class LayoutLoaderMenu {
+  boolean isConfigured()
+}
+----
+
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/secman/applib/role/seed/CausewayExtLayoutGithubRoleAndPermissions.adoc b/antora/components/refguide-index/modules/extensions/pages/index/secman/applib/role/seed/CausewayExtLayoutGithubRoleAndPermissions.adoc
new file mode 100644
index 0000000000..190390ca03
--- /dev/null
+++ b/antora/components/refguide-index/modules/extensions/pages/index/secman/applib/role/seed/CausewayExtLayoutGithubRoleAndPermissions.adoc
@@ -0,0 +1,17 @@
+= CausewayExtLayoutGithubRoleAndPermissions
+: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 [...]
+
+Sets up a role with access to the menu actions contributed by the _LayoutGithub_ extension.
+
+== API
+
+[source,java]
+.CausewayExtLayoutGithubRoleAndPermissions.java
+----
+class CausewayExtLayoutGithubRoleAndPermissions {
+  public static final String NAMESPACE;
+  public static final String ROLE_NAME;
+  CausewayExtLayoutGithubRoleAndPermissions()
+}
+----
+
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/commons/applib/services/tabular/CollectionContentsExporter.adoc b/antora/components/refguide-index/modules/viewer/pages/index/commons/applib/services/tabular/CollectionContentsExporter.adoc
index d0d9ff6581..5397b321e3 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/commons/applib/services/tabular/CollectionContentsExporter.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/commons/applib/services/tabular/CollectionContentsExporter.adoc
@@ -9,13 +9,12 @@ SPI to provide file export to table views.
 .CollectionContentsExporter.java
 ----
 interface CollectionContentsExporter {
-  File createExportFile(DataTable dataTable)
+  void createExport(DataTable dataTable, File tempFile)
   CommonMimeType getMimeType()
   String getTitleLabel()     // <.>
   String getCssClass()     // <.>
   int orderOfAppearanceInUiDropdown()     // <.>
   boolean appliesTo(ObjectSpecification objectType)     // <.>
-  boolean isPageReloadRequiredOnTableViewActivation()     // <.>
 }
 ----
 
@@ -31,11 +30,6 @@ An ordinal, that governs the order of appearance in the UI dropdown.
 --
 Whether this exporter applies to given _objectType_ . If `false` , this exporter is not provided to the end user.
 --
-<.> xref:#isPageReloadRequiredOnTableViewActivation_[isPageReloadRequiredOnTableViewActivation()]
-+
---
-Whether activation of this table presentation view should result in a full page reload.
---
 
 == Members
 
@@ -59,8 +53,3 @@ Lowest comes first.
 === appliesTo(ObjectSpecification)
 
 Whether this exporter applies to given _objectType_ . If `false` , this exporter is not provided to the end user.
-
-[#isPageReloadRequiredOnTableViewActivation_]
-=== isPageReloadRequiredOnTableViewActivation()
-
-Whether activation of this table presentation view should result in a full page reload.
diff --git a/core/adoc/modules/_overview/pages/about.adoc b/core/adoc/modules/_overview/pages/about.adoc
index 47eed73aec..6ed2401956 100644
--- a/core/adoc/modules/_overview/pages/about.adoc
+++ b/core/adoc/modules/_overview/pages/about.adoc
@@ -40,6 +40,7 @@ rectangle "App\n<size:10>[Software System]</size>" <<App>> {
 
 @enduml
 ----
+
 .Projects/Modules (App)
 [cols="3a,5a", options="header"]
 |===
@@ -102,6 +103,7 @@ rectangle "Mavendeps\n<size:10>[Software System]</size>" <<Mavendeps>> {
 Mavendeps.ApacheCausewayMavenDeps .[#707070,thickness=2].> Mavendeps.ApacheCausewayMavenDepsWebapp : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Mavendeps)
 [cols="3a,5a", options="header"]
 |===
@@ -322,6 +324,7 @@ Testing.ApacheCausewayTstSpecCucumberparent .[#707070,thickness=2].> Testing.Apa
 Testing.ApacheCausewayTstUnitTestSupportparent .[#707070,thickness=2].> Testing.ApacheCausewayTstUnitTestSupportapplib : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Testing)
 [cols="3a,5a", options="header"]
 |===
@@ -724,6 +727,7 @@ Root.ApacheCausewayAggregator .[#707070,thickness=2].> Root.ApacheCausewayAntora
 Root.ApacheCausewayAggregator .[#707070,thickness=2].> Root.ApacheCauseway : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Root)
 [cols="3a,5a", options="header"]
 |===
@@ -814,6 +818,7 @@ rectangle "Commons\n<size:10>[Software System]</size>" <<Commons>> {
 
 @enduml
 ----
+
 .Projects/Modules (Commons)
 [cols="3a,5a", options="header"]
 |===
@@ -998,6 +1003,7 @@ Core.ApacheCausewayCore .[#707070,thickness=2].> Core.ApacheCausewayCoreWebApp :
 Core.ApacheCausewayCore .[#707070,thickness=2].> Core.ApacheCausewayApiSchemas : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core)
 [cols="3a,5a", options="header"]
 |===
@@ -1198,6 +1204,7 @@ o.a.i.core.metamodel.services.grid.GridLoaderServiceDefault +
 o.a.i.core.metamodel.services.grid.GridServiceDefault +
 o.a.i.core.metamodel.services.grid.bootstrap.GridMarshallerServiceBootstrap +
 o.a.i.core.metamodel.services.grid.bootstrap.GridSystemServiceBootstrap +
+o.a.i.core.metamodel.services.grid.spi.LayoutResourceLoaderDefault +
 o.a.i.core.metamodel.services.idstringifier.IdStringifierLookupService +
 o.a.i.core.metamodel.services.layout.LayoutServiceDefault +
 o.a.i.core.metamodel.services.metamodel.MetaModelServiceDefault +
@@ -1259,7 +1266,7 @@ org.apache.causeway.core:causeway-core-security:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:core:index/metamodel/object/ManagedObject.adoc[ManagedObject], xref:refguide:core:index/metamodel/services/command/CommandDtoFactory.adoc[CommandDtoFactory], xref:refguide:core:index/metamodel/services/ixn/InteractionDtoFactory.adoc[InteractionDtoFactory], xref:refguide:core:index/metamodel/services/metamodel/MetaModelAnnotator.adoc[MetaModelAnnotator], xref:refguide:core:index/metamodel/services/publishing/CommandPublisher.adoc[CommandPublisher], xref:refguide:core:index/m [...]
+xref:refguide:core:index/metamodel/object/ManagedObject.adoc[ManagedObject], xref:refguide:core:index/metamodel/services/command/CommandDtoFactory.adoc[CommandDtoFactory], xref:refguide:core:index/metamodel/services/grid/GridLoaderServiceDefault.adoc[GridLoaderServiceDefault], xref:refguide:core:index/metamodel/services/grid/spi/LayoutResourceLoader.adoc[LayoutResourceLoader], xref:refguide:core:index/metamodel/services/ixn/InteractionDtoFactory.adoc[InteractionDtoFactory], xref:refguide [...]
 ****
 
 |Apache Causeway Core - Runtime
@@ -1510,6 +1517,7 @@ rectangle "Persistence\n<size:10>[Software System]</size>" <<Persistence>> {
 
 @enduml
 ----
+
 .Projects/Modules (Persistence)
 [cols="3a,5a", options="header"]
 |===
@@ -1631,6 +1639,7 @@ JDO.ApacheCausewayPersistenceJDO .[#707070,thickness=2].> JDO.ApacheCausewayPers
 JDO.ApacheCausewayPersistenceJDO .[#707070,thickness=2].> JDO.ApacheCausewayPersistenceJDOapplib : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (JDO)
 [cols="3a,5a", options="header"]
 |===
@@ -1889,6 +1898,7 @@ JPA.ApacheCausewayPersistenceJPA .[#707070,thickness=2].> JPA.ApacheCausewayPers
 JPA.ApacheCausewayPersistenceJPA .[#707070,thickness=2].> JPA.ApacheCausewayPersistenceJPAintegration : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (JPA)
 [cols="3a,5a", options="header"]
 |===
@@ -2043,6 +2053,7 @@ rectangle "Bypass\n<size:10>[Software System]</size>" <<Bypass>> {
 
 @enduml
 ----
+
 .Projects/Modules (Bypass)
 [cols="3a,5a", options="header"]
 |===
@@ -2110,6 +2121,7 @@ rectangle "Keycloak\n<size:10>[Software System]</size>" <<Keycloak>> {
 
 @enduml
 ----
+
 .Projects/Modules (Keycloak)
 [cols="3a,5a", options="header"]
 |===
@@ -2186,6 +2198,7 @@ rectangle "Shiro\n<size:10>[Software System]</size>" <<Shiro>> {
 
 @enduml
 ----
+
 .Projects/Modules (Shiro)
 [cols="3a,5a", options="header"]
 |===
@@ -2261,6 +2274,7 @@ rectangle "Spring\n<size:10>[Software System]</size>" <<Spring>> {
 
 @enduml
 ----
+
 .Projects/Modules (Spring)
 [cols="3a,5a", options="header"]
 |===
@@ -2370,6 +2384,7 @@ Common.ApacheCausewayViewerCommons .[#707070,thickness=2].> Common.ApacheCausewa
 Common.ApacheCausewayViewerCommons .[#707070,thickness=2].> Common.ApacheCausewayCommonsPrism : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Common)
 [cols="3a,5a", options="header"]
 |===
@@ -2544,6 +2559,7 @@ RestfulObjects.ApacheCausewayViewerRO .[#707070,thickness=2].> RestfulObjects.Ap
 RestfulObjects.ApacheCausewayViewerRO .[#707070,thickness=2].> RestfulObjects.ApacheCausewayViewerROAppLib : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Restful Objects)
 [cols="3a,5a", options="header"]
 |===
@@ -2800,6 +2816,7 @@ Wicket.ApacheCausewayViewerWicket .[#707070,thickness=2].> Wicket.ApacheCauseway
 Wicket.ApacheCausewayViewerWicket .[#707070,thickness=2].> Wicket.ApacheCausewayViewerWicketModel : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Wicket)
 [cols="3a,5a", options="header"]
 |===
@@ -3021,6 +3038,7 @@ Valuetypes.ApacheCausewayValJodaTimeparent .[#707070,thickness=2].> Valuetypes.A
 Valuetypes.ApacheCausewayValJodaTimeparent .[#707070,thickness=2].> Valuetypes.ApacheCausewayValJodaTimeintegration : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Valuetypes)
 [cols="3a,5a", options="header"]
 |===
@@ -3194,6 +3212,7 @@ Asciidoc.ApacheCausewayValAsciidoctorparent .[#707070,thickness=2].> Asciidoc.Ap
 Asciidoc.ApacheCausewayValAsciidoctorui .[#707070,thickness=2].> Asciidoc.ApacheCausewayValAsciidoctoruiwicket : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Asciidoc)
 [cols="3a,5a", options="header"]
 |===
@@ -3451,6 +3470,7 @@ Markdown.ApacheCausewayValMarkdownui .[#707070,thickness=2].> Markdown.ApacheCau
 Markdown.ApacheCausewayValMarkdownparent .[#707070,thickness=2].> Markdown.ApacheCausewayValMarkdownapplib : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Markdown)
 [cols="3a,5a", options="header"]
 |===
@@ -3676,6 +3696,7 @@ Vega.ApacheCausewayValVegaui .[#707070,thickness=2].> Vega.ApacheCausewayValVega
 Vega.ApacheCausewayValVegaparent .[#707070,thickness=2].> Vega.ApacheCausewayValVegaapplib : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Vega)
 [cols="3a,5a", options="header"]
 |===
@@ -3898,6 +3919,18 @@ skinparam rectangle<<Extensions.ApacheCausewayExtFullCalendarWicketUI>> {
   BorderColor #2e6295
   shadowing false
 }
+skinparam rectangle<<Extensions.ApacheCausewayExtLayoutGitHub>> {
+  BackgroundColor #438dd5
+  FontColor #fffffe
+  BorderColor #2e6295
+  shadowing false
+}
+skinparam rectangle<<Extensions.ApacheCausewayExtLayoutGitHubLoader>> {
+  BackgroundColor #438dd5
+  FontColor #fffffe
+  BorderColor #2e6295
+  shadowing false
+}
 skinparam rectangle<<Extensions.ApacheCausewayExtSecMan>> {
   BackgroundColor #438dd5
   FontColor #fffffe
@@ -4077,13 +4110,15 @@ rectangle "Extensions\n<size:10>[Software System]</size>" <<Extensions>> {
   rectangle "==Apache Causeway Ext - FullCalendar Wicket\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtFullCalendarWicket>> as Extensions.ApacheCausewayExtFullCalendarWicket
   rectangle "==Apache Causeway Ext - FullCalendar Wicket (Integration)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtFullCalendarWicketIntegration>> as Extensions.ApacheCausewayExtFullCalendarWicketIntegration
   rectangle "==Apache Causeway Ext - FullCalendar Wicket (UI)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtFullCalendarWicketUI>> as Extensions.ApacheCausewayExtFullCalendarWicketUI
+  rectangle "==Apache Causeway Ext - LayoutGitHub\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtLayoutGitHub>> as Extensions.ApacheCausewayExtLayoutGitHub
+  rectangle "==Apache Causeway Ext - LayoutGitHub Loader\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtLayoutGitHubLoader>> as Extensions.ApacheCausewayExtLayoutGitHubLoader
   rectangle "==Apache Causeway Ext - pdf.js - Parent\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtpdfjsParent>> as Extensions.ApacheCausewayExtpdfjsParent
   rectangle "==Apache Causeway Ext - pdf.js - Applib\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtpdfjsApplib>> as Extensions.ApacheCausewayExtpdfjsApplib
   rectangle "==Apache Causeway Ext - pdf.js - Metamodel\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtpdfjsMetamodel>> as Extensions.ApacheCausewayExtpdfjsMetamodel
   rectangle "==Apache Causeway Ext - pdf.js Wicket\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtpdfjsWicket>> as Extensions.ApacheCausewayExtpdfjsWicket
+  rectangle "==Apache Causeway Extensions\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtensions>> as Extensions.ApacheCausewayExtensions
   rectangle "==Apache Causeway Ext - pdf.js - Wicket (Integration)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtpdfjsWicketIntegration>> as Extensions.ApacheCausewayExtpdfjsWicketIntegration
   rectangle "==Apache Causeway Ext - pdf.js - Wicket (UI)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtpdfjsWicketUI>> as Extensions.ApacheCausewayExtpdfjsWicketUI
-  rectangle "==Apache Causeway Extensions\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtensions>> as Extensions.ApacheCausewayExtensions
   rectangle "==Apache Causeway Ext - Sec Man\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtSecMan>> as Extensions.ApacheCausewayExtSecMan
   rectangle "==Apache Causeway Ext - Sec Man Applib\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManApplib>> as Extensions.ApacheCausewayExtSecManApplib
   rectangle "==Apache Causeway Ext - Sec Man Delegated (Using Shiro)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManDelegatedUsingShiro>> as Extensions.ApacheCausewayExtSecManDelegatedUsingShiro
@@ -4092,9 +4127,9 @@ rectangle "Extensions\n<size:10>[Software System]</size>" <<Extensions>> {
   rectangle "==Apache Causeway Ext - Sec Man Encryption (Using Spring)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManEncryptionUsingSpring>> as Extensions.ApacheCausewayExtSecManEncryptionUsingSpring
   rectangle "==Apache Causeway Ext - Sec Man Integration\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManIntegration>> as Extensions.ApacheCausewayExtSecManIntegration
   rectangle "==Apache Causeway Ext - Sec Man Persistence (Using JDO)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManPersistenceUsingJDO>> as Extensions.ApacheCausewayExtSecManPersistenceUsingJDO
+  rectangle "==Apache Causeway Ext - Audit Trail\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtAuditTrail>> as Extensions.ApacheCausewayExtAuditTrail
   rectangle "==Apache Causeway Ext - Sec Man Persistence (Using JPA)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSecManPersistenceUsingJPA>> as Extensions.ApacheCausewayExtSecManPersistenceUsingJPA
   rectangle "==Apache Causeway Ext - Session Log\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtSessionLog>> as Extensions.ApacheCausewayExtSessionLog
-  rectangle "==Apache Causeway Ext - Audit Trail\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtAuditTrail>> as Extensions.ApacheCausewayExtAuditTrail
   rectangle "==Apache Causeway Ext - Session Log Applib\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSessionLogApplib>> as Extensions.ApacheCausewayExtSessionLogApplib
   rectangle "==Apache Causeway Ext - Session Log Persistence (using JDO)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSessionLogPersistenceusingJDO>> as Extensions.ApacheCausewayExtSessionLogPersistenceusingJDO
   rectangle "==Apache Causeway Ext - Session Log Persistence (using JPA)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtSessionLogPersistenceusingJPA>> as Extensions.ApacheCausewayExtSessionLogPersistenceusingJPA
@@ -4103,9 +4138,9 @@ rectangle "Extensions\n<size:10>[Software System]</size>" <<Extensions>> {
   rectangle "==Apache Causeway Ext - Server Sent Events\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtServerSentEvents>> as Extensions.ApacheCausewayExtServerSentEvents
   rectangle "==Apache Causeway Ext - Server Sent Events (metamodel)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtServerSentEventsmetamodel>> as Extensions.ApacheCausewayExtServerSentEventsmetamodel
   rectangle "==Apache Causeway Ext - Server Sent Events (Wicket)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtServerSentEventsWicket>> as Extensions.ApacheCausewayExtServerSentEventsWicket
+  rectangle "==Apache Causeway Ext - Audit Trail Applib\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtAuditTrailApplib>> as Extensions.ApacheCausewayExtAuditTrailApplib
   rectangle "==Apache Causeway Ext - Tabular (parent)\n<size:10>[Container: packaging: pom]</size>" <<Extensions.ApacheCausewayExtTabularparent>> as Extensions.ApacheCausewayExtTabularparent
   rectangle "==Apache Causeway Ext - Tabular (Applib)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtTabularApplib>> as Extensions.ApacheCausewayExtTabularApplib
-  rectangle "==Apache Causeway Ext - Audit Trail Applib\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtAuditTrailApplib>> as Extensions.ApacheCausewayExtAuditTrailApplib
   rectangle "==Apache Causeway Ext - Tabular (Excel)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtTabularExcel>> as Extensions.ApacheCausewayExtTabularExcel
   rectangle "==Apache Causeway Ext - Audit Trail Persistence (using JDO)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtAuditTrailPersistenceusingJDO>> as Extensions.ApacheCausewayExtAuditTrailPersistenceusingJDO
   rectangle "==Apache Causeway Ext - Audit Trail Persistence (using JPA)\n<size:10>[Container: packaging: jar]</size>" <<Extensions.ApacheCausewayExtAuditTrailPersistenceusingJPA>> as Extensions.ApacheCausewayExtAuditTrailPersistenceusingJPA
@@ -4117,6 +4152,7 @@ rectangle "Extensions\n<size:10>[Software System]</size>" <<Extensions>> {
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtAuditTrail : "<color:#707070>"
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtCORSparent : "<color:#707070>"
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtFullCalendarparent : "<color:#707070>"
+Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtLayoutGitHub : "<color:#707070>"
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtpdfjsParent : "<color:#707070>"
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtSecMan : "<color:#707070>"
 Extensions.ApacheCausewayExtensions .[#707070,thickness=2].> Extensions.ApacheCausewayExtSessionLog : "<color:#707070>"
@@ -4131,6 +4167,7 @@ Extensions.ApacheCausewayExtFullCalendarparent .[#707070,thickness=2].> Extensio
 Extensions.ApacheCausewayExtFullCalendarparent .[#707070,thickness=2].> Extensions.ApacheCausewayExtFullCalendarWicket : "<color:#707070>"
 Extensions.ApacheCausewayExtFullCalendarWicket .[#707070,thickness=2].> Extensions.ApacheCausewayExtFullCalendarWicketIntegration : "<color:#707070>"
 Extensions.ApacheCausewayExtFullCalendarWicket .[#707070,thickness=2].> Extensions.ApacheCausewayExtFullCalendarWicketUI : "<color:#707070>"
+Extensions.ApacheCausewayExtLayoutGitHub .[#707070,thickness=2].> Extensions.ApacheCausewayExtLayoutGitHubLoader : "<color:#707070>"
 Extensions.ApacheCausewayExtpdfjsParent .[#707070,thickness=2].> Extensions.ApacheCausewayExtpdfjsApplib : "<color:#707070>"
 Extensions.ApacheCausewayExtpdfjsParent .[#707070,thickness=2].> Extensions.ApacheCausewayExtpdfjsMetamodel : "<color:#707070>"
 Extensions.ApacheCausewayExtpdfjsParent .[#707070,thickness=2].> Extensions.ApacheCausewayExtpdfjsWicket : "<color:#707070>"
@@ -4154,6 +4191,7 @@ Extensions.ApacheCausewayExtTabularparent .[#707070,thickness=2].> Extensions.Ap
 Extensions.ApacheCausewayExtTabularparent .[#707070,thickness=2].> Extensions.ApacheCausewayExtTabularExcel : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Extensions)
 [cols="3a,5a", options="header"]
 |===
@@ -4383,6 +4421,46 @@ org.apache.causeway.viewer:causeway-viewer-wicket-ui:jar:<managed> +
 xref:refguide:extensions:index/fullcalendar/wkt/ui/CausewayModuleExtFullcalendarWicketUi.adoc[CausewayModuleExtFullcalendarWicketUi], xref:refguide:extensions:index/fullcalendar/wkt/ui/viewer/CausewayModuleExtFullCalendarWicketUi.adoc[CausewayModuleExtFullCalendarWicketUi]
 ****
 
+|Apache Causeway Ext - LayoutGitHub
+[source,yaml]
+----
+Group: org.apache.causeway.extensions
+Artifact: causeway-extensions-layoutgithub
+Type: pom
+Directory: /extensions/core/layoutgithub
+----
+|Allows layouts to be dynamically loaded from a github repo.
+
+|Apache Causeway Ext - LayoutGitHub Loader
+[source,yaml]
+----
+Group: org.apache.causeway.extensions
+Artifact: causeway-extensions-layoutgithub-loader
+Type: jar
+Directory: /extensions/core/layoutgithub/loader
+----
+|Allows layout.xml files to be dynamically loaded from a github repo.
+
+.Components
+****
+o.a.i.extensions.layoutgithub.loader.spi.LayoutResourceLoaderFromGithub +
+****
+
+.Dependencies
+****
+org.apache.causeway.core:causeway-core-metamodel:jar:<managed> +
+org.apache.causeway.valuetypes:causeway-valuetypes-asciidoc-applib:jar:<managed> +
+org.apache.causeway.valuetypes:causeway-valuetypes-asciidoc-builder:jar:<managed> +
+org.assertj:assertj-core:jar:<managed> +
+org.junit.jupiter:junit-jupiter:jar:<managed> +
+org.springframework:spring-web:jar:<managed> +
+****
+
+.Document Index Entries
+****
+xref:refguide:extensions:index/layoutgithub/loader/CausewayModuleExtLayoutGithubLoader.adoc[CausewayModuleExtLayoutGithubLoader], xref:refguide:extensions:index/layoutgithub/loader/menu/LayoutLoaderMenu.adoc[LayoutLoaderMenu]
+****
+
 |Apache Causeway Ext - pdf.js - Parent
 [source,yaml]
 ----
@@ -4533,7 +4611,7 @@ org.springframework.security:spring-security-crypto:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:extensions:index/secman/applib/CausewayModuleExtSecmanApplib.adoc[CausewayModuleExtSecmanApplib], xref:refguide:extensions:index/secman/applib/feature/api/ApplicationFeatureChoices.adoc[ApplicationFeatureChoices], xref:refguide:extensions:index/secman/applib/feature/contributions/ApplicationFeatureViewModel_permissions.adoc[ApplicationFeatureViewModel_permissions], xref:refguide:extensions:index/secman/applib/permission/app/ApplicationOrphanedPermissionManager.adoc[Applicat [...]
+xref:refguide:extensions:index/secman/applib/CausewayModuleExtSecmanApplib.adoc[CausewayModuleExtSecmanApplib], xref:refguide:extensions:index/secman/applib/feature/api/ApplicationFeatureChoices.adoc[ApplicationFeatureChoices], xref:refguide:extensions:index/secman/applib/feature/contributions/ApplicationFeatureViewModel_permissions.adoc[ApplicationFeatureViewModel_permissions], xref:refguide:extensions:index/secman/applib/permission/app/ApplicationOrphanedPermissionManager.adoc[Applicat [...]
 ****
 
 |Apache Causeway Ext - Sec Man Delegated (Using Shiro)
@@ -5035,6 +5113,7 @@ ApplibExcel.ApacheCausewayExtExcelparent .[#707070,thickness=2].> ApplibExcel.Ap
 ApplibExcel.ApacheCausewayExtExcelparent .[#707070,thickness=2].> ApplibExcel.ApacheCausewayExtExcelIntegTests : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Applib: Excel)
 [cols="3a,5a", options="header"]
 |===
@@ -5198,6 +5277,7 @@ CoreCommandLog.ApacheCausewayExtCommandLog .[#707070,thickness=2].> CoreCommandL
 CoreCommandLog.ApacheCausewayExtCommandLog .[#707070,thickness=2].> CoreCommandLog.ApacheCausewayExtCommandLogImplementationJPA : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: Command Log)
 [cols="3a,5a", options="header"]
 |===
@@ -5350,6 +5430,7 @@ rectangle "Core: DocGen\n<size:10>[Software System]</size>" <<CoreDocGen>> {
 CoreDocGen.ApacheCausewayExtDocgen .[#707070,thickness=2].> CoreDocGen.ApacheCausewayExtDocgenHelp : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: DocGen)
 [cols="3a,5a", options="header"]
 |===
@@ -5458,6 +5539,7 @@ CoreExecutionLog.ApacheCausewayExtExecutionLog .[#707070,thickness=2].> CoreExec
 CoreExecutionLog.ApacheCausewayExtExecutionLog .[#707070,thickness=2].> CoreExecutionLog.ApacheCausewayExtExecutionLogImplementationJPA : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: Execution Log)
 [cols="3a,5a", options="header"]
 |===
@@ -5628,6 +5710,7 @@ CoreExecutionOutbox.ApacheCausewayExtExecutionOutbox .[#707070,thickness=2].> Co
 CoreExecutionOutbox.ApacheCausewayExtExecutionOutbox .[#707070,thickness=2].> CoreExecutionOutbox.ApacheCausewayExtExecutionOutboxImplementationJPA : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: Execution Outbox)
 [cols="3a,5a", options="header"]
 |===
@@ -5804,6 +5887,7 @@ rectangle "Core: Execution Republisher\n<size:10>[Software System]</size>" <<Cor
 CoreExecutionRepublisher.ApacheCausewayExtExecutionRepublisher .[#707070,thickness=2].> CoreExecutionRepublisher.ApacheCausewayExtExecutionOutboxRepublisher : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: Execution Republisher)
 [cols="3a,5a", options="header"]
 |===
@@ -5887,6 +5971,7 @@ rectangle "Core: Flyway\n<size:10>[Software System]</size>" <<CoreFlyway>> {
 CoreFlyway.ApacheCausewayExtFlyway .[#707070,thickness=2].> CoreFlyway.ApacheCausewayExtFlywayImpl : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Core: Flyway)
 [cols="3a,5a", options="header"]
 |===
@@ -6023,6 +6108,7 @@ Tooling.ApacheCausewayTooling .[#707070,thickness=2].> Tooling.ApacheCausewayToo
 Tooling.ApacheCausewayTooling .[#707070,thickness=2].> Tooling.ApacheCausewayToolingC4Modeling : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Tooling)
 [cols="3a,5a", options="header"]
 |===
@@ -6374,6 +6460,7 @@ RegressionTests.ApacheCausewayRegressionTestsstableCmdExecAuditSession .[#707070
 RegressionTests.ApacheCausewayRegressionTestsstableCmdExecAuditSession .[#707070,thickness=2].> RegressionTests.ApacheCausewayRegressionTestsstableCmdExecAuditSessionJPA : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Regression Tests)
 [cols="3a,5a", options="header"]
 |===
@@ -6811,6 +6898,7 @@ rectangle "Incubator\n<size:10>[Software System]</size>" <<Incubator>> {
 
 @enduml
 ----
+
 .Projects/Modules (Incubator)
 [cols="3a,5a", options="header"]
 |===
@@ -6898,6 +6986,7 @@ GraphQLViewer.ApacheCausewayIncViewerGraphQL .[#707070,thickness=2].> GraphQLVie
 GraphQLViewer.ApacheCausewayIncViewerGraphQL .[#707070,thickness=2].> GraphQLViewer.ApacheCausewayIncViewerGraphQLTest : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (GraphQL Viewer)
 [cols="3a,5a", options="header"]
 |===
@@ -7042,6 +7131,7 @@ Other.ApacheCausewayExtCommandReplay .[#707070,thickness=2].> Other.ApacheCausew
 Other.ApacheCausewayExtCommandReplay .[#707070,thickness=2].> Other.ApacheCausewayExtCommandReplayforSecondary : "<color:#707070>"
 @enduml
 ----
+
 .Projects/Modules (Other)
 [cols="3a,5a", options="header"]
 |===