diff --git a/docs/1.html b/docs/1.html index 163b0bfc5..61ee0a51e 100644 --- a/docs/1.html +++ b/docs/1.html @@ -73,42 +73,42 @@
-
+
-
- -
+
+ +
-
+
@@ -122,7 +122,7 @@ diff --git a/docs/core/capability/index.html b/docs/core/capability/index.html index 97e496119..ac8f009d7 100644 --- a/docs/core/capability/index.html +++ b/docs/core/capability/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Capability +

Capability

@@ -133,7 +133,7 @@

-

Nasdanika Capability framework allows to discover/load capabilities which meet a requirement. Capabilities are provided by CapabilityFactory create() method. Capability factories may request other capabilities they need. As such, capabilities can be chained. Factories create CapabilityLoaders which provide Flux reactive streams of capabilities. It allows to have an infinite stream of capabilities which are consumed (and produced) as needed. Capability providers may furnish additional information about capabilities. This information can be used for filtering or sorting providers.

+

Nasdanika Capability framework1 allows to discover/load capabilities which meet a requirement. Capabilities are provided by CapabilityFactory create() method. Capability factories may request other capabilities they need. As such, capabilities can be chained. Factories create CapabilityLoaders which provide Flux reactive streams of capabilities. It allows to have an infinite stream of capabilities which are consumed (and produced) as needed. Capability providers may furnish additional information about capabilities. This information can be used for filtering or sorting providers.

A non-technical example of requirement/capability chain graph is a food chain/graph. Food is a requirement. Or “I want to eat” is a requirement. Bread and, say fried eggs are two capabilities meeting/addressing the requirement. Bread requires “wheat”, “water”, and “bake” capabilities. Fried eggs require “egg”, “oil”, and “fry” capabilities. Bread capability provider may implement Vegan marker interface which can be used for filtering. All food capabilities may implement NutritionalInformation interface - it can be used for filtering or sorting.

A more technical example is Java ServiceLoader with service type being a requirement and an instance of the service class being a capability.

Nasdanika capability framework can operate on top of ServiceLoader and may be thought of as a generalization of service loading. In essence, the capability framework is a backward chaining engine as shown in one of the example below.

@@ -259,6 +259,15 @@

AI

A similar approach can be applied to other models - customer/accounts, organization or architecture model, etc.

For example, from the Internet Banking System we can generate something like “Accounts Summary Controller uses Mainframe Banking System Facade to make API calls to the Mainframe Banking System over XML/HTTPS”. “make API calls” may also be generated as “connect” or “make requests”.

In a similar fashion a number of questions/answers can be generated.

+
+
+
    +
  1. +

    Javadoc

    + +
  2. +
+

@@ -271,7 +280,7 @@

AI diff --git a/docs/core/cli/index.html b/docs/core/cli/index.html index a5189b3f7..1e1d2cbd4 100644 --- a/docs/core/cli/index.html +++ b/docs/core/cli/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

CLI +

CLI

@@ -133,19 +133,75 @@

-

Classes in this module allow to declaratively construct command line interfaces. It uses picocli to execute commands and capability framework to collect sub-commands and mix-ins. This way command line interfaces can be constructed top-down (default picocli functionality) - parent commands explicitly define sub-commands, and bottom-up - sub-commands are added to parent commands by the framework.

+

Classes in this module allow to declaratively construct command line interfaces. It uses picocli to execute commands and capability framework to collect sub-commands and mix-ins. This way command line interfaces can be constructed top-down (default picocli functionality) - parent commands explicitly define sub-commands, and bottom-up - sub-commands are added to parent commands by the framework. Top-down construction can be done using out-the-box picocli capabilities - programmatic add and annotations. Both top-down and bottom-up construction can be done using the capability framework which allows sub-commands/mix-ins to request capabilities they need and add themselves to parent commands only if all requirements are met.

+

The module provides a capability to build polymorphic CLI’s - sub-commands and mix-ins may override other sub-commands and mix-ins with the same name. This is similar to method overriding in Object-Oriented languages like Java. For example, a base CLI package may have a basic implementation of some sub-command. A derived package would add dependencies with advanced sub-commands to pom.xml. These sub-commands would replace (override) basic sub-commands during construction of the command hierarchy.

+

Javadoc

Contributing sub-commands

-

Create a sub-class of SubCommandCapabilityFactory and override either createCommand or createCommands methods. Add to module-info.java:

+

In addition to the picocli way of adding sub-commands programmatically and using @Command annotation subcommands element this module provides a few more ways to contribute sub-commands which are explained below.

+

In all cases create a sub-class of SubCommandCapabilityFactory and implement/override the following methods:

+
    +
  • getCommandType - used for declarative matching
  • +
  • createCommand for imperative (programmatic) matching
  • +
  • doCreateCommand: +
      +
    • Declarative - in combination with @SubCommands or @Parent
    • +
    • Imperative - override match() as well.
    • +
    +
  • +
+

Add to module-info.java:

  • provides org.nasdanika.capability.CapabilityFactory with <factory class>
  • -
  • opens <sub-command package name> to info.picocli;
  • +
  • opens <sub-command package name> to info.picocli, org.nasdanika.html.model.app.gen.cli;
+

Opening to org.nasdanika.html.model.app.gen.cli is needed if you want to generate extended documentation (see below).

+

@SubCommands annotation

+

This one is similar to @Command.subcommands - the parent command declares types of sub-commands. However:

+
    +
  • Sub-commands are collected using the capability framework from SubCommandCapabilityFactory’s.
  • +
  • Sub-commands types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types. E.g. you may have HelpCommand interface or base class and all commands implementing/extending this class will be added to the parent command. If there are two commands with the same name one of them might override the other as explained below.
  • +
+

@Parent annotation

+

In this case the sub-command or mix-in class are annotated with @Parent annotation listing types of parents. The sub-command/mix-in will be added to all commands in the hierarchy which are instances of the specified parent types - exact class, interface implementation, or sub-class.

+

Programmatic match

+

The above two ways of matching parent commands and sub-commands are handled by the SubCommandCapabilityFactory.match() method. You may override this method or createCommand() method to programmatically match parent path and decide whether to contribute a sub-command or not.

Contributing mix-ins

-

Create s sub-class of MixInCapabilityFactory, implement getName() and createMixIn() methods. Add to module-info.java:

+

Similar to sub-commands, mix-ins can be contributed top-down and bottom-up - declaratively using annotations and programmatically.

+

In all cased create s sub-class of MixInCapabilityFactory, implement/override:

+
    +
  • getMixInType() - for declarative matching
  • +
  • getName()
  • +
  • createMixIn() for imperative matching, or
  • +
  • doCreateMixIn() +
      +
    • Declarative - in combination with @MixIns or @Parent
    • +
    • Imperative - override match() as well.
    • +
    +
  • +
+

Add to module-info.java:

  • provides org.nasdanika.capability.CapabilityFactory with <factory class>
  • opens <mix-in package name> to info.picocli;
+

@MixIns annotation

+
    +
  • Mix-ins are collected using the capability framework from MixInCapabilityFactory’s.
  • +
  • Mix-in types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types.
  • +
+

@Parent annotation

+

See “@Parent annotation” sub-section in “Contributing sub-commands” section above.

+

Programmatic match

+

The above two ways of matching parent commands and sub-commands/mix-ins are handled by the MixInCapabilityFactory.match() method. You may override this method or createMixIn() method to programmatically match parent path and decide whether to contribute a mix-in or not.

+

Overriding

+

A command/mix-in overrides another command/mix-in if:

+
    +
  • It is a sub-class of that command/mix-in
  • +
  • It implements Overrider interface and returns true from overrides(Object other) method.
  • +
  • It is annotated with @Overrides and the other command is an instance of one of the value classes.
  • +
+

Extended documentation

+

You may annotate commands with @Description to provide additional information in generated HTML site.

Building distributions

A distribution is a collection of modules contributing commands and mix-ins plus launcher scripts for different operating systems. org.nasdanika.cli and org.nasdanika.launcher modules are examples of building distributions as part of Maven build. Building a distribution involves two steps:

@@ -243,7 +308,7 @@

Gene diff --git a/docs/core/common/index.html b/docs/core/common/index.html index 3d5a06c08..09786a9c7 100644 --- a/docs/core/common/index.html +++ b/docs/core/common/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Common +

Common

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/diagram/index.html b/docs/core/diagram/index.html index f40a7529c..27b351cd5 100644 --- a/docs/core/diagram/index.html +++ b/docs/core/diagram/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Diagram +

Diagram

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/drawio/index.html b/docs/core/drawio/index.html index 666e4b71c..5ce9f2ff5 100644 --- a/docs/core/drawio/index.html +++ b/docs/core/drawio/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Drawio +

Drawio

@@ -170,7 +170,7 @@

Model

diff --git a/docs/core/emf/index.html b/docs/core/emf/index.html index e61247eac..a79a3d1aa 100644 --- a/docs/core/emf/index.html +++ b/docs/core/emf/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

EMF +

EMF

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/exec/index.html b/docs/core/exec/index.html index 95aa35170..8ff91e86b 100644 --- a/docs/core/exec/index.html +++ b/docs/core/exec/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Exec +

Exec

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/graph/index.html b/docs/core/graph/index.html index 9ceb5657d..266177d1c 100644 --- a/docs/core/graph/index.html +++ b/docs/core/graph/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Graph +

Graph

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/index.html b/docs/core/index.html index 87ee33928..c3ece6265 100644 --- a/docs/core/index.html +++ b/docs/core/index.html @@ -73,46 +73,46 @@
-
+
-
- -
+
+ +
-
+
-

Core +

Core

@@ -133,7 +133,7 @@

diff --git a/docs/core/maven/index.html b/docs/core/maven/index.html index 1a279290e..11156fdab 100644 --- a/docs/core/maven/index.html +++ b/docs/core/maven/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Maven +

Maven

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/ncore/index.html b/docs/core/ncore/index.html deleted file mode 100644 index 1dd68a0d9..000000000 --- a/docs/core/ncore/index.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - Ncore - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - Nasdanika - -
-
-
-
-
-
-
- -
- -
-
-
-
-
-
- -
-
-
-
-

Ncore -

-
-
-
-
-
-
-

TODO

-
-
-
-
-
-
-
-
-
- -
-
- - \ No newline at end of file diff --git a/docs/core/persistence/index.html b/docs/core/persistence/index.html index ccf88e228..53e097a35 100644 --- a/docs/core/persistence/index.html +++ b/docs/core/persistence/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Persistence +

Persistence

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/core/resources/index.html b/docs/core/resources/index.html index c625895b2..3134f5386 100644 --- a/docs/core/resources/index.html +++ b/docs/core/resources/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Resources +

Resources

@@ -133,7 +133,7 @@

-

TODO

+
@@ -146,7 +146,7 @@

diff --git a/docs/glossary.html b/docs/glossary.html index 2fe4cfb15..74588df58 100644 --- a/docs/glossary.html +++ b/docs/glossary.html @@ -73,45 +73,45 @@
- + Nasdanika
-
+
-
- -
+
+ +
-
+
-

Glossary +

Glossary

@@ -171,7 +171,7 @@

diff --git a/docs/html/bootstrap/index.html b/docs/html/bootstrap/index.html index de88e8b32..af817a007 100644 --- a/docs/html/bootstrap/index.html +++ b/docs/html/bootstrap/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Bootstrap +

Bootstrap

@@ -146,7 +146,7 @@

diff --git a/docs/html/emf/index.html b/docs/html/emf/index.html index ac850a773..9e7e34ca9 100644 --- a/docs/html/emf/index.html +++ b/docs/html/emf/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

EMF +

EMF

@@ -146,7 +146,7 @@

diff --git a/docs/html/html/index.html b/docs/html/html/index.html index 1566930e9..a00e74ef3 100644 --- a/docs/html/html/index.html +++ b/docs/html/html/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

HTML +

HTML

@@ -146,7 +146,7 @@

diff --git a/docs/html/index.html b/docs/html/index.html index 1c1ee9089..1efd06f2c 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -73,46 +73,46 @@
-
+
-
- -
+
+ +
-
+
-

HTML +

HTML

@@ -133,7 +133,7 @@

diff --git a/docs/html/jstree/index.html b/docs/html/jstree/index.html index 793a5d8b6..a02e17284 100644 --- a/docs/html/jstree/index.html +++ b/docs/html/jstree/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

JsTree +

JsTree

@@ -146,7 +146,7 @@

diff --git a/docs/html/models/app/index.html b/docs/html/models/app/index.html index 611eb0707..d736d1db0 100644 --- a/docs/html/models/app/index.html +++ b/docs/html/models/app/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

App +

App

@@ -149,7 +149,7 @@

diff --git a/docs/html/models/bootstrap/index.html b/docs/html/models/bootstrap/index.html index 01bc43c43..e7537ddbf 100644 --- a/docs/html/models/bootstrap/index.html +++ b/docs/html/models/bootstrap/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

Bootstrap +

Bootstrap

@@ -149,7 +149,7 @@

diff --git a/docs/html/models/html/index.html b/docs/html/models/html/index.html index f13d0af7e..218204c63 100644 --- a/docs/html/models/html/index.html +++ b/docs/html/models/html/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

HTML +

HTML

@@ -149,7 +149,7 @@

diff --git a/docs/html/models/index.html b/docs/html/models/index.html index abb84651f..c05c5e40d 100644 --- a/docs/html/models/index.html +++ b/docs/html/models/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Models +

Models

@@ -146,7 +146,7 @@

diff --git a/docs/index.html b/docs/index.html index 621d92c4d..8643cec95 100644 --- a/docs/index.html +++ b/docs/index.html @@ -72,47 +72,47 @@
-
Nasdanika +
Nasdanika
-
+
-
- -
+
+ +
-
+
-

+

@@ -127,7 +127,7 @@ diff --git a/docs/nsd-cli/index.html b/docs/nsd-cli/index.html index f28d7e399..58fc0e791 100644 --- a/docs/nsd-cli/index.html +++ b/docs/nsd-cli/index.html @@ -73,46 +73,46 @@
-
+
-
- -
+
+ +
-
+
-

CLI +

CLI

@@ -120,7 +120,28 @@

-

Nasdanika Command Line Interface (CLI) is a collection of Nasdanika offerings packaged as command line tools.

+

Nasdanika Command Line Interface (CLI) is a suite of Nasdanika capabilities packaged as command line tools.

+

Prerequisites

+

To run Nasdanika CLI you’d need Java 17+. To build from sources you’d also need Maven.

+

Installation

+

Download installation archive from the releases page. On Linux make nsd executable: chmod a+x nsd.

+

Building from sources

+
    +
  • Download sources as a zip file or clone the repository
  • +
  • Run mvn clean verify
  • +
  • After the build completes the distribuion will be available in target/dist directory
  • +
+

Adding to PATH

+

The distribution is portable and local - it can be put to any directory, but it can only be executed from that directory. To create an installation which can be used from any directory you will need to create launcher files with absolute paths.

+

Windows

+
nsd.bat launcher -f options-global -o nsd-global.bat -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules -j "@java"
+
+

Add the installation to the PATH environment variable. You may delete/rename nsd.bat and rename nsd-global.bat to nsd.bat.

+

Linux

+
./nsd launcher -o nsd-global -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules
+
+

Open nsd-global in a text editor and add #!/bin/bash line before the java command line. Make the file executable and add the installation directory to the path. You may remove/rename nsd and rename nsd-global to nsd.

+

If you get java.lang.module.FindException: Module <module name> not found error, open the file in a text editor, locate the problematic module and remove it from the --add-modules list.

@@ -133,7 +154,7 @@

diff --git a/docs/nsd-cli/nsd/app/index.html b/docs/nsd-cli/nsd/app/index.html index 4fb786bd8..6ad4eed30 100644 --- a/docs/nsd-cli/nsd/app/index.html +++ b/docs/nsd-cli/nsd/app/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

app +

app

@@ -137,7 +137,7 @@

Version: -org.nasdanika.html.model.app.gen.cli@2024.4.0 +org.nasdanika.html.model.app.gen.cli@2024.5.0
@@ -160,7 +160,7 @@ 

diff --git a/docs/nsd-cli/nsd/app/site/index.html b/docs/nsd-cli/nsd/app/site/index.html index c4943d0d4..23a31948a 100644 --- a/docs/nsd-cli/nsd/app/site/index.html +++ b/docs/nsd-cli/nsd/app/site/index.html @@ -73,57 +73,57 @@
-
+
-
- -
+
+ +
-
+
@@ -131,7 +131,7 @@
-

site +

site

@@ -140,7 +140,7 @@

Version: -org.nasdanika.html.model.app.gen.cli@2024.4.0 +org.nasdanika.html.model.app.gen.cli@2024.5.0
@@ -165,7 +165,7 @@ 

diff --git a/docs/nsd-cli/nsd/help/index.html b/docs/nsd-cli/nsd/help/index.html index 833e8c555..c02b3548f 100644 --- a/docs/nsd-cli/nsd/help/index.html +++ b/docs/nsd-cli/nsd/help/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

help +

help

@@ -162,7 +162,7 @@

diff --git a/docs/nsd-cli/nsd/help/site/index.html b/docs/nsd-cli/nsd/help/site/index.html index 5e1918c3d..96ddc590b 100644 --- a/docs/nsd-cli/nsd/help/site/index.html +++ b/docs/nsd-cli/nsd/help/site/index.html @@ -73,57 +73,57 @@
-
+
-
- -
+
+ +
-
+
@@ -131,7 +131,7 @@
-

site +

site

@@ -162,7 +162,7 @@

diff --git a/docs/nsd-cli/nsd/http-server/index.html b/docs/nsd-cli/nsd/http-server/index.html index 8ffe040d0..856b1f559 100644 --- a/docs/nsd-cli/nsd/http-server/index.html +++ b/docs/nsd-cli/nsd/http-server/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

http-server +

http-server

@@ -137,9 +137,18 @@

-Usage: nsd http-server [-hV]
+Usage: nsd http-server [-hV] [--http-host=<httpHost>] [--http-port=<httpPort>]
+                       [--http-server-shutdown-timeout=<timeout>]
 Serves HTTP routes
   -h, --help      Show this help message and exit.
+      --http-host=<httpHost>
+                  HTTP host (network interface) to bind to
+      --http-port=<httpPort>
+                  HTTP port. If a port is not specified,
+                  an ephemeral port is used
+      --http-server-shutdown-timeout=<timeout>
+                  Timeout in seconds,
+                  defaults to 3 seconds
   -V, --version   Print version information and exit.
 
@@ -154,7 +163,7 @@

diff --git a/docs/nsd-cli/nsd/index.html b/docs/nsd-cli/nsd/index.html index 21863f926..ea5ee0268 100644 --- a/docs/nsd-cli/nsd/index.html +++ b/docs/nsd-cli/nsd/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

nsd +

nsd

@@ -134,7 +134,7 @@

Version: -org.nasdanika.cli@2024.4.0 +org.nasdanika.cli@2024.5.0
@@ -161,7 +161,7 @@ 

diff --git a/docs/nsd-cli/nsd/java/index.html b/docs/nsd-cli/nsd/java/index.html index 700e8cef5..a78a3d588 100644 --- a/docs/nsd-cli/nsd/java/index.html +++ b/docs/nsd-cli/nsd/java/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

java +

java

@@ -137,7 +137,7 @@

Version: -org.nasdanika.models.java.cli@2024.4.0 +org.nasdanika.models.java.cli@2024.5.0
@@ -160,7 +160,7 @@ 

diff --git a/docs/nsd-cli/nsd/java/junit/index.html b/docs/nsd-cli/nsd/java/junit/index.html index c29be2c37..3d66492d3 100644 --- a/docs/nsd-cli/nsd/java/junit/index.html +++ b/docs/nsd-cli/nsd/java/junit/index.html @@ -73,57 +73,57 @@
-
+
-
- -
+
+ +
-
+
@@ -131,7 +131,7 @@
-

junit +

junit

@@ -140,16 +140,17 @@

Version: -org.nasdanika.models.java.cli@2024.4.0 +org.nasdanika.models.java.cli@2024.5.0
-Usage: nsd java junit [-dhjVw] [--[no-]comment-response] [--disabled]
-                      [--api-endpoint=<apiEndpoint>] [-c=<classes>]
-                      [--class-suffix=<classSuffix>] [-J=<jacoco>]
-                      [-k=<apiKey>] [-l=<limit>] [-m=<deploymentOrModelName>]
-                      [-p=<progressOutput>] [--package-suffix=<packageSuffix>]
-                      [-r=<prompt>] [-s=<sources>] [-t=<coverageType>]
+Usage: nsd java junit [-dhjVw] [--[no-]ai] [--[no-]comment-response]
+                      [--disabled] [--api-endpoint=<apiEndpoint>]
+                      [-c=<classes>] [--class-suffix=<classSuffix>]
+                      [-J=<jacoco>] [-k=<apiKey>] [-l=<limit>]
+                      [-m=<deploymentOrModelName>] [-p=<progressOutput>]
+                      [--package-suffix=<packageSuffix>] [-r=<prompt>]
+                      [-s=<sources>] [-t=<coverageType>]
                       [-v=<apiKeyEnvironmentVariable>] [-e[=<excludes>...]]...
                       [-i[=<includes>...]]... <projectDir> <coverageThreshold>
                       <output>
@@ -158,6 +159,7 @@ 

diff --git a/docs/nsd-cli/nsd/launcher/index.html b/docs/nsd-cli/nsd/launcher/index.html index e7a80b957..48916beca 100644 --- a/docs/nsd-cli/nsd/launcher/index.html +++ b/docs/nsd-cli/nsd/launcher/index.html @@ -73,54 +73,54 @@
-
+
-
- -
+
+ +
-
+
@@ -128,7 +128,7 @@
-

launcher +

launcher

@@ -137,15 +137,15 @@

Version: -org.nasdanika.cli@2024.4.0 +org.nasdanika.cli@2024.5.0
 Usage: nsd launcher [-hstvV] [-a=<args>] [-b=<base>] [-c=<className>]
                     [-C=<classPathModules>] [-f=<optionsFile>]
-                    [-j=<javaCommand>] [-m=<moduleName>] [-o=<output>]
-                    [-p=<pathSeparator>] [-P=<prefix>] [-r=<rootModules>]
-                    [<repositories>...]
+                    [-j=<javaCommand>] [-m=<moduleName>] [-M=<modulesFile>]
+                    [-o=<output>] [-p=<pathSeparator>] [-P=<prefix>]
+                    [-r=<rootModules>] [<repositories>...]
 Generates Java command line from directories of modules/jars
       [<repositories>...]    Directories to scan for modules,
                              defaults to lib
@@ -163,6 +163,8 @@ 

diff --git a/docs/practices/generic/index.html b/docs/practices/generic/index.html index 6098f05cc..af281a277 100644 --- a/docs/practices/generic/index.html +++ b/docs/practices/generic/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Analysis, Visualization & Generation +

Analysis, Visualization & Generation

@@ -196,7 +196,7 @@

Resources

diff --git a/docs/practices/index.html b/docs/practices/index.html index a788aa344..6761d6b4b 100644 --- a/docs/practices/index.html +++ b/docs/practices/index.html @@ -73,46 +73,46 @@
-
+
-
- -
+
+ +
-
+
-

Practices +

Practices

@@ -162,7 +162,7 @@

diff --git a/docs/practices/java/index.html b/docs/practices/java/index.html index 5cf3df133..dda1685ed 100644 --- a/docs/practices/java/index.html +++ b/docs/practices/java/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

Java Analysis, Visualization & Generation +

Java Analysis, Visualization & Generation

@@ -170,7 +170,7 @@

RAG/Chat

diff --git a/docs/practices/junit/index.html b/docs/practices/junit/index.html index 0706232ac..36f7c025f 100644 --- a/docs/practices/junit/index.html +++ b/docs/practices/junit/index.html @@ -73,51 +73,51 @@
-
+
-
- -
+
+ +
-
+
@@ -125,7 +125,7 @@
-

JUnit Tests Generation +

JUnit Tests Generation

@@ -161,6 +161,7 @@

Command line
  • Reference Implementations
    • All-in-one
    • @@ -190,6 +191,8 @@

      Command line

      +

      Nasdanika CLI features JUnit command which generates JUnit tests as explained above.

      Reference Implementations

      This section explains reference implementations

      All-in-one

      @@ -335,7 +338,7 @@

      Te diff --git a/docs/search-documents.js b/docs/search-documents.js index 102cbe331..d7a67e4eb 100644 --- a/docs/search-documents.js +++ b/docs/search-documents.js @@ -1 +1 @@ -var searchDocuments = {"html/index.html":{"action-uuid":"5a980479-45aa-435e-9dbc-0ec9573ce36e","title":"HTML","content":"TODO"},"html/models/app/index.html":{"path":"HTML/Models/App","action-uuid":"1b65d9e6-a32e-4419-a5f4-e39e33360514","title":"App","content":"TODO"},"nsd-cli/nsd/launcher/index.html":{"path":"CLI/nsd/launcher","action-uuid":"84a3c27f-42e7-4a7b-8071-6693f40427c9","title":"launcher","content":"Version: org.nasdanika.cli@2024.4.0 \r\nUsage: nsd launcher [-hstvV] [-a=<args>] [-b=<base>] [-c=<className>]\r\n [-C=<classPathModules>] [-f=<optionsFile>]\r\n [-j=<javaCommand>] [-m=<moduleName>] [-o=<output>]\r\n [-p=<pathSeparator>] [-P=<prefix>] [-r=<rootModules>]\r\n [<repositories>...]\r\nGenerates Java command line from directories of modules/jars\r\n [<repositories>...] Directories to scan for modules,\r\n defaults to lib\r\n -a, --args=<args> Arguments,\r\n defaults to %*\r\n -b, --base=<base> Base repositories directory\r\n -c, --class=<className> Application class,\r\n defaults to org.nasdanika.cli.Application\r\n -C, --claspath-modules=<classPathModules>\r\n Comma-separated list of classpath modules\r\n -f, --options-file=<optionsFile>\r\n File to output options to\r\n -h, --help Show this help message and exit.\r\n -j, --java=<javaCommand> Java command,\r\n defaults to java\r\n -m, --module=<moduleName> Application module,\r\n defaults to org.nasdanika.cli\r\n -o, --output=<output> Output file\r\n -p, --path-separator=<pathSeparator>\r\n Path separator,\r\n defaults to the system path separator\r\n -P, --prefix=<prefix> Module path prefix\r\n -r, --root-modules=<rootModules>\r\n Comma-separated list of root modules\r\n Supports .* and .** patterns\r\n -s, --absolute Use absolute paths\r\n -t, --options Output only options\r\n -v, --verbose Output debug invformation\r\n -V, --version Print version information and exit."},"html/models/bootstrap/index.html":{"path":"HTML/Models/Bootstrap","action-uuid":"4ceffae9-06cb-4972-bec1-1510a1bbeef7","title":"Bootstrap","content":"TODO"},"core/maven/index.html":{"path":"Core/Maven","action-uuid":"c5776345-0155-4f92-a777-6f562f982610","title":"Maven","content":"TODO"},"core/persistence/index.html":{"path":"Core/Persistence","action-uuid":"6b90548e-a6fd-4f8b-9e2b-c8dfdf356bf6","title":"Persistence","content":"TODO"},"core/diagram/index.html":{"path":"Core/Diagram","action-uuid":"fe77df84-09b1-4df0-b656-6b32f0c3e82e","title":"Diagram","content":"TODO"},"html/emf/index.html":{"path":"HTML/EMF","action-uuid":"a2e21827-bb81-4a33-890e-48b25102cdab","title":"EMF","content":"TODO"},"html/bootstrap/index.html":{"path":"HTML/Bootstrap","action-uuid":"500a6e14-d052-458d-9506-0f77a9d88e1f","title":"Bootstrap","content":"TODO"},"nsd-cli/nsd/app/index.html":{"path":"CLI/nsd/app","action-uuid":"51f89fc1-85d2-463e-84d1-8e48136092b6","title":"app","content":"Version: org.nasdanika.html.model.app.gen.cli@2024.4.0 \r\nUsage: nsd app [-hV] [COMMAND]\r\nHTML Application model commands\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n site Generates HTML site"},"core/cli/index.html":{"path":"Core/CLI","action-uuid":"8038c08a-1a30-4d2c-af4f-19f7ef48d8f3","title":"CLI","content":"Classes in this module allow to declaratively construct command line interfaces. It uses picocli to execute commands and capability framework to collect sub-commands and mix-ins. This way command line interfaces can be constructed top-down (default picocli functionality) - parent commands explicitly define sub-commands, and bottom-up - sub-commands are added to parent commands by the framework. Contributing sub-commands Create a sub-class of SubCommandCapabilityFactory and override either createCommand or createCommands methods. Add to module-info.java: provides org.nasdanika.capability.CapabilityFactory with <factory class> opens <sub-command package name> to info.picocli; Contributing mix-ins Create s sub-class of MixInCapabilityFactory, implement getName() and createMixIn() methods. Add to module-info.java: provides org.nasdanika.capability.CapabilityFactory with <factory class> opens <mix-in package name> to info.picocli; Building distributions A distribution is a collection of modules contributing commands and mix-ins plus launcher scripts for different operating systems. org.nasdanika.cli and org.nasdanika.launcher modules are examples of building distributions as part of Maven build. Building a distribution involves two steps: Downloading modules (dependencies) Generating launcher scripts Downloading dependencies Dependencies can be downloaded using Maven dependency plug-in: <project xmlns="http://maven.apache.org/POM/4.0.0"\n\txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n\txsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\n\t\n\t...\n\n\t<dependencies>\n\t\t...\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t...\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-dependency-plugin</artifactId>\n\t\t\t\t<version>3.6.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>copy-dependencies</id>\n\t\t\t\t\t\t<phase>prepare-package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>copy-dependencies</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<outputDirectory>\n\t\t\t\t\t\t\t\t${project.build.directory}/dist/lib\n\t\t\t\t\t\t\t</outputDirectory>\n\t\t\t\t\t\t\t<useRepositoryLayout>true</useRepositoryLayout>\t\t\t\t\t\t\t\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t\n\t\t\t...\n\t</build>\n\n\t... \n</project>\n Generating launcher scripts Launcher scripts can be generated using launcher command. The command can be issued manually from the command line. Alternatively, you can execute the launcher command from an integration test as shown below: public class BuildDistributionIT {\n\t\t\n\t@Test\n\tpublic void generateLauncher() throws IOException {\n\t\tfor (File tf: new File("target").listFiles()) {\n\t\t\tif (tf.getName().endsWith(".jar") && !tf.getName().endsWith("-sources.jar") && !tf.getName().endsWith("-javadoc.jar")) {\n\t\t\t\tFiles.copy(\n\t\t\t\t\t\ttf.toPath(), \n\t\t\t\t\t\tnew File(new File("target/dist/lib"), tf.getName()).toPath(), \n\t\t\t\t\t\tStandardCopyOption.REPLACE_EXISTING);\t\t\n\t\t\t}\n\t\t}\t\t\n\t\t\n\t\tCommandLine launcherCommandLine = new CommandLine(new LauncherCommand());\n\t\tlauncherCommandLine.execute(\n\t\t\t\t"-b", "target/dist", \n\t\t\t\t"-o", "nsd.bat");\n\t\t\n\t\tlauncherCommandLine.execute(\n\t\t\t\t"-b", "target/dist", \n\t\t\t\t"-o", "nsd",\n\t\t\t\t"-p", ":",\n\t\t\t\t"-a", "$@");\t\t\n\t\t\n\t}\n\n}\n If the Maven project which builds the distribution does not contribute its own code, then the for loop copying the jar file can be omitted. To generate a command line which can be used from any directory use -s (absolute) option or -P (prefix) option set to the installation directory. If you encounter command line length limit (8191 characters on Windows), move command options (-p, -classpath, -m) to a file or use -t option to generate just options. Then use @ syntax. For example: @java @<installation directory>\\options %*"},"core/resources/index.html":{"path":"Core/Resources","action-uuid":"02ea724b-103f-4385-a6ee-d32e0daf31b1","title":"Resources","content":"TODO"},"practices/index.html":{"action-uuid":"d822cc69-b655-4bcc-8d39-6bec97f0174c","title":"Practices","content":"Practices explain how to use Nasdanika products to achieve specific goals and explain why particular design choices wer made. The enterprise model provides deeper insight on the WHY in general. The practices are organized into an enterprise continuum from the most generic on the left to the most specific on the right. However, the most specific on the right is still generic and needs to be specialized for a particular application (embodiment): Analysis, Visualization & Generation - describes a general approach on using Nasdanika products. Java Analysis, Visualization & Generation - application of the above to the Java model1 Loading and analyzing Java sources and bytecode, generation of non-Java artifacts such as HTML reports Generation of Java sources. JUnit test generation for low coverage methods - further specialization of the Java practice to identify methods with low test coverage using the Coverage Model and then generate JUnit tests for those methods using the Java model and OpenAI. You can think of the three practices above as progressive “binding of decision” as you move from the left to the right to reach “executability” - ability to deliver value. A java analogy for progressive specialization would be incremental binding of generic types as exemplified below: Map<K,V> - generic map. MyMap<K extends Comparable> extends Map<<K, MyValue<K>> - the above map bound to a single generic parameter with an upper bound. It is a specialization of the above generic map which is also generic. Some decisions were bound, but there are still decisions to be bound. MyMap<String> theMap = ...; - fully bound map. Decisions are bound at variation point. For example, “storage” is a variation point, “blob storage” is one of alternatives, decision to use “blob storage” binds the variation point to a specific alternative. Decision binding forms a graph. Once you bind, say, “storage” variation point, some downstream alternatives may become unavailable because they are incompatible with that binding. Some might be available, but make no sense. For example, a decision to send data unencrypted over a public network is compatible with a decision to purchase some additional strong encryption hardware to use on-prem, but does it make business sense? Different alternatives feature different “quality attributes” - performance, reliability, cost. As the number of variation points and alternatives grows purely human-based decision making becomes inefficient. In this case variation points can be modeled as requirements and alternatives as capability providers or capabilities with quality attributes (seecapability). After this a list of “designs” (a.k.a. “provisioning plans”) can be created. A design/provisioning plan is a collection of compatible capabilities. If a list of designs is short enough it can be analyzed by humans directly. In the case of long lists or a large number of very similar designs decision analysis can be employed for making a selection of a design which is best fit for purpose. The page provides a general overview and the book goes into more details. ↩"},"core/emf/index.html":{"path":"Core/EMF","action-uuid":"79f046f2-43ff-4087-9782-7ee95c90db77","title":"EMF","content":"TODO"},"nsd-cli/nsd/index.html":{"path":"CLI/nsd","action-uuid":"bb10495d-7499-416a-ac4c-50cf04b54e35","title":"nsd","content":"Version: org.nasdanika.cli@2024.4.0 \r\nUsage: nsd [-hV] COMMAND\r\nNasdanika Command Line Interface\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n launcher Generates Java command line from directories of modules/jars\r\n app HTML Application model commands\r\n help Outputs usage for all registred commands\r\n http-server Serves HTTP routes\r\n java Commands related to Java"},"html/models/html/index.html":{"path":"HTML/Models/HTML","action-uuid":"e43c6d12-c25a-4fa6-b32a-bab434f90eae","title":"HTML","content":"TODO"},"index.html":{"action-uuid":"9de2104d-ea7c-4235-92e3-73e7c3c7791a","title":"Nasdanika","content":" Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI Core HTML HTML Bootstrap App Models JsTree Bootstrap EMF HTML GitLab Family Architecture Git Excel ECharts Nature Bank PDF Party Coverage Source Engineering Java Maven Enterprise Function Flow Rules Azure Decision Analysis Capability Flow Ecore Jira Models Data Sources Loader Store Key Extractor Query Engine Requestor Generator Responder Retrieval Augmented Generation (RAG) Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI Medium Publication Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI Core HTML HTML Bootstrap App Models JsTree Bootstrap EMF HTML GitLab Family Architecture Git Excel ECharts Nature Bank PDF Party Coverage Source Engineering Java Maven Enterprise Function Flow Rules Azure Decision Analysis Capability Flow Ecore Jira Models Data Sources Loader Store Key Extractor Query Engine Requestor Generator Responder Retrieval Augmented Generation (RAG) Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI Medium Publication"},"html/jstree/index.html":{"path":"HTML/JsTree","action-uuid":"b043dc0e-aa2f-458b-991a-ecbd671dfe5d","title":"JsTree","content":"TODO"},"nsd-cli/nsd/app/site/index.html":{"path":"CLI/nsd/app/site","action-uuid":"f2c2b41c-643f-4564-a281-3f9b40eb6749","title":"site","content":"Version: org.nasdanika.html.model.app.gen.cli@2024.4.0 \r\nUsage: nsd app site [-dhjlV] [-b=<baseDir>] [-m=<domian>] [-p=<progressOutput>]\r\n [-P=<parallelism>] [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>] [-c=<String=String>]...\r\n [-C=URL]... [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <model> <output>\r\nGenerates HTML site\r\n <model> Model URI, resolved relative\r\n to the current directory\r\n <output> Output directory\r\n -b, --base-dir=<baseDir> Base directory\r\n -c, --context-entry=<String=String>\r\n Context entries.\r\n Shadow entries in contexts and mounts.\r\n -C, --context=URL Context resource URL relative to the current\r\n directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Contexts are composed in the order of\r\n definition, later context entries shadowing the\r\n former\r\n -d, --data Output data\r\n -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Output directory clean includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -l, --[no-]clean Clean working directory\r\n defaults to true\r\n -m, --domain=<domian> Sitemap domain\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the\r\n current directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Mounts shadow context entries.\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n -P, --parallelism=<parallelism>\r\n If the value greater than one then an executor\r\n service is created and injected into the context\r\n to allow concurrent execution.\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -t, --timeout=<timeout> If parallelism is greater than one this option\r\n specifies timout in seconds awaiting completion\r\n of execution. Default value is 60.\r\n -T, --page-template=<pageTemplate>\r\n Page template URI relative\r\n to the current directory\r\n -V, --version Print version information and exit.\r\n -w, --work-dir=<workDir> Working directory\r\nExit codes:\r\n Non-negative number Delegate result\r\n -1 Unhandled exception during execution\r\n -2 Invalid input\r\n -3 Diagnostic failed\r\n -4 Execution failed or was cancelled, successful rollback\r\n -5 Execution failed or was cancelled, rollback failed\r\n -6 Executor service termination timed out"},"glossary.html":{"action-uuid":"ea0c93e2-9290-4c9a-aa1b-5bad7f25b0f6","title":"Glossary","content":"Clear Identifier(s) Hide UUID {{data.value.name}} {{data.value[0].value}} {{item.value}}"},"core/common/index.html":{"path":"Core/Common","action-uuid":"8f5d1746-2345-415d-88dd-461c8e37c986","title":"Common","content":"TODO"},"practices/junit/index.html":{"path":"Practices/JUnit Tests Generation","action-uuid":"6e581d7d-b67d-41a3-8952-849d7e8d6891","title":"JUnit Tests Generation","content":"This practice is a specialization of the Java Analysis, Visualization & Generation Practice for generation of JUnit tests. In particular: Generation of tests for methods or classes with low test coverage Leveraging Gen AI such as OpenAI ChatGPT or Azure OpenAI Service for test generation The above diagram shows Java development activities and artifacts. Black arrows show the typical process, blue arrows show the test generation loop. The developer produces source artifacts which may include non-java artifacts used to generate Java code (e.g. Ecore models), “main” Java sources and test Java sources. Java sources are compiled into bytecode (class files). Here it is important to note that matching of bytecode classes and methods to source code classes and methods might be non-trivial because of: Lambdas Anonymous and method-scope classes Annotation processors like Lombok JUnit tests are compiled and executed. If code coverage, such as jacoco, is configured then test execution produces coverage data. Jacoco stores coverage data in jacoco.exec file. This file is used to generate a coverage report and upload coverage information to systems like SonarQube. In this practice it is also used to select which methods to generate tests for based on coverage data. This diagram provides an insight into the test generation activity: Coverage data and bytecode are used as input to load the Coverage model. Source files, the coverage model, and bytecode (optional) are used to load the Java model of source code. The generator traverses the model and generates unit tests for method with low coverage using a combination of programmatic (traditional) generation and Gen AI. Tests are generated as a Java model as well and then are delivered to the developer for review, modification, and inclusion into the unit test suite. The following section provides an overview of two “local loop” reference implementations (a.k.a. designs/embodiments) - all-in-one and componentized. There are many possible designs leveraging different alternatives at multiple variation points. The sections after the reference implementations section provide an overview of variation points, alternatives, and factors to take into consideration during alternative selection. Reference Implementations All-in-one Componentized Repository scan/crawl Variation points and alternatives Stakeholders & Activities Developer Build machine Test generator GenAI Messages Channels Developer -> Build Machine/Test Generation : Source code Build Machine -> Test Generator : Coverage results, possibly with bytecode Test Generation -> Developer : Generated tests Test Generation - GenAI : Prompt Reference Implementations This section explains reference implementations All-in-one All-in-one generations is implemented as a JUnit test is available in TestGenerator. An example of tests generated by this generator - PetControllerTests. As the name implies, all steps of source analysis and generation are implemented in a single class and are executed in one go. Componentized Componentized test generation which is also executed in one go is implemented in these classes: TestJavaAnalyzers - loads sources, coverage, and inspectors, passes the sources to the inspectors, aggregates and saves results. Coverage Inspector - generates tests for methods with low coverage leveraging TestGenerator capability provided by OpenAITestGenerator. Repository scan/crawl TestGitLab demonstrates how to scan a source repository (GitLab) using REST API, inspect code, generate unit tests, commit them to the server (also over the REST API) and create a merge request. This implementation does not use coverage information, its purpose is to demonstrate operation over the REST API without having to clone a repository, which might be an expensive operation. The implementation uses GitLab Model to communicate with the repository. It uses Java model to load sources and StringBuilder to build test cases. Variation points and alternatives As you have seen above, you can have an AI-powered JUnit test generator in about 230 lines of code, and maybe it would all you need. However, there are many variation points (design dimensions), alternatives at each point and, as such, possible permutations of thereof (designs). This section provides a high level overview of variation points and alternatives. How to assemble a solution from those alternative is specific to your context and there might be different solutions for different contexts and multiple solutions complementing each other. As you proceed with assembling a solution, or a portfolio of solutions, you may identify more variation points and alternatives. To manage the complexity you may use: Enterprise Model for general guidance, Capability framework or Capability model to create a catalog of variation points and alternatives and compute solutions (designs) from them Decision Analysis to select from the computed list of designs Flow to map your development process AS-IS and then augment it with test generation activities at different points. In this section we’ll use the below diagram and the concept of an Enterprise with Stakeholders performing activities and exchanging Messages over Channels. The mission of our enterprise is to deliver quality Java code. The loss function to minimize is loss function = cost * risk / business value. For our purposes we’ll define risk as inversely proportional to tests coverage risk = missed lines / total lines - that’s all we can measure in this simple model. The cost includes resources costs - salary, usage fees for OpenAI. Below is a summary of our enterprise: Stakeholders & Activities: Developer - writes code Build machine - compiles code and executes tests Test generator - generates unit tests GenAI - leveraged by the Test Generator Messages: Source code Bytecode Coverage results Prompt to generate a test Generated tests Channels Developer -> Build Machine : Source code Developer -> Test Generation : Source code Build Machine -> Test Generator : Coverage results, possibly with bytecode Test Generation -> Developer : Generated tests Test Generation - GenAI : Prompt The below sections outline variation points and alternatives for the list items above Stakeholders & Activities Developer A developer writes code - both “business” and test. They use some kind of an editor, likely an IDE - Eclipse, IntelliJ, VS Code. Different IDE’s come with different sets of plug-ins, including AI assistants. Forcing a developer to switch from their IDE of preference to another IDE is likely to cause considerable productivity drop, at least for some period of time, even if the new IDE is considered superior to the old IDE. So, if you want to switch to another IDE just because it has some plug-in which you like - think twice. Build machine A build machine compiles code and executes tests. Technically, compilation and test execution may be separated in two individual activities. We are not doing it for this analysis because it doesn’t carry much relevance to test generation. You can do it for yours. Test generator Test generator generates tests by “looking” at the source code, bytecode, and code coverage results. Because the source code is a model element representing piece of code (method, constructor, …), the generator may traverse the model to “understand” the context. E.g. it may take a look at the method’s class, other classes in the module. If the sources are loaded from a version control system, it may take a look at the commits. And if the source model is part of an organization model, it may look at “sibling” modules and other resources. By analyzing source and bytecode the generator would know methods a given method calls, objects it creates, and also it would know methods calling the method. It will also “know” branch conditions, e.g. switch cases. Using this information the generator may: Generate comments to help the developer Generate mocks, including constructor and static methods mocks Generate tests for different branches Build a variety of prompts for GenAI The test generator may do the following code generated by GenAI: Add to generated test methods commented out - as it is done in the reference implementations “Massage” - remove backticks, parse, add imports - generated and implied. In addition to code generation the generator may ask GenAI to explain code and generate recommendations - it will help the developer to understand the source method and possibly improve it along the way. It may also generate dependency graphs and sequence diagrams. GenAI There may GenAI models out there - cloud, self hosted. Which one to use heavily depends on the context. For example, if you have a large codebase with considerable amount of technical debt having an on-prem model may be a good choice because: You may fine-tune it. Even if you don’t have tons of GPU power and your model is relatively slow you can crawl you code base, generate tests and deliver them to developers for review and inclusion into test suites. In this scenario your cost is on-prem infrastructure and power. Your savings are not having to pay for GenAI in the cloud and developer productivity if your fined tuned model turns out to be more efficient than a “vanilla” LLM. There are many other considerations, of course! Messages In this section we’ll take a look just at bytecode and coverage results delivered to the test generator. The generator operates on models. As such, bytecode and coverage results can be delivered in a “raw” format to be loaded to a model by the generator, or pre-loaded to a model and saved to a file. The second option results in fewer files to pass to the test generator. The model file can be in XMI format or in compressed binary. The XMI format is human-readable, the binary format takes less space on disk. Channels Developer -> Build Machine/Test Generation : Source code For local development the build machine is the same machine where developer creates sources. The test generator is also executed on the developer’s workstation. As such, the delivery channels is the file system. In the case of CI/CD pipeline/build server such as Jenkins or GitHub Actions, a version control systems is the delivery channel. Build Machine -> Test Generator : Coverage results, possibly with bytecode The test generator needs coverage results. If the coverage results are delivered in the raw form, it also needs bytecode (class files) to make sense of the results. Coverage results can be delivered to the test generator using the following channels: Filesystem Jenkins workspace made available to the test generator over HTTP(S) Binary repository. For example, coverage results might be published to the Maven repository as an assembly along with sources, jar file, and javadoc. They can be published in a raw format or as a model. In this modality the tests generator can get everything it needs from a Maven repository. You can use Maven model or Maven Artifact Resolver API to work with Maven repositories. See also Apache Maven Artifact Resolver. Additional value of storing coverage data in a binary repository is that it can serve as an evidence of code quality stored with the compiled code, not in some other system. Source repository. Traditionally storing derived artifacts in a source repository is frowned upon. However, storage is cheap, GitHub Pages use this approach - so, whatever floats your boat! SonarQube - it doesn’t store method level coverage, so the solution would have to operate on the class level and generate test methods for all methods in a class with low coverage. You may have a specialized application/model repository/database and store coverage information there, possibly aligned to your organization structure. Test Generation -> Developer : Generated tests The goal is to deliver generated tests to the developer, make the developer aware that they are available, and possibly track progress of incorporating the generated tests into the test suite. With this in mind, there are the following alternatives/options: Filesystem - for the local loop Source control system - commit, create a merge/pull request. When using this channels you can check if there is already a generated test and whether it needs to be re-generated. If, say, the source method hasn’t changed (the same SHA digest), and the generator version and configuration hasn’t changed - do not re-generate, it will only consume resources and create “noise” - the LLM may return a different response, developers will have to spend time understanding what has changed. You may fork a repository instead of creating a branch. This way all work on tests will be done in the forked repository and the source repository will receive pull requests with fully functional tests. Tests can be generated to a separate directory and then copied to the source directory, or they can be generated directly to the source directory. Tests may be generated with @Disabled annotation so they are clearly visible in the test execution tree, and with @Generated annotation to track changes and merge generated and hand-crafted code. Issue tracking system - either attach generated tests to issues, or create a merge request and reference it from the generated issues. In systems like Jira you may create a hierarchy of issues (epic/story), assign components, labels, fix versions, assignees, etc. You may assign different generated tests to different developers based on size and complexity of the source method. E.g. tests for short methods with low complexity can be assigned to junior developers. This alone may give your team a productivity boost! E-mail or other messaging system. Issue trackers and messaging systems may be used to deliver generated documentation while source control will deliver generated tests. Developers will use the generated documentation such as graphs, sequence diagrams and GenAI explanations/recommendations in conjunction with the generated test code. This channel may implement some sort of backpressure by saying “it is enough for now”, as a human developer would by crying “Enough is enough, I have other stories to work on in this sprint!”. Generating just enough tests is beneficial in the following ways: Does not overwhelm developers Does not result in a stale generated code waiting to be taken a look at Does not waste resources and time to generate code which nobody would look at in the near future Uses the latest (and hopefully the greatest) generator version With backpressure a question of prioritization/sorting arises - what to work on first? Source methods can be sorted according to: Size/complexity Dependency. E.g. method b (caller) calls method a (callee) One strategy might be to work on callee methods first (method a) to provide a solid foundation. Another is to work on caller methods first because callee methods might be tested along the way. These strategies might be combined - some developers (say junior) may work on callee tests and senior developers may be assigned to test (complex) caller (top level) methods. Also, the top-down approach (callers first) might be better for addressing technical debt accrued over time, while bottom-up (callees first) for new development. Test Generation - GenAI : Prompt GenAI is neither free not blazing fast. As such, this channel may implement: Billing Rate limiting (throttling) Budgeting - so many calls per time period Caching Java Sources Source Artifacts Bytecode Coverage Data Developer JUnit Tests Gen AI Code Generation Compilation Test Execution JUnit Test Generation Coverage Report Java Sources Bytecode Coverage Data Developer Gen AI Coverage Model Source Code Model Tests Model Generator JUnit Test Generation Writing Code Compilation Testing Test Generation Gen AI"},"nsd-cli/index.html":{"action-uuid":"2eb88825-feda-4467-973f-6bb464efa365","title":"CLI","content":"Nasdanika Command Line Interface (CLI) is a collection of Nasdanika offerings packaged as command line tools."},"core/drawio/index.html":{"path":"Core/Drawio","action-uuid":"dd312f3f-a04d-4bdc-8538-f3d67819a623","title":"Drawio","content":"Nasdankia provides two Maven modules for working with Drawio diagrams - API and Model. The modules require Java 17 or above. API Drawio module provides Java API for reading and manipulating Drawio diagrams. It is built on top of Graph. The module provides the following interfaces representing elements of a diagram file: Document - the root object of the API representing a file/resource which contains one or more pages. Page - a page containing a diagram (Model). Model - a diagram model containing the diagram root. Root - the root of the model containing layers. Layer - a diagram may have one or more layers. Layers contain Nodes and Connections. Node - a node can be connected to other nodes with connections. A node may contain other nodes and connections. Connection - a connection between two nodes. The below diagram shows relationships between the above interfaces including their super-interfaces: Util provides utility methods such as layout() and methods to navigate and query documents and their elements. Model Drawio Model module provides an EMF Ecore model for diagrams. A model instance can be obtained from the API document by calling Document.toModelDocument() method. The model makes it more convenient to work with the diagram elements by: Making a reference between pages and model elements bi-directional. Introducing Tag class as opposed to a string in the API. Tag is contained by Page and has bi-directional reference with tagged elements. Document The root object of the API representing a file/resource which contains one or more pages Page A page containing a diagram (Model) Model A diagram model containing the diagram root Root The root of the model containing layers Layer A diagram may have one or more layers. Layers contain Nodes and Connections. Link [0..1] Layer Element Element Model Element Node A node can be connected to other nodes with connections. A node may contain other nodes and connections. Connection A connection between two nodes * source 0..1 outgoingConnections * 1 1 1..* * target 0..1 incomingConnections * Tag * * *"},"core/exec/index.html":{"path":"Core/Exec","action-uuid":"0f72ed88-ec5c-4bc8-a82f-33d908b46a91","title":"Exec","content":"TODO"},"core/ncore/index.html":{"path":"Core/Ncore","action-uuid":"ca684430-dbdc-40bf-9928-cbb478692560","title":"Ncore","content":"TODO"},"nsd-cli/nsd/java/junit/index.html":{"path":"CLI/nsd/java/junit","action-uuid":"68cf688c-ea73-4989-a03e-71a82b6c3542","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.4.0 \r\nUsage: nsd java junit [-dhjVw] [--[no-]comment-response] [--disabled]\r\n [--api-endpoint=<apiEndpoint>] [-c=<classes>]\r\n [--class-suffix=<classSuffix>] [-J=<jacoco>]\r\n [-k=<apiKey>] [-l=<limit>] [-m=<deploymentOrModelName>]\r\n [-p=<progressOutput>] [--package-suffix=<packageSuffix>]\r\n [-r=<prompt>] [-s=<sources>] [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <projectDir> <coverageThreshold>\r\n <output>\r\nGenerates JUnit tests\r\n <projectDir> Project directory\r\n <coverageThreshold> Coverage threshold\r\n <output> Output directory\r\n relative to the project directory\r\n --api-endpoint=<apiEndpoint>\r\n OpenAPI endpoint, defaults to\r\n https://api.openai.com/v1/chat/completions\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n --class-suffix=<classSuffix>\r\n Test class suffix\r\n defaults to Tests\r\n --[no-]comment-response\r\n Overwrite existing tests\r\n -d, --data Output data\r\n --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Source includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -J, --jacoco=<jacoco> jacoco.exec file path relative\r\n to the project directory,\r\n defaults to target/jacoco.exec\r\n -k, --api-key=<apiKey> OpenAPI key\r\n -l, --limit=<limit> Maximum number of test classes\r\n to generate\r\n -m, --model=<deploymentOrModelName>\r\n OpenAPI deployment or model\r\n defaults to gpt-4\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n -r, --prompt=<prompt> Propmt\r\n defaults to 'Generate a JUnit 5 test method\r\n leveraging Mockito for the following Java method'\r\n -s, --sources=<sources> Sources directory path relative\r\n to the project directory,\r\n defaults to src/main/java\r\n -t, --coverage-type=<coverageType>\r\n Coverage type\r\n Valid values: complexity, instruction, branch, line\r\n defaults to line\r\n -v, --api-key-variable=<apiKeyEnvironmentVariable>\r\n OpenAPI key environment variable\r\n defaults to OPENAI_API_KEY\r\n -V, --version Print version information and exit.\r\n -w, --overwrite Overwrite existing tests"},"html/html/index.html":{"path":"HTML/HTML","action-uuid":"47e67773-ac8f-476a-8401-349e50425b54","title":"HTML","content":"TODO"},"nsd-cli/nsd/java/index.html":{"path":"CLI/nsd/java","action-uuid":"79ee7499-959a-4129-b8fd-3b483bb62958","title":"java","content":"Version: org.nasdanika.models.java.cli@2024.4.0 \r\nUsage: nsd java [-hV] [COMMAND]\r\nCommands related to Java\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n junit Generates JUnit tests"},"nsd-cli/nsd/help/site/index.html":{"path":"CLI/nsd/help/site","action-uuid":"e39bb31e-d147-406c-a9ac-c45024e0b2fc","title":"site","content":"Usage: nsd help site [-dhjlV] [-b=<baseDir>] [-m=<domian>]\r\n [-p=<progressOutput>] [-P=<parallelism>] [-r=<pageErrors>]\r\n [--root-action-icon=<rootActionIcon>]\r\n [--root-action-location=<rootActionLocation>]\r\n [--root-action-text=<rootActionText>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>] [-c=<String=String>]...\r\n [-C=URL]... [-M=<String=String>]... [-e\r\n [=<excludes>...]]... [-i[=<includes>...]]... <output>\r\nGenerates help HTML site\r\n <output> Output directory\r\n -b, --base-dir=<baseDir> Base directory\r\n -c, --context-entry=<String=String>\r\n Context entries.\r\n Shadow entries in contexts and mounts.\r\n -C, --context=URL Context resource URL relative to the current\r\n directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Contexts are composed in the order of\r\n definition, later context entries shadowing the\r\n former\r\n -d, --data Output data\r\n -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Output directory clean includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -l, --[no-]clean Clean working directory\r\n defaults to true\r\n -m, --domain=<domian> Sitemap domain\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the\r\n current directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Mounts shadow context entries.\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n -P, --parallelism=<parallelism>\r\n If the value greater than one then an executor\r\n service is created and injected into the context\r\n to allow concurrent execution.\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n --root-action-icon=<rootActionIcon>\r\n Root action icon\r\n --root-action-location=<rootActionLocation>\r\n Root action location\r\n --root-action-text=<rootActionText>\r\n Root action text\r\n -t, --timeout=<timeout> If parallelism is greater than one this option\r\n specifies timout in seconds awaiting completion\r\n of execution. Default value is 60.\r\n -T, --page-template=<pageTemplate>\r\n Page template URI relative\r\n to the current directory\r\n -V, --version Print version information and exit.\r\n -w, --work-dir=<workDir> Working directory\r\nExit codes:\r\n Non-negative number Delegate result\r\n -1 Unhandled exception during execution\r\n -2 Invalid input\r\n -3 Diagnostic failed\r\n -4 Execution failed or was cancelled, successful rollback\r\n -5 Execution failed or was cancelled, rollback failed\r\n -6 Executor service termination timed out"},"practices/java/index.html":{"path":"Practices/Java Analysis, Visualization & Generation","action-uuid":"7b830c53-cda8-47ac-8d1d-96767eca4d1c","title":"Java Analysis, Visualization & Generation","content":"This practice is a specialization of the Analysis, Visualization & Generation Practice for using the Java model as a source model, target model, or both. This page provides a high level reference and the book goes into details. So what is possible to do with the Java model/language in addition to generic analysis, visualization and generation? Analysis Java model can be loaded from sources and bytecode. Tests coverage can be loaded from jacoco.exec and class files and associated with model elements. Bytecode information can be used to establish bi-directional references between model elements - field access, method calls. Bytecode can be instrumented to collect runtime cross-referencing such as reflective method calls and field access. Visualization Module, package, class, method dependency graphs. The graphs may reflect coverage data so they can be used for prioritization of addressing technical debt. For example, many well-covered microservices may use a shared library with low coverage. Sequence diagrams Generation Documentation Documentation similar to documentation generated from Ecore models such as Java model above, Family model, or Enterprise model with: * Visualizations mentioned above\n* Documentation produced by GenAI - explainations and recommendations.\n Such documentation may be useful in modernization efforts where there is a need to understand a legacy codebase. It may also be useful in onboarding of new team members and it might help provide deeper insights into the codebase for all team members. Source code Source code with @Generated annotations or @generated Javadoc tags to allow detection of changes in the generated code and re-generation only if there changes in the generator inputs, and the output was not modified since the last generation. It allows concurrent evolution of the generator, generator inputs, and manual modifications. For more details see Solution instantiation. RAG/Chat RAG/Chat on top of the Java model may use bytecode and runtime introspection information in addition to just source code. For example “This method is overridden by … and is called by …”. RAG may be contextual - chat with a class, a method, a package, a module or an application (group of modules) if the model elements are “mounted” under higher level constructs such as products and segments."},"core/capability/index.html":{"path":"Core/Capability","action-uuid":"d3194f83-c4ab-4a70-9a6d-d94d6f09b471","title":"Capability","content":"Nasdanika Capability framework allows to discover/load capabilities which meet a requirement. Capabilities are provided by CapabilityFactory create() method. Capability factories may request other capabilities they need. As such, capabilities can be chained. Factories create CapabilityLoaders which provide Flux reactive streams of capabilities. It allows to have an infinite stream of capabilities which are consumed (and produced) as needed. Capability providers may furnish additional information about capabilities. This information can be used for filtering or sorting providers. A non-technical example of requirement/capability chain graph is a food chain/graph. Food is a requirement. Or “I want to eat” is a requirement. Bread and, say fried eggs are two capabilities meeting/addressing the requirement. Bread requires “wheat”, “water”, and “bake” capabilities. Fried eggs require “egg”, “oil”, and “fry” capabilities. Bread capability provider may implement Vegan marker interface which can be used for filtering. All food capabilities may implement NutritionalInformation interface - it can be used for filtering or sorting. A more technical example is Java ServiceLoader with service type being a requirement and an instance of the service class being a capability. Nasdanika capability framework can operate on top of ServiceLoader and may be thought of as a generalization of service loading. In essence, the capability framework is a backward chaining engine as shown in one of the example below. Client code - requesting a capability Capabilities are loaded by CapabilityLoader. Capability loader can take an iterable of capability factories in its constructor, or it can load them using ServiceLoader as shown in the below code snippet: CapabilityLoader capabilityLoader = new CapabilityLoader();\ncapabilityLoader.getFactories().add(new TestServiceFactory<Object>());\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\t\t\nfor (CapabilityProvider<?> cp: capabilityLoader.load(new TestCapabilityFactory.Requirement("Hello World"), progressMonitor)) {\n\tSystem.out.println(cp);\n\tFlux<?> publisher = cp.getPublisher();\n\t\t\t\n\tpublisher.subscribe(System.out::println);\n}\n Factories can also be added post-construction with getFactories().add(factory). Service capabilities Service requirements and capabilities provide functionality similar to ServiceLoader - requesting instances of specific type, but extend it with ability to provide additional service requirement. This functionality is provided by ServiceCapabilityFactory and ServiceCapabilityFactory.Requirement. CapabilityLoader capabilityLoader = new CapabilityLoader();\ncapabilityLoader.getFactories().add(new TestServiceFactory<Object>());\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\t\t\n@SuppressWarnings({ "unchecked", "rawtypes" })\nServiceCapabilityFactory.Requirement<List<Double>, Double> requirement = (ServiceCapabilityFactory.Requirement) ServiceCapabilityFactory.createRequirement(List.class, null, 33.0);\nfor (CapabilityProvider<?> cp: capabilityLoader.load(requirement, progressMonitor)) {\n\tSystem.out.println(cp);\n\tFlux<?> publisher = cp.getPublisher();\n\t\t\t\n\tpublisher.subscribe(System.out::println);\n}\n It is also possible to load services from ServiceLoader using subclasses of Service. You’d need to subclass ServiceFactory in a module which uses a particular service and override stream(Class<S> service) method as shown below: @Override\nprotected Stream<Provider<S>> stream(Class<S> service) {\n\treturn ServiceLoader.load(service).stream();\n}\n Then you’d need to add the factory to the loader: capabilityLoader.getFactories().add(new TestServiceFactory<Object>());\n Providing a capability As it was mentioned above, capability factories can be explicitly added to CapabilityLoader or loaded using ServiceLoader. Below is an example of a capability factory: public class TestCapabilityFactory implements CapabilityFactory<TestCapabilityFactory.Requirement, Integer> {\n\t\n\tpublic record Requirement(String value){};\n\t\n\t@Override\n\tpublic boolean canHandle(Object requirement) {\n\t\treturn requirement instanceof Requirement;\n\t}\n\n\t@Override\n\tpublic CompletionStage<Iterable<CapabilityProvider<Integer>>> create(\n\t\t\tRequirement requirement,\n\t\t\tBiFunction<Object, ProgressMonitor, CompletionStage<Iterable<CapabilityProvider<Object>>>> resolver,\n\t\t\tProgressMonitor progressMonitor) {\n\t\t\n\t\treturn resolver.apply(MyService.class, progressMonitor).thenApply(cp -> {;\n\t\t\t@SuppressWarnings({ "unchecked", "rawtypes" })\n\t\t\tFlux<MyService> myServiceCapabilityPublisher = (Flux) cp.iterator().next().getPublisher();\n\t\t\t\n\t\t\treturn Collections.singleton(new CapabilityProvider<Integer>() {\n\t\n\t\t\t\t@Override\n\t\t\t\tpublic Flux<Integer> getPublisher() {\n\t\t\t\t\tFunction<MyService, Integer> mapper = ms -> ms.count(((Requirement) requirement).value());\n\t\t\t\t\treturn myServiceCapabilityPublisher.map(mapper);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t});\n\t\t});\n\t}\n\n}\n Applications Services Service capabilities explained above a used by Graph and Function Flow for loading node processors and connection processors for a specific requirement using NodeProcessorFactory and ConnectionProcessorFactory respectively. For example, code generation, execution, simulation. Solutions for architectures One of future application of the capability framework is creation a list of solution alternatives for an architecture/pattern. For example, there might be multiple RAG embodiments with different key types, key extractors, stores, … Some of “design dimensions” are listed below: Key type: Bag of words. Multiple options - just words, words with frequency, tokenized words, word stems. Embedding vector - different embedding models, different dimensions. Store - multiple stores for multiple key types. Multiple indexing and retrieval methods. Chunk size, chunk overlap, chunking algorithm. Generator - multiple models and prompts As you can see a number of potential combinations can easily go into thousands or even be infinite. Reactive approach with filtering and sorting may be helpful in selecting a solution which is a good fit for a particular use case - number and type of data sources etc. For example, if the total size of data is under a few gigabytes an in-memory store may be a better choice than, say, an external (vector) database. Also an old good bag of words might be better than embeddings. E.g. it might be cheaper. Solution alternatives may include temporal aspect or monetary aspects. For example, version X of Y is available at time Z. Z might be absolute or relative. Say, Z days after project kick-off or license fee payment. Identified solutions meeting requirements can have different quality attributes - costs (to build, to run), timeline, etc. These quality attributes can be used for solution analysis. E.g. one solution can be selected as a transition architecture and another as the target architecture. Backward chaining Family reasoning demonstrates application of the capability framework as a backward chaining engine. Family relationships such as grandfather and cousin are constructed by requiring and combining relationships such as child and sibling. Stream processing This possible application is similar to backward reasoning. Imagine an algorithmic trading strategy which uses several technical indicators, such as moving averages, to make trading decisions. Such a strategy would submit requirements for technical indicators which would include symbol, indicator configuration, time frame size. Technical indicators in turn would submit a requirement for raw trading data. A technical indicator such as moving average would start publishing its events once it receives enough trading data frames to compute its average. A trading engine would submit a requirement for strategies. A strategy factory may produce multiple strategies with different configurations. The trading engine would perform “paper” trades, select well-performing strategies and discard ones which perform poorly. This can be an ongoing process - if a strategy deteriorates then it is discarded and a new strategy is requested from strategy publishers - this process can be infinite. AI model training/fine-tuning This application is similar to stream processing and may be combined with backward reasoning. Let’s say we want to train a model to answer questions about family relationships for a specific family. For example, “Who is Alan’s great grandmother?” A single relationship in the model can be expressed in multiple ways in natural language. And multiple relationships can be expressed in a single sentence. For example: Elias is a person Elias is a man Elias is a male Elias is a parent of Fiona Fiona is a child of Elias Elias is a father of Fiona Fiona is a daughter of Elias Paul and Isa are parents of Lea and Elias … So, on top of a model there might be a collection of text generators. Output of those generators can be fed to a model: Supervised - question and answer “How many sisters does Bryan have?” - “Two” “Who are Bryan’s sisters?” - “Clara and Fiona” Unsupervised - factual statements A similar approach can be applied to other models - customer/accounts, organization or architecture model, etc. For example, from the Internet Banking System we can generate something like “Accounts Summary Controller uses Mainframe Banking System Facade to make API calls to the Mainframe Banking System over XML/HTTPS”. “make API calls” may also be generated as “connect” or “make requests”. In a similar fashion a number of questions/answers can be generated."},"core/graph/index.html":{"path":"Core/Graph","action-uuid":"64e4ffc9-7d3c-4833-9b7b-b1904686429f","title":"Graph","content":"TODO"},"core/index.html":{"action-uuid":"e32b6747-9fb6-4f12-aa15-f372a403fd55","title":"Core","content":"TODO"},"html/models/index.html":{"path":"HTML/Models","action-uuid":"9f945679-7d48-49e2-8901-6eacc23861ce","title":"Models","content":"TODO"},"practices/generic/index.html":{"path":"Practices/Analysis, Visualization & Generation","action-uuid":"ed32a671-5d55-4bb4-afcc-bf54f077755e","title":"Analysis, Visualization & Generation","content":"This practice explains how to use Nasdanika products (specifically models) and related products. The above diagram shows the core idea - load input data into a model, modify the model or create a new model from it, and save the models to native (raw) formats. Loading to a model as opposed to working with raw formats gives the following benefits: Unified API Generated model documentation with visualizations Different models may extend classes from core models and be treated similarly Model classes may be subclassed and mixed Cross-reference model elements URI handlers allows to load models from diverse sources On-demand loading of resources and features of model elements Conversion of models to graphs and making them executable with graph processors E.g. want to read/write Excel files - take a look at the Excel metamodel and then use Ecore API to work with the model. Now want to work with PDF? A different metamodel, the same model API. You have Java sources stored in GitLab and want model elements to reflect both Java and GitLab natures of your sources? Create a GitLabRepositoryCompilationUnit class which extends both Compilation Unit and Repository File. Customize Loader to create this class for repository files with java extension. Want to load a PDF file directly from GitLab without having to clone the entire repository? Use GitLabURIHandler! The below diagram illustrates the above concepts: Models can be visualized using: ECharts using the ECharts model, ECharts-Java or by directly generating JavaScript/JSON. Example. PlantUML using DiagramGenerator, the diagram module or by directly generating PlantUML text and calling Plant UML API’s. Example. Holistic model of an organization One use case for the modeling approach outlined above is creation of a holistic model of an organization/corporation as exemplified by the below diagram1 In a corporation different elements of the model are typically stored in different systems and documents like Excel spreadsheets. The modeling approach allows to load those elements in a single resource set and cross-reference them. Elements which are not stored in structured formats can be captured by modeling them in diagrams and mapping those diagrams to models, see Beyond Diagrams. One important reason why a holistic model might be beneficial for an organization is the ability of using it for AI insights. For example, using RAG/Chat on top of the organization model. Such chat can be made context-aware, chatting with the Operations will return result relevant to operations. The above diagram is very simple, a large organization may have many layers, thousands of applications, millions of lines of code. A model for such an organization would take some time to build, but it can be built incrementally - department by department, application by application. The value of building such a model will grow exponentially as more and more elements are added due to the network effect. While the resulting model might be “large”, … define large. Experiments show that a model element in a model like the above takes ~ 500 bytes of RAM. As such, 1 GB of RAM would hold about 2 million model elements. Also, model resources are loaded on demand, so only the model elements needed by some task would be loaded to complete that task. With DynamicDelegate it is possible to have model elements loading their data from multiple sources on demand. The organization model can be built on top of existing “generic” models such as Java, Maven, GitLab, Azure, … Resources TOGAF Enterprise Metamodel Corporate structure ↩ Output Model Transformation Input Model Raw Input Raw Output Cell Excel Resource Paragraph PDF Resource Resource Set GitLab URI Handler MS Excel Workbook GitLab Excel Resource Factory PDF Resource Factory PDF File File system Corporation Marketing Finance Uses Operations HR Builds IT Execution environments Binary packages Source Code Application"},"nsd-cli/nsd/http-server/index.html":{"path":"CLI/nsd/http-server","action-uuid":"5534499b-00a9-4a6d-a9a9-d391231f3346","title":"http-server","content":"Usage: nsd http-server [-hV]\r\nServes HTTP routes\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/help/index.html":{"path":"CLI/nsd/help","action-uuid":"c984ea8a-2239-4bdf-ada8-e477d0cb93b7","title":"help","content":"Usage: nsd help [-ahHV] [-l=<level>] [-o=<output>] [COMMAND]\r\nOutputs usage for all registred commands\r\n -a, --action-model Output to action model\r\n -h, --help Show this help message and exit.\r\n -H, --html Output to HTML\r\n -l, --header-level=<level>\r\n Starting level for HTML header tags in HTML output,\r\n the default value is 1.\r\n -o, --output=<output> Output file\r\n -V, --version Print version information and exit.\r\nCommands:\r\n site Generates help HTML site"}} \ No newline at end of file +var searchDocuments = {"html/index.html":{"action-uuid":"0f4e3df1-a272-4c9e-aa6a-6b541feeca02","title":"HTML","content":"TODO"},"html/models/app/index.html":{"path":"HTML/Models/App","action-uuid":"34c0967b-54a5-420e-b53f-85a4f6200eae","title":"App","content":"TODO"},"nsd-cli/nsd/launcher/index.html":{"path":"CLI/nsd/launcher","action-uuid":"416e9c2f-8437-4ac3-bdc1-76545d395bfe","title":"launcher","content":"Version: org.nasdanika.cli@2024.5.0 \r\nUsage: nsd launcher [-hstvV] [-a=<args>] [-b=<base>] [-c=<className>]\r\n [-C=<classPathModules>] [-f=<optionsFile>]\r\n [-j=<javaCommand>] [-m=<moduleName>] [-M=<modulesFile>]\r\n [-o=<output>] [-p=<pathSeparator>] [-P=<prefix>]\r\n [-r=<rootModules>] [<repositories>...]\r\nGenerates Java command line from directories of modules/jars\r\n [<repositories>...] Directories to scan for modules,\r\n defaults to lib\r\n -a, --args=<args> Arguments,\r\n defaults to %*\r\n -b, --base=<base> Base repositories directory\r\n -c, --class=<className> Application class,\r\n defaults to org.nasdanika.cli.Application\r\n -C, --claspath-modules=<classPathModules>\r\n Comma-separated list of classpath modules\r\n -f, --options-file=<optionsFile>\r\n File to output options to\r\n -h, --help Show this help message and exit.\r\n -j, --java=<javaCommand> Java command,\r\n defaults to java\r\n -m, --module=<moduleName> Application module,\r\n defaults to org.nasdanika.cli\r\n -M, --modules=<modulesFile>\r\n Modules to add to the module path\r\n -o, --output=<output> Output file\r\n -p, --path-separator=<pathSeparator>\r\n Path separator,\r\n defaults to the system path separator\r\n -P, --prefix=<prefix> Module path prefix\r\n -r, --root-modules=<rootModules>\r\n Comma-separated list of root modules\r\n Supports .* and .** patterns\r\n -s, --absolute Use absolute paths\r\n -t, --options Output only options\r\n -v, --verbose Output debug invformation\r\n -V, --version Print version information and exit."},"html/models/bootstrap/index.html":{"path":"HTML/Models/Bootstrap","action-uuid":"c57f41cb-6a7b-4457-83c2-9a45488ec856","title":"Bootstrap","content":"TODO"},"core/maven/index.html":{"path":"Core/Maven","action-uuid":"d7a93f4c-ff1c-4d5f-8dc0-115cb6312360","title":"Maven","content":"Javadoc"},"core/persistence/index.html":{"path":"Core/Persistence","action-uuid":"21d6d971-2965-4be8-a2ab-6f814c0856eb","title":"Persistence","content":"Javadoc"},"core/diagram/index.html":{"path":"Core/Diagram","action-uuid":"836f371e-2ed3-42c2-ad4b-778b8cc662ef","title":"Diagram","content":"Javadoc"},"html/emf/index.html":{"path":"HTML/EMF","action-uuid":"6be1b864-2152-46f7-b5d0-a7b6ae90570d","title":"EMF","content":"TODO"},"html/bootstrap/index.html":{"path":"HTML/Bootstrap","action-uuid":"655794d1-974a-4f97-ace9-41918841fb14","title":"Bootstrap","content":"TODO"},"nsd-cli/nsd/app/index.html":{"path":"CLI/nsd/app","action-uuid":"e06309ac-9d53-4fc4-84d4-6b7ee2d462ba","title":"app","content":"Version: org.nasdanika.html.model.app.gen.cli@2024.5.0 \r\nUsage: nsd app [-hV] [COMMAND]\r\nHTML Application model commands\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n site Generates HTML site"},"core/cli/index.html":{"path":"Core/CLI","action-uuid":"640290cf-75cf-451c-991b-eadbba515710","title":"CLI","content":"Classes in this module allow to declaratively construct command line interfaces. It uses picocli to execute commands and capability framework to collect sub-commands and mix-ins. This way command line interfaces can be constructed top-down (default picocli functionality) - parent commands explicitly define sub-commands, and bottom-up - sub-commands are added to parent commands by the framework. Top-down construction can be done using out-the-box picocli capabilities - programmatic add and annotations. Both top-down and bottom-up construction can be done using the capability framework which allows sub-commands/mix-ins to request capabilities they need and add themselves to parent commands only if all requirements are met. The module provides a capability to build polymorphic CLI’s - sub-commands and mix-ins may override other sub-commands and mix-ins with the same name. This is similar to method overriding in Object-Oriented languages like Java. For example, a base CLI package may have a basic implementation of some sub-command. A derived package would add dependencies with advanced sub-commands to pom.xml. These sub-commands would replace (override) basic sub-commands during construction of the command hierarchy. Javadoc Contributing sub-commands In addition to the picocli way of adding sub-commands programmatically and using @Command annotation subcommands element this module provides a few more ways to contribute sub-commands which are explained below. In all cases create a sub-class of SubCommandCapabilityFactory and implement/override the following methods: getCommandType - used for declarative matching createCommand for imperative (programmatic) matching doCreateCommand: Declarative - in combination with @SubCommands or @Parent Imperative - override match() as well. Add to module-info.java: provides org.nasdanika.capability.CapabilityFactory with <factory class> opens <sub-command package name> to info.picocli, org.nasdanika.html.model.app.gen.cli; Opening to org.nasdanika.html.model.app.gen.cli is needed if you want to generate extended documentation (see below). @SubCommands annotation This one is similar to @Command.subcommands - the parent command declares types of sub-commands. However: Sub-commands are collected using the capability framework from SubCommandCapabilityFactory’s. Sub-commands types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types. E.g. you may have HelpCommand interface or base class and all commands implementing/extending this class will be added to the parent command. If there are two commands with the same name one of them might override the other as explained below. @Parent annotation In this case the sub-command or mix-in class are annotated with @Parent annotation listing types of parents. The sub-command/mix-in will be added to all commands in the hierarchy which are instances of the specified parent types - exact class, interface implementation, or sub-class. Programmatic match The above two ways of matching parent commands and sub-commands are handled by the SubCommandCapabilityFactory.match() method. You may override this method or createCommand() method to programmatically match parent path and decide whether to contribute a sub-command or not. Contributing mix-ins Similar to sub-commands, mix-ins can be contributed top-down and bottom-up - declaratively using annotations and programmatically. In all cased create s sub-class of MixInCapabilityFactory, implement/override: getMixInType() - for declarative matching getName() createMixIn() for imperative matching, or doCreateMixIn() Declarative - in combination with @MixIns or @Parent Imperative - override match() as well. Add to module-info.java: provides org.nasdanika.capability.CapabilityFactory with <factory class> opens <mix-in package name> to info.picocli; @MixIns annotation Mix-ins are collected using the capability framework from MixInCapabilityFactory’s. Mix-in types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types. @Parent annotation See “@Parent annotation” sub-section in “Contributing sub-commands” section above. Programmatic match The above two ways of matching parent commands and sub-commands/mix-ins are handled by the MixInCapabilityFactory.match() method. You may override this method or createMixIn() method to programmatically match parent path and decide whether to contribute a mix-in or not. Overriding A command/mix-in overrides another command/mix-in if: It is a sub-class of that command/mix-in It implements Overrider interface and returns true from overrides(Object other) method. It is annotated with @Overrides and the other command is an instance of one of the value classes. Extended documentation You may annotate commands with @Description to provide additional information in generated HTML site. Building distributions A distribution is a collection of modules contributing commands and mix-ins plus launcher scripts for different operating systems. org.nasdanika.cli and org.nasdanika.launcher modules are examples of building distributions as part of Maven build. Building a distribution involves two steps: Downloading modules (dependencies) Generating launcher scripts Downloading dependencies Dependencies can be downloaded using Maven dependency plug-in: <project xmlns="http://maven.apache.org/POM/4.0.0"\n\txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n\txsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\n\t\n\t...\n\n\t<dependencies>\n\t\t...\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t...\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-dependency-plugin</artifactId>\n\t\t\t\t<version>3.6.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>copy-dependencies</id>\n\t\t\t\t\t\t<phase>prepare-package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>copy-dependencies</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<outputDirectory>\n\t\t\t\t\t\t\t\t${project.build.directory}/dist/lib\n\t\t\t\t\t\t\t</outputDirectory>\n\t\t\t\t\t\t\t<useRepositoryLayout>true</useRepositoryLayout>\t\t\t\t\t\t\t\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t\n\t\t\t...\n\t</build>\n\n\t... \n</project>\n Generating launcher scripts Launcher scripts can be generated using launcher command. The command can be issued manually from the command line. Alternatively, you can execute the launcher command from an integration test as shown below: public class BuildDistributionIT {\n\t\t\n\t@Test\n\tpublic void generateLauncher() throws IOException {\n\t\tfor (File tf: new File("target").listFiles()) {\n\t\t\tif (tf.getName().endsWith(".jar") && !tf.getName().endsWith("-sources.jar") && !tf.getName().endsWith("-javadoc.jar")) {\n\t\t\t\tFiles.copy(\n\t\t\t\t\t\ttf.toPath(), \n\t\t\t\t\t\tnew File(new File("target/dist/lib"), tf.getName()).toPath(), \n\t\t\t\t\t\tStandardCopyOption.REPLACE_EXISTING);\t\t\n\t\t\t}\n\t\t}\t\t\n\t\t\n\t\tModuleLayer layer = Application.class.getModule().getLayer();\n\t\ttry (Writer writer = new FileWriter(new File("target/dist/modules"))) {\n\t\t\tfor (String name: layer.modules().stream().map(Module::getName).sorted().toList()) {\n\t\t\t\twriter.write(name);\n\t\t\t\twriter.write(System.lineSeparator());\n\t\t\t};\n\t\t}\n\t\t\n\t\tCommandLine launcherCommandLine = new CommandLine(new LauncherCommand());\n\t\tlauncherCommandLine.execute(\n\t\t\t\t"-b", "target/dist", \n\t\t\t\t"-M", "target/dist/modules", \n\t\t\t\t"-f", "options",\n\t\t\t\t"-j", "@java",\n\t\t\t\t"-o", "nsd.bat");\n\t\t\n\t\tlauncherCommandLine.execute(\n\t\t\t\t"-b", "target/dist", \n\t\t\t\t"-M", "target/dist/modules", \n\t\t\t\t"-j", "#!/bin/bash\\n\\njava",\n\t\t\t\t"-o", "nsd",\n\t\t\t\t"-p", ":",\n\t\t\t\t"-a", "$@");\t\t\n\t\t\n\t}\n\n}\n If the Maven project which builds the distribution does not contribute its own code, then the for loop copying the jar file can be omitted."},"core/resources/index.html":{"path":"Core/Resources","action-uuid":"bd33b15a-a909-4f15-a5c9-b5d8ba4a13f0","title":"Resources","content":"Javadoc"},"practices/index.html":{"action-uuid":"69f993a9-5902-4e74-8951-5e8fb4ae982e","title":"Practices","content":"Practices explain how to use Nasdanika products to achieve specific goals and explain why particular design choices wer made. The enterprise model provides deeper insight on the WHY in general. The practices are organized into an enterprise continuum from the most generic on the left to the most specific on the right. However, the most specific on the right is still generic and needs to be specialized for a particular application (embodiment): Analysis, Visualization & Generation - describes a general approach on using Nasdanika products. Java Analysis, Visualization & Generation - application of the above to the Java model1 Loading and analyzing Java sources and bytecode, generation of non-Java artifacts such as HTML reports Generation of Java sources. JUnit test generation for low coverage methods - further specialization of the Java practice to identify methods with low test coverage using the Coverage Model and then generate JUnit tests for those methods using the Java model and OpenAI. You can think of the three practices above as progressive “binding of decision” as you move from the left to the right to reach “executability” - ability to deliver value. A java analogy for progressive specialization would be incremental binding of generic types as exemplified below: Map<K,V> - generic map. MyMap<K extends Comparable> extends Map<<K, MyValue<K>> - the above map bound to a single generic parameter with an upper bound. It is a specialization of the above generic map which is also generic. Some decisions were bound, but there are still decisions to be bound. MyMap<String> theMap = ...; - fully bound map. Decisions are bound at variation point. For example, “storage” is a variation point, “blob storage” is one of alternatives, decision to use “blob storage” binds the variation point to a specific alternative. Decision binding forms a graph. Once you bind, say, “storage” variation point, some downstream alternatives may become unavailable because they are incompatible with that binding. Some might be available, but make no sense. For example, a decision to send data unencrypted over a public network is compatible with a decision to purchase some additional strong encryption hardware to use on-prem, but does it make business sense? Different alternatives feature different “quality attributes” - performance, reliability, cost. As the number of variation points and alternatives grows purely human-based decision making becomes inefficient. In this case variation points can be modeled as requirements and alternatives as capability providers or capabilities with quality attributes (seecapability). After this a list of “designs” (a.k.a. “provisioning plans”) can be created. A design/provisioning plan is a collection of compatible capabilities. If a list of designs is short enough it can be analyzed by humans directly. In the case of long lists or a large number of very similar designs decision analysis can be employed for making a selection of a design which is best fit for purpose. The page provides a general overview and the book goes into more details. ↩"},"core/emf/index.html":{"path":"Core/EMF","action-uuid":"aeb2e45d-d4b9-49fb-9313-ea2f5e076da8","title":"EMF","content":"Javadoc"},"nsd-cli/nsd/index.html":{"path":"CLI/nsd","action-uuid":"6606a632-01b6-4a96-987a-082eddb3cf84","title":"nsd","content":"Version: org.nasdanika.cli@2024.5.0 \r\nUsage: nsd [-hV] COMMAND\r\nNasdanika Command Line Interface\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n launcher Generates Java command line from directories of modules/jars\r\n app HTML Application model commands\r\n help Outputs usage for all registred commands\r\n http-server Serves HTTP routes\r\n java Commands related to Java"},"html/models/html/index.html":{"path":"HTML/Models/HTML","action-uuid":"1ec28871-104c-4f5b-837a-b64ac672a65f","title":"HTML","content":"TODO"},"index.html":{"action-uuid":"9d79030d-7bff-4987-8fc3-48a516f17eb7","title":"Nasdanika","content":" Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI Core HTML HTML Bootstrap App Models JsTree Bootstrap EMF HTML GitLab Family Architecture Git Excel ECharts Nature Bank PDF Party Coverage Source Engineering Java Maven Enterprise Function Flow Rules Azure Decision Analysis Capability Flow Ecore Jira Models Data Sources Loader Store Key Extractor Query Engine Requestor Generator Responder Retrieval Augmented Generation (RAG) Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI Medium Publication Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI Core HTML HTML Bootstrap App Models JsTree Bootstrap EMF HTML GitLab Family Architecture Git Excel ECharts Nature Bank PDF Party Coverage Source Engineering Java Maven Enterprise Function Flow Rules Azure Decision Analysis Capability Flow Ecore Jira Models Data Sources Loader Store Key Extractor Query Engine Requestor Generator Responder Retrieval Augmented Generation (RAG) Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI Medium Publication"},"html/jstree/index.html":{"path":"HTML/JsTree","action-uuid":"68577bf6-51f9-44d2-9bba-380611b670e7","title":"JsTree","content":"TODO"},"nsd-cli/nsd/app/site/index.html":{"path":"CLI/nsd/app/site","action-uuid":"7283f6fa-e0f5-48cf-92f4-1d1a156eab2a","title":"site","content":"Version: org.nasdanika.html.model.app.gen.cli@2024.5.0 \r\nUsage: nsd app site [-dhjlV] [-b=<baseDir>] [-m=<domian>] [-p=<progressOutput>]\r\n [-P=<parallelism>] [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>] [-c=<String=String>]...\r\n [-C=URL]... [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <model> <output>\r\nGenerates HTML site\r\n <model> Model URI, resolved relative\r\n to the current directory\r\n <output> Output directory\r\n -b, --base-dir=<baseDir> Base directory\r\n -c, --context-entry=<String=String>\r\n Context entries.\r\n Shadow entries in contexts and mounts.\r\n -C, --context=URL Context resource URL relative to the current\r\n directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Contexts are composed in the order of\r\n definition, later context entries shadowing the\r\n former\r\n -d, --data Output progress data\r\n -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Output directory clean includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -l, --[no-]clean Clean working directory\r\n defaults to true\r\n -m, --domain=<domian> Sitemap domain\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the\r\n current directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Mounts shadow context entries.\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n -P, --parallelism=<parallelism>\r\n If the value greater than one then an executor\r\n service is created and injected into the context\r\n to allow concurrent execution.\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -t, --timeout=<timeout> If parallelism is greater than one this option\r\n specifies timout in seconds awaiting completion\r\n of execution. Default value is 60.\r\n -T, --page-template=<pageTemplate>\r\n Page template URI relative\r\n to the current directory\r\n -V, --version Print version information and exit.\r\n -w, --work-dir=<workDir> Working directory\r\nExit codes:\r\n Non-negative number Delegate result\r\n -1 Unhandled exception during execution\r\n -2 Invalid input\r\n -3 Diagnostic failed\r\n -4 Execution failed or was cancelled, successful rollback\r\n -5 Execution failed or was cancelled, rollback failed\r\n -6 Executor service termination timed out"},"glossary.html":{"action-uuid":"f274797a-5e94-4d41-8a09-7d90b6ca7eb7","title":"Glossary","content":"Clear Identifier(s) Hide UUID {{data.value.name}} {{data.value[0].value}} {{item.value}}"},"core/common/index.html":{"path":"Core/Common","action-uuid":"3476167d-02c7-4261-904f-cc0f01314e7e","title":"Common","content":"Javadoc"},"practices/junit/index.html":{"path":"Practices/JUnit Tests Generation","action-uuid":"89bfe702-c63f-4161-bc74-baa8f0ce2d77","title":"JUnit Tests Generation","content":"This practice is a specialization of the Java Analysis, Visualization & Generation Practice for generation of JUnit tests. In particular: Generation of tests for methods or classes with low test coverage Leveraging Gen AI such as OpenAI ChatGPT or Azure OpenAI Service for test generation The above diagram shows Java development activities and artifacts. Black arrows show the typical process, blue arrows show the test generation loop. The developer produces source artifacts which may include non-java artifacts used to generate Java code (e.g. Ecore models), “main” Java sources and test Java sources. Java sources are compiled into bytecode (class files). Here it is important to note that matching of bytecode classes and methods to source code classes and methods might be non-trivial because of: Lambdas Anonymous and method-scope classes Annotation processors like Lombok JUnit tests are compiled and executed. If code coverage, such as jacoco, is configured then test execution produces coverage data. Jacoco stores coverage data in jacoco.exec file. This file is used to generate a coverage report and upload coverage information to systems like SonarQube. In this practice it is also used to select which methods to generate tests for based on coverage data. This diagram provides an insight into the test generation activity: Coverage data and bytecode are used as input to load the Coverage model. Source files, the coverage model, and bytecode (optional) are used to load the Java model of source code. The generator traverses the model and generates unit tests for method with low coverage using a combination of programmatic (traditional) generation and Gen AI. Tests are generated as a Java model as well and then are delivered to the developer for review, modification, and inclusion into the unit test suite. The following section provides an overview of two “local loop” reference implementations (a.k.a. designs/embodiments) - all-in-one and componentized. There are many possible designs leveraging different alternatives at multiple variation points. The sections after the reference implementations section provide an overview of variation points, alternatives, and factors to take into consideration during alternative selection. Command line Reference Implementations All-in-one Componentized Repository scan/crawl Variation points and alternatives Stakeholders & Activities Developer Build machine Test generator GenAI Messages Channels Developer -> Build Machine/Test Generation : Source code Build Machine -> Test Generator : Coverage results, possibly with bytecode Test Generation -> Developer : Generated tests Test Generation - GenAI : Prompt Command line Nasdanika CLI features JUnit command which generates JUnit tests as explained above. Reference Implementations This section explains reference implementations All-in-one All-in-one generations is implemented as a JUnit test is available in TestGenerator. An example of tests generated by this generator - PetControllerTests. As the name implies, all steps of source analysis and generation are implemented in a single class and are executed in one go. Componentized Componentized test generation which is also executed in one go is implemented in these classes: TestJavaAnalyzers - loads sources, coverage, and inspectors, passes the sources to the inspectors, aggregates and saves results. Coverage Inspector - generates tests for methods with low coverage leveraging TestGenerator capability provided by OpenAITestGenerator. Repository scan/crawl TestGitLab demonstrates how to scan a source repository (GitLab) using REST API, inspect code, generate unit tests, commit them to the server (also over the REST API) and create a merge request. This implementation does not use coverage information, its purpose is to demonstrate operation over the REST API without having to clone a repository, which might be an expensive operation. The implementation uses GitLab Model to communicate with the repository. It uses Java model to load sources and StringBuilder to build test cases. Variation points and alternatives As you have seen above, you can have an AI-powered JUnit test generator in about 230 lines of code, and maybe it would all you need. However, there are many variation points (design dimensions), alternatives at each point and, as such, possible permutations of thereof (designs). This section provides a high level overview of variation points and alternatives. How to assemble a solution from those alternative is specific to your context and there might be different solutions for different contexts and multiple solutions complementing each other. As you proceed with assembling a solution, or a portfolio of solutions, you may identify more variation points and alternatives. To manage the complexity you may use: Enterprise Model for general guidance, Capability framework or Capability model to create a catalog of variation points and alternatives and compute solutions (designs) from them Decision Analysis to select from the computed list of designs Flow to map your development process AS-IS and then augment it with test generation activities at different points. In this section we’ll use the below diagram and the concept of an Enterprise with Stakeholders performing activities and exchanging Messages over Channels. The mission of our enterprise is to deliver quality Java code. The loss function to minimize is loss function = cost * risk / business value. For our purposes we’ll define risk as inversely proportional to tests coverage risk = missed lines / total lines - that’s all we can measure in this simple model. The cost includes resources costs - salary, usage fees for OpenAI. Below is a summary of our enterprise: Stakeholders & Activities: Developer - writes code Build machine - compiles code and executes tests Test generator - generates unit tests GenAI - leveraged by the Test Generator Messages: Source code Bytecode Coverage results Prompt to generate a test Generated tests Channels Developer -> Build Machine : Source code Developer -> Test Generation : Source code Build Machine -> Test Generator : Coverage results, possibly with bytecode Test Generation -> Developer : Generated tests Test Generation - GenAI : Prompt The below sections outline variation points and alternatives for the list items above Stakeholders & Activities Developer A developer writes code - both “business” and test. They use some kind of an editor, likely an IDE - Eclipse, IntelliJ, VS Code. Different IDE’s come with different sets of plug-ins, including AI assistants. Forcing a developer to switch from their IDE of preference to another IDE is likely to cause considerable productivity drop, at least for some period of time, even if the new IDE is considered superior to the old IDE. So, if you want to switch to another IDE just because it has some plug-in which you like - think twice. Build machine A build machine compiles code and executes tests. Technically, compilation and test execution may be separated in two individual activities. We are not doing it for this analysis because it doesn’t carry much relevance to test generation. You can do it for yours. Test generator Test generator generates tests by “looking” at the source code, bytecode, and code coverage results. Because the source code is a model element representing piece of code (method, constructor, …), the generator may traverse the model to “understand” the context. E.g. it may take a look at the method’s class, other classes in the module. If the sources are loaded from a version control system, it may take a look at the commits. And if the source model is part of an organization model, it may look at “sibling” modules and other resources. By analyzing source and bytecode the generator would know methods a given method calls, objects it creates, and also it would know methods calling the method. It will also “know” branch conditions, e.g. switch cases. Using this information the generator may: Generate comments to help the developer Generate mocks, including constructor and static methods mocks Generate tests for different branches Build a variety of prompts for GenAI The test generator may do the following code generated by GenAI: Add to generated test methods commented out - as it is done in the reference implementations “Massage” - remove backticks, parse, add imports - generated and implied. In addition to code generation the generator may ask GenAI to explain code and generate recommendations - it will help the developer to understand the source method and possibly improve it along the way. It may also generate dependency graphs and sequence diagrams. GenAI There may GenAI models out there - cloud, self hosted. Which one to use heavily depends on the context. For example, if you have a large codebase with considerable amount of technical debt having an on-prem model may be a good choice because: You may fine-tune it. Even if you don’t have tons of GPU power and your model is relatively slow you can crawl you code base, generate tests and deliver them to developers for review and inclusion into test suites. In this scenario your cost is on-prem infrastructure and power. Your savings are not having to pay for GenAI in the cloud and developer productivity if your fined tuned model turns out to be more efficient than a “vanilla” LLM. There are many other considerations, of course! Messages In this section we’ll take a look just at bytecode and coverage results delivered to the test generator. The generator operates on models. As such, bytecode and coverage results can be delivered in a “raw” format to be loaded to a model by the generator, or pre-loaded to a model and saved to a file. The second option results in fewer files to pass to the test generator. The model file can be in XMI format or in compressed binary. The XMI format is human-readable, the binary format takes less space on disk. Channels Developer -> Build Machine/Test Generation : Source code For local development the build machine is the same machine where developer creates sources. The test generator is also executed on the developer’s workstation. As such, the delivery channels is the file system. In the case of CI/CD pipeline/build server such as Jenkins or GitHub Actions, a version control systems is the delivery channel. Build Machine -> Test Generator : Coverage results, possibly with bytecode The test generator needs coverage results. If the coverage results are delivered in the raw form, it also needs bytecode (class files) to make sense of the results. Coverage results can be delivered to the test generator using the following channels: Filesystem Jenkins workspace made available to the test generator over HTTP(S) Binary repository. For example, coverage results might be published to the Maven repository as an assembly along with sources, jar file, and javadoc. They can be published in a raw format or as a model. In this modality the tests generator can get everything it needs from a Maven repository. You can use Maven model or Maven Artifact Resolver API to work with Maven repositories. See also Apache Maven Artifact Resolver. Additional value of storing coverage data in a binary repository is that it can serve as an evidence of code quality stored with the compiled code, not in some other system. Source repository. Traditionally storing derived artifacts in a source repository is frowned upon. However, storage is cheap, GitHub Pages use this approach - so, whatever floats your boat! SonarQube - it doesn’t store method level coverage, so the solution would have to operate on the class level and generate test methods for all methods in a class with low coverage. You may have a specialized application/model repository/database and store coverage information there, possibly aligned to your organization structure. Test Generation -> Developer : Generated tests The goal is to deliver generated tests to the developer, make the developer aware that they are available, and possibly track progress of incorporating the generated tests into the test suite. With this in mind, there are the following alternatives/options: Filesystem - for the local loop Source control system - commit, create a merge/pull request. When using this channels you can check if there is already a generated test and whether it needs to be re-generated. If, say, the source method hasn’t changed (the same SHA digest), and the generator version and configuration hasn’t changed - do not re-generate, it will only consume resources and create “noise” - the LLM may return a different response, developers will have to spend time understanding what has changed. You may fork a repository instead of creating a branch. This way all work on tests will be done in the forked repository and the source repository will receive pull requests with fully functional tests. Tests can be generated to a separate directory and then copied to the source directory, or they can be generated directly to the source directory. Tests may be generated with @Disabled annotation so they are clearly visible in the test execution tree, and with @Generated annotation to track changes and merge generated and hand-crafted code. Issue tracking system - either attach generated tests to issues, or create a merge request and reference it from the generated issues. In systems like Jira you may create a hierarchy of issues (epic/story), assign components, labels, fix versions, assignees, etc. You may assign different generated tests to different developers based on size and complexity of the source method. E.g. tests for short methods with low complexity can be assigned to junior developers. This alone may give your team a productivity boost! E-mail or other messaging system. Issue trackers and messaging systems may be used to deliver generated documentation while source control will deliver generated tests. Developers will use the generated documentation such as graphs, sequence diagrams and GenAI explanations/recommendations in conjunction with the generated test code. This channel may implement some sort of backpressure by saying “it is enough for now”, as a human developer would by crying “Enough is enough, I have other stories to work on in this sprint!”. Generating just enough tests is beneficial in the following ways: Does not overwhelm developers Does not result in a stale generated code waiting to be taken a look at Does not waste resources and time to generate code which nobody would look at in the near future Uses the latest (and hopefully the greatest) generator version With backpressure a question of prioritization/sorting arises - what to work on first? Source methods can be sorted according to: Size/complexity Dependency. E.g. method b (caller) calls method a (callee) One strategy might be to work on callee methods first (method a) to provide a solid foundation. Another is to work on caller methods first because callee methods might be tested along the way. These strategies might be combined - some developers (say junior) may work on callee tests and senior developers may be assigned to test (complex) caller (top level) methods. Also, the top-down approach (callers first) might be better for addressing technical debt accrued over time, while bottom-up (callees first) for new development. Test Generation - GenAI : Prompt GenAI is neither free not blazing fast. As such, this channel may implement: Billing Rate limiting (throttling) Budgeting - so many calls per time period Caching Java Sources Source Artifacts Bytecode Coverage Data Developer JUnit Tests Gen AI Code Generation Compilation Test Execution JUnit Test Generation Coverage Report Java Sources Bytecode Coverage Data Developer Gen AI Coverage Model Source Code Model Tests Model Generator JUnit Test Generation Writing Code Compilation Testing Test Generation Gen AI"},"nsd-cli/index.html":{"action-uuid":"f87ba156-ad54-41e7-ab43-639e50968de2","title":"CLI","content":"Nasdanika Command Line Interface (CLI) is a suite of Nasdanika capabilities packaged as command line tools. Prerequisites To run Nasdanika CLI you’d need Java 17+. To build from sources you’d also need Maven. Installation Download installation archive from the releases page. On Linux make nsd executable: chmod a+x nsd. Building from sources Download sources as a zip file or clone the repository Run mvn clean verify After the build completes the distribuion will be available in target/dist directory Adding to PATH The distribution is portable and local - it can be put to any directory, but it can only be executed from that directory. To create an installation which can be used from any directory you will need to create launcher files with absolute paths. Windows nsd.bat launcher -f options-global -o nsd-global.bat -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules -j "@java"\n Add the installation to the PATH environment variable. You may delete/rename nsd.bat and rename nsd-global.bat to nsd.bat. Linux ./nsd launcher -o nsd-global -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules\n Open nsd-global in a text editor and add #!/bin/bash line before the java command line. Make the file executable and add the installation directory to the path. You may remove/rename nsd and rename nsd-global to nsd. If you get java.lang.module.FindException: Module <module name> not found error, open the file in a text editor, locate the problematic module and remove it from the --add-modules list."},"core/drawio/index.html":{"path":"Core/Drawio","action-uuid":"191c1736-4edb-4e34-8bf5-cd2547b4debd","title":"Drawio","content":"Nasdankia provides two Maven modules for working with Drawio diagrams - API and Model. The modules require Java 17 or above. API Drawio module provides Java API for reading and manipulating Drawio diagrams. It is built on top of Graph. The module provides the following interfaces representing elements of a diagram file: Document - the root object of the API representing a file/resource which contains one or more pages. Page - a page containing a diagram (Model). Model - a diagram model containing the diagram root. Root - the root of the model containing layers. Layer - a diagram may have one or more layers. Layers contain Nodes and Connections. Node - a node can be connected to other nodes with connections. A node may contain other nodes and connections. Connection - a connection between two nodes. The below diagram shows relationships between the above interfaces including their super-interfaces: Util provides utility methods such as layout() and methods to navigate and query documents and their elements. Model Drawio Model module provides an EMF Ecore model for diagrams. A model instance can be obtained from the API document by calling Document.toModelDocument() method. The model makes it more convenient to work with the diagram elements by: Making a reference between pages and model elements bi-directional. Introducing Tag class as opposed to a string in the API. Tag is contained by Page and has bi-directional reference with tagged elements. Document The root object of the API representing a file/resource which contains one or more pages Page A page containing a diagram (Model) Model A diagram model containing the diagram root Root The root of the model containing layers Layer A diagram may have one or more layers. Layers contain Nodes and Connections. Link [0..1] Layer Element Element Model Element Node A node can be connected to other nodes with connections. A node may contain other nodes and connections. Connection A connection between two nodes * source 0..1 outgoingConnections * 1 1 1..* * target 0..1 incomingConnections * Tag * * *"},"core/exec/index.html":{"path":"Core/Exec","action-uuid":"270ee777-dd05-4b92-8685-b15da705d59c","title":"Exec","content":"Javadoc"},"nsd-cli/nsd/java/junit/index.html":{"path":"CLI/nsd/java/junit","action-uuid":"1331611e-39b6-41ec-83ad-a5d84bd8749a","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.5.0 \r\nUsage: nsd java junit [-dhjVw] [--[no-]ai] [--[no-]comment-response]\r\n [--disabled] [--api-endpoint=<apiEndpoint>]\r\n [-c=<classes>] [--class-suffix=<classSuffix>]\r\n [-J=<jacoco>] [-k=<apiKey>] [-l=<limit>]\r\n [-m=<deploymentOrModelName>] [-p=<progressOutput>]\r\n [--package-suffix=<packageSuffix>] [-r=<prompt>]\r\n [-s=<sources>] [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <projectDir> <coverageThreshold>\r\n <output>\r\nGenerates JUnit tests\r\n <projectDir> Project directory\r\n <coverageThreshold> Coverage threshold\r\n <output> Output directory\r\n relative to the project directory\r\n --[no-]ai Use AI, defaults to true\r\n --api-endpoint=<apiEndpoint>\r\n OpenAPI endpoint, defaults to\r\n https://api.openai.com/v1/chat/completions\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n --class-suffix=<classSuffix>\r\n Test class suffix\r\n defaults to Tests\r\n --[no-]comment-response\r\n Comment AI responses\r\n defaults to true\r\n -d, --data Output progress data\r\n --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Source includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -J, --jacoco=<jacoco> jacoco.exec file path relative\r\n to the project directory,\r\n defaults to target/jacoco.exec\r\n -k, --api-key=<apiKey> OpenAPI key\r\n -l, --limit=<limit> Maximum number of test classes\r\n to generate\r\n -m, --model=<deploymentOrModelName>\r\n OpenAPI deployment or model\r\n defaults to gpt-4\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n -r, --prompt=<prompt> Propmt\r\n defaults to 'Generate a JUnit 5 test method\r\n leveraging Mockito for the following Java method'\r\n -s, --sources=<sources> Sources directory path relative\r\n to the project directory,\r\n defaults to src/main/java\r\n -t, --coverage-type=<coverageType>\r\n Coverage type\r\n Valid values: complexity, instruction, branch, line\r\n defaults to line\r\n -v, --api-key-variable=<apiKeyEnvironmentVariable>\r\n OpenAPI key environment variable\r\n defaults to OPENAI_API_KEY\r\n -V, --version Print version information and exit.\r\n -w, --overwrite Overwrite existing tests"},"html/html/index.html":{"path":"HTML/HTML","action-uuid":"4a31e215-827a-4c18-b82f-1c952ee5f6a7","title":"HTML","content":"TODO"},"nsd-cli/nsd/java/index.html":{"path":"CLI/nsd/java","action-uuid":"7e86718c-86ce-42c9-b762-aacb532c510a","title":"java","content":"Version: org.nasdanika.models.java.cli@2024.5.0 \r\nUsage: nsd java [-hV] [COMMAND]\r\nCommands related to Java\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n junit Generates JUnit tests"},"nsd-cli/nsd/help/site/index.html":{"path":"CLI/nsd/help/site","action-uuid":"29ab1c67-0fb7-426b-b234-0e65337e49d6","title":"site","content":"Usage: nsd help site [-dhjlV] [-b=<baseDir>] [-m=<domian>]\r\n [-p=<progressOutput>] [-P=<parallelism>] [-r=<pageErrors>]\r\n [--root-action-icon=<rootActionIcon>]\r\n [--root-action-location=<rootActionLocation>]\r\n [--root-action-text=<rootActionText>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>] [-c=<String=String>]...\r\n [-C=URL]... [-M=<String=String>]... [-e\r\n [=<excludes>...]]... [-i[=<includes>...]]... <output>\r\nGenerates help HTML site\r\n <output> Output directory\r\n -b, --base-dir=<baseDir> Base directory\r\n -c, --context-entry=<String=String>\r\n Context entries.\r\n Shadow entries in contexts and mounts.\r\n -C, --context=URL Context resource URL relative to the current\r\n directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Contexts are composed in the order of\r\n definition, later context entries shadowing the\r\n former\r\n -d, --data Output progress data\r\n -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -h, --help Show this help message and exit.\r\n -i, --include[=<includes>...]\r\n Output directory clean includes\r\n Ant pattern\r\n -j, --json Output progress in JSON\r\n -l, --[no-]clean Clean working directory\r\n defaults to true\r\n -m, --domain=<domian> Sitemap domain\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the\r\n current directory. YAML, JSON, or properties. In\r\n properties dots are treated as key path\r\n separators. Type is inferred from the content\r\n type header, if it is present, or extension.\r\n Mounts shadow context entries.\r\n -p, --progress=<progressOutput>\r\n Output file for progress monitor\r\n -P, --parallelism=<parallelism>\r\n If the value greater than one then an executor\r\n service is created and injected into the context\r\n to allow concurrent execution.\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n --root-action-icon=<rootActionIcon>\r\n Root action icon\r\n --root-action-location=<rootActionLocation>\r\n Root action location\r\n --root-action-text=<rootActionText>\r\n Root action text\r\n -t, --timeout=<timeout> If parallelism is greater than one this option\r\n specifies timout in seconds awaiting completion\r\n of execution. Default value is 60.\r\n -T, --page-template=<pageTemplate>\r\n Page template URI relative\r\n to the current directory\r\n -V, --version Print version information and exit.\r\n -w, --work-dir=<workDir> Working directory\r\nExit codes:\r\n Non-negative number Delegate result\r\n -1 Unhandled exception during execution\r\n -2 Invalid input\r\n -3 Diagnostic failed\r\n -4 Execution failed or was cancelled, successful rollback\r\n -5 Execution failed or was cancelled, rollback failed\r\n -6 Executor service termination timed out"},"practices/java/index.html":{"path":"Practices/Java Analysis, Visualization & Generation","action-uuid":"ac323943-8e4f-4522-bac2-a0f90a2f67c9","title":"Java Analysis, Visualization & Generation","content":"This practice is a specialization of the Analysis, Visualization & Generation Practice for using the Java model as a source model, target model, or both. This page provides a high level reference and the book goes into details. So what is possible to do with the Java model/language in addition to generic analysis, visualization and generation? Analysis Java model can be loaded from sources and bytecode. Tests coverage can be loaded from jacoco.exec and class files and associated with model elements. Bytecode information can be used to establish bi-directional references between model elements - field access, method calls. Bytecode can be instrumented to collect runtime cross-referencing such as reflective method calls and field access. Visualization Module, package, class, method dependency graphs. The graphs may reflect coverage data so they can be used for prioritization of addressing technical debt. For example, many well-covered microservices may use a shared library with low coverage. Sequence diagrams Generation Documentation Documentation similar to documentation generated from Ecore models such as Java model above, Family model, or Enterprise model with: * Visualizations mentioned above\n* Documentation produced by GenAI - explainations and recommendations.\n Such documentation may be useful in modernization efforts where there is a need to understand a legacy codebase. It may also be useful in onboarding of new team members and it might help provide deeper insights into the codebase for all team members. Source code Source code with @Generated annotations or @generated Javadoc tags to allow detection of changes in the generated code and re-generation only if there changes in the generator inputs, and the output was not modified since the last generation. It allows concurrent evolution of the generator, generator inputs, and manual modifications. For more details see Solution instantiation. RAG/Chat RAG/Chat on top of the Java model may use bytecode and runtime introspection information in addition to just source code. For example “This method is overridden by … and is called by …”. RAG may be contextual - chat with a class, a method, a package, a module or an application (group of modules) if the model elements are “mounted” under higher level constructs such as products and segments."},"core/capability/index.html":{"path":"Core/Capability","action-uuid":"61726c59-c9d6-40fe-b28d-cfad4164b5d2","title":"Capability","content":"Nasdanika Capability framework1 allows to discover/load capabilities which meet a requirement. Capabilities are provided by CapabilityFactory create() method. Capability factories may request other capabilities they need. As such, capabilities can be chained. Factories create CapabilityLoaders which provide Flux reactive streams of capabilities. It allows to have an infinite stream of capabilities which are consumed (and produced) as needed. Capability providers may furnish additional information about capabilities. This information can be used for filtering or sorting providers. A non-technical example of requirement/capability chain graph is a food chain/graph. Food is a requirement. Or “I want to eat” is a requirement. Bread and, say fried eggs are two capabilities meeting/addressing the requirement. Bread requires “wheat”, “water”, and “bake” capabilities. Fried eggs require “egg”, “oil”, and “fry” capabilities. Bread capability provider may implement Vegan marker interface which can be used for filtering. All food capabilities may implement NutritionalInformation interface - it can be used for filtering or sorting. A more technical example is Java ServiceLoader with service type being a requirement and an instance of the service class being a capability. Nasdanika capability framework can operate on top of ServiceLoader and may be thought of as a generalization of service loading. In essence, the capability framework is a backward chaining engine as shown in one of the example below. Client code - requesting a capability Capabilities are loaded by CapabilityLoader. Capability loader can take an iterable of capability factories in its constructor, or it can load them using ServiceLoader as shown in the below code snippet: CapabilityLoader capabilityLoader = new CapabilityLoader();\ncapabilityLoader.getFactories().add(new TestServiceFactory<Object>());\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\t\t\nfor (CapabilityProvider<?> cp: capabilityLoader.load(new TestCapabilityFactory.Requirement("Hello World"), progressMonitor)) {\n\tSystem.out.println(cp);\n\tFlux<?> publisher = cp.getPublisher();\n\t\t\t\n\tpublisher.subscribe(System.out::println);\n}\n Factories can also be added post-construction with getFactories().add(factory). Service capabilities Service requirements and capabilities provide functionality similar to ServiceLoader - requesting instances of specific type, but extend it with ability to provide additional service requirement. This functionality is provided by ServiceCapabilityFactory and ServiceCapabilityFactory.Requirement. CapabilityLoader capabilityLoader = new CapabilityLoader();\ncapabilityLoader.getFactories().add(new TestServiceFactory<Object>());\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\t\t\n@SuppressWarnings({ "unchecked", "rawtypes" })\nServiceCapabilityFactory.Requirement<List<Double>, Double> requirement = (ServiceCapabilityFactory.Requirement) ServiceCapabilityFactory.createRequirement(List.class, null, 33.0);\nfor (CapabilityProvider<?> cp: capabilityLoader.load(requirement, progressMonitor)) {\n\tSystem.out.println(cp);\n\tFlux<?> publisher = cp.getPublisher();\n\t\t\t\n\tpublisher.subscribe(System.out::println);\n}\n It is also possible to load services from ServiceLoader using subclasses of Service. You’d need to subclass ServiceFactory in a module which uses a particular service and override stream(Class<S> service) method as shown below: @Override\nprotected Stream<Provider<S>> stream(Class<S> service) {\n\treturn ServiceLoader.load(service).stream();\n}\n Then you’d need to add the factory to the loader: capabilityLoader.getFactories().add(new TestServiceFactory<Object>());\n Providing a capability As it was mentioned above, capability factories can be explicitly added to CapabilityLoader or loaded using ServiceLoader. Below is an example of a capability factory: public class TestCapabilityFactory implements CapabilityFactory<TestCapabilityFactory.Requirement, Integer> {\n\t\n\tpublic record Requirement(String value){};\n\t\n\t@Override\n\tpublic boolean canHandle(Object requirement) {\n\t\treturn requirement instanceof Requirement;\n\t}\n\n\t@Override\n\tpublic CompletionStage<Iterable<CapabilityProvider<Integer>>> create(\n\t\t\tRequirement requirement,\n\t\t\tBiFunction<Object, ProgressMonitor, CompletionStage<Iterable<CapabilityProvider<Object>>>> resolver,\n\t\t\tProgressMonitor progressMonitor) {\n\t\t\n\t\treturn resolver.apply(MyService.class, progressMonitor).thenApply(cp -> {;\n\t\t\t@SuppressWarnings({ "unchecked", "rawtypes" })\n\t\t\tFlux<MyService> myServiceCapabilityPublisher = (Flux) cp.iterator().next().getPublisher();\n\t\t\t\n\t\t\treturn Collections.singleton(new CapabilityProvider<Integer>() {\n\t\n\t\t\t\t@Override\n\t\t\t\tpublic Flux<Integer> getPublisher() {\n\t\t\t\t\tFunction<MyService, Integer> mapper = ms -> ms.count(((Requirement) requirement).value());\n\t\t\t\t\treturn myServiceCapabilityPublisher.map(mapper);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t});\n\t\t});\n\t}\n\n}\n Applications Services Service capabilities explained above a used by Graph and Function Flow for loading node processors and connection processors for a specific requirement using NodeProcessorFactory and ConnectionProcessorFactory respectively. For example, code generation, execution, simulation. Solutions for architectures One of future application of the capability framework is creation a list of solution alternatives for an architecture/pattern. For example, there might be multiple RAG embodiments with different key types, key extractors, stores, … Some of “design dimensions” are listed below: Key type: Bag of words. Multiple options - just words, words with frequency, tokenized words, word stems. Embedding vector - different embedding models, different dimensions. Store - multiple stores for multiple key types. Multiple indexing and retrieval methods. Chunk size, chunk overlap, chunking algorithm. Generator - multiple models and prompts As you can see a number of potential combinations can easily go into thousands or even be infinite. Reactive approach with filtering and sorting may be helpful in selecting a solution which is a good fit for a particular use case - number and type of data sources etc. For example, if the total size of data is under a few gigabytes an in-memory store may be a better choice than, say, an external (vector) database. Also an old good bag of words might be better than embeddings. E.g. it might be cheaper. Solution alternatives may include temporal aspect or monetary aspects. For example, version X of Y is available at time Z. Z might be absolute or relative. Say, Z days after project kick-off or license fee payment. Identified solutions meeting requirements can have different quality attributes - costs (to build, to run), timeline, etc. These quality attributes can be used for solution analysis. E.g. one solution can be selected as a transition architecture and another as the target architecture. Backward chaining Family reasoning demonstrates application of the capability framework as a backward chaining engine. Family relationships such as grandfather and cousin are constructed by requiring and combining relationships such as child and sibling. Stream processing This possible application is similar to backward reasoning. Imagine an algorithmic trading strategy which uses several technical indicators, such as moving averages, to make trading decisions. Such a strategy would submit requirements for technical indicators which would include symbol, indicator configuration, time frame size. Technical indicators in turn would submit a requirement for raw trading data. A technical indicator such as moving average would start publishing its events once it receives enough trading data frames to compute its average. A trading engine would submit a requirement for strategies. A strategy factory may produce multiple strategies with different configurations. The trading engine would perform “paper” trades, select well-performing strategies and discard ones which perform poorly. This can be an ongoing process - if a strategy deteriorates then it is discarded and a new strategy is requested from strategy publishers - this process can be infinite. AI model training/fine-tuning This application is similar to stream processing and may be combined with backward reasoning. Let’s say we want to train a model to answer questions about family relationships for a specific family. For example, “Who is Alan’s great grandmother?” A single relationship in the model can be expressed in multiple ways in natural language. And multiple relationships can be expressed in a single sentence. For example: Elias is a person Elias is a man Elias is a male Elias is a parent of Fiona Fiona is a child of Elias Elias is a father of Fiona Fiona is a daughter of Elias Paul and Isa are parents of Lea and Elias … So, on top of a model there might be a collection of text generators. Output of those generators can be fed to a model: Supervised - question and answer “How many sisters does Bryan have?” - “Two” “Who are Bryan’s sisters?” - “Clara and Fiona” Unsupervised - factual statements A similar approach can be applied to other models - customer/accounts, organization or architecture model, etc. For example, from the Internet Banking System we can generate something like “Accounts Summary Controller uses Mainframe Banking System Facade to make API calls to the Mainframe Banking System over XML/HTTPS”. “make API calls” may also be generated as “connect” or “make requests”. In a similar fashion a number of questions/answers can be generated. Javadoc ↩"},"core/graph/index.html":{"path":"Core/Graph","action-uuid":"c1c31db5-6d35-44ba-94cb-3a5eb60ee2b9","title":"Graph","content":"Javadoc"},"core/index.html":{"action-uuid":"8085527a-8566-4a27-857e-c28f4a3bc134","title":"Core","content":"TODO"},"html/models/index.html":{"path":"HTML/Models","action-uuid":"83939a39-8301-4ee1-9a1c-864c131dec21","title":"Models","content":"TODO"},"practices/generic/index.html":{"path":"Practices/Analysis, Visualization & Generation","action-uuid":"174436a1-dc8a-4044-b6ec-6ebfcaba75fa","title":"Analysis, Visualization & Generation","content":"This practice explains how to use Nasdanika products (specifically models) and related products. The above diagram shows the core idea - load input data into a model, modify the model or create a new model from it, and save the models to native (raw) formats. Loading to a model as opposed to working with raw formats gives the following benefits: Unified API Generated model documentation with visualizations Different models may extend classes from core models and be treated similarly Model classes may be subclassed and mixed Cross-reference model elements URI handlers allows to load models from diverse sources On-demand loading of resources and features of model elements Conversion of models to graphs and making them executable with graph processors E.g. want to read/write Excel files - take a look at the Excel metamodel and then use Ecore API to work with the model. Now want to work with PDF? A different metamodel, the same model API. You have Java sources stored in GitLab and want model elements to reflect both Java and GitLab natures of your sources? Create a GitLabRepositoryCompilationUnit class which extends both Compilation Unit and Repository File. Customize Loader to create this class for repository files with java extension. Want to load a PDF file directly from GitLab without having to clone the entire repository? Use GitLabURIHandler! The below diagram illustrates the above concepts: Models can be visualized using: ECharts using the ECharts model, ECharts-Java or by directly generating JavaScript/JSON. Example. PlantUML using DiagramGenerator, the diagram module or by directly generating PlantUML text and calling Plant UML API’s. Example. Holistic model of an organization One use case for the modeling approach outlined above is creation of a holistic model of an organization/corporation as exemplified by the below diagram1 In a corporation different elements of the model are typically stored in different systems and documents like Excel spreadsheets. The modeling approach allows to load those elements in a single resource set and cross-reference them. Elements which are not stored in structured formats can be captured by modeling them in diagrams and mapping those diagrams to models, see Beyond Diagrams. One important reason why a holistic model might be beneficial for an organization is the ability of using it for AI insights. For example, using RAG/Chat on top of the organization model. Such chat can be made context-aware, chatting with the Operations will return result relevant to operations. The above diagram is very simple, a large organization may have many layers, thousands of applications, millions of lines of code. A model for such an organization would take some time to build, but it can be built incrementally - department by department, application by application. The value of building such a model will grow exponentially as more and more elements are added due to the network effect. While the resulting model might be “large”, … define large. Experiments show that a model element in a model like the above takes ~ 500 bytes of RAM. As such, 1 GB of RAM would hold about 2 million model elements. Also, model resources are loaded on demand, so only the model elements needed by some task would be loaded to complete that task. With DynamicDelegate it is possible to have model elements loading their data from multiple sources on demand. The organization model can be built on top of existing “generic” models such as Java, Maven, GitLab, Azure, … Resources TOGAF Enterprise Metamodel Corporate structure ↩ Output Model Transformation Input Model Raw Input Raw Output Cell Excel Resource Paragraph PDF Resource Resource Set GitLab URI Handler MS Excel Workbook GitLab Excel Resource Factory PDF Resource Factory PDF File File system Corporation Marketing Finance Uses Operations HR Builds IT Execution environments Binary packages Source Code Application"},"nsd-cli/nsd/http-server/index.html":{"path":"CLI/nsd/http-server","action-uuid":"f696eb74-b66f-4875-b85f-55ff7105744a","title":"http-server","content":"Usage: nsd http-server [-hV] [--http-host=<httpHost>] [--http-port=<httpPort>]\r\n [--http-server-shutdown-timeout=<timeout>]\r\nServes HTTP routes\r\n -h, --help Show this help message and exit.\r\n --http-host=<httpHost>\r\n HTTP host (network interface) to bind to\r\n --http-port=<httpPort>\r\n HTTP port. If a port is not specified,\r\n an ephemeral port is used\r\n --http-server-shutdown-timeout=<timeout>\r\n Timeout in seconds,\r\n defaults to 3 seconds\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/help/index.html":{"path":"CLI/nsd/help","action-uuid":"8f232118-5be2-405c-8ffe-00c8f37676dd","title":"help","content":"Usage: nsd help [-ahHV] [-l=<level>] [-o=<output>] [COMMAND]\r\nOutputs usage for all registred commands\r\n -a, --action-model Output to action model\r\n -h, --help Show this help message and exit.\r\n -H, --html Output to HTML\r\n -l, --header-level=<level>\r\n Starting level for HTML header tags in HTML output,\r\n the default value is 1.\r\n -o, --output=<output> Output file\r\n -V, --version Print version information and exit.\r\nCommands:\r\n site Generates help HTML site"}} \ No newline at end of file diff --git a/docs/search.html b/docs/search.html index f06f599e1..2b9803638 100644 --- a/docs/search.html +++ b/docs/search.html @@ -37,45 +37,45 @@
      - + Nasdanika
      -
      +
      -
      - -
      +
      + +
      -
      +
      -

      Search +

      Search

      @@ -278,7 +278,7 @@

      results.split(' ').includes(node.original['data-nsd-label-uuid']); return tree; }({"core":{"data":[{"a_attr":{"onclick":"window.location='index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='1.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='https://leanpub.com/u/pvlasov';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='https://leanpub.com/beyond-diagrams';"},"data-nsd-label-uuid":"8b9e0220-87a7-439f-9f4a-1e6d612baec2","id":"e9ff48da-c941-4ae6-93c5-b9afc6927d44","text":"Beyond Diagrams","type":"leaf"},{"a_attr":{"onclick":"window.location='https://leanpub.com/java-analysis';"},"data-nsd-label-uuid":"05ecf0f1-eed1-41b4-9a94-cdf559b6e3c8","id":"5857f6c2-12af-4b42-b5b6-05ec43b489ab","text":"Java Analysis, Visualization, and Generation","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"df0a92ae-d17e-44a7-98bf-62c4da658452","id":"e6320d69-8031-45f3-bea6-258228491c81","text":"Books","type":"leaf"},{"a_attr":{"onclick":"window.location='practices/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='practices/generic/index.html';"},"data-nsd-label-uuid":"174436a1-dc8a-4044-b6ec-6ebfcaba75fa","id":"e2ab136d-9d91-4a8d-ac02-ccfac00350ee","text":"Analysis, Visualization & Generation","type":"leaf"},{"a_attr":{"onclick":"window.location='practices/java/index.html';"},"data-nsd-label-uuid":"ac323943-8e4f-4522-bac2-a0f90a2f67c9","id":"ae402d3c-65b3-41ec-99ef-b6e47eae76a8","text":"Java Analysis, Visualization & Generation","type":"leaf"},{"a_attr":{"onclick":"window.location='practices/junit/index.html';"},"data-nsd-label-uuid":"89bfe702-c63f-4161-bc74-baa8f0ce2d77","id":"e34cbc65-8311-4b3d-a708-f0420a39f11e","text":"JUnit Tests Generation","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"69f993a9-5902-4e74-8951-5e8fb4ae982e","id":"c94bba32-8ccb-43ed-9d07-4672fd59e97c","text":"Practices","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/app/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/app/site/index.html';"},"data-nsd-label-uuid":"7283f6fa-e0f5-48cf-92f4-1d1a156eab2a","id":"f63a6c89-3359-47d6-adad-dd175b36062d","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"e06309ac-9d53-4fc4-84d4-6b7ee2d462ba","id":"513e4a2b-99bc-4bac-911d-6cd0811251e9","text":"app","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/help/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/help/site/index.html';"},"data-nsd-label-uuid":"29ab1c67-0fb7-426b-b234-0e65337e49d6","id":"8c557abe-1214-4b65-bb4d-e269bbda40cc","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"8f232118-5be2-405c-8ffe-00c8f37676dd","id":"5ee2b22f-5783-4319-a27c-a00f810c0395","text":"help","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/http-server/index.html';"},"data-nsd-label-uuid":"f696eb74-b66f-4875-b85f-55ff7105744a","id":"e3a8a561-7580-4922-ba01-c48f77daf9dd","text":"http-server","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/java/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/java/junit/index.html';"},"data-nsd-label-uuid":"1331611e-39b6-41ec-83ad-a5d84bd8749a","id":"14884dab-8911-4245-8a00-fb7a466b0a16","text":"junit","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"7e86718c-86ce-42c9-b762-aacb532c510a","id":"86915dba-9653-473e-8c22-b67dea89df6c","text":"java","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/launcher/index.html';"},"data-nsd-label-uuid":"416e9c2f-8437-4ac3-bdc1-76545d395bfe","id":"8e296afb-7d0e-47de-a736-1b710804e985","text":"launcher","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"6606a632-01b6-4a96-987a-082eddb3cf84","id":"a57ca2d2-263b-4283-bd92-940d6990392b","text":"nsd","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"f87ba156-ad54-41e7-ab43-639e50968de2","id":"e744996b-1088-4601-ba33-da5465434780","text":"CLI","type":"leaf"},{"a_attr":{"onclick":"window.location='https://github.com/Nasdanika-Models';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='https://architecture.models.nasdanika.org';"},"data-nsd-label-uuid":"16c706d0-9c0a-48d3-8647-3bd0a310525b","id":"c958e243-1f93-4050-8379-5ebf9238bc30","text":"Architecture","type":"leaf"},{"a_attr":{"onclick":"window.location='https://azure.models.nasdanika.org';"},"data-nsd-label-uuid":"9c390f01-31bd-4390-84e9-abed5a981811","id":"cbaa1f85-12aa-4854-8c24-52d864a36607","text":"Azure","type":"leaf"},{"a_attr":{"onclick":"window.location='https://bank.models.nasdanika.org';"},"data-nsd-label-uuid":"350bf846-9560-454d-abf5-cefae36c1952","id":"2fc850f7-360a-46ab-9e54-fb7eab7728b8","text":"Bank","type":"leaf"},{"a_attr":{"onclick":"window.location='https://capability.models.nasdanika.org';"},"data-nsd-label-uuid":"f40bbc01-e17d-43a1-b07d-068563770a44","id":"25ba1b69-edae-4d5a-ae01-cb9b8300820f","text":"Capability","type":"leaf"},{"a_attr":{"onclick":"window.location='https://coverage.models.nasdanika.org';"},"data-nsd-label-uuid":"7dd91e7d-4e16-42c7-ab2f-facee8783226","id":"4980b970-e0bc-4798-9827-8334cb654b30","text":"Coverage","type":"leaf"},{"a_attr":{"onclick":"window.location='https://mcda.models.nasdanika.org';"},"data-nsd-label-uuid":"7792946b-9a0d-4cb4-9728-8d658fbe5f2c","id":"4b5a615f-cd8a-47eb-9c6e-368ac78dbbc8","text":"Decision Analysis","type":"leaf"},{"a_attr":{"onclick":"window.location='https://echarts.models.nasdanika.org/graph';"},"data-nsd-label-uuid":"93206766-d135-4fe4-9b70-45bc333b276e","id":"188b9187-476d-4852-ab90-ac417383b4ca","text":"ECharts","type":"leaf"},{"a_attr":{"onclick":"window.location='https://ecore.models.nasdanika.org';"},"data-nsd-label-uuid":"2cdfbf75-8dc4-43bc-81bc-725cf9580d9b","id":"f8713ab4-da8b-4994-be23-2cab5ee90fbb","text":"Ecore","type":"leaf"},{"a_attr":{"onclick":"window.location='https://enterprise.models.nasdanika.org';"},"data-nsd-label-uuid":"da1d650b-6958-456d-8796-37e076d01584","id":"45829c35-85c1-46d6-9e20-564a65f53c8e","text":"Enterprise","type":"leaf"},{"a_attr":{"onclick":"window.location='https://excel.models.nasdanika.org';"},"data-nsd-label-uuid":"90cf7cc1-979e-422b-a4bf-f6b1f15d723d","id":"86346169-f840-4b5a-9ed1-6ffa40fde551","text":"Excel","type":"leaf"},{"a_attr":{"onclick":"window.location='https://family.models.nasdanika.org';"},"data-nsd-label-uuid":"8b8758a9-c075-4b74-9600-f254c02db7ee","id":"5e842855-1ce0-450f-9282-612f44f4dcc4","text":"Family","type":"leaf"},{"a_attr":{"onclick":"window.location='https://flow.models.nasdanika.org';"},"data-nsd-label-uuid":"84ccfd12-dcb0-4219-8121-086208fb24b3","id":"568b965c-2c46-47a8-a307-3f7ebd59aca4","text":"Flow","type":"leaf"},{"a_attr":{"onclick":"window.location='https://function-flow.models.nasdanika.org';"},"data-nsd-label-uuid":"5eae6134-862e-4de8-a941-38e8cbfa0903","id":"d3e4911a-7af3-4c2e-8fcf-1954d3e9098a","text":"Function Flow","type":"leaf"},{"a_attr":{"onclick":"window.location='https://git.models.nasdanika.org';"},"data-nsd-label-uuid":"0899754d-506d-4e26-863e-fb9406157009","id":"fd605806-a8cb-4b1c-99bb-08e9549a0a71","text":"Git","type":"leaf"},{"a_attr":{"onclick":"window.location='https://gitlab.models.nasdanika.org';"},"data-nsd-label-uuid":"7b6f2780-57fe-4e86-9e06-0cc7f8ca51e4","id":"995833de-bd17-4b44-b579-e863dbba9c14","text":"GitLab","type":"leaf"},{"a_attr":{"onclick":"window.location='https://java.models.nasdanika.org';"},"data-nsd-label-uuid":"45b1e91e-9966-43b6-a372-514ff4d75522","id":"327ef4da-80eb-4cff-974c-8aa074fbe5f3","text":"Java","type":"leaf"},{"a_attr":{"onclick":"window.location='https://jira.models.nasdanika.org';"},"data-nsd-label-uuid":"a593098a-d816-489b-b9e0-91857251a163","id":"1912b30c-c48a-4724-8101-e60e5b239d3d","text":"Jira","type":"leaf"},{"a_attr":{"onclick":"window.location='https://maven.models.nasdanika.org';"},"data-nsd-label-uuid":"0c64bf2d-124c-46a2-ab93-55b224454213","id":"4b824653-6639-4a18-9392-7415f0f124f3","text":"Maven","type":"leaf"},{"a_attr":{"onclick":"window.location='https://nature.models.nasdanika.org';"},"data-nsd-label-uuid":"1eae965b-e3ca-483f-9af1-c1ae31d06ecd","id":"982ab118-2498-4a04-9315-06dcac592c46","text":"Nature","type":"leaf"},{"a_attr":{"onclick":"window.location='https://pdf.models.nasdanika.org';"},"data-nsd-label-uuid":"66bfb51e-2df5-48db-8d40-b5ada3fefbbc","id":"32f6329f-3e04-4e95-b484-e8d9264eecb8","text":"PDF","type":"leaf"},{"a_attr":{"onclick":"window.location='https://party.models.nasdanika.org';"},"data-nsd-label-uuid":"e7b8eb8b-7531-4feb-9c23-4f7a1789f587","id":"6cf8bbf9-194f-4356-b4fd-008c478f69db","text":"Party","type":"leaf"},{"a_attr":{"onclick":"window.location='https://rules.models.nasdanika.org';"},"data-nsd-label-uuid":"5de44bcf-986f-4f37-840d-db65ea5df506","id":"05bf7fd7-c156-44c4-baa6-8638707c4e11","text":"Rules","type":"leaf"},{"a_attr":{"onclick":"window.location='https://source-engineering.models.nasdanika.org';"},"data-nsd-label-uuid":"e7837198-2d19-4b14-8876-92150bcac0e8","id":"213a0d53-2420-4841-bcd8-a951edd5ccd3","text":"Source Engineering","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"10bda318-aa5f-455a-8ef2-ef0bf148326c","id":"67c59d5c-8fd9-408e-877b-d85aaf2bb8d6","text":"Models","type":"leaf"},{"a_attr":{"onclick":"window.location='html/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='html/bootstrap/index.html';"},"data-nsd-label-uuid":"655794d1-974a-4f97-ace9-41918841fb14","id":"06a918a9-c383-4d08-9d50-e044c137f8a4","text":"Bootstrap","type":"leaf"},{"a_attr":{"onclick":"window.location='html/emf/index.html';"},"data-nsd-label-uuid":"6be1b864-2152-46f7-b5d0-a7b6ae90570d","id":"5abc885e-d58c-4860-b68c-f00019374025","text":"EMF","type":"leaf"},{"a_attr":{"onclick":"window.location='html/html/index.html';"},"data-nsd-label-uuid":"4a31e215-827a-4c18-b82f-1c952ee5f6a7","id":"97840b37-27bd-49b9-8daa-6a1719f35736","text":"HTML","type":"leaf"},{"a_attr":{"onclick":"window.location='html/jstree/index.html';"},"data-nsd-label-uuid":"68577bf6-51f9-44d2-9bba-380611b670e7","id":"94ac5ede-efca-4f98-b79d-d6968a206810","text":"JsTree","type":"leaf"},{"a_attr":{"onclick":"window.location='html/models/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='html/models/app/index.html';"},"data-nsd-label-uuid":"34c0967b-54a5-420e-b53f-85a4f6200eae","id":"6f73f297-a2f6-48f7-ae72-64015d98185b","text":"App","type":"leaf"},{"a_attr":{"onclick":"window.location='html/models/bootstrap/index.html';"},"data-nsd-label-uuid":"c57f41cb-6a7b-4457-83c2-9a45488ec856","id":"540f3237-9cc3-40be-a59e-fe1f1e43be16","text":"Bootstrap","type":"leaf"},{"a_attr":{"onclick":"window.location='html/models/html/index.html';"},"data-nsd-label-uuid":"1ec28871-104c-4f5b-837a-b64ac672a65f","id":"162363e5-1a1a-4bbd-86a1-57c783b57bf8","text":"HTML","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"83939a39-8301-4ee1-9a1c-864c131dec21","id":"13b47983-8b63-43f0-8779-680d48626138","text":"Models","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"0f4e3df1-a272-4c9e-aa6a-6b541feeca02","id":"e2071f44-0c99-4589-9679-ac26b25f2b67","text":"HTML","type":"leaf"},{"a_attr":{"onclick":"window.location='core/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='core/cli/index.html';"},"data-nsd-label-uuid":"640290cf-75cf-451c-991b-eadbba515710","id":"6f30adbf-9e57-421d-9dcd-158b51262c41","text":"CLI","type":"leaf"},{"a_attr":{"onclick":"window.location='core/capability/index.html';"},"data-nsd-label-uuid":"61726c59-c9d6-40fe-b28d-cfad4164b5d2","id":"584a441a-881a-4bde-ae5e-6a34be527398","text":"Capability","type":"leaf"},{"a_attr":{"onclick":"window.location='core/common/index.html';"},"data-nsd-label-uuid":"3476167d-02c7-4261-904f-cc0f01314e7e","id":"214290fe-a6c5-4ded-b9ed-84bad13fba97","text":"Common","type":"leaf"},{"a_attr":{"onclick":"window.location='core/diagram/index.html';"},"data-nsd-label-uuid":"836f371e-2ed3-42c2-ad4b-778b8cc662ef","id":"8182d149-3e1f-4e5a-ac48-7a1ad3f62f40","text":"Diagram","type":"leaf"},{"a_attr":{"onclick":"window.location='core/drawio/index.html';"},"data-nsd-label-uuid":"191c1736-4edb-4e34-8bf5-cd2547b4debd","id":"40b55777-abc0-4bbd-a422-275d55565990","text":"Drawio","type":"leaf"},{"a_attr":{"onclick":"window.location='core/emf/index.html';"},"data-nsd-label-uuid":"aeb2e45d-d4b9-49fb-9313-ea2f5e076da8","id":"f54a2e9c-adba-4dd4-878b-b441e245f3f9","text":"EMF","type":"leaf"},{"a_attr":{"onclick":"window.location='core/exec/index.html';"},"data-nsd-label-uuid":"270ee777-dd05-4b92-8685-b15da705d59c","id":"3a24d7ad-a586-4942-85f9-d55692fc40ef","text":"Exec","type":"leaf"},{"a_attr":{"onclick":"window.location='core/graph/index.html';"},"data-nsd-label-uuid":"c1c31db5-6d35-44ba-94cb-3a5eb60ee2b9","id":"cbec6bda-35ff-4146-b8f5-cbc416682a93","text":"Graph","type":"leaf"},{"a_attr":{"onclick":"window.location='core/maven/index.html';"},"data-nsd-label-uuid":"d7a93f4c-ff1c-4d5f-8dc0-115cb6312360","id":"573d0a13-9a93-4ff7-b2ca-2ed91c5a7b99","text":"Maven","type":"leaf"},{"a_attr":{"onclick":"window.location='https://ncore.models.nasdanika.org/';"},"data-nsd-label-uuid":"7a679172-703f-4a68-b7fb-2a22d51322c1","id":"05f766c2-d0ff-4233-86bc-fbf6ebd92caa","text":"Ncore","type":"leaf"},{"a_attr":{"onclick":"window.location='core/persistence/index.html';"},"data-nsd-label-uuid":"21d6d971-2965-4be8-a2ab-6f814c0856eb","id":"f82a26d8-f51d-4ba6-a175-05a22658e4a1","text":"Persistence","type":"leaf"},{"a_attr":{"onclick":"window.location='core/resources/index.html';"},"data-nsd-label-uuid":"bd33b15a-a909-4f15-a5c9-b5d8ba4a13f0","id":"3b5e56f3-365a-4010-9ef6-e08ba2cfb2c5","text":"Resources","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"8085527a-8566-4a27-857e-c28f4a3bc134","id":"153b88e8-f85d-4ded-952e-7e8f84a2ff09","text":"Core","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"36750faf-dde2-4f28-9cce-0af504bf19b6","id":"d7b0b89a-e613-49b8-a0e2-23618f227787","text":"(blank)","type":"leaf"},{"data-nsd-label-uuid":"bae11137-6cb2-4b4c-8cd0-a47391adad90","icon":"fas fa-search","id":"50d591df-3888-4dbc-bb9d-459e8fe40ea8","text":"Search","type":"leaf"},{"a_attr":{"onclick":"window.location='glossary.html';"},"data-nsd-label-uuid":"f274797a-5e94-4d41-8a09-7d90b6ca7eb7","id":"b9b947a3-57c7-4455-92be-8bc47d0b5e98","text":"Glossary","type":"leaf"}],"text":"Children"},{"children":[{"a_attr":{"onclick":"window.location='https://github.com/Nasdanika/nasdanika.github.io/';"},"data-nsd-label-uuid":"6bb8be1d-f64c-4285-8828-18fcc8ab3895","icon":"fab fa-github","id":"558891a9-a2d2-4b33-b35c-f9b60f76535a","text":"Source","type":"leaf"}],"text":"Navigation"}],"data-nsd-label-uuid":"9d79030d-7bff-4987-8fc3-48a516f17eb7","icon":"https://docs.nasdanika.org/images/nasdanika-logo.png","id":"31bd2dab-7a4e-4a6c-8ed8-3a2017399d45","text":"Nasdanika","type":"leaf"}]},"search":{"show_only_matches":true},"plugins":["state","search"],"state":{"key":"nsd-site-map-tree"}})); });

      @@ -293,7 +293,7 @@

      diff --git a/docs/semantic-info.json b/docs/semantic-info.json index f7a750505..12aa53c6b 100644 --- a/docs/semantic-info.json +++ b/docs/semantic-info.json @@ -1,6 +1,6 @@ [ { - "identifiers": ["uuid:9de2104d-ea7c-4235-92e3-73e7c3c7791a"], + "identifiers": ["uuid:9d79030d-7bff-4987-8fc3-48a516f17eb7"], "name": "Nasdanika", "icon": "https://docs.nasdanika.org/images/nasdanika-logo.png", "location": "index.html", @@ -12,9 +12,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9de2104d-ea7c-4235-92e3-73e7c3c7791a"] + "identifiers": ["uuid:9d79030d-7bff-4987-8fc3-48a516f17eb7"] }, - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"], + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"], "location": "1.html", "type": { "name": "Action", @@ -24,9 +24,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:3e72fd32-fb9f-40ca-bfd5-f24b71963cf7"], + "identifiers": ["uuid:df0a92ae-d17e-44a7-98bf-62c4da658452"], "name": "Books", "location": "https://leanpub.com/u/pvlasov", "type": { @@ -37,9 +37,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:3e72fd32-fb9f-40ca-bfd5-f24b71963cf7"] + "identifiers": ["uuid:df0a92ae-d17e-44a7-98bf-62c4da658452"] }, - "identifiers": ["uuid:5fdceaf5-457d-496b-a229-0445f4454db3"], + "identifiers": ["uuid:8b9e0220-87a7-439f-9f4a-1e6d612baec2"], "name": "Beyond Diagrams", "location": "https://leanpub.com/beyond-diagrams", "type": { @@ -50,9 +50,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:3e72fd32-fb9f-40ca-bfd5-f24b71963cf7"] + "identifiers": ["uuid:df0a92ae-d17e-44a7-98bf-62c4da658452"] }, - "identifiers": ["uuid:854c7b01-dfdb-4f06-8ce6-293d3649c4fb"], + "identifiers": ["uuid:05ecf0f1-eed1-41b4-9a94-cdf559b6e3c8"], "name": "Java Analysis, Visualization, and Generation", "location": "https://leanpub.com/java-analysis", "type": { @@ -63,9 +63,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:d822cc69-b655-4bcc-8d39-6bec97f0174c"], + "identifiers": ["uuid:69f993a9-5902-4e74-8951-5e8fb4ae982e"], "name": "Practices", "location": "practices/index.html", "type": { @@ -76,9 +76,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:d822cc69-b655-4bcc-8d39-6bec97f0174c"] + "identifiers": ["uuid:69f993a9-5902-4e74-8951-5e8fb4ae982e"] }, - "identifiers": ["uuid:ed32a671-5d55-4bb4-afcc-bf54f077755e"], + "identifiers": ["uuid:174436a1-dc8a-4044-b6ec-6ebfcaba75fa"], "name": "Analysis, Visualization & Generation", "location": "practices/generic/index.html", "type": { @@ -89,9 +89,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:d822cc69-b655-4bcc-8d39-6bec97f0174c"] + "identifiers": ["uuid:69f993a9-5902-4e74-8951-5e8fb4ae982e"] }, - "identifiers": ["uuid:7b830c53-cda8-47ac-8d1d-96767eca4d1c"], + "identifiers": ["uuid:ac323943-8e4f-4522-bac2-a0f90a2f67c9"], "name": "Java Analysis, Visualization & Generation", "location": "practices/java/index.html", "type": { @@ -102,9 +102,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:d822cc69-b655-4bcc-8d39-6bec97f0174c"] + "identifiers": ["uuid:69f993a9-5902-4e74-8951-5e8fb4ae982e"] }, - "identifiers": ["uuid:6e581d7d-b67d-41a3-8952-849d7e8d6891"], + "identifiers": ["uuid:89bfe702-c63f-4161-bc74-baa8f0ce2d77"], "name": "JUnit Tests Generation", "location": "practices/junit/index.html", "type": { @@ -115,9 +115,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:2eb88825-feda-4467-973f-6bb464efa365"], + "identifiers": ["uuid:f87ba156-ad54-41e7-ab43-639e50968de2"], "name": "CLI", "location": "nsd-cli/index.html", "type": { @@ -128,9 +128,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:2eb88825-feda-4467-973f-6bb464efa365"] + "identifiers": ["uuid:f87ba156-ad54-41e7-ab43-639e50968de2"] }, - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"], + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"], "name": "nsd", "location": "nsd-cli/nsd/index.html", "type": { @@ -141,9 +141,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"] + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"] }, - "identifiers": ["uuid:51f89fc1-85d2-463e-84d1-8e48136092b6"], + "identifiers": ["uuid:e06309ac-9d53-4fc4-84d4-6b7ee2d462ba"], "name": "app", "location": "nsd-cli/nsd/app/index.html", "type": { @@ -154,9 +154,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:51f89fc1-85d2-463e-84d1-8e48136092b6"] + "identifiers": ["uuid:e06309ac-9d53-4fc4-84d4-6b7ee2d462ba"] }, - "identifiers": ["uuid:f2c2b41c-643f-4564-a281-3f9b40eb6749"], + "identifiers": ["uuid:7283f6fa-e0f5-48cf-92f4-1d1a156eab2a"], "name": "site", "location": "nsd-cli/nsd/app/site/index.html", "type": { @@ -167,9 +167,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"] + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"] }, - "identifiers": ["uuid:c984ea8a-2239-4bdf-ada8-e477d0cb93b7"], + "identifiers": ["uuid:8f232118-5be2-405c-8ffe-00c8f37676dd"], "name": "help", "location": "nsd-cli/nsd/help/index.html", "type": { @@ -180,9 +180,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:c984ea8a-2239-4bdf-ada8-e477d0cb93b7"] + "identifiers": ["uuid:8f232118-5be2-405c-8ffe-00c8f37676dd"] }, - "identifiers": ["uuid:e39bb31e-d147-406c-a9ac-c45024e0b2fc"], + "identifiers": ["uuid:29ab1c67-0fb7-426b-b234-0e65337e49d6"], "name": "site", "location": "nsd-cli/nsd/help/site/index.html", "type": { @@ -193,9 +193,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"] + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"] }, - "identifiers": ["uuid:5534499b-00a9-4a6d-a9a9-d391231f3346"], + "identifiers": ["uuid:f696eb74-b66f-4875-b85f-55ff7105744a"], "name": "http-server", "location": "nsd-cli/nsd/http-server/index.html", "type": { @@ -206,9 +206,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"] + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"] }, - "identifiers": ["uuid:79ee7499-959a-4129-b8fd-3b483bb62958"], + "identifiers": ["uuid:7e86718c-86ce-42c9-b762-aacb532c510a"], "name": "java", "location": "nsd-cli/nsd/java/index.html", "type": { @@ -219,9 +219,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:79ee7499-959a-4129-b8fd-3b483bb62958"] + "identifiers": ["uuid:7e86718c-86ce-42c9-b762-aacb532c510a"] }, - "identifiers": ["uuid:68cf688c-ea73-4989-a03e-71a82b6c3542"], + "identifiers": ["uuid:1331611e-39b6-41ec-83ad-a5d84bd8749a"], "name": "junit", "location": "nsd-cli/nsd/java/junit/index.html", "type": { @@ -232,9 +232,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:bb10495d-7499-416a-ac4c-50cf04b54e35"] + "identifiers": ["uuid:6606a632-01b6-4a96-987a-082eddb3cf84"] }, - "identifiers": ["uuid:84a3c27f-42e7-4a7b-8071-6693f40427c9"], + "identifiers": ["uuid:416e9c2f-8437-4ac3-bdc1-76545d395bfe"], "name": "launcher", "location": "nsd-cli/nsd/launcher/index.html", "type": { @@ -245,9 +245,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"], + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"], "name": "Models", "location": "https://github.com/Nasdanika-Models", "type": { @@ -258,9 +258,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:9199d88b-bcb4-4107-8ea7-7228527e2268"], + "identifiers": ["uuid:16c706d0-9c0a-48d3-8647-3bd0a310525b"], "name": "Architecture", "location": "https://architecture.models.nasdanika.org", "type": { @@ -271,9 +271,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:f2026899-d296-4ce8-8bb9-98f66a567a90"], + "identifiers": ["uuid:9c390f01-31bd-4390-84e9-abed5a981811"], "name": "Azure", "location": "https://azure.models.nasdanika.org", "type": { @@ -284,9 +284,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:6697320b-53b8-47b6-a3fb-98eb0e91e88f"], + "identifiers": ["uuid:350bf846-9560-454d-abf5-cefae36c1952"], "name": "Bank", "location": "https://bank.models.nasdanika.org", "type": { @@ -297,9 +297,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:04755dea-5cc8-413c-a39e-305c206c149e"], + "identifiers": ["uuid:f40bbc01-e17d-43a1-b07d-068563770a44"], "name": "Capability", "location": "https://capability.models.nasdanika.org", "type": { @@ -310,9 +310,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:347c621e-7faf-4946-9922-6ffa7c41a221"], + "identifiers": ["uuid:7dd91e7d-4e16-42c7-ab2f-facee8783226"], "name": "Coverage", "location": "https://coverage.models.nasdanika.org", "type": { @@ -323,9 +323,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:14db8138-9b21-4394-91c6-db8b1e2d0557"], + "identifiers": ["uuid:7792946b-9a0d-4cb4-9728-8d658fbe5f2c"], "name": "Decision Analysis", "location": "https://mcda.models.nasdanika.org", "type": { @@ -336,9 +336,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:6ff6c339-6989-41eb-a102-3aedbbe0afc0"], + "identifiers": ["uuid:93206766-d135-4fe4-9b70-45bc333b276e"], "name": "ECharts", "location": "https://echarts.models.nasdanika.org/graph", "type": { @@ -349,9 +349,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:c6f732a3-30de-46c2-ad0f-24c7d489b266"], + "identifiers": ["uuid:2cdfbf75-8dc4-43bc-81bc-725cf9580d9b"], "name": "Ecore", "location": "https://ecore.models.nasdanika.org", "type": { @@ -362,9 +362,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:8cbb020f-7f8f-4138-aecc-88f764235e56"], + "identifiers": ["uuid:da1d650b-6958-456d-8796-37e076d01584"], "name": "Enterprise", "location": "https://enterprise.models.nasdanika.org", "type": { @@ -375,9 +375,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:d71c0aa8-95ae-49a2-a265-c2293c0682b4"], + "identifiers": ["uuid:90cf7cc1-979e-422b-a4bf-f6b1f15d723d"], "name": "Excel", "location": "https://excel.models.nasdanika.org", "type": { @@ -388,9 +388,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:090e1f71-445a-4f22-b3d2-b8225297d5e0"], + "identifiers": ["uuid:8b8758a9-c075-4b74-9600-f254c02db7ee"], "name": "Family", "location": "https://family.models.nasdanika.org", "type": { @@ -401,9 +401,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:ef964150-8a69-411e-ac32-7ece4e617868"], + "identifiers": ["uuid:84ccfd12-dcb0-4219-8121-086208fb24b3"], "name": "Flow", "location": "https://flow.models.nasdanika.org", "type": { @@ -414,9 +414,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:14825f9f-e958-4360-9230-57b9e33c6f3a"], + "identifiers": ["uuid:5eae6134-862e-4de8-a941-38e8cbfa0903"], "name": "Function Flow", "location": "https://function-flow.models.nasdanika.org", "type": { @@ -427,9 +427,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:19b74cf0-ec6b-496a-9c8d-08d847e737a4"], + "identifiers": ["uuid:0899754d-506d-4e26-863e-fb9406157009"], "name": "Git", "location": "https://git.models.nasdanika.org", "type": { @@ -440,9 +440,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:a5e28166-6a98-475f-95df-9d11386b2a0d"], + "identifiers": ["uuid:7b6f2780-57fe-4e86-9e06-0cc7f8ca51e4"], "name": "GitLab", "location": "https://gitlab.models.nasdanika.org", "type": { @@ -453,9 +453,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:6eb78462-576a-4607-b60a-c9897431d9a2"], + "identifiers": ["uuid:45b1e91e-9966-43b6-a372-514ff4d75522"], "name": "Java", "location": "https://java.models.nasdanika.org", "type": { @@ -466,9 +466,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:f52c5bb9-5cc4-4f21-9357-78ae07e56bcc"], + "identifiers": ["uuid:a593098a-d816-489b-b9e0-91857251a163"], "name": "Jira", "location": "https://jira.models.nasdanika.org", "type": { @@ -479,9 +479,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:110fa7dd-d50f-4c17-b4d8-73ab6de2d82b"], + "identifiers": ["uuid:0c64bf2d-124c-46a2-ab93-55b224454213"], "name": "Maven", "location": "https://maven.models.nasdanika.org", "type": { @@ -492,9 +492,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:de8001f8-c66c-443c-af68-3ca3331a021a"], + "identifiers": ["uuid:1eae965b-e3ca-483f-9af1-c1ae31d06ecd"], "name": "Nature", "location": "https://nature.models.nasdanika.org", "type": { @@ -505,9 +505,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:87f95392-12dc-4872-94cd-c9e8e7d14366"], + "identifiers": ["uuid:66bfb51e-2df5-48db-8d40-b5ada3fefbbc"], "name": "PDF", "location": "https://pdf.models.nasdanika.org", "type": { @@ -518,9 +518,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:4f480c22-5ac9-4980-8069-dc3989515271"], + "identifiers": ["uuid:e7b8eb8b-7531-4feb-9c23-4f7a1789f587"], "name": "Party", "location": "https://party.models.nasdanika.org", "type": { @@ -531,9 +531,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:8d40977c-7a02-4d11-9863-60d329ba2970"], + "identifiers": ["uuid:5de44bcf-986f-4f37-840d-db65ea5df506"], "name": "Rules", "location": "https://rules.models.nasdanika.org", "type": { @@ -544,9 +544,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:199226bd-9d7d-4933-8271-e2f1ff9a1354"] + "identifiers": ["uuid:10bda318-aa5f-455a-8ef2-ef0bf148326c"] }, - "identifiers": ["uuid:58802dcd-dea3-4432-8a94-f76db90d8899"], + "identifiers": ["uuid:e7837198-2d19-4b14-8876-92150bcac0e8"], "name": "Source Engineering", "location": "https://source-engineering.models.nasdanika.org", "type": { @@ -557,9 +557,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"], + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"], "name": "HTML", "location": "html/index.html", "type": { @@ -570,9 +570,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"] + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"] }, - "identifiers": ["uuid:500a6e14-d052-458d-9506-0f77a9d88e1f"], + "identifiers": ["uuid:655794d1-974a-4f97-ace9-41918841fb14"], "name": "Bootstrap", "location": "html/bootstrap/index.html", "type": { @@ -583,9 +583,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"] + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"] }, - "identifiers": ["uuid:a2e21827-bb81-4a33-890e-48b25102cdab"], + "identifiers": ["uuid:6be1b864-2152-46f7-b5d0-a7b6ae90570d"], "name": "EMF", "location": "html/emf/index.html", "type": { @@ -596,9 +596,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"] + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"] }, - "identifiers": ["uuid:47e67773-ac8f-476a-8401-349e50425b54"], + "identifiers": ["uuid:4a31e215-827a-4c18-b82f-1c952ee5f6a7"], "name": "HTML", "location": "html/html/index.html", "type": { @@ -609,9 +609,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"] + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"] }, - "identifiers": ["uuid:b043dc0e-aa2f-458b-991a-ecbd671dfe5d"], + "identifiers": ["uuid:68577bf6-51f9-44d2-9bba-380611b670e7"], "name": "JsTree", "location": "html/jstree/index.html", "type": { @@ -622,9 +622,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5a980479-45aa-435e-9dbc-0ec9573ce36e"] + "identifiers": ["uuid:0f4e3df1-a272-4c9e-aa6a-6b541feeca02"] }, - "identifiers": ["uuid:9f945679-7d48-49e2-8901-6eacc23861ce"], + "identifiers": ["uuid:83939a39-8301-4ee1-9a1c-864c131dec21"], "name": "Models", "location": "html/models/index.html", "type": { @@ -635,9 +635,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9f945679-7d48-49e2-8901-6eacc23861ce"] + "identifiers": ["uuid:83939a39-8301-4ee1-9a1c-864c131dec21"] }, - "identifiers": ["uuid:1b65d9e6-a32e-4419-a5f4-e39e33360514"], + "identifiers": ["uuid:34c0967b-54a5-420e-b53f-85a4f6200eae"], "name": "App", "location": "html/models/app/index.html", "type": { @@ -648,9 +648,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9f945679-7d48-49e2-8901-6eacc23861ce"] + "identifiers": ["uuid:83939a39-8301-4ee1-9a1c-864c131dec21"] }, - "identifiers": ["uuid:4ceffae9-06cb-4972-bec1-1510a1bbeef7"], + "identifiers": ["uuid:c57f41cb-6a7b-4457-83c2-9a45488ec856"], "name": "Bootstrap", "location": "html/models/bootstrap/index.html", "type": { @@ -661,9 +661,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9f945679-7d48-49e2-8901-6eacc23861ce"] + "identifiers": ["uuid:83939a39-8301-4ee1-9a1c-864c131dec21"] }, - "identifiers": ["uuid:e43c6d12-c25a-4fa6-b32a-bab434f90eae"], + "identifiers": ["uuid:1ec28871-104c-4f5b-837a-b64ac672a65f"], "name": "HTML", "location": "html/models/html/index.html", "type": { @@ -674,9 +674,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:630c32ae-6995-4f18-9ca5-1d22904894b8"] + "identifiers": ["uuid:36750faf-dde2-4f28-9cce-0af504bf19b6"] }, - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"], + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"], "name": "Core", "location": "core/index.html", "type": { @@ -687,9 +687,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:8038c08a-1a30-4d2c-af4f-19f7ef48d8f3"], + "identifiers": ["uuid:640290cf-75cf-451c-991b-eadbba515710"], "name": "CLI", "location": "core/cli/index.html", "type": { @@ -700,9 +700,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:d3194f83-c4ab-4a70-9a6d-d94d6f09b471"], + "identifiers": ["uuid:61726c59-c9d6-40fe-b28d-cfad4164b5d2"], "name": "Capability", "location": "core/capability/index.html", "type": { @@ -713,9 +713,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:8f5d1746-2345-415d-88dd-461c8e37c986"], + "identifiers": ["uuid:3476167d-02c7-4261-904f-cc0f01314e7e"], "name": "Common", "location": "core/common/index.html", "type": { @@ -726,9 +726,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:fe77df84-09b1-4df0-b656-6b32f0c3e82e"], + "identifiers": ["uuid:836f371e-2ed3-42c2-ad4b-778b8cc662ef"], "name": "Diagram", "location": "core/diagram/index.html", "type": { @@ -739,9 +739,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:dd312f3f-a04d-4bdc-8538-f3d67819a623"], + "identifiers": ["uuid:191c1736-4edb-4e34-8bf5-cd2547b4debd"], "name": "Drawio", "location": "core/drawio/index.html", "type": { @@ -752,9 +752,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:79f046f2-43ff-4087-9782-7ee95c90db77"], + "identifiers": ["uuid:aeb2e45d-d4b9-49fb-9313-ea2f5e076da8"], "name": "EMF", "location": "core/emf/index.html", "type": { @@ -765,9 +765,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:0f72ed88-ec5c-4bc8-a82f-33d908b46a91"], + "identifiers": ["uuid:270ee777-dd05-4b92-8685-b15da705d59c"], "name": "Exec", "location": "core/exec/index.html", "type": { @@ -778,9 +778,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:64e4ffc9-7d3c-4833-9b7b-b1904686429f"], + "identifiers": ["uuid:c1c31db5-6d35-44ba-94cb-3a5eb60ee2b9"], "name": "Graph", "location": "core/graph/index.html", "type": { @@ -791,9 +791,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:c5776345-0155-4f92-a777-6f562f982610"], + "identifiers": ["uuid:d7a93f4c-ff1c-4d5f-8dc0-115cb6312360"], "name": "Maven", "location": "core/maven/index.html", "type": { @@ -804,22 +804,22 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:ca684430-dbdc-40bf-9928-cbb478692560"], + "identifiers": ["uuid:7a679172-703f-4a68-b7fb-2a22d51322c1"], "name": "Ncore", - "location": "core/ncore/index.html", + "location": "https://ncore.models.nasdanika.org/", "type": { - "name": "Action", + "name": "Link", "ns-uri": "ecore://nasdanika.org/html/app" } }, { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:6b90548e-a6fd-4f8b-9e2b-c8dfdf356bf6"], + "identifiers": ["uuid:21d6d971-2965-4be8-a2ab-6f814c0856eb"], "name": "Persistence", "location": "core/persistence/index.html", "type": { @@ -830,9 +830,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:e32b6747-9fb6-4f12-aa15-f372a403fd55"] + "identifiers": ["uuid:8085527a-8566-4a27-857e-c28f4a3bc134"] }, - "identifiers": ["uuid:02ea724b-103f-4385-a6ee-d32e0daf31b1"], + "identifiers": ["uuid:bd33b15a-a909-4f15-a5c9-b5d8ba4a13f0"], "name": "Resources", "location": "core/resources/index.html", "type": { @@ -843,9 +843,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9de2104d-ea7c-4235-92e3-73e7c3c7791a"] + "identifiers": ["uuid:9d79030d-7bff-4987-8fc3-48a516f17eb7"] }, - "identifiers": ["uuid:acd95d60-199f-4718-b01e-34612b8c3176"], + "identifiers": ["uuid:bae11137-6cb2-4b4c-8cd0-a47391adad90"], "name": "Search", "icon": "fas fa-search", "location": "search.html", @@ -857,9 +857,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:9de2104d-ea7c-4235-92e3-73e7c3c7791a"] + "identifiers": ["uuid:9d79030d-7bff-4987-8fc3-48a516f17eb7"] }, - "identifiers": ["uuid:ea0c93e2-9290-4c9a-aa1b-5bad7f25b0f6"], + "identifiers": ["uuid:f274797a-5e94-4d41-8a09-7d90b6ca7eb7"], "name": "Glossary", "location": "glossary.html", "type": { @@ -870,9 +870,9 @@ { "container": { "reference": "navigation", - "identifiers": ["uuid:9de2104d-ea7c-4235-92e3-73e7c3c7791a"] + "identifiers": ["uuid:9d79030d-7bff-4987-8fc3-48a516f17eb7"] }, - "identifiers": ["uuid:b0b73871-0d85-442c-b2ef-567b743eb9d4"], + "identifiers": ["uuid:6bb8be1d-f64c-4285-8828-18fcc8ab3895"], "name": "Source", "icon": "fab fa-github", "location": "https://github.com/Nasdanika/nasdanika.github.io/", diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 661a8b59e..410522e42 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,202 +2,197 @@ https://docs.nasdanika.org/1.html - 2024-05-05T22:18:46.180-04:00 + 2024-05-12T05:03:05.094-04:00 weekly https://docs.nasdanika.org/core/capability/index.html - 2024-05-05T22:18:46.282-04:00 + 2024-05-12T05:03:05.196-04:00 weekly https://docs.nasdanika.org/core/cli/index.html - 2024-05-05T22:18:46.279-04:00 + 2024-05-12T05:03:05.193-04:00 weekly https://docs.nasdanika.org/core/common/index.html - 2024-05-05T22:18:46.284-04:00 + 2024-05-12T05:03:05.200-04:00 weekly https://docs.nasdanika.org/core/diagram/index.html - 2024-05-05T22:18:46.287-04:00 + 2024-05-12T05:03:05.203-04:00 weekly https://docs.nasdanika.org/core/drawio/index.html - 2024-05-05T22:18:46.292-04:00 + 2024-05-12T05:03:05.207-04:00 weekly https://docs.nasdanika.org/core/emf/index.html - 2024-05-05T22:18:46.295-04:00 + 2024-05-12T05:03:05.209-04:00 weekly https://docs.nasdanika.org/core/exec/index.html - 2024-05-05T22:18:46.298-04:00 + 2024-05-12T05:03:05.211-04:00 weekly https://docs.nasdanika.org/core/graph/index.html - 2024-05-05T22:18:46.302-04:00 + 2024-05-12T05:03:05.214-04:00 weekly https://docs.nasdanika.org/core/index.html - 2024-05-05T22:18:46.276-04:00 + 2024-05-12T05:03:05.189-04:00 weekly https://docs.nasdanika.org/core/maven/index.html - 2024-05-05T22:18:46.305-04:00 - weekly - - - https://docs.nasdanika.org/core/ncore/index.html - 2024-05-05T22:18:46.308-04:00 + 2024-05-12T05:03:05.220-04:00 weekly https://docs.nasdanika.org/core/persistence/index.html - 2024-05-05T22:18:46.310-04:00 + 2024-05-12T05:03:05.224-04:00 weekly https://docs.nasdanika.org/core/resources/index.html - 2024-05-05T22:18:46.313-04:00 + 2024-05-12T05:03:05.227-04:00 weekly https://docs.nasdanika.org/glossary.html - 2024-05-05T22:18:46.319-04:00 + 2024-05-12T05:03:05.236-04:00 weekly https://docs.nasdanika.org/html/bootstrap/index.html - 2024-05-05T22:18:46.257-04:00 + 2024-05-12T05:03:05.162-04:00 weekly https://docs.nasdanika.org/html/emf/index.html - 2024-05-05T22:18:46.260-04:00 + 2024-05-12T05:03:05.166-04:00 weekly https://docs.nasdanika.org/html/html/index.html - 2024-05-05T22:18:46.263-04:00 + 2024-05-12T05:03:05.170-04:00 weekly https://docs.nasdanika.org/html/index.html - 2024-05-05T22:18:46.253-04:00 + 2024-05-12T05:03:05.159-04:00 weekly https://docs.nasdanika.org/html/jstree/index.html - 2024-05-05T22:18:46.265-04:00 + 2024-05-12T05:03:05.174-04:00 weekly https://docs.nasdanika.org/html/models/app/index.html - 2024-05-05T22:18:46.269-04:00 + 2024-05-12T05:03:05.181-04:00 weekly https://docs.nasdanika.org/html/models/bootstrap/index.html - 2024-05-05T22:18:46.271-04:00 + 2024-05-12T05:03:05.183-04:00 weekly https://docs.nasdanika.org/html/models/html/index.html - 2024-05-05T22:18:46.274-04:00 + 2024-05-12T05:03:05.185-04:00 weekly https://docs.nasdanika.org/html/models/index.html - 2024-05-05T22:18:46.267-04:00 + 2024-05-12T05:03:05.177-04:00 weekly https://docs.nasdanika.org/index.html - 2024-05-05T22:18:46.177-04:00 + 2024-05-12T05:03:05.090-04:00 weekly https://docs.nasdanika.org/nsd-cli/index.html - 2024-05-05T22:18:46.210-04:00 + 2024-05-12T05:03:05.122-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/app/index.html - 2024-05-05T22:18:46.215-04:00 + 2024-05-12T05:03:05.129-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/app/site/index.html - 2024-05-05T22:18:46.219-04:00 + 2024-05-12T05:03:05.134-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/help/index.html - 2024-05-05T22:18:46.222-04:00 + 2024-05-12T05:03:05.138-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/help/site/index.html - 2024-05-05T22:18:46.232-04:00 + 2024-05-12T05:03:05.141-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/http-server/index.html - 2024-05-05T22:18:46.238-04:00 + 2024-05-12T05:03:05.145-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/index.html - 2024-05-05T22:18:46.212-04:00 + 2024-05-12T05:03:05.125-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/java/index.html - 2024-05-05T22:18:46.242-04:00 + 2024-05-12T05:03:05.148-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/java/junit/index.html - 2024-05-05T22:18:46.246-04:00 + 2024-05-12T05:03:05.151-04:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/launcher/index.html - 2024-05-05T22:18:46.250-04:00 + 2024-05-12T05:03:05.154-04:00 weekly https://docs.nasdanika.org/practices/generic/index.html - 2024-05-05T22:18:46.187-04:00 + 2024-05-12T05:03:05.101-04:00 weekly https://docs.nasdanika.org/practices/index.html - 2024-05-05T22:18:46.183-04:00 + 2024-05-12T05:03:05.098-04:00 weekly https://docs.nasdanika.org/practices/java/index.html - 2024-05-05T22:18:46.190-04:00 + 2024-05-12T05:03:05.104-04:00 weekly https://docs.nasdanika.org/practices/junit/index.html - 2024-05-05T22:18:46.205-04:00 + 2024-05-12T05:03:05.117-04:00 weekly https://docs.nasdanika.org/search.html - 2024-05-05T22:18:46.316-04:00 + 2024-05-12T05:03:05.233-04:00 weekly \ No newline at end of file diff --git a/model/cli/cli.xmi b/model/cli/cli.xmi index 5b296b368..898fc9473 100644 --- a/model/cli/cli.xmi +++ b/model/cli/cli.xmi @@ -1,28 +1,28 @@ - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + diff --git a/model/cli/readme.md b/model/cli/readme.md index 5b7dd72cb..c2d32269e 100644 --- a/model/cli/readme.md +++ b/model/cli/readme.md @@ -1 +1,43 @@ -Nasdanika Command Line Interface (CLI) is a collection of Nasdanika offerings packaged as command line tools. \ No newline at end of file +Nasdanika Command Line Interface (CLI) is a suite of Nasdanika capabilities packaged as command line tools. + +## Prerequisites + +To run Nasdanika CLI you'd need Java 17+. +To build from sources you'd also need Maven. + +## Installation + +Download installation archive from the [releases](https://github.com/Nasdanika/cli/releases) page. +On Linux make ``nsd`` executable: ``chmod a+x nsd``. + +## Building from sources + +* Download [sources](https://github.com/Nasdanika/cli) as a zip file or clone the repository +* Run ``mvn clean verify`` +* After the build completes the distribuion will be available in ``target/dist`` directory + +## Adding to PATH + +The distribution is portable and local - it can be put to any directory, but it can only be executed from that directory. +To create an installation which can be used from any directory you will need to create launcher files with absolute paths. + +### Windows + +``` +nsd.bat launcher -f options-global -o nsd-global.bat -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules -j "@java" +``` + +Add the installation to the ``PATH`` environment variable. +You may delete/rename ``nsd.bat`` and rename ``nsd-global.bat`` to ``nsd.bat``. + +### Linux + +``` +./nsd launcher -o nsd-global -s -m org.nasdanika.launcher -c org.nasdanika.launcher.Launcher -M modules +``` + +Open ``nsd-global`` in a text editor and add ``#!/bin/bash`` line before the java command line. +Make the file executable and add the installation directory to the path. +You may remove/rename ``nsd`` and rename ``nsd-global`` to ``nsd``. + +If you get ``java.lang.module.FindException: Module not found`` error, open the file in a text editor, locate the problematic module and remove it from the ``--add-modules`` list. \ No newline at end of file diff --git a/model/core/capability/readme.md b/model/core/capability/readme.md index 6a29649e6..d191c2a23 100644 --- a/model/core/capability/readme.md +++ b/model/core/capability/readme.md @@ -1,4 +1,4 @@ -Nasdanika Capability framework allows to discover/load capabilities which meet a requirement. +Nasdanika Capability framework[^javadoc] allows to discover/load capabilities which meet a requirement. Capabilities are provided by [CapabilityFactory](https://javadoc.io/doc/org.nasdanika.core/capability/latest/org.nasdanika.capability/org/nasdanika/capability/CapabilityFactory.html) ``create()`` method. Capability factories may request other capabilities they need. As such, capabilities can be chained. @@ -7,6 +7,8 @@ It allows to have an infinite stream of capabilities which are consumed (and pro Capability providers may furnish additional information about capabilities. This information can be used for filtering or sorting providers. +[^javadoc]: [Javadoc](https://javadoc.io/doc/org.nasdanika.core/capability/latest/org.nasdanika.capability/org/nasdanika/capability/package-summary.html) + A non-technical example of requirement/capability chain graph is a food chain/graph. Food is a requirement. Or "I want to eat" is a requirement. Bread and, say fried eggs are two capabilities meeting/addressing the requirement. diff --git a/model/core/cli/readme.md b/model/core/cli/readme.md index 10b5f8b15..f84100101 100644 --- a/model/core/cli/readme.md +++ b/model/core/cli/readme.md @@ -1,23 +1,99 @@ Classes in this module allow to declaratively construct command line interfaces. It uses [picocli](https://picocli.info/) to execute commands and [capability framework](../capability/index.html) to collect sub-commands and mix-ins. This way command line interfaces can be constructed top-down (default picocli functionality) - parent commands explicitly define sub-commands, and bottom-up - sub-commands are added to parent commands by the framework. +Top-down construction can be done using out-the-box picocli capabilities - programmatic add and annotations. +Both top-down and bottom-up construction can be done using the [capability](../capability/index.html) framework which allows sub-commands/mix-ins to request capabilities they need +and add themselves to parent commands only if all requirements are met. + +The module provides a capability to build polymorphic CLI's - sub-commands and mix-ins may override other sub-commands and mix-ins with the same name. +This is similar to method overriding in Object-Oriented languages like Java. +For example, a base CLI package may have a basic implementation of some sub-command. +A derived package would add dependencies with advanced sub-commands to ``pom.xml``. +These sub-commands would replace (override) basic sub-commands during construction of the command hierarchy. + +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/cli/latest/org.nasdanika.cli/org/nasdanika/cli/package-summary.html) ## Contributing sub-commands -Create a sub-class of ``SubCommandCapabilityFactory`` and override either ``createCommand`` or ``createCommands`` methods. +In addition to the picocli way of adding sub-commands programmatically and using ``@Command`` annotation ``subcommands`` element this module provides a few more ways to contribute sub-commands which are explained below. + +In all cases create a sub-class of ``SubCommandCapabilityFactory`` and implement/override the following methods: + +* ``getCommandType`` - used for declarative matching +* ``createCommand`` for imperative (programmatic) matching +* ``doCreateCommand``: + * Declarative - in combination with ``@SubCommands`` or ``@Parent`` + * Imperative - override ``match()`` as well. + Add to ``module-info.java``: * ``provides org.nasdanika.capability.CapabilityFactory with `` -* ``opens to info.picocli;`` +* ``opens to info.picocli, org.nasdanika.html.model.app.gen.cli;`` + +Opening to ``org.nasdanika.html.model.app.gen.cli`` is needed if you want to generate extended documentation (see below). + +### @SubCommands annotation + +This one is similar to ``@Command.subcommands`` - the parent command declares types of sub-commands. +However: + +* Sub-commands are collected using the capability framework from ``SubCommandCapabilityFactory``'s. +* Sub-commands types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types. E.g. you may have ``HelpCommand`` interface or base class and all commands implementing/extending this class will be added to the parent command. If there are two commands with the same name one of them might override the other as explained below. + +### @Parent annotation + +In this case the sub-command or mix-in class are annotated with ``@Parent`` annotation listing types of parents. +The sub-command/mix-in will be added to all commands in the hierarchy which are instances of the specified parent types - exact class, interface implementation, or sub-class. + +### Programmatic match + +The above two ways of matching parent commands and sub-commands are handled by the ``SubCommandCapabilityFactory.match()`` method. +You may override this method or ``createCommand()`` method to programmatically match parent path and decide whether to contribute a sub-command or not. ## Contributing mix-ins -Create s sub-class of ``MixInCapabilityFactory``, implement ``getName()`` and ``createMixIn()`` methods. +Similar to sub-commands, mix-ins can be contributed top-down and bottom-up - declaratively using annotations and programmatically. + +In all cased create s sub-class of ``MixInCapabilityFactory``, implement/override: + +* ``getMixInType()`` - for declarative matching +* ``getName()`` +* ``createMixIn()`` for imperative matching, or +* ``doCreateMixIn()`` + * Declarative - in combination with ``@MixIns`` or ``@Parent`` + * Imperative - override ``match()`` as well. + Add to ``module-info.java``: * ``provides org.nasdanika.capability.CapabilityFactory with `` * ``opens to info.picocli;`` +### @MixIns annotation + +* Mix-ins are collected using the capability framework from ``MixInCapabilityFactory``'s. +* Mix-in types listed in the annotation are base types - classes or interfaces - not necessarily concrete implementation types. + +### @Parent annotation + +See "@Parent annotation" sub-section in "Contributing sub-commands" section above. + +### Programmatic match + +The above two ways of matching parent commands and sub-commands/mix-ins are handled by the ``MixInCapabilityFactory.match()`` method. +You may override this method or ``createMixIn()`` method to programmatically match parent path and decide whether to contribute a mix-in or not. + +## Overriding + +A command/mix-in overrides another command/mix-in if: + +* It is a sub-class of that command/mix-in +* It implements ``Overrider`` interface and returns ``true`` from ``overrides(Object other)`` method. +* It is annotated with ``@Overrides`` and the other command is an instance of one of the value classes. + +## Extended documentation + +You may annotate commands with [``@Description``](https://javadoc.io/doc/org.nasdanika.core/cli/latest/org.nasdanika.cli/org/nasdanika/cli/Description.html) to provide additional information in generated HTML site. + ## Building distributions A distribution is a collection of modules contributing commands and mix-ins plus launcher scripts for different operating systems. @@ -95,13 +171,26 @@ public class BuildDistributionIT { } } + ModuleLayer layer = Application.class.getModule().getLayer(); + try (Writer writer = new FileWriter(new File("target/dist/modules"))) { + for (String name: layer.modules().stream().map(Module::getName).sorted().toList()) { + writer.write(name); + writer.write(System.lineSeparator()); + }; + } + CommandLine launcherCommandLine = new CommandLine(new LauncherCommand()); launcherCommandLine.execute( "-b", "target/dist", + "-M", "target/dist/modules", + "-f", "options", + "-j", "@java", "-o", "nsd.bat"); launcherCommandLine.execute( "-b", "target/dist", + "-M", "target/dist/modules", + "-j", "#!/bin/bash\n\njava", "-o", "nsd", "-p", ":", "-a", "$@"); @@ -113,14 +202,3 @@ public class BuildDistributionIT { If the Maven project which builds the distribution does not contribute its own code, then the ``for`` loop copying the jar file can be omitted. -To generate a command line which can be used from any directory use ``-s`` (absolute) option or ``-P`` (prefix) option set to the installation directory. - -If you encounter command line length limit (8191 characters on Windows), move command options (``-p``, ``-classpath``, ``-m``) to a file -or use ``-t`` option to generate just options. -Then use ``@`` syntax. -For example: - -``` -@java @\options %* -``` - diff --git a/model/core/common/readme.md b/model/core/common/readme.md index 30404ce4c..30c5bf0d8 100644 --- a/model/core/common/readme.md +++ b/model/core/common/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/common/latest/org.nasdanika.common/module-summary.html) \ No newline at end of file diff --git a/model/core/diagram/readme.md b/model/core/diagram/readme.md index 30404ce4c..120af262c 100644 --- a/model/core/diagram/readme.md +++ b/model/core/diagram/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/diagram/latest/org.nasdanika.diagram/module-summary.html) \ No newline at end of file diff --git a/model/core/drawio/.$classes.drawio.bkp b/model/core/drawio/.$classes.drawio.bkp deleted file mode 100644 index 61d3a5549..000000000 --- a/model/core/drawio/.$classes.drawio.bkp +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/model/core/emf/readme.md b/model/core/emf/readme.md index 30404ce4c..445e6efb4 100644 --- a/model/core/emf/readme.md +++ b/model/core/emf/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/emf/latest/org.nasdanika.emf/module-summary.html) \ No newline at end of file diff --git a/model/core/exec/readme.md b/model/core/exec/readme.md index 30404ce4c..029e186b9 100644 --- a/model/core/exec/readme.md +++ b/model/core/exec/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/exec/latest/org.nasdanika.exec/module-summary.html) \ No newline at end of file diff --git a/model/core/graph/readme.md b/model/core/graph/readme.md index 30404ce4c..df40ea549 100644 --- a/model/core/graph/readme.md +++ b/model/core/graph/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/graph/latest/org.nasdanika.graph/module-summary.html) \ No newline at end of file diff --git a/model/core/maven/readme.md b/model/core/maven/readme.md index 30404ce4c..e3b38f4ee 100644 --- a/model/core/maven/readme.md +++ b/model/core/maven/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/maven/latest/org.nasdanika.maven/module-summary.html) \ No newline at end of file diff --git a/model/core/ncore/readme.md b/model/core/ncore/readme.md deleted file mode 100644 index 30404ce4c..000000000 --- a/model/core/ncore/readme.md +++ /dev/null @@ -1 +0,0 @@ -TODO \ No newline at end of file diff --git a/model/core/persistence/readme.md b/model/core/persistence/readme.md index 30404ce4c..df17ded24 100644 --- a/model/core/persistence/readme.md +++ b/model/core/persistence/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/persistence/latest/org.nasdanika.persistence/module-summary.html) \ No newline at end of file diff --git a/model/core/resources/readme.md b/model/core/resources/readme.md index 30404ce4c..b50a3eae4 100644 --- a/model/core/resources/readme.md +++ b/model/core/resources/readme.md @@ -1 +1 @@ -TODO \ No newline at end of file +[Javadoc](https://javadoc.io/doc/org.nasdanika.core/resources/latest/org.nasdanika.resources/module-summary.html) \ No newline at end of file diff --git a/model/nasdanika.drawio b/model/nasdanika.drawio index 3e6c8f885..90f9a65e6 100644 --- a/model/nasdanika.drawio +++ b/model/nasdanika.drawio @@ -1,4 +1,4 @@ - + @@ -28,7 +28,7 @@ - + @@ -68,7 +68,7 @@ - + @@ -330,11 +330,11 @@ - + - + diff --git a/model/practices/junit/readme.md b/model/practices/junit/readme.md index b98083f6b..9e1f0b32f 100644 --- a/model/practices/junit/readme.md +++ b/model/practices/junit/readme.md @@ -43,6 +43,9 @@ The sections after the reference implementations section provide an overview of [TOC levels=6] +## Command line + +[Nasdanika CLI](https://docs.nasdanika.org/nsd-cli/index.html) features [JUnit](https://docs.nasdanika.org/nsd-cli/nsd/java/junit/index.html) command which generates JUnit tests as explained above. ## Reference Implementations diff --git a/pom.xml b/pom.xml index 6c26ea100..310186f5d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,20 +3,20 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.nasdanika - 2024.4.0 + 2024.5.0 docs jar Nasdanika Documentation Site - 2024.4.0 + 2024.5.0 org.nasdanika.html app-model-gen - 2024.4.0 + ${html.version} org.junit.jupiter