From dfb87e950372c928dfa167f933e8d886373aef74 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Mon, 30 Dec 2024 19:48:38 -0500 Subject: [PATCH] Link fix --- docs/core/capability/index.html | 38 +-- docs/core/cli/index.html | 38 +-- docs/core/common/index.html | 38 +-- docs/core/diagram/index.html | 38 +-- docs/core/drawio/index.html | 38 +-- docs/core/emf/index.html | 38 +-- docs/core/exec/index.html | 38 +-- docs/core/graph/index.html | 38 +-- docs/core/http/index.html | 38 +-- docs/core/index.html | 34 +-- docs/core/mapping/index.html | 38 +-- docs/core/maven/index.html | 38 +-- docs/core/persistence/index.html | 38 +-- docs/core/resources/index.html | 38 +-- docs/demos/module-graph-full.html | 36 +++ docs/demos/module-graph.html | 36 +++ docs/glossary.html | 36 +-- docs/html/bootstrap/index.html | 38 +-- docs/html/html/index.html | 38 +-- docs/html/index.html | 34 +-- docs/html/jstree/index.html | 38 +-- docs/index.html | 34 +-- docs/nsd-cli/index.html | 34 +-- docs/nsd-cli/nsd/app/index.html | 32 +-- docs/nsd-cli/nsd/app/site/index.html | 32 +-- docs/nsd-cli/nsd/drawio/html-app/index.html | 32 +-- .../nsd/drawio/html-app/save/index.html | 32 +-- .../nsd/drawio/html-app/site/index.html | 32 +-- docs/nsd-cli/nsd/drawio/index.html | 32 +-- .../nsd/gitlab/contribute/gsh/index.html | 32 +-- docs/nsd-cli/nsd/gitlab/contribute/index.html | 32 +-- .../nsd/gitlab/contribute/invoke/index.html | 32 +-- .../nsd/gitlab/contribute/junit/index.html | 32 +-- .../gitlab/contribute/junit/jacoco/index.html | 32 +-- .../contribute/retrospect/gsh/index.html | 32 +-- .../gitlab/contribute/retrospect/index.html | 32 +-- .../contribute/retrospect/invoke/index.html | 32 +-- docs/nsd-cli/nsd/gitlab/gsh/index.html | 32 +-- docs/nsd-cli/nsd/gitlab/index.html | 32 +-- docs/nsd-cli/nsd/gitlab/invoke/index.html | 32 +-- docs/nsd-cli/nsd/gsh/index.html | 32 +-- docs/nsd-cli/nsd/help/index.html | 32 +-- docs/nsd-cli/nsd/help/site/index.html | 32 +-- docs/nsd-cli/nsd/http-server/index.html | 32 +-- docs/nsd-cli/nsd/index.html | 32 +-- docs/nsd-cli/nsd/invoke/index.html | 32 +-- docs/nsd-cli/nsd/java/index.html | 32 +-- docs/nsd-cli/nsd/java/junit/index.html | 32 +-- docs/nsd-cli/nsd/java/junit/jacoco/index.html | 32 +-- docs/nsd-cli/nsd/launcher/index.html | 32 +-- .../nsd/model/ecore-html-app/index.html | 32 +-- .../nsd/model/ecore-html-app/save/index.html | 32 +-- .../nsd/model/ecore-html-app/site/index.html | 32 +-- docs/nsd-cli/nsd/model/html-app/index.html | 32 +-- .../nsd/model/html-app/save/index.html | 32 +-- .../nsd/model/html-app/site/index.html | 32 +-- docs/nsd-cli/nsd/model/index.html | 32 +-- docs/nsd-cli/nsd/model/save/index.html | 32 +-- .../nsd-cli/nsd/rules/action-model/index.html | 32 +-- docs/nsd-cli/nsd/rules/index.html | 32 +-- docs/nsd-cli/nsd/rules/list/index.html | 32 +-- docs/nsd-cli/nsd/rules/site/index.html | 32 +-- docs/nsd-cli/nsd/shell/index.html | 32 +-- docs/practices/generic/index.html | 38 +-- docs/practices/index.html | 34 +-- docs/practices/java/index.html | 38 +-- docs/practices/junit/index.html | 38 +-- docs/search-documents.js | 2 +- docs/search.html | 36 +-- docs/semantic-info.json | 238 +++++++++--------- docs/sitemap.xml | 136 +++++----- model/nasdanika.drawio | 2 +- 72 files changed, 1383 insertions(+), 1311 deletions(-) diff --git a/docs/core/capability/index.html b/docs/core/capability/index.html index 9fe95f73e..9ff49a87b 100644 --- a/docs/core/capability/index.html +++ b/docs/core/capability/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Capability +

Capability

@@ -810,7 +810,7 @@

AI diff --git a/docs/core/cli/index.html b/docs/core/cli/index.html index da507fa03..cae20f467 100644 --- a/docs/core/cli/index.html +++ b/docs/core/cli/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

CLI +

CLI

@@ -416,7 +416,7 @@

Assembly

diff --git a/docs/core/common/index.html b/docs/core/common/index.html index 602c00574..fbfa123ec 100644 --- a/docs/core/common/index.html +++ b/docs/core/common/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Common +

Common

@@ -151,7 +151,7 @@

diff --git a/docs/core/diagram/index.html b/docs/core/diagram/index.html index f308748a4..24a3e57f0 100644 --- a/docs/core/diagram/index.html +++ b/docs/core/diagram/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Diagram +

Diagram

@@ -151,7 +151,7 @@

diff --git a/docs/core/drawio/index.html b/docs/core/drawio/index.html index 578943c92..a1ceb061e 100644 --- a/docs/core/drawio/index.html +++ b/docs/core/drawio/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Drawio +

Drawio

@@ -261,7 +261,7 @@

Ecore Model

diff --git a/docs/core/emf/index.html b/docs/core/emf/index.html index 889c9411e..82e7579a4 100644 --- a/docs/core/emf/index.html +++ b/docs/core/emf/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

EMF +

EMF

@@ -151,7 +151,7 @@

diff --git a/docs/core/exec/index.html b/docs/core/exec/index.html index 3dbd3ce98..1299370da 100644 --- a/docs/core/exec/index.html +++ b/docs/core/exec/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Exec +

Exec

@@ -151,7 +151,7 @@

diff --git a/docs/core/graph/index.html b/docs/core/graph/index.html index 598b0d5e7..d427a8fa3 100644 --- a/docs/core/graph/index.html +++ b/docs/core/graph/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Graph +

Graph

@@ -391,7 +391,7 @@
Wiring
diff --git a/docs/core/http/index.html b/docs/core/http/index.html index 22e8f6b03..d6d12cc93 100644 --- a/docs/core/http/index.html +++ b/docs/core/http/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

HTTP +

HTTP

@@ -151,7 +151,7 @@

diff --git a/docs/core/index.html b/docs/core/index.html index c712047e0..3504210a5 100644 --- a/docs/core/index.html +++ b/docs/core/index.html @@ -74,46 +74,46 @@
-
+
-
- -
+
+ +
-
+
-

Core +

Core

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

diff --git a/docs/core/mapping/index.html b/docs/core/mapping/index.html index ac719642b..1341ab04d 100644 --- a/docs/core/mapping/index.html +++ b/docs/core/mapping/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Mapping +

Mapping

@@ -1036,7 +1036,7 @@

property-descending< diff --git a/docs/core/maven/index.html b/docs/core/maven/index.html index dd0be78c8..98179a41c 100644 --- a/docs/core/maven/index.html +++ b/docs/core/maven/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Maven +

Maven

@@ -246,7 +246,7 @@

URI Handler

diff --git a/docs/core/persistence/index.html b/docs/core/persistence/index.html index d97841bfd..c13c8ca48 100644 --- a/docs/core/persistence/index.html +++ b/docs/core/persistence/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Persistence +

Persistence

@@ -151,7 +151,7 @@

diff --git a/docs/core/resources/index.html b/docs/core/resources/index.html index 7b6705102..2ca1cdd64 100644 --- a/docs/core/resources/index.html +++ b/docs/core/resources/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Resources +

Resources

@@ -151,7 +151,7 @@

diff --git a/docs/demos/module-graph-full.html b/docs/demos/module-graph-full.html index d08f52270..6d95cb705 100644 --- a/docs/demos/module-graph-full.html +++ b/docs/demos/module-graph-full.html @@ -2552,6 +2552,42 @@ + + + + + + + + + + + +
-
+
-

Glossary +

Glossary

@@ -172,7 +172,7 @@

diff --git a/docs/html/bootstrap/index.html b/docs/html/bootstrap/index.html index f7dde25dd..583a7cfe5 100644 --- a/docs/html/bootstrap/index.html +++ b/docs/html/bootstrap/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

Bootstrap +

Bootstrap

@@ -151,7 +151,7 @@

diff --git a/docs/html/html/index.html b/docs/html/html/index.html index 6396e0efd..99daac603 100644 --- a/docs/html/html/index.html +++ b/docs/html/html/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

HTML +

HTML

@@ -151,7 +151,7 @@

diff --git a/docs/html/index.html b/docs/html/index.html index 9174b4580..4bc9d822e 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -74,46 +74,46 @@
-
+
-
- -
+
+ +
-
+
-

HTML +

HTML

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

diff --git a/docs/html/jstree/index.html b/docs/html/jstree/index.html index a4671f3ce..50f6f0b4f 100644 --- a/docs/html/jstree/index.html +++ b/docs/html/jstree/index.html @@ -74,52 +74,52 @@
-
+
-
- -
+
+ +
-
+
@@ -127,7 +127,7 @@
-

JsTree +

JsTree

@@ -151,7 +151,7 @@

diff --git a/docs/index.html b/docs/index.html index 0dec42355..0f3449407 100644 --- a/docs/index.html +++ b/docs/index.html @@ -73,47 +73,47 @@
-
Nasdanika +
Nasdanika
-
+
-
- -
+
+ +
-
+
-

+

@@ -128,7 +128,7 @@ diff --git a/docs/nsd-cli/index.html b/docs/nsd-cli/index.html index a7e5a5d9e..9aa705555 100644 --- a/docs/nsd-cli/index.html +++ b/docs/nsd-cli/index.html @@ -74,46 +74,46 @@
-
+
-
- -
+
+ +
-
+
-

CLI +

CLI

@@ -156,7 +156,7 @@

Linux

diff --git a/docs/nsd-cli/nsd/app/index.html b/docs/nsd-cli/nsd/app/index.html index 1bfd4e0a8..6488ece39 100644 --- a/docs/nsd-cli/nsd/app/index.html +++ b/docs/nsd-cli/nsd/app/index.html @@ -74,35 +74,35 @@
-
+
-
- -
+
+ +
-
+
@@ -126,7 +126,7 @@
-

Analysis, Visualization & Generation +

Analysis, Visualization & Generation

@@ -197,7 +197,7 @@

Resources

diff --git a/docs/practices/index.html b/docs/practices/index.html index da31bc7ac..c50b30a7e 100644 --- a/docs/practices/index.html +++ b/docs/practices/index.html @@ -74,46 +74,46 @@
-
+
-
- -
+
+ +
-
+
-

Practices +

Practices

@@ -163,7 +163,7 @@

diff --git a/docs/practices/java/index.html b/docs/practices/java/index.html index 1374d764f..c1821f208 100644 --- a/docs/practices/java/index.html +++ b/docs/practices/java/index.html @@ -74,51 +74,51 @@
-
+
-
- -
+
+ +
-
+
@@ -126,7 +126,7 @@
-

Java Analysis, Visualization & Generation +

Java Analysis, Visualization & Generation

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

RAG/Chat

diff --git a/docs/practices/junit/index.html b/docs/practices/junit/index.html index 030fef95d..e61a8b5ad 100644 --- a/docs/practices/junit/index.html +++ b/docs/practices/junit/index.html @@ -74,51 +74,51 @@
-
+
-
- -
+
+ +
-
+
@@ -126,7 +126,7 @@
-

JUnit Tests Generation +

JUnit Tests Generation

@@ -339,7 +339,7 @@

Te diff --git a/docs/search-documents.js b/docs/search-documents.js index 79a2fb1d9..ffcb63f00 100644 --- a/docs/search-documents.js +++ b/docs/search-documents.js @@ -1 +1 @@ -var searchDocuments = {"html/index.html":{"link-uuid":"54132499-8909-400b-aac1-43cbf2d545d1","title":"HTML","content":"Sources"},"nsd-cli/nsd/model/html-app/site/index.html":{"path":"CLI/nsd/model/html-app/site","link-uuid":"5bd766eb-6711-4178-b0d1-8b0704f9a360","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model html-app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>]\r\n [-F=<pageTemplateFile>] [-m=<domian>]\r\n [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"core/maven/index.html":{"path":"Core/Maven","link-uuid":"234c2e91-e3b6-4ca5-b0df-678439550f93","title":"Maven","content":"Nasdanika Maven module uses Maven Resolver Supplier to provide capabilities for Dependency and ClassLoader requirements. Sources Javadoc Dependency CapabilityLoader capabilityLoader = new CapabilityLoader();\nDependencyRequestRecord requirement = new DependencyRequestRecord(\n\t\tnew String[] { "org.apache.groovy:groovy-all:pom:4.0.23" }, \n\t\tnull, \n\t\tnull, \n\t\t"target/test-repo");\n\t\t\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nCollection<File> result = capabilityLoader.loadOne(requirement, progressMonitor);\n The above code snippet loads org.apache.groovy:groovy-all:pom:4.0.23 and its dependencies into target/test-repo directory and returns a list of jar files. ClassLoader CapabilityLoader capabilityLoader = new CapabilityLoader();\nClassLoaderRequirement requirement = new ClassLoaderRequirement(\n\t\tnull, // String[] modulePath,\n\t\tnull, // String[] rootModules,\n\t\tnew ModuleLayer[] { getClass().getModule().getLayer() }, \n\t\tgetClass().getClassLoader(), // ClassLoader parentClassLoader,\n\t\ttrue, // boolean singleLayerClassLoader,\t\t\t\t\n\t\tnew String[] { "org.apache.groovy:groovy-all:pom:4.0.23" }, \n\t\tnull, \n\t\tnull, \n\t\t"target/test-repo",\n\t\tSystem.out::println);\n\t\t\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nClassLoader result = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(ClassLoader.class, null, requirement),\n\t\tprogressMonitor);\n\t\t\nClass<?> scriptEngineFactoryClass = result.loadClass("org.codehaus.groovy.jsr223.GroovyScriptEngineFactory");\n The above code snippet: Loads org.apache.groovy:groovy-all:pom:4.0.23 and its dependencies into target/test-repo directory Creates a ClassLoader Loads org.codehaus.groovy.jsr223.GroovyScriptEngineFactory class Default configuration DependencyCapabilityFactory, which is responsible for resolving and downloading dependencies, loads default configuration in the following way: If org.nasdanika.maven.DependencyCapabilityFactory.config.yml system property is set, then it is treated as a URL of a configuration YAML resource. The URL is resolved relative to the current directory. If org.nasdanika.maven.DependencyCapabilityFactory.config.json system property is set, then it is treated as a URL of a configuration JSON resource. The URL is resolved relative to the current directory. If NSD_DEPENDENCY_RESOLVER_CONFIG_YAML_URL environment variable is set, then it is treated as an absolute URL of a configuration YAML resource. If NSD_DEPENDENCY_RESOLVER_CONFIG_JSON_URL environment variable is set, then it is treated as an absolute URL of a configuration JSON resource. If NSD_DEPENDENCY_RESOLVER_CONFIG_YAML environment variable is set, then it is treated as YAML configuration. If NSD_DEPENDENCY_RESOLVER_CONFIG_JSON environment variable is set, then it is treated as JSON configuration. If dependency-reolver-config.yml file exists in the current directory the it is loaded as YAML. If dependency-reolver-config.json file exists in the current directory the it is loaded as JSON. The loaded configuration is interpolated with system properties and environment variables. E.g. ${my-property} will be expanded to the value of my-property system property if it is set. Respectively, ${env.MY_ENV_VAR} will be expanded to the value of MY_ENV_VAR environment variable if it is set. Property expansion can be escaped with additional {} e.g. ${my-property} will be expanded to ${my-property} regardless of whether my-properety system property is set or not. Configuration specification modulePath - optional String or List, module path. If null, derived from root modules if they are present rootModules - optional String or List, root modules. The first root module is used to obtain the class loader oneLayerClassLoader - optional boolean indicating whether a single class loader shall be used for all modules in in the layer dependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format. E.g. org.apache.groovy:groovy-all:pom:4.0.23 managedDependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format remoteRepositories - Map (single remote repository) or List of Maps of remote repository definitions loaded into RemoteRepoRecord: id - String, repo ID type - String, optional repo type url - String, repository URL proxy - optional Map: type - String, http or https host - String port - integer auth - authentication (see below) auth - Map: username - String password - String mirroredRepositories - Map or List, mirrored repositories localRepository - optional String, path to the local repository to download dependencies to. Defaults to repository. URI Handler Maven URIHandler handles URIs of the following format: maven://<groupId>/<artifactId>/<extension>/<version>/<resource path>[?classifier=<classifier>]. For example, for maven://org.nasdanika.models.architecture/model/jar/2024.8.0/model/architecture.ecore?classifier=model URI model/architecture.ecore resource would be loaded from model-2024.8.0-model.jar in org.nasdanika.models.architecture group model artifact version 2024.8.0 as shown in the snippet below: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nResourceSet resourceSet = capabilityLoader.loadOne(requirement, progressMonitor);\nURI modeURI = URI.createURI("maven://org.nasdanika.models.architecture/model/jar/2024.8.0/model/architecture.ecore?classifier=model");\nResource resource = resourceSet.getResource(modeURI, true);\nSystem.out.println(resource.getContents());"},"nsd-cli/nsd/gsh/index.html":{"path":"CLI/nsd/gsh","link-uuid":"6930bdd9-91e8-46c8-877d-c9e8203de001","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gsh [-hV] [--progress-console] [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>] [-p=<String=String>]...\r\n [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/diagram/index.html":{"path":"Core/Diagram","link-uuid":"521cf79a-0d13-469f-8812-f3fe4d1694ef","title":"Diagram","content":"Sources Javadoc"},"nsd-cli/nsd/rules/action-model/index.html":{"path":"CLI/nsd/rules/action-model","link-uuid":"4023b714-b637-4102-b913-942751ce6673","title":"action-model","content":"Usage: nsd rules action-model [-fhRV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... <model> <output>\r\nGenerates rule set documentation action model\r\n <model> Model URI or file path, resolved relative\r\n to the current directory\r\n or looked up in registered rule sets\r\n if -R option is provided\r\n <output> Output file\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 type\r\n header, if it is present, or extension. Contexts\r\n are composed in the order of definition, later\r\n context entries shadowing the former\r\n -f, --file Mdel parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext 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 type\r\n header, if it is present, or extension. Mounts\r\n shadow context entries.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -R, --registered Use registered rule set\r\n with provided URI\r\n -V, --version Print version information and exit."},"html/bootstrap/index.html":{"path":"HTML/Bootstrap","link-uuid":"ece1521e-f6d1-4300-af1a-ec9f686636d7","title":"Bootstrap","content":"Sources Javadoc"},"nsd-cli/nsd/app/index.html":{"path":"CLI/nsd/app","link-uuid":"8ace60fd-23a4-485a-af76-9f19e8425f10","title":"app","content":"Version: org.nasdanika.models.app.cli@2024.12.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"},"index.html":{"link-uuid":"fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4","title":"Nasdanika","content":" Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI HTTP Mapping Core JsTree Bootstrap HTML HTML GitLab Architecture Git Excel ECharts Nature Bank PDF Party Source Engineering Java Maven Enterprise Function Flow Rules Azure Ecore Jira Bootstrap App Capability Coverage Decision Analysis Family Flow HTML Models Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI YouTube Channel Medium Publication Template Repositories AWS Diagram (Drawio Site) Bob the Builder (Drawio site) Function Flow Concurrent Executable Diagrams Executable Diagram Dynamic Proxy General Purpose Executable Diagrams Internet Banking System (Drawio Site) Internet Banking System (C4 Model mapping) Maven Graph Semantic Mapping CLI Compute Graph Demos Nasdanika"},"nsd-cli/nsd/model/ecore-html-app/save/index.html":{"path":"CLI/nsd/model/ecore-html-app/save","link-uuid":"43e10ad7-4ad7-42b4-a742-d6bf1d6c1433","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app save [-hV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Cl\r\n ass>]...\r\n [--extension-resource-factory=<String=Class\r\n >]...\r\n [--protocol-resource-factory=<String=Class>\r\n ]... <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/app/site/index.html":{"path":"CLI/nsd/app/site","link-uuid":"217a9773-d7bf-4884-a30e-0e8535bd3dfd","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>] [-T=<pageTemplate>]\r\n [-w=<workDir>] [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]... [-i\r\n [=<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 -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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"core/common/index.html":{"path":"Core/Common","link-uuid":"78daff3b-b26f-466d-9fb8-cb633c8bec78","title":"Common","content":"Sources Javadoc"},"nsd-cli/nsd/model/html-app/index.html":{"path":"CLI/nsd/model/html-app","link-uuid":"8bb9d4b7-5ff1-4f2d-a87a-097a24bb16d6","title":"html-app","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model html-app [-fhRV] [-P=<insertionIndex>] [-r=<rootLabel>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [-M=<String=String>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates html application model from a drawio document\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 directory.\r\n YAML, JSON, or properties. In properties dots are\r\n treated as key path separators. Type is inferred from\r\n the content type header, if it is present, or\r\n extension. Contexts are composed in the order of\r\n definition, later context entries shadowing the former\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the current\r\n directory. YAML, JSON, or properties. In properties\r\n dots are treated as key path separators. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Mounts shadow context entries.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"practices/junit/index.html":{"path":"Practices/JUnit Tests Generation","link-uuid":"ba54a576-ba48-47cf-aac2-f96938d6a76e","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 nor 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 Retrieval Augmented Generation Java Sources Bytecode Coverage Data Developer Gen AI Coverage Model Source Code Model Tests Model Generator JUnit Test Generation Retrieval Augmented Generation Writing Code Compilation Testing Test Generation Gen AI Retrieval Augmented Generation"},"nsd-cli/index.html":{"link-uuid":"8f67c12c-24ad-4219-9dda-be26c6520110","title":"CLI","content":"Nasdanika Command Line Interface (CLI) is a suite of Nasdanika capabilities packaged as command line tools. Sources 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","link-uuid":"b22f0146-0b59-4157-91ef-6a34c3508a34","title":"Drawio","content":"Nasdankia provides two Maven modules for working with Drawio diagrams - API and Model. The modules require Java 17 or above. API Page and element links Generating documentation sites Executable diagrams Invocable URIs Java Ecore Model 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. Sources JavaDoc Page and element links Nasdanika Drawio API extends the concept of linking to pages to cross-document linking to pages and page elements by name or ID. Link targets (pages or elements) are available via getLinkTarget() method. Drawio page links have the following format: data:page/id,<page id> with page/id being the “media type” and <page id> being the “data” of a Data URL. Nasdanika Drawio API extends it to additional media types: page/name element/id element/name The data (selector) format has the following format: Page: [<diagram resource>#]<page selector> Diagram resource is a URI resolved relative to the current document URI. If not present then the link target page is in the same document. Page selector is either page ID or URL encoded page name depending on the media type - id or name. Element: [<diagram resource>#][<page selector>/]<element selector>] Diagram resource is a URI resolved relative to the current document URI. If not present then the link target element is in the same document. Page selector is either of: id,<page id> name,<URL encoded page name> Element selector is either page ID or URL encoded element label text (stripped of HTML formatting) depending on the media type - id or name. For elements URL’s page selector is required if diagram resource URI is present. Examples: Page links: data:page/name,compressed.drawio#Page-1 - Link to compressed first page data:page/name,compressed.drawio#Page+2 - Link to compressed second page Element links: data:element/id,7KSC1_O8d7ACaxm1iSCq-1 - Link by ID to an element on the same page data:element/name,name,Page+2/Linked - Link by name to Linked on Page 2 referenced by name data:element/name,compressed.drawio#name,Page+2/Linked - Link to Linked on compressed second page This approach allows to create a multi-resource graph of diagrams. Nasdanika Drawio API also supports loading of documents from arbitrary URI’s using a URI resolver. For example, maven://<gav>/<resource path> to load from Maven resources or gitlab://<project>/<path> to load resources from GitLab without cloning a repository, provided there is a handler (Function<URI,InputStream>) supporting the aforementioned URI’s. Generating documentation sites With Nasdanika CLI drawio > html-app > site command pipeline can be used to generate documentation web sites from Drawio diagrams: Demo Video explaining how the above demo was created Template repository Internet Banking System - another demo: a sample C4 Model Visual Communication Continuum - a Medium story which provides an overview of the approach and compares it with semantic mapping Semantic Mapping - a medium story focusing on Semantic Mapping Executable diagrams With Nasdanika Drawio API and other products you can make your diagrams executable as explained in the following sections. Invocable URIs You may set diagram element properties to URIs of processors. This approach is explained in General Purpose Executable Graphs and Diagrams Medium story. A demo repository is here - https://github.com/Nasdanika-Demos/executable-diagram-dynamic-proxy. You can use this site/ repository as a starting point for your diagramming ecosystem: Site Code Java You can create graph element processors for diagram elements in Java. Executable (computational) graphs & diagrams story provides a high level overview of executable graphs and diagrams. Graph documentation features more technical details and code samples. Compute Graph Demo provides examples of this and semantic mapping (below) approaches using the compute graph from the “Executable (computational) graphs & diagrams” story. Ecore 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 links from diagram elements to pages and other diagram 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. Sources JavaDoc 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. 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 * * * Link Target linkTarget 0..1 Page-1"},"nsd-cli/nsd/gitlab/contribute/invoke/index.html":{"path":"CLI/nsd/gitlab/contribute/invoke","link-uuid":"699a83e8-68d1-4a66-8680-f92146440fe0","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab contribute invoke [-fhV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri>\r\n [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/mapping/index.html":{"path":"Core/Mapping","link-uuid":"310e8453-7243-45ce-8743-3eda6ec2bc92","title":"Mapping","content":"(Semantic) mapping is a process of creating and populating Ecore models from other data sources, Drawio diagrams in particular. This module provides base mapping functionality and the Drawio module provides concrete implementation classes and several Drawio-specific comparators which use element properties and geometry. This page provides a combined documentation for both generic and Drawio-specific mapping. Resources: Semantic Mapping Medium Story provides a high-level overview focusing more on the WHAT and the WHY while this page focuses more on the HOW. Most code snippets below are taken from the semantic mapping demo. EMF Ecore ContentProvider DrawioContentProvider Loading Drawio resources Phases & properties Initialization initializer Groovy initializer Mapping Script Java intitializer Mapping Initializer method type ref-id Contributor.initialize() page-element prototype selector target-selector reference features end container Example contents Examples USA Joe self source start target features-ref Representations Filtering Configuration config-prototype Documentation Label Markers identity configuration Tooltip Contributor.configure() Operations arguments iterator pass selector invoke Groovy mapper Mapping Script Java mapper Mapping Mapping method Mapping Selector Feature Mapping argument-type comparator condition expression greedy invoke path nop position type Comparators Geometric Angular clockwise counterclockwise Cartesian down-left down-right left-down left-up right-down right-up up-left up-right Dependency flow reverse-flow expression key label label-descending natural property property-descending EMF Ecore This section is a brief introduction to EMF Ecore, which is used to create metamodels of problem domains. These metamodels are then used as mapping targets. It is important to mention that metamodels and documentation generated from them have value on their own - they establish a common (ubiquitous) language.1 Eclipse Modeling Framework (EMF) is an Eclipse-based modeling framework and code generation facility for building tools and other applications based on a structured data model. Ecore is the core (meta-)model at the heart of EMF. It allows expressing other models by leveraging its constructs. Ecore is also its own metamodel (i.e.: Ecore is defined in terms of itself).2 Simply put, Ecore is a way to create (domain specific) languages understandable by both humans and computers. The above diagrams shows key Ecore concepts and their relationships. E prefix is dropped for clarity. E.g. EPackage is shown as Package. More detailed documentation can be found here - https://ecore.models.nasdanika.org/ (work in progress) Metamodel Module - Java/Maven module or an OSGi bundle. Contains zero or more models with each model containing a root package. Package - a group of classifiers and sub-packages. Packages are identified (keyed) by namespace URI’s. Classifier - a class, data type or enumeration. Data type - a bridge to the Java type system. Enumeration - a collection of literals. Class - contains zero or more structural features - attributes and references and zero or more operations. May inherit from zero or more superclasses. Can be abstract and can be an interface. Structural feature - can hold single or multiple values Attribute - holds a “simple” value such as String, Date, number. Reference - relationship between two objects (EObjects). Unidirectional, but can be associated with another reference (opposite) to form a bi-directional relationship. References can be containment (composition) and non-containment (aggregation). Model Resource set - a group of related resources identified by a URI. Resource sets have associated packages, resource factories, adapter factories, and URI handlers not shown on the diagram. Resource - a group of objects. A resource is identified by a URI. Object - an instance of a metamodel class. Below is a concrete example using the Family metamodel and model: Metamodel Module - org.nasdanika.models.family:model Maven module, org.nasdanika.models.family Java module. Package - family defined in family.ecore resource with ecore://nasdanika.org/models/family namespace URI, several Java packages. Class - Man class inheriting from Person class. Structural feature Attribute - name attribute of Man (inherited from NamedElement). Reference Person.father - single non-containment reference, Person.children - many non-containment reference. Family.members - many containment reference. Model Resource set - created with a factory which treats .drawio diagram files as resources with diagram elements mapped to the family model. Resource - family.drawio file. Object - Paul and Elias are instances of Man class. Elias references Paul as his father. It is important to note that resources are identified by URI’s, not URL’s. It allows to load resources from multiple data sources - files, URL’s, databases, source repositories such as Git, binary repositories such as Maven. Using Nasdanika classes it is also possible to load objects from multiple sources on access. For example, a person’s id and name can be loaded from, say, Excel file or a database. Some other attributes may be loaded by making HTTP requests only if the client code reads those attributes. EMF Ecore provides facilities to read/write resources from/to XMI files and binary files. It also provides tools for creating models. Eclipse CDO allows to store models in distributed repositories. Nasdanika provides factories to load models from Drawio diagrams, MS Excel, Java sources, PDF files, and CSV files. It also provides URI handlers for loading models from classpath resources, GitLab & Maven repositories. There is also a documentation generator for Ecore models. In addition to the family model mentioned above, you can find examples of Ecore models and generated documentation on this site. ContentProvider For the purposes of mapping the source structures are abstracted by the ContentProvider interface, whith the following methods: Collection<? extends S> getChildren(S element /*, Predicate<S> predicate */) - returns element children. URI getBaseURI(S element) - URI for resolving resources such as documentation. Object getProperty(S element, String property) - returns property used to perform mapping. Marked asMarked(S element) - for reporting locations of errors. S getConnectionSource(S element) - If the element is a connection/association - returns its source. Otherwise returns null. S getConnectionTarget(S element) - If the argument is a connection/association - returns its target. Otherwise returns null. String getName(S element) - Element name, e.g. Drawio element label text without HTML markup. String getDescription(S element) - Element description, e.g. Drawio element tooltip. Object getIdentity(S obj) - Object identity such as a unique ID or a URI. DrawioContentProvider DrawioContentProvider is an implementation of the ContentProvider for working with Drawio diagrams. It loads mapping properties from YAML in config property or a YAML resource specified in config-ref property. It also takes element and page links into account in parent/child relationships - linked elements are considered children of linking elements. DrawioContentProvider uses base-uri property for resolving the element base URI. If this property is not set, then the base URI is the URI of the drawio file plus a fragment, which is not significant for resolving relative URI’s. If base-uri property is set, then it is resolved relative to the parent’s base URI or the Drawio resource URI if there is no parent. Loading Drawio resources While you can use DrawioContentProvider directly and customize it to your needs, the primary usage scenario is to load Drawio diagrams as Ecore resources - mapping is performed behind the scenes: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nResourceSet resourceSet = capabilityLoader.loadOne(requirement, progressMonitor);\nFile diagramFile = new File("diagram.drawio").getCanonicalFile();\nResource resource = resourceSet.getResource(URI.createFileURI(diagramFile.getAbsolutePath()), true);\t\t\nEObject root = resource.getContents().get(0);\t\n In the above code snippet a resource set is loaded from a CapabilityLoader and contains all resource factories and EPackages provided as capabilities. It includes ConfigurationLoadingDrawioResourceFactory which is registered to load .drawio and .png files. This factory customizes mapping properties: mapping - if this property is set, its value is parsed as YAML which is used as property source. mapping-ref - if mapping property is not set and this property is set, then this property value treated as a location of a YAML resource containing mapping configuration. The location (URI) is resolved relative to the base URI of the element. Phases & properties Mapping is a non-trivial process. In the case of diagrams the order in which diagram elements are mapped is not under control of the user - it depends on the order of creation of the diagram elements. Therefore, the mapping process consists of several phases and some of them may involve multiple passes. This section describes the mapping process in the order of phases. A phase section explains element configuration properties (keys) used for that phase. In some phases only one property is used. In this case the phase name is the same as the property name. In the mapping reference pages properties are ordered alphabetically. Initialization In this first phase source elements are associated with (mapped to) target elements. For example, a person image can be associated with a person object from the family model. The phase is called “Initialization” because the mapping process is similar to assigning a value to a variable in languages like Java and virtually identical to what happens in JavaScript where objects are essentially maps. The following sections explain the configuration properties used in the initialization phase. initializer initializer property value shall be an Invocable URI resolved relative to the base URI. The invocable is bound to the following arguments by name: registry - Consumer<BiConsumer<Map<EObject, EObject>,ProgressMonitor>> callback to obtain a map of source elements to target elements once all target elements are initialized (created), but not necessarily fully configured. contentProvider - content provider progressMonitor - progress monitor resourceSet - can be used to load target model elements capabilityLoader - can be used to load capabilities, including invocable URIs Then it is invoked with the source object as a single positional argument. It may return null - in this case type would be used to create a target element, if specified. This property can be used, for example, to look-up target elements defined elsewhere. Say, a list of family members can be defined in an MS Excel workbook, but family relationships in a diagram. Another example is “progressive enrichment”. For example, high-level architecture is defined in some model and a diagram uses initializers for already defined architecture elements and type for their sub-elements. This approach can be applied multiple times similar to how Docker images are assembled from layers and base images - you can layer fine-grained models/diagrams over coarse-grained ones. If you are old enough to remember JPEG images being loaded over a slow dial-up connection - something like that. In order to implement lookup initializers, override configureInitializer(), configureInvocable() or getVariables() in sub-classes of AbstractMappingFactory or getVariables() in a subclass of ConfigurationLoadingDrawioResourceFactory. Groovy initializer Mapping initializer: initializer.groovy\n Script import org.nasdanika.models.architecture.ArchitectureFactory\n\nArchitectureFactory.eINSTANCE.createDomain();\n Java intitializer Mapping initializer: data:java/org.nasdanika.demos.diagrams.mapping.Services::nodeInitializer\n Initializer method public static ArchitectureDescriptionElement nodeInitializer(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor loadingProgressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment,\n\t\t@Parameter(name = "contentProvider") ContentProvider<Element> contentProvider,\n\t\t@Parameter(name = "registry") Consumer<BiConsumer<Map<EObject, EObject>,ProgressMonitor>> registry,\n\t\t@Parameter(name = "progressMonitor") ProgressMonitor mappingProgressMonitor,\n\t\t@Parameter(name = "resourceSet") ResourceSet resourceSet,\n\t\t@Parameter(name = "capabilityLoader") CapabilityLoader capabilityLoader,\n\t\tElement source) {\n\tArchitectureDescriptionElement architectureDescriptionElement = ArchitectureFactory.eINSTANCE.createArchitectureDescriptionElement();\n\tarchitectureDescriptionElement.setDescription("I was created by a Java initializer");\n\treturn architectureDescriptionElement;\t\t\t\t\n}\n Note the use of positional and named parameters: The first 4 parameters are bound positionally when invocable URI is loaded The 5 named parameters a bound by name by the mapper The last parameter is used for invocation (also positional) type type property is used if there is no initializer or if it returned null. The value of property is the type of the target element. Types are looked up in the factory packages in the following way: If the value contains a hash (#) then it is treated as a type URI. For example ecore://nasdanika.org/models/family#//Man. If the value contains a dot (.) then it is treated as a qualified EClass name with EPackage prefix before the dot. For example family.Man. There may be more than one dot if EClass is defined in a sub-package. For example, exec.content.Markdown. Otherwise, the value is treated as an unqualified EClass name - registered EPackages (and sub-packages recursively) are sorted by Namespace URI, iterated, and the first found EClass with matching name is used to create a target element. A combination of initializer and type can be used for mapping in different contexts. For example, when loading a stand-alone model initializer would evaluate to null and then type would be used. When the same diagram loaded in the context of a larger model, initializer may evaluate to a target element looked up in that larger model. Example: type: architecture.c4.System\n A Java analogy for type: Object isaDiagramElement = getClassLoader().loadClass(type).newInstance();\n ref-id ref-id is some identifier to resolve to a target element. If there is already a target element created/resolved with initializer or type and isRefIProxydURI() returns true, then ref-id is treated as EObject proxy URI resolved relative to the base URI (see below). You may need to use this approach in case of circular references between resources or if the target element type and URI are known, but the element itself is not available during the load time. If there is no target element yet, then ref-id is used to look it up in the resource set. You may use a “physical” URI to load objects on demand, or “logical”/“semantic” URI for already loaded objects. Say, ssn:123-45-6789 to lookup a person by their SSN. Contributor.initialize() Initialization can be customized by creating a service capability of type AbstractMappingFactory.Contriutor and overriding its initialize() method. page-element If there is no target element for a diagram element yet and the diagram element’s page-element property is set to true then its target element is set to the first found target element of diagram elements linking to the page. For example, on the System Context Diagram the “Internet Banking System” element links to the Container diagram page where the “Internet Banking System” container is the page element. As a result, both of these diagram elements map to the same target element. There should be one page element per page. Having more than one may lead to an unpredictable behavior. Using page-element you can define a high-level structure on one diagram page, link other pages to the diagram elements and refine their definitions. This process can be repeated to build a hierarchy of pages as demonstrated in the “Internet Banking System Architecture” demo mentioned above. If the target element of a page element extends NamedElement then the page name is used as element’s name if hasn’t been already set by other means. prototype prototype is a Spring Expression Language (SpEL) expression evaluating to a diagram element. The target element of that diagram element is copied and the copy is used as the target element of this diagram element. Also, the prototype configuration (properties) is applied to this target element. Example: getPage().getDocument().getModelElementById('web-server-prototype') Prototypes allow to define common configuration in one element and then reuse it in other elements. For example, a web server prototype may define an icon and then all web server elements would inherit that configuration. Prototypes can be chained - you may create an inheritance hierarchy of diagram elements. Drawio classes provide convenience methods for finding diagram elements: Element.getModelElementById(String id) Element.getModelElementByProperty(String name, String value) Element.getModelElementsByProperty(String name, String value) Document.getPageById(String id) Document.getPageByName(String name) If you want to inherit just configuration, but not the target element, then use config-prototype property instead of prototype. selector selector is a Spring Expression Language (SpEL) expression evaluating to a diagram element. The target element of that diagram element is used as the target element of this diagram element. Selectors allow to use the same target element on multiple diagrams. For example, in the Internet Banking System E-Mail System is defined on the System Context Diagram and selected (referenced) on the Container Diagram with getModel().getPage().getDocument().getModelElementByProperty('semantic-id', 'microsoft-exchange') expression. The expression is evaluated in the context of the diagram element with access to the following variables: registry pass progressMonitor resourceSet capabilityLoader Please note that you may also use the extended link syntax to associate more than one diagram element with a single target element. If you are selecting by diagram element id or label, then the extended link syntax is preferable to using selector expression. In the “Internet Banking System” C4 Model demo Single-Page Application is defined on the Container Diagram and linked from the API Application Component Diagram with data:element/id,name,Container+Diagram/single-page-application) link. target-selector Spring Expression Language (SpEL) expression evaluating to a target element. Target selectors are similar to initializers with the following differences: Target selectors are evaluated after initializers An initializer is evaluated once, but a target selector might be evaluated multiple times until it returns a non-null value or the maximum number of passes is exceeded A target selector is only evaluated if there isn’t a target element already Target selectors can be used to evaluate target elements using target elements of other elements. For example, a target selector of a child node may need a target element of its parent to resolve its own target element. The expression is evaluated in the context of the diagram element with access to the following variables: * registry * pass * progressMonitor * resourceSet * capabilityLoader reference Diagram elements can be associated with target elements’ references. A Java analogy would be: List<Person> isaChildrenDiagramElement = familyWorkBook.findById("isa").getChildren();\n reference property associates a diagram element with a reference of the target element of the first matched ancestor for mapping purposes. If the element has mapped descendants, their matching targets elements are added to the reference. Reference value can be a string or a map. The string form is equivalent to the map form with just the name entry. The map form supports the following keys: comparator - used to sort reference elements, see the Comparators section. condition - a SpEL boolean expression evaluated in the context of the ancestor target element. If not provided, matches the first mapped ancestor. Has access to the following variables: sourcePath - a list of ancestors starting with the parent registry expression - a SpEL EObject expression evaluated in the context of the ancestor target element. If not provided, the ancestor itself is used. Has access to the following variables: sourcePath - a list of ancestors starting with the parent registry name - reference name element-condition - a SpEL boolean expression evaluated in the context of the descendant (contents) target element. If not provided, elements are matched by type compatibility with the reference type. Has access to the following variables: sourcePath - source containment path registry element-expression - a SpEL EObject expression evaluated in the context of the descendant (contents) target element. If not provided, the descendant itself is used. Has access to the following variables: sourcePath - source containment path registry See References demo for examples of using reference mapping. features features property defines mapping of target element structural features - references and attributes. Feature mapping demo provides a few examples of reference mapping. The value of the property shall be a map with the following supported keys: end container contents self source start target end For connections - mapping specification, as explained in the Feature Mapping section, for the connection end feature to map the connection target semantic element3 to a feature of the connection semantic element. end: father\n The above specification means “set father reference of the connection semantic element to the semantic element of its end (Joe)”. container Mapping specification for the container element in container/contents permutation. Contains one or more of the following sub-keys with each containing a map of feature names to a mapping specification or a list of feature names. self - this element is a container other - the other element is a container Example type: family.Polity\nfeatures:\n container:\n self: \n residents:\n argument-type: family.Person\n path: 1\n other: constituents\n The above example shows Texas feature mapping: self means Texas itself. The mapping specifies that immediate children of this element (path: 1) shall be added to this (Texas) semantic element residents collection if they are instances of family.Person. Joe diagram element is an immediate child of the Texas diagram element. other means USA because USA contains Texas. This mapping specifies that this (Texas’) target element shall be added to the constituents feature of its container (USA) regardless of the containment path length. In the example the containment path length is 1. Please note that when a diagram element is linked to a page, then the page’s page element is logically merged with that element. In the Internet Banking System Architecture GetBalanceRequest is contained by Internet Banking System with path=3 - they appear on different diagrams (pages), but these diagrams are connected with page links. contents Mapping specification for the contents element in container/contents permutation. Contains one or more of the following sub-keys with each containing a map of feature names to a mapping specification or a list of feature names. self - this element is contained by the other other - the other element is contained by this element Examples USA contents:\n other: \ncountry:\n path: 2\n The above feature map for USA means that other is either Florida, Texas, Jane or Joe - they are all contained in USA directly or indirectly. Path 2 means that only Jane and Joe match this mapping. And country means that their country reference shall be set to USA. Joe contents:\n self: \ncountry:\n path: 2\n The above feature map for Joe means that other is either Texas or USA - they both contain Joe, Texas directly and USA transitively. Path 2 means that only USA matches this mapping. And country means that Joe’s country reference shall be set to USA. self A map of feature names to Spring Expression Language (SpEL) expressions or a list of expressions evaluating to the feature value or feature element value. The expression is evaluated in the context of the source diagram element and has access to the following variables: value - semantic element registry - a map of diagram element to semantic elements source For connections - mapping specification for the connection source feature to map the connection semantic element to a feature of the connection source semantic element. If there are no connection semantic elements, then the connection target semantic element is used instead (pass-through connection). source: father\n The above specification at the Jane -> Joe connection means to set connection source (Jane) father feature to connection target semantic element (Joe) because the connection itself doesn’t have semantic elements. In pseudo-code: connection.getSource().setFather(connection.getTarget());\n start For connections - mapping specification for the connection start feature to map the connection source semantic element to a feature of the connection semantic element. start: child\n The above specification means “set child reference of the connection semantic element to the semantic element of its start (Jane)”. target For connections - mapping specification for the connection target feature to map the connection semantic element to a feature of the connection target semantic element. If the connection doesn’t have semantic elements (pass-through connection), then the connection source semantic element is used instead. target: children\n The above specification at the Jane -> Joe connection means to set connection target (Joe) children feature to the connection source semantic element (Jane) because the connection itself doesn’t have semantic elements. In pseudo-code: connection.getTarget().getChildren().add(connection.getSource());\n features-ref features-ref property value shall be a string which is treated as a URI resolved relative to the base URI. Resource at the URI is parsed as YAML. Representations For semantic elements which extend ModelElement the loading process injects representations which can be used in Markdown documentation and as icons in generated HTML documentation. The loading process injects two representations: drawio - a Drawio diagram containing pages where the page element maps to this target element. image - loaded from diagram element style image. Representation reduce documentation effort and drive consistency. Filtering Representations can be customized (filtered) by creating a service capability of type AbstractMappingFactory.Contributor implementing AbstractDrawioFactory.RepresentationElementFilter and implementing its filterRepresentation() method. This functionality can be used, for example to style elements based on information retrieved from external systems. For example: Development status - Planned/Backlog, In Progress, Blocked, Done Runtime status - Operational, Overloaded, Failed, Planned maintenance Quality/technical debt status - OK, Warning, Danger Configuration After diagram elements are mapped to target elements (initialized) and their features are mapped, they are configured using their diagram element properties as explained below. config-prototype With config-prototype property you can inherit configuration from another diagram element. Property value shall be a Spring Expression Language (SpEL) expression evaluating to a diagram element. Diagram element configuration (properties) is applied to this semantic element. Example: getDocument().getModelElementById('web-server-prototype') Config prototypes allow to define common configuration in one element and then reuse it in other elements. For example, a web server prototype may define an icon and then all web server element would inherit that configuration. Config prototypes can be chained - you may create an inheritance hierarchy of diagram elements. Documentation Documentation properties can be used to add documentation to target elements which implement Documented interface. Documentation can be provided in documentation property in Markdown, plain text, or HTML. Markdown is the default documentation format. You can modify it by setting doc-format property. Supported values are markdown, text, and html. It might be more convenient to maintain documentation in an external resource. In this case specify the documentation resource URI in doc-ref property. The resource URI is resolved relative to the base URI of the diagram element. If doc-format is not set, it is inferred from the resource extension - HTML for .htm and .html, text for .txt, Markdown otherwise. Documentation may also be configured via configuration or configuration-ref. Label If the target element extends NamedElement and its name is not set, then diagram element label converted to plain text is used as semantic element name. Markers If the target element implements Marked then the loading process adds diagram element markers to the semantic element. It allows to track provenance of data elements which might important in scenarios where model elements are loaded from diverse sources and even a single element may be loaded from several sources. For example, attributes are loaded from an Excel workbook and relationships from a Drawio diagram. The loading process is aware of Git repositories - if it detects that the diagram file is under source control it would store Git-specific information in markers - repository path, branch, commit hash, remotes, and head references. identity If the target element extends StringIdentity, identity property can be used to specify the id attribute. If this property is not provided, then Drawio model element ID is used as identity. Drawio element id’s are editable, but duplicate id’s are not allowed on the same page. You may have duplicate semantic id’s in different containers on the same page. In this case you may use identity. Identity can also be set using the configuration and configuration-ref YAML, this property is a shortcut way. configuration Target elements may be configured by providing a YAML configuration map in the configuration property or a URI of a configuration resource in the configuration-ref property. The URI is resolved relative to the base URI of the diagram element. Configuration YAML maps target element features (attributes and references) to their values as shown in the below example: location: %id%/index.html\nicon: /images/mapping.svg\nchildren:\n - Action:\n location: mapping-reference.html\n text: Mapping Reference\n content:\n Interpolator:\n source:\n Markdown:\n style: true\n source:\n exec.content.Resource: mapping-reference.md\n Note singleton maps specifying child elements. The key of of such maps is a type as explained in the “Initialization” > “type” section: Action - a short type name, there is only one Action class available during loading Interpolator - also a short type name exec.content.Resource - a fully qualified type name because there are two Resource classes - in the content package and in the resources package “Load specification” model documentation pages provide information about configuration keys supported by a specific type. Examples: Action class Load Specification Woman class Load Specification Tooltip If the target element extends NamedElement and its description is not set, then diagram element tooltip is used as semantic element description. Contributor.configure() Configuration can be customized by creating a service capability of type AbstractMappingFactory.Contributor and overriding its configure() method. Operations Using operations and operations-ref properties you may specify target element operations to be invoked. operations value shall be a YAML map of invocation target to operation names and then to invocation specifications explained below, operations-ref shall be a URI of a resource containing a YAML map. The URI is resolved relative to the diagram element base URI. The invocation target is either self, source or target`.sourceandtarget`` are applicable only to connections. The invocation specification is either a map or a list of maps. The sections below describe the keys supported by the maps. Examples: type: Fox\noperations:\n self:\n eats: \n arguments:\n food: "#registry.get(outgoingConnections[0].target)"\n pass: 2\n operations:\n source:\n eats: \n arguments:\n food: "#registry.get(target)"\n arguments A map of parameter names to SpEL expression evaluating their values in the context of the iterator element (see below). Argument names are used for operation selection/matching - a candidate operation must have parameters with matching names. The map does not have to contain entries for all operation parameters. Nulls are used as arguments for parameters which are not present in the map. iterator An optional SpEL expression which returns a value to iterate over and invoke the operation for every element. If the result is java.util.Iterator then it is used AS-IS. If the result is Iterable, Stream, or array, an iterator is created to iterate over the elements. If the result is null, then an empty iterator is created. Otherwise, a singleton iterator is created wrapping the result. It allows to invoke the operation zero or more times. If not defined, the iterator contains the source diagram element. pass An optional integer specifying the pass in which this operation shall be invoked. Use for ordering operation invocations. In the above example, because we want the Fox to eat the Hare after the Hare eats the Grass, we need so set pass to 1 for the Fox. selector An optional SpEL boolean expression evaluated in the context of the operation to disambiguate overloaded operations. invoke The last phase of mapping is invoking Invocable URIs specified in invoke property. URIs are resolved relative to the base URI. Invocables are bound to the following arguments by name: target - target (semantic) element, can be null pass registry - a map of source elements to target elements contentProvider progressMonitor resourceSet capabilityLoader Then it is invoked with the source element as a single positional argument. If the invokable return false it means that it could not complete its job in this pass and it will in invoked again in subsequent passes until it returns anything other than false. This functionlity can be used for procedural/imperative mapping in configuration/declarative mapping is not enough or you just prefer to do things procedurally. Groovy mapper Mapping invoke: mapper.groovy\n Script import org.nasdanika.models.nature.Color\n\nSystem.out.println("---");\nSystem.out.println("Source: " + args);\nSystem.out.println("Target: " + target);\nSystem.out.println("Pass: " + pass);\n\ntarget.setColor(Color.BROWN);\n\nreturn pass > 2; // Just to test multiple invocations\n Java mapper Mapping invoke: data:java/org.nasdanika.demos.diagrams.mapping.Services::connectionMapper\n Mapping method \npublic static void connectionMapper(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor loadingProgressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment,\n\t\t@Parameter(name = "target") Object target,\n\t\t@Parameter(name = "pass") int pass,\n\t\t@Parameter(name = "contentProvider") ContentProvider<Element> contentProvider,\n\t\t@Parameter(name = "registry") Map<EObject, EObject> registry,\n\t\t@Parameter(name = "progressMonitor") ProgressMonitor mappingProgressMonitor,\n\t\t@Parameter(name = "resourceSet") ResourceSet resourceSet,\n\t\t@Parameter(name = "capabilityLoader") CapabilityLoader capabilityLoader,\n\t\tConnection source) {\n\n\tSystem.out.println("--- Java mapper ---");\t\t\t\t\n\tSystem.out.println("Connection: " + source);\t\t\n\tSystem.out.println("Pass: " + pass);\t\t\n}\t\n Note the use of positional and named parameters: The first 4 parameters are bound positionally when invocable URI is loaded The 5 named parameters a bound by name by the mapper The last parameter is used for invocation (also positional) Mapping Selector Mapping selector can be used to select zero or more target elements for feature mapping. If it is not provided, then the diagram element’s target element is used for feature mapping, if it is present. Mapping selector shall be a YAML document containing either a single string or a list of strings. The strings are treated as Spring Expression Language (SpEL)] expression evaluating to a target element or a collection of target elements to use for feature mapping. Expressions are evaluated in the context of the diagram element and have access to the following variables: registry progressMonitor resourceSet capabilityLoader Mapping selectors may be used to associate multiple semantic elements with a diagram element for feature mapping purposes. Mapping selector can be defined in mapping-selector property or in an external resource with URI specified in mapping-selector-ref property. The resource URI is resolved relative to the base URI of the diagram element. Feature Mapping This section explains the structure of feature map values. The mapping value can be either a string or a map. If it is a string it is treated as a singleton map to true (unconditional mapping). The below two snippets are equivalent: container:\n other: elements\n container:\n other: \n elements: true\n The map value supports the following keys: argument-type Specifies the type of feature elements to be set/added. String or a list of strings. Each string is a type name as defined above Optionally prefixed with ! for negation. In the case of a list of strings the result is a logical OR - if any of elements matches. Only instances of matching types will be set/added. If absent, the feature type is used. Argument type can be used to restrict elements to a specific subtype of the feature type. Examples: In the below snippet elements of type Transition and its sub-types are excluded from the elements. container:\n self: \n elements:\n argument-type: "!Transition"\n path: 2\n In this example only elements of type Person (and its sub-types) are added to the members feature. container:\n self: \n members:\n argument-type: Person\n This example is equivalent to the previous one, but lists Person sub-types Man and Woman explicitly. container:\n self: \n members:\n argument-type:\n - Man\n - Woman\n comparator Comparator is used for sorting elements of “many” features. See the Comparators section below for a list of available comparators and their configurations. condition A SpEL boolean expression evaluated in the context of the candidate diagram element with the following variables: value - semantic element of the candidate diagram element path - containment path registry - a map of diagram element to semantic elements progressMonitor resourceSet capabilityLoader expression A SpEL expression evaluating to a feature value in the context of the diagram element with with the following variables: value - semantic element of the diagram element path - containment path registry - a map of diagram element to semantic elements progressMonitor resourceSet capabilityLoader greedy Greedy is used with containment features and specifies what to do if a candidate object is already contained by another object: no-children - grab the object if it is contained by an ancestor of this semantic element. This is the default behavior. false - do not grab true - always grab invoke Invocable URI resolved relative to the base URI. The invocable is bound to the following arguments by name: argumentValue - feature value or value evaluated by expression. baseURI context progressMonitor registry sourcePath type resourceSet capabilityLoader It is invoked with argument as positional argument and shall return feature value. path Either an integer number or a list of boolean SpEL expressions to match the path. If an integer, then it is used to match path length as shown in the example below, which matches only immediate children container:\n self: \n elements:\n path: 1\n If a list, then it matches if the list size is equal to the path length and each element evaluates to true in the context of a given path element. Expressions have access to registry variable - a map of diagram elements to semantic (target) elements. nop If true then no mapping is performed and the chain mapper is not invoked. It can be used in scenarios with a default (chained) mapper to prevent the default behavior. position A number specifying the position of the element in the feature collection. Please note that while this key is supported using it may lead to loading errors if the feature collection is smaller than the position. Because the loading order is generally not controlled by the diagram author, only 0 position is guaranteed to work all the time. type Type of the feature object to match. String as defined in the Initialization / type section. Can be used in other mappings. Comparators Comparators are used for “many” features to order elements. A comparator instance is created by AbstractDrawioFactory.createMapperComparator() method which can be overridden in subclasses to provide support for additional comparators. The following comparators are provided “out of the box”: Geometric Diagram element position convey semantics. However, most diagramming tools ignore it. I.e. they lose information or force diagrammers to keep geometry and semantics in sync. Geometric comparators allow to order semantic elements according to the positions of their diagram elements - to semantize geometry. There are two classes of geometric comparators - Angular and Cartesian. Angular Angular comparators use angles to order elements. There are two flavors - clockwise and counterclockwise. clockwise Compares elements by their angle relative to the node of the semantic element which holds the many reference. For example, in the Living Beings demo “Bird”, “Fish”, and “Bacteria” are compared by their angle to the “Living Beings” with the angle counted from “12 o’clock” - 90 degrees (default). Feature mapping with comparators of “Bird”, “Fish”, and “Bacteria” are defined at the connections from “Living Beings” as: source: \nelements:\n comparator: clockwise\n To specify the base angle other than 90 degree use the map version of comparator definition where clockwise is the key mapping to a number or string value. The number value is used as the angle value in degrees. The string value is treated as a Spring Expression Language (SpEL) expression evaluated in the context of the “parent” node. The expression may evaluate to a number or to a node. In the latter case the result is used to compute the angle between the context node and the result node. In the Living Beings example “Streptococcus”, …, “Staphyllococcus” are compared relative to the “Bacteria” node with the base angle being the angle between the “Bacteria” node and “Living Beings” node. As such, “Streptococcus” is the smallest node and “Staphyllococcus” is the largest. With the default angle of 90 degrees “Lactobacyllus” would be the smallest and “Streptococcus” would be the largest. Feature mapping with comparators of “Streptococcus”, …, “Staphyllococcus” is defined at connections from “Bacteria” to the respective genus nodes as: source: \nelements:\n comparator: \nclockwise: incoming[0].source\n incoming[0] evaluates to the connection from “Living Beings” to “Bacteria” and source evaluates to “Living Beings”. counterclockwise Reverse of clockwise. Cartesian Cartesian comparators use horizontal and vertical positions to compare/order elements with 2 coordinates and 2 directions in each it gives us 8 permutations. down-left Compares nodes by their vertical order first with higher nodes being smaller and then by horizontal order with nodes on the right being smaller. Nodes are considered vertically equal if they vertically overlap. down-right Compares nodes by their vertical order first with higher nodes being smaller and then by horizontal order with nodes on the left being smaller. Nodes are considered vertically equal if they vertically overlap. This comparator can be used for org. charts. left-down Compares nodes by their horizontal order first with nodes on the right being smaller and then by vertical order with higher nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. left-up Compares nodes by their horizontal order first with nodes on the right being smaller and then by vertical order with lower nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. right-down Compares nodes by their horizontal order first with nodes on the left being smaller and then by vertical order with higher nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. right-up Compares nodes by their horizontal order first with nodes on the left being smaller and then by vertical order with lower nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. up-left Compares nodes by their vertical order first with lower nodes being smaller and then by horizontal order with nodes on the right being smaller. Nodes are considered vertically equal if they vertically overlap. up-right Compares nodes by their vertical order first with lower nodes being smaller and then by horizontal order with nodes on the left being smaller. Nodes are considered vertically equal if they vertically overlap. Dependency flow and reverse-flow order elements based on how they are connected to each other. flow If one element is reachable from the other by traversing connections, then the reachable element is larger than the source element. In case of circular references the element with the smaller number of traversals to the other element is considered smaller. If elements are not connected they are compared by the fall-back comparator. Flow comparator can be used for workflows and PERT charts. If this comparator’s value is a String, then it is used as a name of the fallback comparator. In the below example children in the Sample Family will be smaller than their parents and siblings will be compared using labels. container:\n self: \nmembers:\n argument-type: Person\n comparator: \nflow: label\n If the value is a map, then it may have the following keys: condition - A boolean SpEL expression evaluated in the context of a connection being traversed. It may be used to traverse only connections which match the condition. fallback - Fallback comparator. The below snippet shows the Internet Banking System Container diagram comparator: container:\n self: \nelements:\n path: 1\n comparator: \nflow: \nfallback: label\n condition: id != 'send-email'\n The condition specifies that a connection with sent-mail ID shall not be traversed. reverse-flow Same as flow but with target nodes being smaller than source nodes. expression A SpEL expression evaluated in the context of the feature element with other variable referencing the element to compare with. The expression has access to the following variables: registry progressMonitor resourceSet capabilityLoader key A SpEL expression evaluated in the context of the feature element. The expression must return a value which would be used for comparison using the natural comparator. label Uses the diagram element label converted to plain text as a sorting key. In the Family mapping demo family members are sorted by label using the following feature map definition: container:\n self: \nmembers:\n argument-type: Person\n comparator: label\n label-descending Uses the diagram element label converted to plain text as a sorting key to compare in reverse alphabetical order. natural Uses the feature element’s compareTo() method for comparable elements. Otherwise compares using the hash code. Nulls are greater than non-nulls. property Uses diagram element property as a sorting key. A singleton map. For example: property: label\n property-descending The same as property, but compares in reverse alphabetical order. https://martinfowler.com/bliki/UbiquitousLanguage.html ↩ https://en.wikipedia.org/wiki/Eclipse_Modeling_Framework ↩ Here and below the term “semantic element” is used interchangeably with the term “target element” to avoid confusion with connection target element. ↩ Module Package Classifier Class Data type Enum Structural Feature Attribute Reference * * * Literal * * Operation * Parameter * * Metamodel Resource Set Resource Object * * Model Page-1"},"nsd-cli/nsd/gitlab/invoke/index.html":{"path":"CLI/nsd/gitlab/invoke","link-uuid":"38d96a5f-6723-4c9e-8a58-c6e04fa421a6","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab invoke [-fhV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri>\r\n [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/java/junit/index.html":{"path":"CLI/nsd/java/junit","link-uuid":"9c7cb60b-fa27-471c-bafc-1f1b006a1672","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.12.0 \r\nUsage: nsd java junit [-fhVw] [--[no-]ai] [--[no-]comment-response]\r\n [--disabled] [--progress-console] [--progress-data]\r\n [--progress-json] [--api-endpoint=<apiEndpoint>]\r\n [--class-suffix=<classSuffix>] [-k=<apiKey>] [-l=<limit>]\r\n [-m=<deploymentOrModelName>]\r\n [--package-suffix=<packageSuffix>]\r\n [--progress-output=<progressOutput>] [-r=<prompt>]\r\n [-s=<sources>] [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <projectURI> <coverageThreshold>\r\n <output> [COMMAND]\r\nGenerates JUnit tests\r\n <projectURI> Project URI\r\n <coverageThreshold> Coverage threshold\r\n <output> Output URI\r\n relative to the project URI\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 --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 --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -f Project URI is a file path\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 -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 --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\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 URI path relative\r\n to the project URIy,\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\r\nCommands:\r\n jacoco Loads coverage from jacoco.exec and classes directory"},"nsd-cli/nsd/model/save/index.html":{"path":"CLI/nsd/model/save","link-uuid":"1c444dee-1ba2-4baf-a27d-da1165441bcb","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]... <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/contribute/retrospect/invoke/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect/invoke","link-uuid":"d89994fb-3b5e-4e28-8e3a-4e06176b4d73","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab contribute retrospect invoke [-fhV] [--progress-console]\r\n [--progress-data] [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri> [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/drawio/html-app/index.html":{"path":"CLI/nsd/drawio/html-app","link-uuid":"1a831d5f-8c39-4faa-a8d1-21bc9ca7200e","title":"html-app","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd drawio html-app [-fhRV] [-b=<base>] [-P=<insertionIndex>]\r\n [-r=<rootLabel>]\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates html application model from a drawio document\r\n -b, --base-uri=<base> Base URI. E.g. 'pages/'\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"nsd-cli/nsd/gitlab/contribute/junit/jacoco/index.html":{"path":"CLI/nsd/gitlab/contribute/junit/jacoco","link-uuid":"3813a50b-3d07-4bfa-8417-a92c7c1659ad","title":"jacoco","content":"Usage: nsd gitlab contribute junit jacoco [-hV] [-c=<classes>] [-j=<jacoco>]\r\n [-m=<moduleName>]\r\nLoads coverage from jacoco.exec and classes directory\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n -h, --help Show this help message and exit.\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 -m, --module=<moduleName> Coverage module name\r\n -V, --version Print version information and exit."},"practices/java/index.html":{"path":"Practices/Java Analysis, Visualization & Generation","link-uuid":"05c18178-0099-49ad-9f37-2de804f5820a","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","link-uuid":"854a555f-5c19-4aca-945e-5a16918d44c4","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. Capability providers may also provide functionality such as: Implement Autocloseable and release resources associated with capabilities upon closing. Implement Lock or ReadWriteLock to guard access to provided capabilities. Extending on the above, a capability provider may implement Domain/Realm with a command stack - obtain, execute commands with locking, close. 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. “bake” capability is provided by an oven which may have a command stack or a lock because only one thing can be baked at a time. 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 examples below. Sources Javadoc Client code - requesting a capability Service capabilities Providing a capability Loading Invocables from URIs Examples String value URL encoded URL and Base64 encoded Java Constructor Static method @Parameter annotation Script Spec JSON YAML Drawio diagram Specification URI Data value/ java/ spel/ application//invocable Hierarchical YAML/JSON specification EMF Requesting a ResourceSet With all packages and factories Selecting contributors Providing ResourceSet instance Contributing EPackages Resource factories URI handlers Applications Services Solutions for architectures Backward chaining Stream processing AI model training/fine-tuning 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 There is a number of implementations of CapabilityFactory is different Nasdanika modules, most of them extending ServiceCapability. In Eclipse or other IDE open CapabilityFactory type hierarchy to discover available implementations. Loading Invocables from URIs The capability framework allows to create/load implementations of Invocable from URIs: In conjunction with the Maven module implementations can be loaded from Maven repositories. Invocables can be implemented in scripting languages, e.g. Groovy. Scripts may use dependencies loaded from Maven repositories. Script engine themselves can be loaded from Maven repositories. Drawio diagrams can be made executable by adding invocable URI properties to diagram elements. They can then be wrapped into a dynamic proxy and invocable URI’s. Examples String value URL encoded data:value/String,Hello+World data URL is converted to an Invocable which takes zero arguments and returns URL-decoded data part of the URL (after comma). CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:value/String,Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n URL and Base64 encoded data:value/String;base64,SGVsbG8= is converted to an Invocable which takes zero arguments and returns URL-decoded and then Base64 decoded data part converted to String. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:value/String;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n Java Constructor data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8= is converted to an Invocable which invokes MyTestClass constructor. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n In the above code snippet invocable is invoked with no arguments, which matches the below constructor passing the decoded data part of the URL in binding argument: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment) {\n\t...\n}\t\n The below snippet passes 33 argument to invoke(): CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke(33);\nSystem.out.println(result);\n Which matches the below constructor: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding, \n\t\tint arg) {\n\t...\n}\n 33 is passed via the arg argument. Static method Static methods can be addresed by adding :: and method name after the class name as in this URL: data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=. The resulting Invocable will select the best matching factory method. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n In the above code snippet invoke() has no arguments and therefore the below method matches: public static MyTestClass factory(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding) {\n\t...\n}\n As with constructors, the decoded data part is passed to the method as binding argument. In the below snippet invoke() takes 55 argument: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke(55);\nSystem.out.println(result);\n Which matches the below method: public static MyTestClass factory(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding,\n\t\tint arg) {\n\t...\n}\n @Parameter annotation Parameter annotation can be used on method and constructor parameters to provide parameter name and optionally narrow parameter type. Script The below snippet exectutes test.groovy script in the current directory. ScriptEngineManger is used to get a ScriptEngine by extension. Therefore, the engine factory shall be registered with the script engine manager. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createFileURI(new File("test.groovy").getCanonicalPath());\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n This is the test script: import org.nasdanika.capability.CapabilityFactory.Loader\nimport org.nasdanika.common.ProgressMonitor\n\n// Script arguments for reference\nLoader loader = args[0];\nProgressMonitor loaderProgressMonitor = args[1];\nObject data = args[2];\n\nSystem.out.println(args);\n"I've got " + args.length + " arguments!"\n Similar to Java constructors and static methods, it takes the following arguments: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods URI’s fragment value or null Invocable arguments In the below code the script receives Hello as its third argument (binding) and Universe as its fourth argument: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createFileURI(new File("test.groovy").getCanonicalPath()).appendFragment("Hello");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke("Universe");\nSystem.out.println(result);\n Spec Spec URI’s allow to specify Maven dependencies to construct a ClassLoader for loading Java classes including script engine factories. It is also to specify a module path to construct a module layer. JSON CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI specUri = URI.createFileURI(new File("test-specs/java.json").getCanonicalPath()).appendFragment("Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n The above snippet uses the below spec to create an instance of MyTestClass: {\n\t"type": "org.nasdanika.capability.tests.MyTestClass",\n\t"bind": [\n\t\t"data:value/String,Some+other+value"\n\t]\n}\t\n Similar to data URL’s a matching constructor is found for the following arguments: CapabilityFactory.Loader ProgressMonitor String - URL decoded URI fragment, may be null Bindings loaded from the bind array of URI’s Below is the matching constructor: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tString fragment,\n\t\tString bind) {\n\t...;\n}\t\n YAML CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor(true);\nURI specUri = URI.createFileURI(new File("test-specs/groovy.yml").getCanonicalPath()).appendFragment("Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n The above snippet executes Groovy script specified inline in the below YAML: script:\n engineFactory: org.codehaus.groovy.jsr223.GroovyScriptEngineFactory\n source: |\n "Hello, world! " + myBinding + " " + args[2]\n bindings:\n myBinding: data:value/String,Some+value\ndependencies: org.apache.groovy:groovy-all:pom:4.0.23\nlocalRepository: target/groovy-test-repo\n In this case org.apache.groovy:groovy-all:pom:4.0.23 Maven coordinates are used to load Groovy with all dependencies and construct a ClassLoader. Because the engine was loaded at runtime, it is not known to the ScriptEngineManager and has to be explicitly specified. The script gets an args array with loader, progress monitor, decoded fragment and arguments passed to invoke(). It also gets named bindings loaded from the bindings map entries. Drawio diagram Below is a YAML spec with an embedded diagram: diagram:\n source: |\n <mxfile ...abridged... </mxfile>\n processor: processor\n bind: bind\n interfaces: java.util.function.Function\n And this is a YAML specification which references a diagram: diagram:\n location: diagram.drawio\n processor: processor\n bind: bind\n interfaces: java.util.function.Function\n The below code loads the spec, passes the fragment to the diagram as properties in addition to the properties from the spec, creates a dynamic proxy which invokes diagram element processors, and uses the proxy to execute the diagram logic: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI specUri = URI.createFileURI(new File("diagram-function.yml").getCanonicalPath()).appendFragment("my-property=Hello");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nFunction<String,Object> result = invocable.invoke();\nSystem.out.println(result);\nSystem.out.println(result.apply("YAML"));\n See Capability tests and Executable Diagrams Dynamic Proxy demo for more examples. Specification URI This section explains supported URI formats. Please note that using a custom URIHandler you may: Normalize “logical” URI’s to supported “physical” URI’s. Implement openStream() For example normalized my-building-blocks://gen-ai/chat-completions to a specification of a chat completions component, say, gitlab://my-shared-components/open-ai/chat-completions.yml and then implement openStream() which supports gitlab scheme[^gitlab_urihandler] Data Data URI has the following format: data:[<mediatype>][;base64],<data>[#fragment]. The following sections describe supported media types. value/ an instance of the class is constructed from the data part bytes, fragment is ignored. if the class name does not contain dots then java.lang. prefix is added to the class name. Examples: * data:value/String,Hello+World * data:value/String;base64,SGVsbG8= java/ Class constructors or static methods are wrapped into an Invocable and the matching constructor/method is invoked from the resulting Invocable.invoke(). Constructors/methods shall have the following signature: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods byte[] - the data part String - fragment Optional additional parameters for arguments passed to the result Invocable Examples: data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=#World data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8= spel/ Evaluates a Spring Expression Langauge (SpEL) expression. Binding by name sets variables. Arguments array is passed to the expression as the root object. It the array is of size 1 then its single element is used as the root object. Example: data:spel/%23myVar+%2B+%23this This online URL Decoder/Encoder can be used to encode expressions. application//invocable With format being either yaml or json. YAML or JSON specification (see below) encoded into the data part. Example: data:application/yaml/invocable;base64,c2Nya...abridged...1yZXBv Hierarchical If the hierarchical URI’s last segment ends with .yml or .yaml (case insensitive) it is treated as a YAML specification (see below). If the last segment ends with .json (also case insensitive) it is treated as a JSON specification. Otherwise a script engine is looked up by extension (the part of the last segments after the last dot). E.g. groovy. Scripts receive args binding (variable) of type Object[] with the following elements: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods String - fragment Arguments passed to the result Invocable YAML/JSON specification YAML/JSON specification is pre-processed and then loaded into InvocableRequirement. The specification supports the following configuration entries: diagram - Map, loaded into DiagramRecord: location - String, URI of the diagram location relative to the specification location. source - String, diagram source. Either location or source shall be used. base - String, base URI if source is used properties - Map, properties to pass to the diagram. Nested properties can be addressed using “.” (dot) separator. For arrays index is used as key. E.g. people.3.name. If URI fragment is present it is parsed into name/value pairs in the same way as query strings are parsed. Fragment properties overwrite spec properties. processor - optional String, property to load processor specifications from. One diagram element may have multiple processor specifications in different properties. Also, property expansion can be used to customize processor specification. E.g. %env%/storage.yaml would point to different specifications depending on the value of %env% property. bind - optional String, property for a dynamic proxy method name or signature interfaces - optional String or List, dynamic proxy interfaces type - String, class name or method reference is ends with ::<static method name> script - Map, loaded into ScriptRecord: location - String, URI of script sources source - String, script source. Either location or source shall be used language - String, script language (mime type) for source. For location if language is not specified it is derived from extension. engineFactory - String, fully qualified name of a script engine factory implementation. Use if the engine is loaded from dependencies and therefore is not visible to the script engine manager. If engineFactory is specified language and location extension are ignored. bindings - Map, values are treated as Invocable URIs providing binding values. Loader, progress monitor, fragment and invocable arguments are available to the script via the args binding of type Object[]. bind - String or List, Invocable URIs to bind to the type Invocable. Not supported by diagram and script. modulePath - optional String or List, module path. If null, derived from root modules if they are present rootModules - optional String or List, root modules. The first root module is used to obtain the class loader oneLayerClassLoader - optional boolean indicating whether a single class loader shall be used for all modules in in the layer dependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format. E.g. org.apache.groovy:groovy-all:pom:4.0.23 managedDependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format remoteRepositories - Map (single remote repository) or List of Maps of remote repository definitions loaded into RemoteRepoRecord: id - String, repo ID type - String, optional repo type url - String, repository URL proxy - optional Map: type - String, http or https host - String port - integer auth - authentication (see below) auth - Map: username - String password - String mirroredRepositories - Map or List, mirrored repositories localRepository - optional String, path to the local repository to download dependencies to. Defaults to repository. Maven dependency resolution uses default values as explained in the Maven module documentation. diagram, type and script are mutually exclusive. Note: extends key is reserved for future releases to support spec inheritance. Configuration is pre-pThe by interpolating system properties and environment variables. E.g. ${my-property} will be expanded to the value of my-property system property if it is set. Respectively, ${env.MY_ENV_VAR} will be expanded to the value of MY_ENV_VAR environment variable if it is set. Property expansion can be escaped with additional {} e.g. ${my-property} will be expanded to ${my-property} regardless of whether my-properety system property is set or not. EMF Many of Nasdanika capabilities are based on Eclipse Modeling Framework (EMF)2, Ecore3 models in particular. One of key objects in EMF Ecore is a ResourceSet. Resource set has a package registry, resource factory registry, and URI converter. org.nasdanika.capability.emf packages provides capability factories for contributing to resource set. It allows to request resource set from a capability loader and the returned resource set would be configured with registered EPackages, resource factories, adapter factories and URIHandlers. Requesting a ResourceSet With all packages and factories CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nfor (CapabilityProvider<?> capabilityProvider: capabilityLoader.load(requirement, progressMonitor)) {\n\tResourceSet resourceSet = (ResourceSet) capabilityProvider.getPublisher().blockFirst();\n}\n Selecting contributors CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\nPredicate<ResourceSetContributor> contributorPredicate = ...;\nResourceSetRequirement serviceRequirement = new ResourceSetRequirement(null, contributorPredicate);\n\t\t\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class, null, serviceRequirement);\t\t\n\nfor (CapabilityProvider<?> capabilityProvider: capabilityLoader.load(requirement, progressMonitor)) {\n\tResourceSet resourceSet = (ResourceSet) capabilityProvider.getPublisher().blockFirst();\n}\n Providing ResourceSet instance You may provide an instance of ResourceSet to configure in the requirement. Contributing EPackages Create a class extending EPackageCapabilityFactory: public class NcoreEPackageResourceSetCapabilityFactory extends EPackageCapabilityFactory {\n\n\t@Override\n\tprotected EPackage getEPackage() {\n\t\treturn NcorePackage.eINSTANCE;\n\t}\n\n\t@Override\n\tprotected URI getDocumentationURI() {\n\t\treturn URI.createURI("https://ncore.models.nasdanika.org/");\n\t}\n\n}\n and add it to module-info.java provides: provides CapabilityFactory with NcoreEPackageResourceSetCapabilityFactory;\n Resource factories Create a class extending ResourceFactoryCapabilityFactory: public class XMIResourceFactoryCapabilityFactory extends ResourceFactoryCapabilityFactory {\n\n\t@Override\n\tprotected Factory getResourceFactory() {\n\t\treturn new XMIResourceFactoryImpl();\n\t}\n\t\n\t@Override\n\tprotected String getExtension() {\n\t\treturn Resource.Factory.Registry.DEFAULT_EXTENSION;\n\t}\n\n}\n and add it to module-info.java provides CapabilityFactory. URI handlers Create a class extending URIConverterContributorCapabilityFactory: public class ClassPathURIHandlerResourceSetCapabilityFactory extends URIConverterContributorCapabilityFactory {\n\n\t@Override\n\tprotected void contribute(URIConverter uriConverter, ProgressMonitor progressMonitor) {\t\n\t\turiConverter.getURIHandlers().add(0, new URIHandlerImpl() {\n\n\t\t\t@Override\n\t\t\tpublic boolean canHandle(URI uri) {\n\t\t\t\treturn uri != null && Util.CLASSPATH_SCHEME.equals(uri.scheme());\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException {\n\t\t\t\treturn DefaultConverter.INSTANCE.toInputStream(uri);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t}\n\t\n}\n and add it to module-info.java provides CapabilityFactory. 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 ↩ See Eclipse Modeling Framework (EMF) - Tutorial and EMF Eclipse Modeling Framework book for more details. ↩ See EMF Ecore chapter in Beyond Diagrams book for a high-level overview of EMF Ecore. ↩"},"nsd-cli/nsd/shell/index.html":{"path":"CLI/nsd/shell","link-uuid":"4a069308-3ba8-48ee-9223-b74e72b835b3","title":"shell","content":"Usage: nsd shell [-hV]\r\nStarts an interactive shell\r\nor executes commands from input\r\nfiles or URL's\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit."},"core/graph/index.html":{"path":"Core/Graph","link-uuid":"9ae6aaba-8274-4633-9fe5-add6d814ced1","title":"Graph","content":"Nasdanika Graph module provides classes for visiting and processing graphs with two types of relationships between graph elements: Containment - one element is contained by another Connection - one element (node) connecting to another node via a connection. On the diagram below containment relationships are shown in bold black and connections in blue Examples of such graphs: A file system with directories containing files and other directories. Connections may take multiple forms such as symbolic links or files, e.g. HTML files, referencing other files. Organizational structure with a hierarchy of organizational units and connections between them. For example, one unit may pass work product to another unit, or a unit may provide services to other units. Country, state, county, city, street, house, people living in that house; family relationships between people and ownership relationships between people and houses. Diagrams, such as Drawio diagrams with a diagram file (resource) containing a Document which contains pages, pages containing layers, and layers containing nodes and connections. Nodes may be nested. Nasdanika Drawio is a module for working with Drawio diagrams. It is built on top of this module. Processes/(work)flows - processes consist of activities and nested processes. Activities are connected by transitions. Distributed systems, such as cloud solutions - availability zones, data centers, clusters, nodes, pods, containers, processes inside containers. All of them communicating to each other via network connections. Work hierarchy and dependencies - in issue trackers issues may be organized into a hierarchy (e.g. Initiative, Epic, Story, Sub-Task in Jira) and have different types of dependencies. In Java a jar contains packages containing sub-packages and classes. Classes contain fields and methods. Fields reference their types, methods call methods of other classes, … EMF Ecore models contain packages. Packages contain sub-packages and classifiers including classes. Classes contain references to other classes. References may be configured as containment (composition) or non-containment. Resources Graph API Processing Dispatching Processors and processor factories Reflection ReflectiveProcessorFactoryProvider Capability Wiring Resources Sources Javadoc Medium stories: General purpose executable graphs and diagrams Concurrent Executable Diagrams Executable (computational) graphs & diagrams Graph API The graph API has 3 interfaces: Element - super-interface for Connection and Node below. Elements may contain other elements. Containment is implemented with <T> T accept(BiFunction<? super Element, Map<? extends Element, T>, T> visitor), which can be thought of as a hierarchical bottom-up reduce - the visitor function is invoked with an element being visited as its first argument and a map of element’s children to results returned by the visitor as the second argument. For leaf elements the second argument may be either an empty map or null. Depending on the map type used by implementations they may also need to implement equals() and hashCode(). Node extends Element and may have incoming and outgoing connections. Connection extends Element and has source and target nodes. Processing Graph processing means associating some behavior with graph elements. That behavior (code execution) may modify the graph or perform other actions. Examples of graph processing: Generate code (HTML site) from a diagram. Demos: Internet Banking System Sample Family Living beings Update a diagram with information from external source. For example, there might be a diagram of a (software) system. Diagram elements can be updated as follows: During development - colors may reflect completion status. Say, in progress elements in blue, completed elements in green, elements with issues in red or amber. In production - color elements based on their monitoring status. Offline - grey, good - green, overloaded - amber, broken - red. The above two examples may be combined - a documentation site might be generated from a system diagram. The diagram may be updated with statuses as part of the generation process and embedded to the home page. A click on a diagram element would navigate to an element documentation page, which may contain detailed status information pulled from tracking/monitoring systems during generation. Dispatching One form of graph processing is dispatching of graph elements to Java methods annotated with Handler annotation. The annotation takes a Spring boolean expression. Graph elements are passed to methods for which the expression is blank or evaluates to true. Below is a code snippet from AliceBobHandlers class: @Handler("getProperty('my-property') == 'xyz'")\npublic String bob(Node bob) {\n\tSystem.out.println(bob.getLabel());\n\treturn bob.getLabel();\n}\n Below is a test method from TestDrawio.testDispatch() test method which dispatches to the above handler method: Document document = Document.load(getClass().getResource("alice-bob.drawio"));\n\t\t\nAliceBobHandlers aliceBobHandlers = new AliceBobHandlers();\t\t\nObject result = document.dispatch(aliceBobHandlers);\nSystem.out.println(result);\n Dispatching is suitable for processing where processing logic for different graph elements does not need to access processing logic of other elements. An example of such logic would be updating diagram elements based on statuses retrieved from tracking/monitoring systems - each element is updated individually. Processors and processor factories Processor package provides means for creating graph element processors and wiring them together so they can interact. One area of where such functionality would be needed is executable diagrams. For example, a flow processor/simulator. Activity processors would need to pass control to connected activities via connection processors. Activity processors may also need to access facilities of their parent processors. The below diagram shows interaction of two nodes via a connection. Connections are bi-directional - source processor may interact with the target processor and vice versa. Some connections may be “pass-through” - just passing interactions without doing any processing. A pass-through connection is depicted below. Graph element processors are wired together with handlers and endpoints: A handler is a java object provided by a processor for receiving interactions from other processors via endpoints. An endpoint is a java object provided to a processor for interacting with other processors. An endpoint may be of the same type as a handler or a handler may be used as an endpoint. This might be the case if processing is performed sequentially in a single JVM. Alternatively, an endpoint may be of different type than the handler it passes interactions to. For example: Endpoint methods may return Futures or CompletionStages of counterpart handler methods - when an endpoint method is invoked it would invoke handler’s method asynchronously. Endpoint methods may take different parameters. E.g. an endpoint method can take InputStream, save it to some storage and pass a URL to the handler method. Processors can also interact by looking up other processors in the processor registry. Endpoints are created by implementations Processors are created in two steps: Processor configs are created by subclasses of ProcessorConfigFactory, e.g. NopEndpointProcessorConfigFactory Processors are created from configs by subclasses of ProcessorFactory overriding createProcessor() method. Client code creates processors by calling createProcessors() method. This method return a registry - Map<Element,ProcessorInfo<P>>. The registry allows the client code to interact with the handler/endpoint/processor wiring created from the graph. TestDrawio.testProcessor() method provides an example of using an anonymous implementation of NopEndpointProcessorFactory for graph processing. Reflection A good deal of processor creation logic is selection of a processor to create for a given graph element in a given situation/context and then “wiring” configuration to the processor. There are two processor factory classes and ReflectiveProcessorWirer class which make the selection/matching/wiring process easier. ReflectiveProcessorFactoryProvider ReflectiveProcessorFactoryProvider invokes methods annotated with Processor annotation to create processors. SyncProcessorFactory is an example of reflective processor factory. Below is one of factory methods: @Processor(\n\ttype = NodeAdapter.class,\n\tvalue = "get() instanceof T(org.nasdanika.models.functionflow.FunctionFlow)")\npublic Object createFunctionFlowProcessor(\n\tNodeProcessorConfig<?,?> config, \n\tboolean parallel, \n\tBiConsumer<Element,BiConsumer<ProcessorInfo<Object>,ProgressMonitor>> infoProvider,\n\tFunction<ProgressMonitor, Object> next,\t\t\n\tProgressMonitor progressMonitor) {\t\n\treturn new FunctionFlowProcessor();\n}\n Capability CapabilityProcessorFactory uses the Nasdanika Capability Framework to delegate processor creation to capability factories. ReflectiveProcessorServiceFactory provides such a capability by collecting reflective targets from capability providers and then using ReflectiveProcessorFactoryProvider mentioned above. This approach provides high level of decoupling between code which executes the graph and code which creates processors. FunctionFlowTests executes a graph loaded from a Drawio diagram. It constructs a processor factory as shown below: CapabilityLoader capabilityLoader = new CapabilityLoader();\t\t\nCapabilityProcessorFactory<Object, BiFunction<Object, ProgressMonitor, Object>> processorFactory = new CapabilityProcessorFactory<Object, BiFunction<Object, ProgressMonitor, Object>>(\n\t\tBiFunction.class, \n\t\tBiFunction.class, \n\t\tBiFunction.class, \n\t\tnull, \n\t\tcapabilityLoader); \n SyncProcessorFactory mentioned above is contributed by SyncCapabilityFactory: @Override\npublic boolean canHandle(Object requirement) {\n\tif (requirement instanceof ReflectiveProcessorFactoryProviderTargetRequirement) {\n\t\tReflectiveProcessorFactoryProviderTargetRequirement<?,?> targetRequirement = (ReflectiveProcessorFactoryProviderTargetRequirement<?,?>) requirement;\n\t\tif (targetRequirement.processorType() == BiFunction.class) { // To account for generic parameters create a non-generic sub-interface binding those parameters.\n\t\t\tProcessorRequirement<?, ?> processorRequiremment = targetRequirement.processorRequirement();\n\t\t\tif (processorRequiremment.handlerType() == BiFunction.class && processorRequiremment.endpointType() == BiFunction.class) {\n\t\t\t\treturn processorRequiremment.requirement() == null; // Customize if needed\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n@Override\npublic CompletionStage<Iterable<CapabilityProvider<Object>>> create(\n\tReflectiveProcessorFactoryProviderTargetRequirement<Object, BiFunction<Object, ProgressMonitor, Object>> requirement,\n\tBiFunction<Object, ProgressMonitor, CompletionStage<Iterable<CapabilityProvider<Object>>>> resolver,\n\tProgressMonitor progressMonitor) {\t\t\n\treturn CompletableFuture.completedStage(Collections.singleton(CapabilityProvider.of(new SyncProcessorFactory())));\t\n}\n canHandle() returns true if the factory can handle the requriement passed to it. create() creates a new instance of SyncProcessorFactory. Note, that create() may request other capabilities. Say, an instsance of OpenAIClient to generate code using chat completions. SyncCapabilityFactory is registered in module-info.java: exports org.nasdanika.models.functionflow.processors.targets.java.sync;\nopens org.nasdanika.models.functionflow.processors.targets.java.sync to org.nasdanika.common; // For loading resources\n\nprovides CapabilityFactory with SyncCapabilityFactory;\n Note that a package containing reflective factories and processors shall be opened to org.nasdanika.common for reflection to work. Wiring Processors created by the above factories are introspected for the following annotations: All processors: ChildProcessor - field a method to inject processor or config of element’s child matching the selector expression. ChildProcessors - field or method to inject a map of children elements to their processor info. ParentProcessor - field or method to inject processor or config of element’s parent. ProcessorElement - field or method to inject the graph element. Registry - field or method to inject the registry - a map of graph elements to their info. RegistryEntry - field or method to inject a matching registry entry. Node processors: IncomingEndpoint - field or method to inject a matching incoming endpoint. IncomingEndpoints - field or method to inject a map of incoming connections to their endpoints completion stages. IncomingHandler - field or method to obtain a handler for an incoming connection. IncomingHandlerConsumers - field or method to inject a map of incoming connections to java.util.function.Consumers of handlers. OutgoingEndpoint - field or method to inject a matching outgoing endpoint. OutgoingEndpoints - field or method to inject a map of outgoing connections to their endpoints completion stages. OutgoingHandler - field or method to obtain a handler for an outgoing connection. OutgoingHandlerConsumers - field or method to inject a map of outgoing connections to consumers of handlers. Connection processors: SourceEndpoint - field or method into which a connection source endpoint is injected. Source endpoint allows the connection processor to interact with the connection source handler. SourceHandler - field or method from which the connection source handler is obtained. TargetEndpoint - field or method into which a connection target endpoint is injected. Target endpoint allows the connection processor to interact with the connection target handler. TargetHandler - Field or method from which the connection target handler is obtained. Element/Node/Connection configuration is declaratively “wired” to processors’ fields and methods. Configuration can also be wired imperatively. Declarative and imperative styles can be used together. Below is an example of using @OutgoingEndpoint annotation by StartProcessor: public class StartProcessor implements BiFunction<Object, ProgressMonitor, Object> {\n\n\tprotected Collection<BiFunction<Object, ProgressMonitor, Object>> outgoingEndpoints = Collections.synchronizedCollection(new ArrayList<>());\t\n\t\n\t@Override\n\tpublic Object apply(Object arg, ProgressMonitor progressMonitor) {\n\t\tMap<BiFunction<Object, ProgressMonitor, Object>, Object> outgoingEndpointsResults = new LinkedHashMap<>();\n\t\tfor (BiFunction<Object, ProgressMonitor, Object> e: outgoingEndpoints) {\n\t\t\toutgoingEndpointsResults.put(e, e.apply(arg, progressMonitor));\n\t\t}\n\t\treturn outgoingEndpointsResults;\n\t}\n\t\n\t@OutgoingEndpoint\n\tpublic void addOutgoingEndpoint(BiFunction<Object, ProgressMonitor, Object> endpoint) {\n\t\toutgoingEndpoints.add(endpoint);\n\t}\n\n}``` Root A B A1 A2 B1 Page-1 Node Processor Node Processor source -> target processor target -> source processor Page-1 Node Processor Node Processor Page-1"},"nsd-cli/nsd/drawio/html-app/site/index.html":{"path":"CLI/nsd/drawio/html-app/site","link-uuid":"090f266c-df29-4fb5-a5f9-e8df11c3a8fe","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd drawio html-app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>]\r\n [-F=<pageTemplateFile>] [-m=<domian>]\r\n [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/model/html-app/save/index.html":{"path":"CLI/nsd/model/html-app/save","link-uuid":"aecd4efa-4fa1-4118-bea2-8264fc5093e8","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model html-app save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>].\r\n ..\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/rules/list/index.html":{"path":"CLI/nsd/rules/list","link-uuid":"d9fc9fd9-081a-4f69-a0b2-58bf2212e392","title":"list","content":"Usage: nsd rules list [-hrV] [--progress-console] [--progress-data]\r\n [--progress-json] [-o=<output>]\r\n [--progress-output=<progressOutput>] [--exclude-rule\r\n [=<ruleExcludes>...]]... [--exclude-rule-set\r\n [=<ruleSetExcludes>...]]... [--include-rule\r\n [=<ruleIncludes>...]]... [--include-rule-set\r\n [=<ruleSetIncludes>...]]...\r\nLists available rule sets and rules\r\n --exclude-rule[=<ruleExcludes>...]\r\n ID's of rules to exclude\r\n --exclude-rule-set[=<ruleSetExcludes>...]\r\n ID's of rule sets to exclude\r\n -h, --help Show this help message and exit.\r\n --include-rule[=<ruleIncludes>...]\r\n ID's of rules to include\r\n --include-rule-set[=<ruleSetIncludes>...]\r\n ID's of rule sets to include\r\n -o, --output=<output> Output file\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --[no-]rules Output rules\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/gsh/index.html":{"path":"CLI/nsd/gitlab/gsh","link-uuid":"7efa02fb-6135-4beb-b213-0b81d57914f6","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab gsh [-hV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/http-server/index.html":{"path":"CLI/nsd/http-server","link-uuid":"c3bc5c40-d57f-4065-8fa9-1867dfd874c7","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/model/index.html":{"path":"CLI/nsd/model","link-uuid":"186e29ad-5b74-415e-832b-9716cbe8413a","title":"model","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model [-fhV] [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]... <uri> [COMMAND]\r\nLoads EObject from a URI or file\r\n <uri> EObject URI or file path, resolved relative\r\n to the current directory\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit.\r\nCommands:\r\n ecore-html-app Generates Ecore model documentation html app model\r\n html-app Generates html application model from a drawio document\r\n save Saves model to a file"},"nsd-cli/nsd/launcher/index.html":{"path":"CLI/nsd/launcher","link-uuid":"a8eaa357-5a16-4ce0-a1d4-2ec69088f783","title":"launcher","content":"Version: org.nasdanika.cli@2024.12.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 information\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/rules/site/index.html":{"path":"CLI/nsd/rules/site","link-uuid":"593d870e-fa3a-4e53-8b71-c089a299a62f","title":"site","content":"Usage: nsd rules site [-fhlRV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [--root-action-icon=<rootActionIcon>]\r\n [--root-action-location=<rootActionLocation>]\r\n [--root-action-text=<rootActionText>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]... [-i\r\n [=<includes>...]]... <model> <output>\r\nGenerates rule set documentation site\r\n <model> Model URI, resolved relative\r\n to the current directory\r\n or looked up in registered rule sets\r\n if -R option is provided\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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -f, --file Mdel parameter is a file path\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\r\n -R, --registered Use registered rule set\r\n with provided URI\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"},"core/persistence/index.html":{"path":"Core/Persistence","link-uuid":"0b67c53b-6a75-4dec-a11e-ca4bd93b3583","title":"Persistence","content":"Sources Javadoc"},"nsd-cli/nsd/drawio/index.html":{"path":"CLI/nsd/drawio","link-uuid":"8b1170c8-d0c8-4ec6-aa61-65cbab137fab","title":"drawio","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd drawio [-fhV] [-p=<String=String>]... [-P=URL]...\r\n [-u=<String=String>]... [-U=URL of URI to URL mapping\r\n resource]... <document> [COMMAND]\r\nLoads Drawio document from a URI or file\r\n <document> Document URI or file path, resolved relative\r\n to the current directory\r\n -f, --file Document parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in the\r\n order of definition, later properties replacing the\r\n former\r\n -u, --uri=<String=String>\r\n URI to URL mapping\r\n Target URLs are resolved\r\n relative to the document URL\r\n -U, --uris=URL of URI to URL mapping resource\r\n URI map resource URL relative to the document file\r\n YAML, JSON, or properties\r\n Type is inferred from the content type header, if it\r\n is present,\r\n or extension\r\n -V, --version Print version information and exit.\r\nCommands:\r\n html-app Generates html application model from a drawio document"},"nsd-cli/nsd/java/junit/jacoco/index.html":{"path":"CLI/nsd/java/junit/jacoco","link-uuid":"ef3da8e0-4c12-4703-9b5c-0b874a2022b9","title":"jacoco","content":"Usage: nsd java junit jacoco [-hV] [-c=<classes>] [-j=<jacoco>]\r\n [-m=<moduleName>]\r\nLoads coverage from jacoco.exec and classes directory\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n -h, --help Show this help message and exit.\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 -m, --module=<moduleName> Coverage module name\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/contribute/index.html":{"path":"CLI/nsd/gitlab/contribute","link-uuid":"85fb33c9-254b-4edf-af0c-2ca3fa21d1e4","title":"contribute","content":"Usage: nsd gitlab contribute [-hV] [-a=<String=String>]... (<authorEmail>\r\n <authorName> [-m=<commitMessage>] [-b=<branch>]\r\n [-f] [-s]) [[-t=<targetBranch>] [--[no-]\r\n allow-collaboration]\r\n [--approvals-before-merge=<approvalsBeforeMerge>]\r\n [--assignee=<Assignee ID>]...\r\n [--merge-request-description=<description>] [--\r\n [no-]discussion-locked] [--label=<labels>]...\r\n [--milestone=<milestoneId>] [--[no-]\r\n remove-source-branch] [--reviewer=<Reviewer\r\n ID>]... [--[no-]squash]\r\n [--merge-request-title=<title>]\r\n [--state-event=<stateEvent>]] [COMMAND]\r\nParent for sub-command contributing via GitLabURIHandler\r\n -a, --alias=<String=String>\r\n Map project alias (key) to project ID or path (value)\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommit\r\n <authorEmail> Commit author eMail\r\n <authorName> Commit author name\r\n -b, --branch=<branch> Branch to commit to\r\n -f, --force Force commit\r\n -m, --commit-message=<commitMessage>\r\n Commit message\r\n -s, --stats With stats\r\nMerge request\r\n --[no-]allow-collaboration\r\n\r\n --approvals-before-merge=<approvalsBeforeMerge>\r\n Number of approvals before merge\r\n --assignee=<Assignee ID>\r\n Assignee ID\r\n --[no-]discussion-locked\r\n\r\n --label=<labels>\r\n --merge-request-description=<description>\r\n\r\n --merge-request-title=<title>\r\n\r\n --milestone=<milestoneId>\r\n Milestone ID\r\n --[no-]remove-source-branch\r\n\r\n --reviewer=<Reviewer ID>\r\n Reviewer ID\r\n --[no-]squash\r\n --state-event=<stateEvent>\r\n Valid values: close, reopen\r\n -t, --target-branch=<targetBranch>\r\n Target branch, defaults to the original branch\r\nCommands:\r\n gsh Groovy Shell\r\n invoke Invokes URI\r\n junit Generates JUnit tests\r\n retrospect Parent for sub-commands contributing based on history"},"core/cli/index.html":{"path":"Core/CLI","link-uuid":"078f1c10-01a6-4f00-8a3d-95bd7ac56ea8","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. Sources Javadoc Medium stories: Beyond PicoCLI Declarative Command Pipelines Contributing sub-commands @SubCommands annotation @ParentCommands annotation Programmatic match Contributing mix-ins @MixIns annotation @ParentCommands annotation Programmatic match Overriding Extended documentation Commands Mix-ins Shell Closing commands Building distributions Downloading dependencies Generating launcher scripts Assembly 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. @ParentCommands annotation In this case the sub-command or mix-in class are annotated with @ParentCommands 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, or implement Adaptable and return non-null value from adaptTo(Class) method. This allows to create declarative command pipelines as explained in the Declarative Command Pipelines Medium story. 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. @ParentCommands annotation See “@ParentCommands 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. Commands The CLI module provides several base command classes: CommandBase - base class with standard help mix-in CommandGroup - base class for commands which don’t have own functionality, only sub-commands ContextCommand - command with options to configure Context DelegatingCommand - options to configure Context and ProgressMonitor and delegate execution to SupplierFactory HelpCommand - outputs usage for the command hierarchy in text, html, action model, or generates a documentation site Mix-ins The module also provides several mix-ins: ContextMixIn - creates and configures Context ProgressMonitorMixIn - creates and configures ProgressMonitor ResourceSetMixIn - creates and configures ResourceSet using CapabilityLoader to add packages, resource and adapter factories, … Shell ShellCommand can be used to execute multiple commands in the same JVM. Closing commands Commands implementing org.nasdanika.common.Closeable, including CommandBase and its subclasses are closed recursively. This functionality can be used to release resources or save state to the permanent storage, e.g. file system. 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 a Maven build. Building a distribution involves the following steps: Downloading modules (dependencies) Generating launcher scripts Building an assembly (zip) All of the above steps are executed by mvn verify or mvn clean verify 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. Assembly Create an assembly file dist.xml similar to the one below in src\\assembly directory: <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"\n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">\n <id>dist</id>\n <formats>\n <format>tar.gz</format>\n <format>tar.bz2</format>\n <format>zip</format>\n </formats>\n <fileSets>\n <fileSet>\n <directory>${project.build.directory}/dist</directory>\n <outputDirectory>/</outputDirectory>\n <useDefaultExcludes>false</useDefaultExcludes>\n </fileSet>\n </fileSets>\n</assembly>\n then add the following plugin definition to pom.xml: <plugin>\n\t<artifactId>maven-assembly-plugin</artifactId>\n\t<version>3.7.1</version>\n\t<configuration>\n\t\t<outputDirectory>${project.build.directory}</outputDirectory>\n\t\t<formats>zip</formats>\n\t\t<appendAssemblyId>false</appendAssemblyId>\n\t\t<finalName>nsd-cli-${project.version}</finalName>\n\t\t<descriptors>\n\t\t\t<descriptor>src/assembly/dist.xml</descriptor>\n\t\t</descriptors>\n\t</configuration>\n <executions>\n <execution>\n <id>create-archive</id>\n <phase>verify</phase>\n <goals>\n <goal>single</goal>\n </goals>\n </execution>\n </executions>\n</plugin>\t\t \t\t\t\n Change the final name to your CLI name. E.g. my-company-cli."},"core/resources/index.html":{"path":"Core/Resources","link-uuid":"39a80721-f157-4a22-941f-62f99126a1b5","title":"Resources","content":"Sources Javadoc"},"practices/index.html":{"link-uuid":"5c45f75b-c116-4a2b-a392-c1f5db57c772","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. ↩"},"nsd-cli/nsd/invoke/index.html":{"path":"CLI/nsd/invoke","link-uuid":"340c8501-61e4-4cae-bfd1-fd4a9d10d499","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd invoke [-fhV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri> [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/emf/index.html":{"path":"Core/EMF","link-uuid":"c639f1c2-b4c8-4718-842d-587f39d0a44a","title":"EMF","content":"Sources Javadoc"},"nsd-cli/nsd/gitlab/contribute/gsh/index.html":{"path":"CLI/nsd/gitlab/contribute/gsh","link-uuid":"ba83be68-3ccd-4ce0-97df-e3828aeb47dd","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab contribute gsh [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/index.html":{"path":"CLI/nsd","link-uuid":"c56f3d25-65af-4e21-b80e-5fe2fb7aa4e9","title":"nsd","content":"Version: org.nasdanika.cli@2024.12.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 drawio Loads Drawio document from a URI or file\r\n gitlab Commands for working with GitLab\r\n gsh Groovy Shell\r\n help Outputs usage for all registred commands\r\n http-server Serves HTTP routes\r\n invoke Invokes URI\r\n java Commands related to Java\r\n model Loads EObject from a URI or file\r\n rules Rules commands\r\n shell Starts an interactive shell"},"nsd-cli/nsd/gitlab/contribute/retrospect/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect","link-uuid":"572a725f-4e5a-4498-93b4-62992db8761c","title":"retrospect","content":"Usage: nsd gitlab contribute retrospect [-hV] [--ref=<ref>] [--since=<since>]\r\n [--until=<until>] [--path=<paths>]...\r\n <project> [COMMAND]\r\nParent for sub-commands contributing based on history\r\n <project> Project ID or path\r\n -h, --help Show this help message and exit.\r\n --path=<paths> Paths of interest\r\n --ref=<ref> Reference - branch, tag, or commit\r\n --since=<since> Since date in ISO8601 format yyyy-MM-dd'T'HH:mm:ssZ\r\n --until=<until> Since date in ISO8601 format yyyy-MM-dd'T'HH:mm:ssZ\r\n -V, --version Print version information and exit.\r\nCommands:\r\n gsh Groovy Shell\r\n invoke Invokes URI"},"nsd-cli/nsd/drawio/html-app/save/index.html":{"path":"CLI/nsd/drawio/html-app/save","link-uuid":"eeec6e75-c768-4c1f-ba70-ab96cfbc886e","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd drawio html-app save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>]\r\n ...\r\n [--extension-resource-factory=<String=Class>]...\r\n\r\n [--protocol-resource-factory=<String=Class>]...\r\n <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"html/jstree/index.html":{"path":"HTML/JsTree","link-uuid":"256e5f01-4e3b-401b-817f-f0211e68f08a","title":"JsTree","content":"Sources Javadoc"},"nsd-cli/nsd/model/ecore-html-app/index.html":{"path":"CLI/nsd/model/ecore-html-app","link-uuid":"855e1e23-9b7b-41a9-9f0e-09506d540a2d","title":"ecore-html-app","content":"Version: org.nasdanika.models.ecore.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app [-fhRV] [-P=<insertionIndex>] [-r=<rootLabel>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [--content-type-resource-factory=<String=Class>]\r\n ...\r\n [--extension-resource-factory=<String=Class>]...\r\n [-M=<String=String>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates Ecore model documentation html app model\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 directory.\r\n YAML, JSON, or properties. In properties dots are\r\n treated as key path separators. Type is inferred from\r\n the content type header, if it is present, or\r\n extension. Contexts are composed in the order of\r\n definition, later context entries shadowing the former\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the current\r\n directory. YAML, JSON, or properties. In properties\r\n dots are treated as key path separators. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Mounts shadow context entries.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"glossary.html":{"link-uuid":"b62c2e33-595d-4119-9c16-74cc9b09b32d","title":"Glossary","content":"Clear Identifier(s) Hide UUID {{data.value.name}} {{data.value[0].value}} {{item.value}}"},"nsd-cli/nsd/rules/index.html":{"path":"CLI/nsd/rules","link-uuid":"1b9261e4-d4bf-4963-823f-15fe92e20476","title":"rules","content":"Usage: nsd rules [-hV] [COMMAND]\r\nRules commands\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n action-model Generates rule set documentation action model\r\n list Lists available rule sets and rules\r\n site Generates rule set documentation site"},"core/exec/index.html":{"path":"Core/Exec","link-uuid":"1c81ca9c-4663-4cfe-b02a-753e6b1c95b8","title":"Exec","content":"Sources Javadoc"},"html/html/index.html":{"path":"HTML/HTML","link-uuid":"1a631497-143a-4798-b284-1de34dd191a9","title":"HTML","content":"Sources Javadoc"},"nsd-cli/nsd/gitlab/contribute/junit/index.html":{"path":"CLI/nsd/gitlab/contribute/junit","link-uuid":"2081a7f5-09d4-45b5-ac43-ac17c41694d3","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.12.0 \r\nUsage: nsd gitlab contribute junit [-fhVw] [--[no-]ai] [--[no-]\r\n comment-response] [--disabled]\r\n [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--api-endpoint=<apiEndpoint>]\r\n [--class-suffix=<classSuffix>] [-k=<apiKey>]\r\n [-l=<limit>] [-m=<deploymentOrModelName>]\r\n [--package-suffix=<packageSuffix>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<prompt>] [-s=<sources>]\r\n [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e\r\n [=<excludes>...]]... [-i[=<includes>...]]...\r\n <projectURI> <coverageThreshold> <output>\r\n [COMMAND]\r\nGenerates JUnit tests\r\n <projectURI> Project URI\r\n <coverageThreshold> Coverage threshold\r\n <output> Output URI\r\n relative to the project URI\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 --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 --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -f Project URI is a file path\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 -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 --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\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 URI path relative\r\n to the project URIy,\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\r\nCommands:\r\n jacoco Loads coverage from jacoco.exec and classes directory"},"nsd-cli/nsd/java/index.html":{"path":"CLI/nsd/java","link-uuid":"6aaf298d-8c20-4324-913e-a04b05260285","title":"java","content":"Version: org.nasdanika.models.java.cli@2024.12.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","link-uuid":"2f9f67bd-cb80-40dc-9863-d29959fe22b3","title":"site","content":"Usage: nsd help site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [--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 -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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/gitlab/contribute/retrospect/gsh/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect/gsh","link-uuid":"2a935f00-544b-49e2-9747-5d2f9496f9f4","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab contribute retrospect gsh [-hV] [--progress-console]\r\n [--progress-data] [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/index.html":{"link-uuid":"4fa3bcd8-f85d-4204-aa48-69825a5542e4","title":"Core","content":"Sources"},"practices/generic/index.html":{"path":"Practices/Analysis, Visualization & Generation","link-uuid":"d727b659-9685-456a-a48c-734e1e30697b","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 Transformation 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 Transformation Corporation Marketing Finance Uses Operations HR Builds IT Execution environments Binary packages Source Code Application Transformation"},"nsd-cli/nsd/gitlab/index.html":{"path":"CLI/nsd/gitlab","link-uuid":"a2a87981-ae84-4b68-8c52-371646a2165f","title":"gitlab","content":"Usage: nsd gitlab [-hV] [-l=<clientRateLimit>] [-t=<accessToken>] [-u=<url>]\r\n [-w=<clientRateLimitWindow>] [COMMAND]\r\nCommands for working with GitLab\r\n -h, --help Show this help message and exit.\r\n -l, --client-rate-limit=<clientRateLimit>\r\n Client enforced rate limit\r\n use this option if the server limits requests rate,\r\n but does not rate limit headers to the client\r\n only errors if the rate limit is exceeded\r\n -t, --access-token=<accessToken>\r\n GitLab access token, defaults to the value of\r\n GITLAB_ACCESS_TOKEN environment variable\r\n -u, --url=<url> GitLab URL, defaults to the value of\r\n GITLAB_URL environment variable\r\n -V, --version Print version information and exit.\r\n -w, --client-rate-limit-window=<clientRateLimitWindow>\r\n Client enforced rate limit window in seconds\r\n defaults to 10\r\n ignored if the client rate limit is not set\r\nCommands:\r\n contribute Parent for sub-command contributing via GitLabURIHandler\r\n gsh Groovy Shell\r\n invoke Invokes URI"},"core/http/index.html":{"path":"Core/HTTP","link-uuid":"b8f674f1-9d3f-4fe7-8aa9-7774f6271e66","title":"HTTP","content":"Sources Javadoc"},"nsd-cli/nsd/model/ecore-html-app/site/index.html":{"path":"CLI/nsd/model/ecore-html-app/site","link-uuid":"cd60c42f-7211-4300-b694-c248157f795d","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app site [-hlV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [-b=<baseDir>] [-F=<pageTemplateFile>]\r\n [-m=<domian>] [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e\r\n [=<excludes>...]]... [-i\r\n [=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/help/index.html":{"path":"CLI/nsd/help","link-uuid":"f460352e-1d31-4ca2-ad0e-56c29428a8c9","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":{"link-uuid":"ec620720-90e7-451f-88ea-f12a690f2a19","title":"HTML","content":"Sources"},"nsd-cli/nsd/model/html-app/site/index.html":{"path":"CLI/nsd/model/html-app/site","link-uuid":"5bd766eb-6711-4178-b0d1-8b0704f9a360","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model html-app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>]\r\n [-F=<pageTemplateFile>] [-m=<domian>]\r\n [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"core/maven/index.html":{"path":"Core/Maven","link-uuid":"0d53ab80-3272-4949-bba4-00a2434c6c4c","title":"Maven","content":"Nasdanika Maven module uses Maven Resolver Supplier to provide capabilities for Dependency and ClassLoader requirements. Sources Javadoc Dependency CapabilityLoader capabilityLoader = new CapabilityLoader();\nDependencyRequestRecord requirement = new DependencyRequestRecord(\n\t\tnew String[] { "org.apache.groovy:groovy-all:pom:4.0.23" }, \n\t\tnull, \n\t\tnull, \n\t\t"target/test-repo");\n\t\t\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nCollection<File> result = capabilityLoader.loadOne(requirement, progressMonitor);\n The above code snippet loads org.apache.groovy:groovy-all:pom:4.0.23 and its dependencies into target/test-repo directory and returns a list of jar files. ClassLoader CapabilityLoader capabilityLoader = new CapabilityLoader();\nClassLoaderRequirement requirement = new ClassLoaderRequirement(\n\t\tnull, // String[] modulePath,\n\t\tnull, // String[] rootModules,\n\t\tnew ModuleLayer[] { getClass().getModule().getLayer() }, \n\t\tgetClass().getClassLoader(), // ClassLoader parentClassLoader,\n\t\ttrue, // boolean singleLayerClassLoader,\t\t\t\t\n\t\tnew String[] { "org.apache.groovy:groovy-all:pom:4.0.23" }, \n\t\tnull, \n\t\tnull, \n\t\t"target/test-repo",\n\t\tSystem.out::println);\n\t\t\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nClassLoader result = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(ClassLoader.class, null, requirement),\n\t\tprogressMonitor);\n\t\t\nClass<?> scriptEngineFactoryClass = result.loadClass("org.codehaus.groovy.jsr223.GroovyScriptEngineFactory");\n The above code snippet: Loads org.apache.groovy:groovy-all:pom:4.0.23 and its dependencies into target/test-repo directory Creates a ClassLoader Loads org.codehaus.groovy.jsr223.GroovyScriptEngineFactory class Default configuration DependencyCapabilityFactory, which is responsible for resolving and downloading dependencies, loads default configuration in the following way: If org.nasdanika.maven.DependencyCapabilityFactory.config.yml system property is set, then it is treated as a URL of a configuration YAML resource. The URL is resolved relative to the current directory. If org.nasdanika.maven.DependencyCapabilityFactory.config.json system property is set, then it is treated as a URL of a configuration JSON resource. The URL is resolved relative to the current directory. If NSD_DEPENDENCY_RESOLVER_CONFIG_YAML_URL environment variable is set, then it is treated as an absolute URL of a configuration YAML resource. If NSD_DEPENDENCY_RESOLVER_CONFIG_JSON_URL environment variable is set, then it is treated as an absolute URL of a configuration JSON resource. If NSD_DEPENDENCY_RESOLVER_CONFIG_YAML environment variable is set, then it is treated as YAML configuration. If NSD_DEPENDENCY_RESOLVER_CONFIG_JSON environment variable is set, then it is treated as JSON configuration. If dependency-reolver-config.yml file exists in the current directory the it is loaded as YAML. If dependency-reolver-config.json file exists in the current directory the it is loaded as JSON. The loaded configuration is interpolated with system properties and environment variables. E.g. ${my-property} will be expanded to the value of my-property system property if it is set. Respectively, ${env.MY_ENV_VAR} will be expanded to the value of MY_ENV_VAR environment variable if it is set. Property expansion can be escaped with additional {} e.g. ${my-property} will be expanded to ${my-property} regardless of whether my-properety system property is set or not. Configuration specification modulePath - optional String or List, module path. If null, derived from root modules if they are present rootModules - optional String or List, root modules. The first root module is used to obtain the class loader oneLayerClassLoader - optional boolean indicating whether a single class loader shall be used for all modules in in the layer dependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format. E.g. org.apache.groovy:groovy-all:pom:4.0.23 managedDependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format remoteRepositories - Map (single remote repository) or List of Maps of remote repository definitions loaded into RemoteRepoRecord: id - String, repo ID type - String, optional repo type url - String, repository URL proxy - optional Map: type - String, http or https host - String port - integer auth - authentication (see below) auth - Map: username - String password - String mirroredRepositories - Map or List, mirrored repositories localRepository - optional String, path to the local repository to download dependencies to. Defaults to repository. URI Handler Maven URIHandler handles URIs of the following format: maven://<groupId>/<artifactId>/<extension>/<version>/<resource path>[?classifier=<classifier>]. For example, for maven://org.nasdanika.models.architecture/model/jar/2024.8.0/model/architecture.ecore?classifier=model URI model/architecture.ecore resource would be loaded from model-2024.8.0-model.jar in org.nasdanika.models.architecture group model artifact version 2024.8.0 as shown in the snippet below: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nResourceSet resourceSet = capabilityLoader.loadOne(requirement, progressMonitor);\nURI modeURI = URI.createURI("maven://org.nasdanika.models.architecture/model/jar/2024.8.0/model/architecture.ecore?classifier=model");\nResource resource = resourceSet.getResource(modeURI, true);\nSystem.out.println(resource.getContents());"},"nsd-cli/nsd/gsh/index.html":{"path":"CLI/nsd/gsh","link-uuid":"6930bdd9-91e8-46c8-877d-c9e8203de001","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gsh [-hV] [--progress-console] [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>] [-p=<String=String>]...\r\n [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/diagram/index.html":{"path":"Core/Diagram","link-uuid":"0cd651ce-1699-4b4e-868c-0cd6e6ca7c49","title":"Diagram","content":"Sources Javadoc"},"nsd-cli/nsd/rules/action-model/index.html":{"path":"CLI/nsd/rules/action-model","link-uuid":"4023b714-b637-4102-b913-942751ce6673","title":"action-model","content":"Usage: nsd rules action-model [-fhRV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... <model> <output>\r\nGenerates rule set documentation action model\r\n <model> Model URI or file path, resolved relative\r\n to the current directory\r\n or looked up in registered rule sets\r\n if -R option is provided\r\n <output> Output file\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 type\r\n header, if it is present, or extension. Contexts\r\n are composed in the order of definition, later\r\n context entries shadowing the former\r\n -f, --file Mdel parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext 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 type\r\n header, if it is present, or extension. Mounts\r\n shadow context entries.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -R, --registered Use registered rule set\r\n with provided URI\r\n -V, --version Print version information and exit."},"html/bootstrap/index.html":{"path":"HTML/Bootstrap","link-uuid":"2f238adc-13f1-406c-be82-80390bfffb58","title":"Bootstrap","content":"Sources Javadoc"},"nsd-cli/nsd/app/index.html":{"path":"CLI/nsd/app","link-uuid":"8ace60fd-23a4-485a-af76-9f19e8425f10","title":"app","content":"Version: org.nasdanika.models.app.cli@2024.12.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"},"index.html":{"link-uuid":"4b254e60-aab3-492a-9868-b3995a73bc46","title":"Nasdanika","content":" Common Resources Persistence Ncore Diagram Graph Drawio EMF Exec Maven Capability CLI HTTP Mapping Core JsTree Bootstrap HTML HTML GitLab Architecture Git Excel ECharts Nature Bank PDF Party Source Engineering Java Maven Enterprise Function Flow Rules Azure Ecore Jira Bootstrap App Capability Coverage Decision Analysis Family Flow HTML Models Analysis, Visualization & Generation Java Analysis, Visualization & Generation JUnit Tests Generation Practices Beyond Diagrams Java Analysis, Visualization, and Generation Books CLI YouTube Channel Medium Publication Template Repositories AWS Diagram (Drawio Site) Bob the Builder (Drawio site) Function Flow Concurrent Executable Diagrams Executable Diagram Dynamic Proxy General Purpose Executable Diagrams Internet Banking System (Drawio Site) Internet Banking System (C4 Model mapping) Maven Graph Semantic Mapping CLI Compute Graph Demos Nasdanika"},"nsd-cli/nsd/model/ecore-html-app/save/index.html":{"path":"CLI/nsd/model/ecore-html-app/save","link-uuid":"43e10ad7-4ad7-42b4-a742-d6bf1d6c1433","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app save [-hV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Cl\r\n ass>]...\r\n [--extension-resource-factory=<String=Class\r\n >]...\r\n [--protocol-resource-factory=<String=Class>\r\n ]... <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/app/site/index.html":{"path":"CLI/nsd/app/site","link-uuid":"217a9773-d7bf-4884-a30e-0e8535bd3dfd","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>] [-T=<pageTemplate>]\r\n [-w=<workDir>] [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]... [-i\r\n [=<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 -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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"core/common/index.html":{"path":"Core/Common","link-uuid":"c71bc150-a96c-43bd-9089-f914244c567a","title":"Common","content":"Sources Javadoc"},"nsd-cli/nsd/model/html-app/index.html":{"path":"CLI/nsd/model/html-app","link-uuid":"8bb9d4b7-5ff1-4f2d-a87a-097a24bb16d6","title":"html-app","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model html-app [-fhRV] [-P=<insertionIndex>] [-r=<rootLabel>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [-M=<String=String>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates html application model from a drawio document\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 directory.\r\n YAML, JSON, or properties. In properties dots are\r\n treated as key path separators. Type is inferred from\r\n the content type header, if it is present, or\r\n extension. Contexts are composed in the order of\r\n definition, later context entries shadowing the former\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the current\r\n directory. YAML, JSON, or properties. In properties\r\n dots are treated as key path separators. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Mounts shadow context entries.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"practices/junit/index.html":{"path":"Practices/JUnit Tests Generation","link-uuid":"78ecbb39-34b1-46a2-b8fe-18d8177ee712","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 nor 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 Retrieval Augmented Generation Java Sources Bytecode Coverage Data Developer Gen AI Coverage Model Source Code Model Tests Model Generator JUnit Test Generation Retrieval Augmented Generation Writing Code Compilation Testing Test Generation Gen AI Retrieval Augmented Generation"},"nsd-cli/index.html":{"link-uuid":"333aae15-02e4-44fb-8ac9-c37cbfabb909","title":"CLI","content":"Nasdanika Command Line Interface (CLI) is a suite of Nasdanika capabilities packaged as command line tools. Sources 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","link-uuid":"d6351d9d-4484-40ad-9287-1ec216cf35ce","title":"Drawio","content":"Nasdankia provides two Maven modules for working with Drawio diagrams - API and Model. The modules require Java 17 or above. API Page and element links Generating documentation sites Executable diagrams Invocable URIs Java Ecore Model 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. Sources JavaDoc Page and element links Nasdanika Drawio API extends the concept of linking to pages to cross-document linking to pages and page elements by name or ID. Link targets (pages or elements) are available via getLinkTarget() method. Drawio page links have the following format: data:page/id,<page id> with page/id being the “media type” and <page id> being the “data” of a Data URL. Nasdanika Drawio API extends it to additional media types: page/name element/id element/name The data (selector) format has the following format: Page: [<diagram resource>#]<page selector> Diagram resource is a URI resolved relative to the current document URI. If not present then the link target page is in the same document. Page selector is either page ID or URL encoded page name depending on the media type - id or name. Element: [<diagram resource>#][<page selector>/]<element selector>] Diagram resource is a URI resolved relative to the current document URI. If not present then the link target element is in the same document. Page selector is either of: id,<page id> name,<URL encoded page name> Element selector is either page ID or URL encoded element label text (stripped of HTML formatting) depending on the media type - id or name. For elements URL’s page selector is required if diagram resource URI is present. Examples: Page links: data:page/name,compressed.drawio#Page-1 - Link to compressed first page data:page/name,compressed.drawio#Page+2 - Link to compressed second page Element links: data:element/id,7KSC1_O8d7ACaxm1iSCq-1 - Link by ID to an element on the same page data:element/name,name,Page+2/Linked - Link by name to Linked on Page 2 referenced by name data:element/name,compressed.drawio#name,Page+2/Linked - Link to Linked on compressed second page This approach allows to create a multi-resource graph of diagrams. Nasdanika Drawio API also supports loading of documents from arbitrary URI’s using a URI resolver. For example, maven://<gav>/<resource path> to load from Maven resources or gitlab://<project>/<path> to load resources from GitLab without cloning a repository, provided there is a handler (Function<URI,InputStream>) supporting the aforementioned URI’s. Generating documentation sites With Nasdanika CLI drawio > html-app > site command pipeline can be used to generate documentation web sites from Drawio diagrams: Demo Video explaining how the above demo was created Template repository Internet Banking System - another demo: a sample C4 Model Visual Communication Continuum - a Medium story which provides an overview of the approach and compares it with semantic mapping Semantic Mapping - a medium story focusing on Semantic Mapping Executable diagrams With Nasdanika Drawio API and other products you can make your diagrams executable as explained in the following sections. Invocable URIs You may set diagram element properties to URIs of processors. This approach is explained in General Purpose Executable Graphs and Diagrams Medium story. A demo repository is here - https://github.com/Nasdanika-Demos/executable-diagram-dynamic-proxy. You can use this site/ repository as a starting point for your diagramming ecosystem: Site Code Java You can create graph element processors for diagram elements in Java. Executable (computational) graphs & diagrams story provides a high level overview of executable graphs and diagrams. Graph documentation features more technical details and code samples. Compute Graph Demo provides examples of this and semantic mapping (below) approaches using the compute graph from the “Executable (computational) graphs & diagrams” story. Ecore 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 links from diagram elements to pages and other diagram 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. Sources JavaDoc 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. 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 * * * Link Target linkTarget 0..1 Page-1"},"nsd-cli/nsd/gitlab/contribute/invoke/index.html":{"path":"CLI/nsd/gitlab/contribute/invoke","link-uuid":"699a83e8-68d1-4a66-8680-f92146440fe0","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab contribute invoke [-fhV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri>\r\n [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/mapping/index.html":{"path":"Core/Mapping","link-uuid":"e410c273-a0c1-482c-83ba-0e5f3c610203","title":"Mapping","content":"(Semantic) mapping is a process of creating and populating Ecore models from other data sources, Drawio diagrams in particular. This module provides base mapping functionality and the Drawio module provides concrete implementation classes and several Drawio-specific comparators which use element properties and geometry. This page provides a combined documentation for both generic and Drawio-specific mapping. Resources: Semantic Mapping Medium Story provides a high-level overview focusing more on the WHAT and the WHY while this page focuses more on the HOW. Most code snippets below are taken from the semantic mapping demo. EMF Ecore ContentProvider DrawioContentProvider Loading Drawio resources Phases & properties Initialization initializer Groovy initializer Mapping Script Java intitializer Mapping Initializer method type ref-id Contributor.initialize() page-element prototype selector target-selector reference features end container Example contents Examples USA Joe self source start target features-ref Representations Filtering Configuration config-prototype Documentation Label Markers identity configuration Tooltip Contributor.configure() Operations arguments iterator pass selector invoke Groovy mapper Mapping Script Java mapper Mapping Mapping method Mapping Selector Feature Mapping argument-type comparator condition expression greedy invoke path nop position type Comparators Geometric Angular clockwise counterclockwise Cartesian down-left down-right left-down left-up right-down right-up up-left up-right Dependency flow reverse-flow expression key label label-descending natural property property-descending EMF Ecore This section is a brief introduction to EMF Ecore, which is used to create metamodels of problem domains. These metamodels are then used as mapping targets. It is important to mention that metamodels and documentation generated from them have value on their own - they establish a common (ubiquitous) language.1 Eclipse Modeling Framework (EMF) is an Eclipse-based modeling framework and code generation facility for building tools and other applications based on a structured data model. Ecore is the core (meta-)model at the heart of EMF. It allows expressing other models by leveraging its constructs. Ecore is also its own metamodel (i.e.: Ecore is defined in terms of itself).2 Simply put, Ecore is a way to create (domain specific) languages understandable by both humans and computers. The above diagrams shows key Ecore concepts and their relationships. E prefix is dropped for clarity. E.g. EPackage is shown as Package. More detailed documentation can be found here - https://ecore.models.nasdanika.org/ (work in progress) Metamodel Module - Java/Maven module or an OSGi bundle. Contains zero or more models with each model containing a root package. Package - a group of classifiers and sub-packages. Packages are identified (keyed) by namespace URI’s. Classifier - a class, data type or enumeration. Data type - a bridge to the Java type system. Enumeration - a collection of literals. Class - contains zero or more structural features - attributes and references and zero or more operations. May inherit from zero or more superclasses. Can be abstract and can be an interface. Structural feature - can hold single or multiple values Attribute - holds a “simple” value such as String, Date, number. Reference - relationship between two objects (EObjects). Unidirectional, but can be associated with another reference (opposite) to form a bi-directional relationship. References can be containment (composition) and non-containment (aggregation). Model Resource set - a group of related resources identified by a URI. Resource sets have associated packages, resource factories, adapter factories, and URI handlers not shown on the diagram. Resource - a group of objects. A resource is identified by a URI. Object - an instance of a metamodel class. Below is a concrete example using the Family metamodel and model: Metamodel Module - org.nasdanika.models.family:model Maven module, org.nasdanika.models.family Java module. Package - family defined in family.ecore resource with ecore://nasdanika.org/models/family namespace URI, several Java packages. Class - Man class inheriting from Person class. Structural feature Attribute - name attribute of Man (inherited from NamedElement). Reference Person.father - single non-containment reference, Person.children - many non-containment reference. Family.members - many containment reference. Model Resource set - created with a factory which treats .drawio diagram files as resources with diagram elements mapped to the family model. Resource - family.drawio file. Object - Paul and Elias are instances of Man class. Elias references Paul as his father. It is important to note that resources are identified by URI’s, not URL’s. It allows to load resources from multiple data sources - files, URL’s, databases, source repositories such as Git, binary repositories such as Maven. Using Nasdanika classes it is also possible to load objects from multiple sources on access. For example, a person’s id and name can be loaded from, say, Excel file or a database. Some other attributes may be loaded by making HTTP requests only if the client code reads those attributes. EMF Ecore provides facilities to read/write resources from/to XMI files and binary files. It also provides tools for creating models. Eclipse CDO allows to store models in distributed repositories. Nasdanika provides factories to load models from Drawio diagrams, MS Excel, Java sources, PDF files, and CSV files. It also provides URI handlers for loading models from classpath resources, GitLab & Maven repositories. There is also a documentation generator for Ecore models. In addition to the family model mentioned above, you can find examples of Ecore models and generated documentation on this site. ContentProvider For the purposes of mapping the source structures are abstracted by the ContentProvider interface, whith the following methods: Collection<? extends S> getChildren(S element /*, Predicate<S> predicate */) - returns element children. URI getBaseURI(S element) - URI for resolving resources such as documentation. Object getProperty(S element, String property) - returns property used to perform mapping. Marked asMarked(S element) - for reporting locations of errors. S getConnectionSource(S element) - If the element is a connection/association - returns its source. Otherwise returns null. S getConnectionTarget(S element) - If the argument is a connection/association - returns its target. Otherwise returns null. String getName(S element) - Element name, e.g. Drawio element label text without HTML markup. String getDescription(S element) - Element description, e.g. Drawio element tooltip. Object getIdentity(S obj) - Object identity such as a unique ID or a URI. DrawioContentProvider DrawioContentProvider is an implementation of the ContentProvider for working with Drawio diagrams. It loads mapping properties from YAML in config property or a YAML resource specified in config-ref property. It also takes element and page links into account in parent/child relationships - linked elements are considered children of linking elements. DrawioContentProvider uses base-uri property for resolving the element base URI. If this property is not set, then the base URI is the URI of the drawio file plus a fragment, which is not significant for resolving relative URI’s. If base-uri property is set, then it is resolved relative to the parent’s base URI or the Drawio resource URI if there is no parent. Loading Drawio resources While you can use DrawioContentProvider directly and customize it to your needs, the primary usage scenario is to load Drawio diagrams as Ecore resources - mapping is performed behind the scenes: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nResourceSet resourceSet = capabilityLoader.loadOne(requirement, progressMonitor);\nFile diagramFile = new File("diagram.drawio").getCanonicalFile();\nResource resource = resourceSet.getResource(URI.createFileURI(diagramFile.getAbsolutePath()), true);\t\t\nEObject root = resource.getContents().get(0);\t\n In the above code snippet a resource set is loaded from a CapabilityLoader and contains all resource factories and EPackages provided as capabilities. It includes ConfigurationLoadingDrawioResourceFactory which is registered to load .drawio and .png files. This factory customizes mapping properties: mapping - if this property is set, its value is parsed as YAML which is used as property source. mapping-ref - if mapping property is not set and this property is set, then this property value treated as a location of a YAML resource containing mapping configuration. The location (URI) is resolved relative to the base URI of the element. Phases & properties Mapping is a non-trivial process. In the case of diagrams the order in which diagram elements are mapped is not under control of the user - it depends on the order of creation of the diagram elements. Therefore, the mapping process consists of several phases and some of them may involve multiple passes. This section describes the mapping process in the order of phases. A phase section explains element configuration properties (keys) used for that phase. In some phases only one property is used. In this case the phase name is the same as the property name. In the mapping reference pages properties are ordered alphabetically. Initialization In this first phase source elements are associated with (mapped to) target elements. For example, a person image can be associated with a person object from the family model. The phase is called “Initialization” because the mapping process is similar to assigning a value to a variable in languages like Java and virtually identical to what happens in JavaScript where objects are essentially maps. The following sections explain the configuration properties used in the initialization phase. initializer initializer property value shall be an Invocable URI resolved relative to the base URI. The invocable is bound to the following arguments by name: registry - Consumer<BiConsumer<Map<EObject, EObject>,ProgressMonitor>> callback to obtain a map of source elements to target elements once all target elements are initialized (created), but not necessarily fully configured. contentProvider - content provider progressMonitor - progress monitor resourceSet - can be used to load target model elements capabilityLoader - can be used to load capabilities, including invocable URIs Then it is invoked with the source object as a single positional argument. It may return null - in this case type would be used to create a target element, if specified. This property can be used, for example, to look-up target elements defined elsewhere. Say, a list of family members can be defined in an MS Excel workbook, but family relationships in a diagram. Another example is “progressive enrichment”. For example, high-level architecture is defined in some model and a diagram uses initializers for already defined architecture elements and type for their sub-elements. This approach can be applied multiple times similar to how Docker images are assembled from layers and base images - you can layer fine-grained models/diagrams over coarse-grained ones. If you are old enough to remember JPEG images being loaded over a slow dial-up connection - something like that. In order to implement lookup initializers, override configureInitializer(), configureInvocable() or getVariables() in sub-classes of AbstractMappingFactory or getVariables() in a subclass of ConfigurationLoadingDrawioResourceFactory. Groovy initializer Mapping initializer: initializer.groovy\n Script import org.nasdanika.models.architecture.ArchitectureFactory\n\nArchitectureFactory.eINSTANCE.createDomain();\n Java intitializer Mapping initializer: data:java/org.nasdanika.demos.diagrams.mapping.Services::nodeInitializer\n Initializer method public static ArchitectureDescriptionElement nodeInitializer(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor loadingProgressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment,\n\t\t@Parameter(name = "contentProvider") ContentProvider<Element> contentProvider,\n\t\t@Parameter(name = "registry") Consumer<BiConsumer<Map<EObject, EObject>,ProgressMonitor>> registry,\n\t\t@Parameter(name = "progressMonitor") ProgressMonitor mappingProgressMonitor,\n\t\t@Parameter(name = "resourceSet") ResourceSet resourceSet,\n\t\t@Parameter(name = "capabilityLoader") CapabilityLoader capabilityLoader,\n\t\tElement source) {\n\tArchitectureDescriptionElement architectureDescriptionElement = ArchitectureFactory.eINSTANCE.createArchitectureDescriptionElement();\n\tarchitectureDescriptionElement.setDescription("I was created by a Java initializer");\n\treturn architectureDescriptionElement;\t\t\t\t\n}\n Note the use of positional and named parameters: The first 4 parameters are bound positionally when invocable URI is loaded The 5 named parameters a bound by name by the mapper The last parameter is used for invocation (also positional) type type property is used if there is no initializer or if it returned null. The value of property is the type of the target element. Types are looked up in the factory packages in the following way: If the value contains a hash (#) then it is treated as a type URI. For example ecore://nasdanika.org/models/family#//Man. If the value contains a dot (.) then it is treated as a qualified EClass name with EPackage prefix before the dot. For example family.Man. There may be more than one dot if EClass is defined in a sub-package. For example, exec.content.Markdown. Otherwise, the value is treated as an unqualified EClass name - registered EPackages (and sub-packages recursively) are sorted by Namespace URI, iterated, and the first found EClass with matching name is used to create a target element. A combination of initializer and type can be used for mapping in different contexts. For example, when loading a stand-alone model initializer would evaluate to null and then type would be used. When the same diagram loaded in the context of a larger model, initializer may evaluate to a target element looked up in that larger model. Example: type: architecture.c4.System\n A Java analogy for type: Object isaDiagramElement = getClassLoader().loadClass(type).newInstance();\n ref-id ref-id is some identifier to resolve to a target element. If there is already a target element created/resolved with initializer or type and isRefIProxydURI() returns true, then ref-id is treated as EObject proxy URI resolved relative to the base URI (see below). You may need to use this approach in case of circular references between resources or if the target element type and URI are known, but the element itself is not available during the load time. If there is no target element yet, then ref-id is used to look it up in the resource set. You may use a “physical” URI to load objects on demand, or “logical”/“semantic” URI for already loaded objects. Say, ssn:123-45-6789 to lookup a person by their SSN. Contributor.initialize() Initialization can be customized by creating a service capability of type AbstractMappingFactory.Contriutor and overriding its initialize() method. page-element If there is no target element for a diagram element yet and the diagram element’s page-element property is set to true then its target element is set to the first found target element of diagram elements linking to the page. For example, on the System Context Diagram the “Internet Banking System” element links to the Container diagram page where the “Internet Banking System” container is the page element. As a result, both of these diagram elements map to the same target element. There should be one page element per page. Having more than one may lead to an unpredictable behavior. Using page-element you can define a high-level structure on one diagram page, link other pages to the diagram elements and refine their definitions. This process can be repeated to build a hierarchy of pages as demonstrated in the “Internet Banking System Architecture” demo mentioned above. If the target element of a page element extends NamedElement then the page name is used as element’s name if hasn’t been already set by other means. prototype prototype is a Spring Expression Language (SpEL) expression evaluating to a diagram element. The target element of that diagram element is copied and the copy is used as the target element of this diagram element. Also, the prototype configuration (properties) is applied to this target element. Example: getPage().getDocument().getModelElementById('web-server-prototype') Prototypes allow to define common configuration in one element and then reuse it in other elements. For example, a web server prototype may define an icon and then all web server elements would inherit that configuration. Prototypes can be chained - you may create an inheritance hierarchy of diagram elements. Drawio classes provide convenience methods for finding diagram elements: Element.getModelElementById(String id) Element.getModelElementByProperty(String name, String value) Element.getModelElementsByProperty(String name, String value) Document.getPageById(String id) Document.getPageByName(String name) If you want to inherit just configuration, but not the target element, then use config-prototype property instead of prototype. selector selector is a Spring Expression Language (SpEL) expression evaluating to a diagram element. The target element of that diagram element is used as the target element of this diagram element. Selectors allow to use the same target element on multiple diagrams. For example, in the Internet Banking System E-Mail System is defined on the System Context Diagram and selected (referenced) on the Container Diagram with getModel().getPage().getDocument().getModelElementByProperty('semantic-id', 'microsoft-exchange') expression. The expression is evaluated in the context of the diagram element with access to the following variables: registry pass progressMonitor resourceSet capabilityLoader Please note that you may also use the extended link syntax to associate more than one diagram element with a single target element. If you are selecting by diagram element id or label, then the extended link syntax is preferable to using selector expression. In the “Internet Banking System” C4 Model demo Single-Page Application is defined on the Container Diagram and linked from the API Application Component Diagram with data:element/id,name,Container+Diagram/single-page-application) link. target-selector Spring Expression Language (SpEL) expression evaluating to a target element. Target selectors are similar to initializers with the following differences: Target selectors are evaluated after initializers An initializer is evaluated once, but a target selector might be evaluated multiple times until it returns a non-null value or the maximum number of passes is exceeded A target selector is only evaluated if there isn’t a target element already Target selectors can be used to evaluate target elements using target elements of other elements. For example, a target selector of a child node may need a target element of its parent to resolve its own target element. The expression is evaluated in the context of the diagram element with access to the following variables: * registry * pass * progressMonitor * resourceSet * capabilityLoader reference Diagram elements can be associated with target elements’ references. A Java analogy would be: List<Person> isaChildrenDiagramElement = familyWorkBook.findById("isa").getChildren();\n reference property associates a diagram element with a reference of the target element of the first matched ancestor for mapping purposes. If the element has mapped descendants, their matching targets elements are added to the reference. Reference value can be a string or a map. The string form is equivalent to the map form with just the name entry. The map form supports the following keys: comparator - used to sort reference elements, see the Comparators section. condition - a SpEL boolean expression evaluated in the context of the ancestor target element. If not provided, matches the first mapped ancestor. Has access to the following variables: sourcePath - a list of ancestors starting with the parent registry expression - a SpEL EObject expression evaluated in the context of the ancestor target element. If not provided, the ancestor itself is used. Has access to the following variables: sourcePath - a list of ancestors starting with the parent registry name - reference name element-condition - a SpEL boolean expression evaluated in the context of the descendant (contents) target element. If not provided, elements are matched by type compatibility with the reference type. Has access to the following variables: sourcePath - source containment path registry element-expression - a SpEL EObject expression evaluated in the context of the descendant (contents) target element. If not provided, the descendant itself is used. Has access to the following variables: sourcePath - source containment path registry See References demo for examples of using reference mapping. features features property defines mapping of target element structural features - references and attributes. Feature mapping demo provides a few examples of reference mapping. The value of the property shall be a map with the following supported keys: end container contents self source start target end For connections - mapping specification, as explained in the Feature Mapping section, for the connection end feature to map the connection target semantic element3 to a feature of the connection semantic element. end: father\n The above specification means “set father reference of the connection semantic element to the semantic element of its end (Joe)”. container Mapping specification for the container element in container/contents permutation. Contains one or more of the following sub-keys with each containing a map of feature names to a mapping specification or a list of feature names. self - this element is a container other - the other element is a container Example type: family.Polity\nfeatures:\n container:\n self: \n residents:\n argument-type: family.Person\n path: 1\n other: constituents\n The above example shows Texas feature mapping: self means Texas itself. The mapping specifies that immediate children of this element (path: 1) shall be added to this (Texas) semantic element residents collection if they are instances of family.Person. Joe diagram element is an immediate child of the Texas diagram element. other means USA because USA contains Texas. This mapping specifies that this (Texas’) target element shall be added to the constituents feature of its container (USA) regardless of the containment path length. In the example the containment path length is 1. Please note that when a diagram element is linked to a page, then the page’s page element is logically merged with that element. In the Internet Banking System Architecture GetBalanceRequest is contained by Internet Banking System with path=3 - they appear on different diagrams (pages), but these diagrams are connected with page links. contents Mapping specification for the contents element in container/contents permutation. Contains one or more of the following sub-keys with each containing a map of feature names to a mapping specification or a list of feature names. self - this element is contained by the other other - the other element is contained by this element Examples USA contents:\n other: \ncountry:\n path: 2\n The above feature map for USA means that other is either Florida, Texas, Jane or Joe - they are all contained in USA directly or indirectly. Path 2 means that only Jane and Joe match this mapping. And country means that their country reference shall be set to USA. Joe contents:\n self: \ncountry:\n path: 2\n The above feature map for Joe means that other is either Texas or USA - they both contain Joe, Texas directly and USA transitively. Path 2 means that only USA matches this mapping. And country means that Joe’s country reference shall be set to USA. self A map of feature names to Spring Expression Language (SpEL) expressions or a list of expressions evaluating to the feature value or feature element value. The expression is evaluated in the context of the source diagram element and has access to the following variables: value - semantic element registry - a map of diagram element to semantic elements source For connections - mapping specification for the connection source feature to map the connection semantic element to a feature of the connection source semantic element. If there are no connection semantic elements, then the connection target semantic element is used instead (pass-through connection). source: father\n The above specification at the Jane -> Joe connection means to set connection source (Jane) father feature to connection target semantic element (Joe) because the connection itself doesn’t have semantic elements. In pseudo-code: connection.getSource().setFather(connection.getTarget());\n start For connections - mapping specification for the connection start feature to map the connection source semantic element to a feature of the connection semantic element. start: child\n The above specification means “set child reference of the connection semantic element to the semantic element of its start (Jane)”. target For connections - mapping specification for the connection target feature to map the connection semantic element to a feature of the connection target semantic element. If the connection doesn’t have semantic elements (pass-through connection), then the connection source semantic element is used instead. target: children\n The above specification at the Jane -> Joe connection means to set connection target (Joe) children feature to the connection source semantic element (Jane) because the connection itself doesn’t have semantic elements. In pseudo-code: connection.getTarget().getChildren().add(connection.getSource());\n features-ref features-ref property value shall be a string which is treated as a URI resolved relative to the base URI. Resource at the URI is parsed as YAML. Representations For semantic elements which extend ModelElement the loading process injects representations which can be used in Markdown documentation and as icons in generated HTML documentation. The loading process injects two representations: drawio - a Drawio diagram containing pages where the page element maps to this target element. image - loaded from diagram element style image. Representation reduce documentation effort and drive consistency. Filtering Representations can be customized (filtered) by creating a service capability of type AbstractMappingFactory.Contributor implementing AbstractDrawioFactory.RepresentationElementFilter and implementing its filterRepresentation() method. This functionality can be used, for example to style elements based on information retrieved from external systems. For example: Development status - Planned/Backlog, In Progress, Blocked, Done Runtime status - Operational, Overloaded, Failed, Planned maintenance Quality/technical debt status - OK, Warning, Danger Configuration After diagram elements are mapped to target elements (initialized) and their features are mapped, they are configured using their diagram element properties as explained below. config-prototype With config-prototype property you can inherit configuration from another diagram element. Property value shall be a Spring Expression Language (SpEL) expression evaluating to a diagram element. Diagram element configuration (properties) is applied to this semantic element. Example: getDocument().getModelElementById('web-server-prototype') Config prototypes allow to define common configuration in one element and then reuse it in other elements. For example, a web server prototype may define an icon and then all web server element would inherit that configuration. Config prototypes can be chained - you may create an inheritance hierarchy of diagram elements. Documentation Documentation properties can be used to add documentation to target elements which implement Documented interface. Documentation can be provided in documentation property in Markdown, plain text, or HTML. Markdown is the default documentation format. You can modify it by setting doc-format property. Supported values are markdown, text, and html. It might be more convenient to maintain documentation in an external resource. In this case specify the documentation resource URI in doc-ref property. The resource URI is resolved relative to the base URI of the diagram element. If doc-format is not set, it is inferred from the resource extension - HTML for .htm and .html, text for .txt, Markdown otherwise. Documentation may also be configured via configuration or configuration-ref. Label If the target element extends NamedElement and its name is not set, then diagram element label converted to plain text is used as semantic element name. Markers If the target element implements Marked then the loading process adds diagram element markers to the semantic element. It allows to track provenance of data elements which might important in scenarios where model elements are loaded from diverse sources and even a single element may be loaded from several sources. For example, attributes are loaded from an Excel workbook and relationships from a Drawio diagram. The loading process is aware of Git repositories - if it detects that the diagram file is under source control it would store Git-specific information in markers - repository path, branch, commit hash, remotes, and head references. identity If the target element extends StringIdentity, identity property can be used to specify the id attribute. If this property is not provided, then Drawio model element ID is used as identity. Drawio element id’s are editable, but duplicate id’s are not allowed on the same page. You may have duplicate semantic id’s in different containers on the same page. In this case you may use identity. Identity can also be set using the configuration and configuration-ref YAML, this property is a shortcut way. configuration Target elements may be configured by providing a YAML configuration map in the configuration property or a URI of a configuration resource in the configuration-ref property. The URI is resolved relative to the base URI of the diagram element. Configuration YAML maps target element features (attributes and references) to their values as shown in the below example: location: %id%/index.html\nicon: /images/mapping.svg\nchildren:\n - Action:\n location: mapping-reference.html\n text: Mapping Reference\n content:\n Interpolator:\n source:\n Markdown:\n style: true\n source:\n exec.content.Resource: mapping-reference.md\n Note singleton maps specifying child elements. The key of of such maps is a type as explained in the “Initialization” > “type” section: Action - a short type name, there is only one Action class available during loading Interpolator - also a short type name exec.content.Resource - a fully qualified type name because there are two Resource classes - in the content package and in the resources package “Load specification” model documentation pages provide information about configuration keys supported by a specific type. Examples: Action class Load Specification Woman class Load Specification Tooltip If the target element extends NamedElement and its description is not set, then diagram element tooltip is used as semantic element description. Contributor.configure() Configuration can be customized by creating a service capability of type AbstractMappingFactory.Contributor and overriding its configure() method. Operations Using operations and operations-ref properties you may specify target element operations to be invoked. operations value shall be a YAML map of invocation target to operation names and then to invocation specifications explained below, operations-ref shall be a URI of a resource containing a YAML map. The URI is resolved relative to the diagram element base URI. The invocation target is either self, source or target`.sourceandtarget`` are applicable only to connections. The invocation specification is either a map or a list of maps. The sections below describe the keys supported by the maps. Examples: type: Fox\noperations:\n self:\n eats: \n arguments:\n food: "#registry.get(outgoingConnections[0].target)"\n pass: 2\n operations:\n source:\n eats: \n arguments:\n food: "#registry.get(target)"\n arguments A map of parameter names to SpEL expression evaluating their values in the context of the iterator element (see below). Argument names are used for operation selection/matching - a candidate operation must have parameters with matching names. The map does not have to contain entries for all operation parameters. Nulls are used as arguments for parameters which are not present in the map. iterator An optional SpEL expression which returns a value to iterate over and invoke the operation for every element. If the result is java.util.Iterator then it is used AS-IS. If the result is Iterable, Stream, or array, an iterator is created to iterate over the elements. If the result is null, then an empty iterator is created. Otherwise, a singleton iterator is created wrapping the result. It allows to invoke the operation zero or more times. If not defined, the iterator contains the source diagram element. pass An optional integer specifying the pass in which this operation shall be invoked. Use for ordering operation invocations. In the above example, because we want the Fox to eat the Hare after the Hare eats the Grass, we need so set pass to 1 for the Fox. selector An optional SpEL boolean expression evaluated in the context of the operation to disambiguate overloaded operations. invoke The last phase of mapping is invoking Invocable URIs specified in invoke property. URIs are resolved relative to the base URI. Invocables are bound to the following arguments by name: target - target (semantic) element, can be null pass registry - a map of source elements to target elements contentProvider progressMonitor resourceSet capabilityLoader Then it is invoked with the source element as a single positional argument. If the invokable return false it means that it could not complete its job in this pass and it will in invoked again in subsequent passes until it returns anything other than false. This functionlity can be used for procedural/imperative mapping in configuration/declarative mapping is not enough or you just prefer to do things procedurally. Groovy mapper Mapping invoke: mapper.groovy\n Script import org.nasdanika.models.nature.Color\n\nSystem.out.println("---");\nSystem.out.println("Source: " + args);\nSystem.out.println("Target: " + target);\nSystem.out.println("Pass: " + pass);\n\ntarget.setColor(Color.BROWN);\n\nreturn pass > 2; // Just to test multiple invocations\n Java mapper Mapping invoke: data:java/org.nasdanika.demos.diagrams.mapping.Services::connectionMapper\n Mapping method \npublic static void connectionMapper(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor loadingProgressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment,\n\t\t@Parameter(name = "target") Object target,\n\t\t@Parameter(name = "pass") int pass,\n\t\t@Parameter(name = "contentProvider") ContentProvider<Element> contentProvider,\n\t\t@Parameter(name = "registry") Map<EObject, EObject> registry,\n\t\t@Parameter(name = "progressMonitor") ProgressMonitor mappingProgressMonitor,\n\t\t@Parameter(name = "resourceSet") ResourceSet resourceSet,\n\t\t@Parameter(name = "capabilityLoader") CapabilityLoader capabilityLoader,\n\t\tConnection source) {\n\n\tSystem.out.println("--- Java mapper ---");\t\t\t\t\n\tSystem.out.println("Connection: " + source);\t\t\n\tSystem.out.println("Pass: " + pass);\t\t\n}\t\n Note the use of positional and named parameters: The first 4 parameters are bound positionally when invocable URI is loaded The 5 named parameters a bound by name by the mapper The last parameter is used for invocation (also positional) Mapping Selector Mapping selector can be used to select zero or more target elements for feature mapping. If it is not provided, then the diagram element’s target element is used for feature mapping, if it is present. Mapping selector shall be a YAML document containing either a single string or a list of strings. The strings are treated as Spring Expression Language (SpEL)] expression evaluating to a target element or a collection of target elements to use for feature mapping. Expressions are evaluated in the context of the diagram element and have access to the following variables: registry progressMonitor resourceSet capabilityLoader Mapping selectors may be used to associate multiple semantic elements with a diagram element for feature mapping purposes. Mapping selector can be defined in mapping-selector property or in an external resource with URI specified in mapping-selector-ref property. The resource URI is resolved relative to the base URI of the diagram element. Feature Mapping This section explains the structure of feature map values. The mapping value can be either a string or a map. If it is a string it is treated as a singleton map to true (unconditional mapping). The below two snippets are equivalent: container:\n other: elements\n container:\n other: \n elements: true\n The map value supports the following keys: argument-type Specifies the type of feature elements to be set/added. String or a list of strings. Each string is a type name as defined above Optionally prefixed with ! for negation. In the case of a list of strings the result is a logical OR - if any of elements matches. Only instances of matching types will be set/added. If absent, the feature type is used. Argument type can be used to restrict elements to a specific subtype of the feature type. Examples: In the below snippet elements of type Transition and its sub-types are excluded from the elements. container:\n self: \n elements:\n argument-type: "!Transition"\n path: 2\n In this example only elements of type Person (and its sub-types) are added to the members feature. container:\n self: \n members:\n argument-type: Person\n This example is equivalent to the previous one, but lists Person sub-types Man and Woman explicitly. container:\n self: \n members:\n argument-type:\n - Man\n - Woman\n comparator Comparator is used for sorting elements of “many” features. See the Comparators section below for a list of available comparators and their configurations. condition A SpEL boolean expression evaluated in the context of the candidate diagram element with the following variables: value - semantic element of the candidate diagram element path - containment path registry - a map of diagram element to semantic elements progressMonitor resourceSet capabilityLoader expression A SpEL expression evaluating to a feature value in the context of the diagram element with with the following variables: value - semantic element of the diagram element path - containment path registry - a map of diagram element to semantic elements progressMonitor resourceSet capabilityLoader greedy Greedy is used with containment features and specifies what to do if a candidate object is already contained by another object: no-children - grab the object if it is contained by an ancestor of this semantic element. This is the default behavior. false - do not grab true - always grab invoke Invocable URI resolved relative to the base URI. The invocable is bound to the following arguments by name: argumentValue - feature value or value evaluated by expression. baseURI context progressMonitor registry sourcePath type resourceSet capabilityLoader It is invoked with argument as positional argument and shall return feature value. path Either an integer number or a list of boolean SpEL expressions to match the path. If an integer, then it is used to match path length as shown in the example below, which matches only immediate children container:\n self: \n elements:\n path: 1\n If a list, then it matches if the list size is equal to the path length and each element evaluates to true in the context of a given path element. Expressions have access to registry variable - a map of diagram elements to semantic (target) elements. nop If true then no mapping is performed and the chain mapper is not invoked. It can be used in scenarios with a default (chained) mapper to prevent the default behavior. position A number specifying the position of the element in the feature collection. Please note that while this key is supported using it may lead to loading errors if the feature collection is smaller than the position. Because the loading order is generally not controlled by the diagram author, only 0 position is guaranteed to work all the time. type Type of the feature object to match. String as defined in the Initialization / type section. Can be used in other mappings. Comparators Comparators are used for “many” features to order elements. A comparator instance is created by AbstractDrawioFactory.createMapperComparator() method which can be overridden in subclasses to provide support for additional comparators. The following comparators are provided “out of the box”: Geometric Diagram element position convey semantics. However, most diagramming tools ignore it. I.e. they lose information or force diagrammers to keep geometry and semantics in sync. Geometric comparators allow to order semantic elements according to the positions of their diagram elements - to semantize geometry. There are two classes of geometric comparators - Angular and Cartesian. Angular Angular comparators use angles to order elements. There are two flavors - clockwise and counterclockwise. clockwise Compares elements by their angle relative to the node of the semantic element which holds the many reference. For example, in the Living Beings demo “Bird”, “Fish”, and “Bacteria” are compared by their angle to the “Living Beings” with the angle counted from “12 o’clock” - 90 degrees (default). Feature mapping with comparators of “Bird”, “Fish”, and “Bacteria” are defined at the connections from “Living Beings” as: source: \nelements:\n comparator: clockwise\n To specify the base angle other than 90 degree use the map version of comparator definition where clockwise is the key mapping to a number or string value. The number value is used as the angle value in degrees. The string value is treated as a Spring Expression Language (SpEL) expression evaluated in the context of the “parent” node. The expression may evaluate to a number or to a node. In the latter case the result is used to compute the angle between the context node and the result node. In the Living Beings example “Streptococcus”, …, “Staphyllococcus” are compared relative to the “Bacteria” node with the base angle being the angle between the “Bacteria” node and “Living Beings” node. As such, “Streptococcus” is the smallest node and “Staphyllococcus” is the largest. With the default angle of 90 degrees “Lactobacyllus” would be the smallest and “Streptococcus” would be the largest. Feature mapping with comparators of “Streptococcus”, …, “Staphyllococcus” is defined at connections from “Bacteria” to the respective genus nodes as: source: \nelements:\n comparator: \nclockwise: incoming[0].source\n incoming[0] evaluates to the connection from “Living Beings” to “Bacteria” and source evaluates to “Living Beings”. counterclockwise Reverse of clockwise. Cartesian Cartesian comparators use horizontal and vertical positions to compare/order elements with 2 coordinates and 2 directions in each it gives us 8 permutations. down-left Compares nodes by their vertical order first with higher nodes being smaller and then by horizontal order with nodes on the right being smaller. Nodes are considered vertically equal if they vertically overlap. down-right Compares nodes by their vertical order first with higher nodes being smaller and then by horizontal order with nodes on the left being smaller. Nodes are considered vertically equal if they vertically overlap. This comparator can be used for org. charts. left-down Compares nodes by their horizontal order first with nodes on the right being smaller and then by vertical order with higher nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. left-up Compares nodes by their horizontal order first with nodes on the right being smaller and then by vertical order with lower nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. right-down Compares nodes by their horizontal order first with nodes on the left being smaller and then by vertical order with higher nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. right-up Compares nodes by their horizontal order first with nodes on the left being smaller and then by vertical order with lower nodes being smaller. Nodes are considered horizontally equal if they horizontally overlap. up-left Compares nodes by their vertical order first with lower nodes being smaller and then by horizontal order with nodes on the right being smaller. Nodes are considered vertically equal if they vertically overlap. up-right Compares nodes by their vertical order first with lower nodes being smaller and then by horizontal order with nodes on the left being smaller. Nodes are considered vertically equal if they vertically overlap. Dependency flow and reverse-flow order elements based on how they are connected to each other. flow If one element is reachable from the other by traversing connections, then the reachable element is larger than the source element. In case of circular references the element with the smaller number of traversals to the other element is considered smaller. If elements are not connected they are compared by the fall-back comparator. Flow comparator can be used for workflows and PERT charts. If this comparator’s value is a String, then it is used as a name of the fallback comparator. In the below example children in the Sample Family will be smaller than their parents and siblings will be compared using labels. container:\n self: \nmembers:\n argument-type: Person\n comparator: \nflow: label\n If the value is a map, then it may have the following keys: condition - A boolean SpEL expression evaluated in the context of a connection being traversed. It may be used to traverse only connections which match the condition. fallback - Fallback comparator. The below snippet shows the Internet Banking System Container diagram comparator: container:\n self: \nelements:\n path: 1\n comparator: \nflow: \nfallback: label\n condition: id != 'send-email'\n The condition specifies that a connection with sent-mail ID shall not be traversed. reverse-flow Same as flow but with target nodes being smaller than source nodes. expression A SpEL expression evaluated in the context of the feature element with other variable referencing the element to compare with. The expression has access to the following variables: registry progressMonitor resourceSet capabilityLoader key A SpEL expression evaluated in the context of the feature element. The expression must return a value which would be used for comparison using the natural comparator. label Uses the diagram element label converted to plain text as a sorting key. In the Family mapping demo family members are sorted by label using the following feature map definition: container:\n self: \nmembers:\n argument-type: Person\n comparator: label\n label-descending Uses the diagram element label converted to plain text as a sorting key to compare in reverse alphabetical order. natural Uses the feature element’s compareTo() method for comparable elements. Otherwise compares using the hash code. Nulls are greater than non-nulls. property Uses diagram element property as a sorting key. A singleton map. For example: property: label\n property-descending The same as property, but compares in reverse alphabetical order. https://martinfowler.com/bliki/UbiquitousLanguage.html ↩ https://en.wikipedia.org/wiki/Eclipse_Modeling_Framework ↩ Here and below the term “semantic element” is used interchangeably with the term “target element” to avoid confusion with connection target element. ↩ Module Package Classifier Class Data type Enum Structural Feature Attribute Reference * * * Literal * * Operation * Parameter * * Metamodel Resource Set Resource Object * * Model Page-1"},"nsd-cli/nsd/gitlab/invoke/index.html":{"path":"CLI/nsd/gitlab/invoke","link-uuid":"38d96a5f-6723-4c9e-8a58-c6e04fa421a6","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab invoke [-fhV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri>\r\n [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/java/junit/index.html":{"path":"CLI/nsd/java/junit","link-uuid":"9c7cb60b-fa27-471c-bafc-1f1b006a1672","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.12.0 \r\nUsage: nsd java junit [-fhVw] [--[no-]ai] [--[no-]comment-response]\r\n [--disabled] [--progress-console] [--progress-data]\r\n [--progress-json] [--api-endpoint=<apiEndpoint>]\r\n [--class-suffix=<classSuffix>] [-k=<apiKey>] [-l=<limit>]\r\n [-m=<deploymentOrModelName>]\r\n [--package-suffix=<packageSuffix>]\r\n [--progress-output=<progressOutput>] [-r=<prompt>]\r\n [-s=<sources>] [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <projectURI> <coverageThreshold>\r\n <output> [COMMAND]\r\nGenerates JUnit tests\r\n <projectURI> Project URI\r\n <coverageThreshold> Coverage threshold\r\n <output> Output URI\r\n relative to the project URI\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 --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 --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -f Project URI is a file path\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 -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 --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\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 URI path relative\r\n to the project URIy,\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\r\nCommands:\r\n jacoco Loads coverage from jacoco.exec and classes directory"},"nsd-cli/nsd/model/save/index.html":{"path":"CLI/nsd/model/save","link-uuid":"1c444dee-1ba2-4baf-a27d-da1165441bcb","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]... <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/contribute/retrospect/invoke/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect/invoke","link-uuid":"d89994fb-3b5e-4e28-8e3a-4e06176b4d73","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd gitlab contribute retrospect invoke [-fhV] [--progress-console]\r\n [--progress-data] [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri> [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/drawio/html-app/index.html":{"path":"CLI/nsd/drawio/html-app","link-uuid":"1a831d5f-8c39-4faa-a8d1-21bc9ca7200e","title":"html-app","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd drawio html-app [-fhRV] [-b=<base>] [-P=<insertionIndex>]\r\n [-r=<rootLabel>]\r\n [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates html application model from a drawio document\r\n -b, --base-uri=<base> Base URI. E.g. 'pages/'\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"nsd-cli/nsd/gitlab/contribute/junit/jacoco/index.html":{"path":"CLI/nsd/gitlab/contribute/junit/jacoco","link-uuid":"3813a50b-3d07-4bfa-8417-a92c7c1659ad","title":"jacoco","content":"Usage: nsd gitlab contribute junit jacoco [-hV] [-c=<classes>] [-j=<jacoco>]\r\n [-m=<moduleName>]\r\nLoads coverage from jacoco.exec and classes directory\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n -h, --help Show this help message and exit.\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 -m, --module=<moduleName> Coverage module name\r\n -V, --version Print version information and exit."},"practices/java/index.html":{"path":"Practices/Java Analysis, Visualization & Generation","link-uuid":"b3ba7a9f-54f5-4c3e-a9bc-6cd85f10387b","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","link-uuid":"bbd73087-4469-4887-914a-2fbfc684a44c","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. Capability providers may also provide functionality such as: Implement Autocloseable and release resources associated with capabilities upon closing. Implement Lock or ReadWriteLock to guard access to provided capabilities. Extending on the above, a capability provider may implement Domain/Realm with a command stack - obtain, execute commands with locking, close. 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. “bake” capability is provided by an oven which may have a command stack or a lock because only one thing can be baked at a time. 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 examples below. Sources Javadoc Client code - requesting a capability Service capabilities Providing a capability Loading Invocables from URIs Examples String value URL encoded URL and Base64 encoded Java Constructor Static method @Parameter annotation Script Spec JSON YAML Drawio diagram Specification URI Data value/ java/ spel/ application//invocable Hierarchical YAML/JSON specification EMF Requesting a ResourceSet With all packages and factories Selecting contributors Providing ResourceSet instance Contributing EPackages Resource factories URI handlers Applications Services Solutions for architectures Backward chaining Stream processing AI model training/fine-tuning 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 There is a number of implementations of CapabilityFactory is different Nasdanika modules, most of them extending ServiceCapability. In Eclipse or other IDE open CapabilityFactory type hierarchy to discover available implementations. Loading Invocables from URIs The capability framework allows to create/load implementations of Invocable from URIs: In conjunction with the Maven module implementations can be loaded from Maven repositories. Invocables can be implemented in scripting languages, e.g. Groovy. Scripts may use dependencies loaded from Maven repositories. Script engine themselves can be loaded from Maven repositories. Drawio diagrams can be made executable by adding invocable URI properties to diagram elements. They can then be wrapped into a dynamic proxy and invocable URI’s. Examples String value URL encoded data:value/String,Hello+World data URL is converted to an Invocable which takes zero arguments and returns URL-decoded data part of the URL (after comma). CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:value/String,Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n URL and Base64 encoded data:value/String;base64,SGVsbG8= is converted to an Invocable which takes zero arguments and returns URL-decoded and then Base64 decoded data part converted to String. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:value/String;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n Java Constructor data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8= is converted to an Invocable which invokes MyTestClass constructor. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n In the above code snippet invocable is invoked with no arguments, which matches the below constructor passing the decoded data part of the URL in binding argument: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding,\n\t\tString fragment) {\n\t...\n}\t\n The below snippet passes 33 argument to invoke(): CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke(33);\nSystem.out.println(result);\n Which matches the below constructor: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding, \n\t\tint arg) {\n\t...\n}\n 33 is passed via the arg argument. Static method Static methods can be addresed by adding :: and method name after the class name as in this URL: data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=. The resulting Invocable will select the best matching factory method. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n In the above code snippet invoke() has no arguments and therefore the below method matches: public static MyTestClass factory(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding) {\n\t...\n}\n As with constructors, the decoded data part is passed to the method as binding argument. In the below snippet invoke() takes 55 argument: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createURI("data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8=");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke(55);\nSystem.out.println(result);\n Which matches the below method: public static MyTestClass factory(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tbyte[] binding,\n\t\tint arg) {\n\t...\n}\n @Parameter annotation Parameter annotation can be used on method and constructor parameters to provide parameter name and optionally narrow parameter type. Script The below snippet exectutes test.groovy script in the current directory. ScriptEngineManger is used to get a ScriptEngine by extension. Therefore, the engine factory shall be registered with the script engine manager. CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createFileURI(new File("test.groovy").getCanonicalPath());\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n This is the test script: import org.nasdanika.capability.CapabilityFactory.Loader\nimport org.nasdanika.common.ProgressMonitor\n\n// Script arguments for reference\nLoader loader = args[0];\nProgressMonitor loaderProgressMonitor = args[1];\nObject data = args[2];\n\nSystem.out.println(args);\n"I've got " + args.length + " arguments!"\n Similar to Java constructors and static methods, it takes the following arguments: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods URI’s fragment value or null Invocable arguments In the below code the script receives Hello as its third argument (binding) and Universe as its fourth argument: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI requirement = URI.createFileURI(new File("test.groovy").getCanonicalPath()).appendFragment("Hello");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, requirement),\n\t\tprogressMonitor);\nObject result = invocable.invoke("Universe");\nSystem.out.println(result);\n Spec Spec URI’s allow to specify Maven dependencies to construct a ClassLoader for loading Java classes including script engine factories. It is also to specify a module path to construct a module layer. JSON CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI specUri = URI.createFileURI(new File("test-specs/java.json").getCanonicalPath()).appendFragment("Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n The above snippet uses the below spec to create an instance of MyTestClass: {\n\t"type": "org.nasdanika.capability.tests.MyTestClass",\n\t"bind": [\n\t\t"data:value/String,Some+other+value"\n\t]\n}\t\n Similar to data URL’s a matching constructor is found for the following arguments: CapabilityFactory.Loader ProgressMonitor String - URL decoded URI fragment, may be null Bindings loaded from the bind array of URI’s Below is the matching constructor: public MyTestClass(\n\t\tCapabilityFactory.Loader loader, \n\t\tProgressMonitor progressMonitor, \n\t\tString fragment,\n\t\tString bind) {\n\t...;\n}\t\n YAML CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor(true);\nURI specUri = URI.createFileURI(new File("test-specs/groovy.yml").getCanonicalPath()).appendFragment("Hello+World");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nObject result = invocable.invoke();\nSystem.out.println(result);\n The above snippet executes Groovy script specified inline in the below YAML: script:\n engineFactory: org.codehaus.groovy.jsr223.GroovyScriptEngineFactory\n source: |\n "Hello, world! " + myBinding + " " + args[2]\n bindings:\n myBinding: data:value/String,Some+value\ndependencies: org.apache.groovy:groovy-all:pom:4.0.23\nlocalRepository: target/groovy-test-repo\n In this case org.apache.groovy:groovy-all:pom:4.0.23 Maven coordinates are used to load Groovy with all dependencies and construct a ClassLoader. Because the engine was loaded at runtime, it is not known to the ScriptEngineManager and has to be explicitly specified. The script gets an args array with loader, progress monitor, decoded fragment and arguments passed to invoke(). It also gets named bindings loaded from the bindings map entries. Drawio diagram Below is a YAML spec with an embedded diagram: diagram:\n source: |\n <mxfile ...abridged... </mxfile>\n processor: processor\n bind: bind\n interfaces: java.util.function.Function\n And this is a YAML specification which references a diagram: diagram:\n location: diagram.drawio\n processor: processor\n bind: bind\n interfaces: java.util.function.Function\n The below code loads the spec, passes the fragment to the diagram as properties in addition to the properties from the spec, creates a dynamic proxy which invokes diagram element processors, and uses the proxy to execute the diagram logic: CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nURI specUri = URI.createFileURI(new File("diagram-function.yml").getCanonicalPath()).appendFragment("my-property=Hello");\nInvocable invocable = capabilityLoader.loadOne(\n\t\tServiceCapabilityFactory.createRequirement(Invocable.class, null, new URIInvocableRequirement(specUri)),\n\t\tprogressMonitor);\nFunction<String,Object> result = invocable.invoke();\nSystem.out.println(result);\nSystem.out.println(result.apply("YAML"));\n See Capability tests and Executable Diagrams Dynamic Proxy demo for more examples. Specification URI This section explains supported URI formats. Please note that using a custom URIHandler you may: Normalize “logical” URI’s to supported “physical” URI’s. Implement openStream() For example normalized my-building-blocks://gen-ai/chat-completions to a specification of a chat completions component, say, gitlab://my-shared-components/open-ai/chat-completions.yml and then implement openStream() which supports gitlab scheme[^gitlab_urihandler] Data Data URI has the following format: data:[<mediatype>][;base64],<data>[#fragment]. The following sections describe supported media types. value/ an instance of the class is constructed from the data part bytes, fragment is ignored. if the class name does not contain dots then java.lang. prefix is added to the class name. Examples: * data:value/String,Hello+World * data:value/String;base64,SGVsbG8= java/ Class constructors or static methods are wrapped into an Invocable and the matching constructor/method is invoked from the resulting Invocable.invoke(). Constructors/methods shall have the following signature: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods byte[] - the data part String - fragment Optional additional parameters for arguments passed to the result Invocable Examples: data:java/org.nasdanika.capability.tests.MyTestClass;base64,SGVsbG8=#World data:java/org.nasdanika.capability.tests.MyTestClass::factory;base64,SGVsbG8= spel/ Evaluates a Spring Expression Langauge (SpEL) expression. Binding by name sets variables. Arguments array is passed to the expression as the root object. It the array is of size 1 then its single element is used as the root object. Example: data:spel/%23myVar+%2B+%23this This online URL Decoder/Encoder can be used to encode expressions. application//invocable With format being either yaml or json. YAML or JSON specification (see below) encoded into the data part. Example: data:application/yaml/invocable;base64,c2Nya...abridged...1yZXBv Hierarchical If the hierarchical URI’s last segment ends with .yml or .yaml (case insensitive) it is treated as a YAML specification (see below). If the last segment ends with .json (also case insensitive) it is treated as a JSON specification. Otherwise a script engine is looked up by extension (the part of the last segments after the last dot). E.g. groovy. Scripts receive args binding (variable) of type Object[] with the following elements: CapabilityFactory.Loader to request additional capabilities if needed ProgressMonitor to report progress and pass to the loader methods String - fragment Arguments passed to the result Invocable YAML/JSON specification YAML/JSON specification is pre-processed and then loaded into InvocableRequirement. The specification supports the following configuration entries: diagram - Map, loaded into DiagramRecord: location - String, URI of the diagram location relative to the specification location. source - String, diagram source. Either location or source shall be used. base - String, base URI if source is used properties - Map, properties to pass to the diagram. Nested properties can be addressed using “.” (dot) separator. For arrays index is used as key. E.g. people.3.name. If URI fragment is present it is parsed into name/value pairs in the same way as query strings are parsed. Fragment properties overwrite spec properties. processor - optional String, property to load processor specifications from. One diagram element may have multiple processor specifications in different properties. Also, property expansion can be used to customize processor specification. E.g. %env%/storage.yaml would point to different specifications depending on the value of %env% property. bind - optional String, property for a dynamic proxy method name or signature interfaces - optional String or List, dynamic proxy interfaces type - String, class name or method reference is ends with ::<static method name> script - Map, loaded into ScriptRecord: location - String, URI of script sources source - String, script source. Either location or source shall be used language - String, script language (mime type) for source. For location if language is not specified it is derived from extension. engineFactory - String, fully qualified name of a script engine factory implementation. Use if the engine is loaded from dependencies and therefore is not visible to the script engine manager. If engineFactory is specified language and location extension are ignored. bindings - Map, values are treated as Invocable URIs providing binding values. Loader, progress monitor, fragment and invocable arguments are available to the script via the args binding of type Object[]. bind - String or List, Invocable URIs to bind to the type Invocable. Not supported by diagram and script. modulePath - optional String or List, module path. If null, derived from root modules if they are present rootModules - optional String or List, root modules. The first root module is used to obtain the class loader oneLayerClassLoader - optional boolean indicating whether a single class loader shall be used for all modules in in the layer dependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format. E.g. org.apache.groovy:groovy-all:pom:4.0.23 managedDependencies - optional String or List of dependencies in <groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>} format remoteRepositories - Map (single remote repository) or List of Maps of remote repository definitions loaded into RemoteRepoRecord: id - String, repo ID type - String, optional repo type url - String, repository URL proxy - optional Map: type - String, http or https host - String port - integer auth - authentication (see below) auth - Map: username - String password - String mirroredRepositories - Map or List, mirrored repositories localRepository - optional String, path to the local repository to download dependencies to. Defaults to repository. Maven dependency resolution uses default values as explained in the Maven module documentation. diagram, type and script are mutually exclusive. Note: extends key is reserved for future releases to support spec inheritance. Configuration is pre-pThe by interpolating system properties and environment variables. E.g. ${my-property} will be expanded to the value of my-property system property if it is set. Respectively, ${env.MY_ENV_VAR} will be expanded to the value of MY_ENV_VAR environment variable if it is set. Property expansion can be escaped with additional {} e.g. ${my-property} will be expanded to ${my-property} regardless of whether my-properety system property is set or not. EMF Many of Nasdanika capabilities are based on Eclipse Modeling Framework (EMF)2, Ecore3 models in particular. One of key objects in EMF Ecore is a ResourceSet. Resource set has a package registry, resource factory registry, and URI converter. org.nasdanika.capability.emf packages provides capability factories for contributing to resource set. It allows to request resource set from a capability loader and the returned resource set would be configured with registered EPackages, resource factories, adapter factories and URIHandlers. Requesting a ResourceSet With all packages and factories CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class);\t\t\nfor (CapabilityProvider<?> capabilityProvider: capabilityLoader.load(requirement, progressMonitor)) {\n\tResourceSet resourceSet = (ResourceSet) capabilityProvider.getPublisher().blockFirst();\n}\n Selecting contributors CapabilityLoader capabilityLoader = new CapabilityLoader();\nProgressMonitor progressMonitor = new PrintStreamProgressMonitor();\n\nPredicate<ResourceSetContributor> contributorPredicate = ...;\nResourceSetRequirement serviceRequirement = new ResourceSetRequirement(null, contributorPredicate);\n\t\t\nRequirement<ResourceSetRequirement, ResourceSet> requirement = ServiceCapabilityFactory.createRequirement(ResourceSet.class, null, serviceRequirement);\t\t\n\nfor (CapabilityProvider<?> capabilityProvider: capabilityLoader.load(requirement, progressMonitor)) {\n\tResourceSet resourceSet = (ResourceSet) capabilityProvider.getPublisher().blockFirst();\n}\n Providing ResourceSet instance You may provide an instance of ResourceSet to configure in the requirement. Contributing EPackages Create a class extending EPackageCapabilityFactory: public class NcoreEPackageResourceSetCapabilityFactory extends EPackageCapabilityFactory {\n\n\t@Override\n\tprotected EPackage getEPackage() {\n\t\treturn NcorePackage.eINSTANCE;\n\t}\n\n\t@Override\n\tprotected URI getDocumentationURI() {\n\t\treturn URI.createURI("https://ncore.models.nasdanika.org/");\n\t}\n\n}\n and add it to module-info.java provides: provides CapabilityFactory with NcoreEPackageResourceSetCapabilityFactory;\n Resource factories Create a class extending ResourceFactoryCapabilityFactory: public class XMIResourceFactoryCapabilityFactory extends ResourceFactoryCapabilityFactory {\n\n\t@Override\n\tprotected Factory getResourceFactory() {\n\t\treturn new XMIResourceFactoryImpl();\n\t}\n\t\n\t@Override\n\tprotected String getExtension() {\n\t\treturn Resource.Factory.Registry.DEFAULT_EXTENSION;\n\t}\n\n}\n and add it to module-info.java provides CapabilityFactory. URI handlers Create a class extending URIConverterContributorCapabilityFactory: public class ClassPathURIHandlerResourceSetCapabilityFactory extends URIConverterContributorCapabilityFactory {\n\n\t@Override\n\tprotected void contribute(URIConverter uriConverter, ProgressMonitor progressMonitor) {\t\n\t\turiConverter.getURIHandlers().add(0, new URIHandlerImpl() {\n\n\t\t\t@Override\n\t\t\tpublic boolean canHandle(URI uri) {\n\t\t\t\treturn uri != null && Util.CLASSPATH_SCHEME.equals(uri.scheme());\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException {\n\t\t\t\treturn DefaultConverter.INSTANCE.toInputStream(uri);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t}\n\t\n}\n and add it to module-info.java provides CapabilityFactory. 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 ↩ See Eclipse Modeling Framework (EMF) - Tutorial and EMF Eclipse Modeling Framework book for more details. ↩ See EMF Ecore chapter in Beyond Diagrams book for a high-level overview of EMF Ecore. ↩"},"nsd-cli/nsd/shell/index.html":{"path":"CLI/nsd/shell","link-uuid":"4a069308-3ba8-48ee-9223-b74e72b835b3","title":"shell","content":"Usage: nsd shell [-hV]\r\nStarts an interactive shell\r\nor executes commands from input\r\nfiles or URL's\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit."},"core/graph/index.html":{"path":"Core/Graph","link-uuid":"4dec2691-78b8-4428-90b1-ca57bd1176a2","title":"Graph","content":"Nasdanika Graph module provides classes for visiting and processing graphs with two types of relationships between graph elements: Containment - one element is contained by another Connection - one element (node) connecting to another node via a connection. On the diagram below containment relationships are shown in bold black and connections in blue Examples of such graphs: A file system with directories containing files and other directories. Connections may take multiple forms such as symbolic links or files, e.g. HTML files, referencing other files. Organizational structure with a hierarchy of organizational units and connections between them. For example, one unit may pass work product to another unit, or a unit may provide services to other units. Country, state, county, city, street, house, people living in that house; family relationships between people and ownership relationships between people and houses. Diagrams, such as Drawio diagrams with a diagram file (resource) containing a Document which contains pages, pages containing layers, and layers containing nodes and connections. Nodes may be nested. Nasdanika Drawio is a module for working with Drawio diagrams. It is built on top of this module. Processes/(work)flows - processes consist of activities and nested processes. Activities are connected by transitions. Distributed systems, such as cloud solutions - availability zones, data centers, clusters, nodes, pods, containers, processes inside containers. All of them communicating to each other via network connections. Work hierarchy and dependencies - in issue trackers issues may be organized into a hierarchy (e.g. Initiative, Epic, Story, Sub-Task in Jira) and have different types of dependencies. In Java a jar contains packages containing sub-packages and classes. Classes contain fields and methods. Fields reference their types, methods call methods of other classes, … EMF Ecore models contain packages. Packages contain sub-packages and classifiers including classes. Classes contain references to other classes. References may be configured as containment (composition) or non-containment. Resources Graph API Processing Dispatching Processors and processor factories Reflection ReflectiveProcessorFactoryProvider Capability Wiring Resources Sources Javadoc Medium stories: General purpose executable graphs and diagrams Concurrent Executable Diagrams Executable (computational) graphs & diagrams Graph API The graph API has 3 interfaces: Element - super-interface for Connection and Node below. Elements may contain other elements. Containment is implemented with <T> T accept(BiFunction<? super Element, Map<? extends Element, T>, T> visitor), which can be thought of as a hierarchical bottom-up reduce - the visitor function is invoked with an element being visited as its first argument and a map of element’s children to results returned by the visitor as the second argument. For leaf elements the second argument may be either an empty map or null. Depending on the map type used by implementations they may also need to implement equals() and hashCode(). Node extends Element and may have incoming and outgoing connections. Connection extends Element and has source and target nodes. Processing Graph processing means associating some behavior with graph elements. That behavior (code execution) may modify the graph or perform other actions. Examples of graph processing: Generate code (HTML site) from a diagram. Demos: Internet Banking System Sample Family Living beings Update a diagram with information from external source. For example, there might be a diagram of a (software) system. Diagram elements can be updated as follows: During development - colors may reflect completion status. Say, in progress elements in blue, completed elements in green, elements with issues in red or amber. In production - color elements based on their monitoring status. Offline - grey, good - green, overloaded - amber, broken - red. The above two examples may be combined - a documentation site might be generated from a system diagram. The diagram may be updated with statuses as part of the generation process and embedded to the home page. A click on a diagram element would navigate to an element documentation page, which may contain detailed status information pulled from tracking/monitoring systems during generation. Dispatching One form of graph processing is dispatching of graph elements to Java methods annotated with Handler annotation. The annotation takes a Spring boolean expression. Graph elements are passed to methods for which the expression is blank or evaluates to true. Below is a code snippet from AliceBobHandlers class: @Handler("getProperty('my-property') == 'xyz'")\npublic String bob(Node bob) {\n\tSystem.out.println(bob.getLabel());\n\treturn bob.getLabel();\n}\n Below is a test method from TestDrawio.testDispatch() test method which dispatches to the above handler method: Document document = Document.load(getClass().getResource("alice-bob.drawio"));\n\t\t\nAliceBobHandlers aliceBobHandlers = new AliceBobHandlers();\t\t\nObject result = document.dispatch(aliceBobHandlers);\nSystem.out.println(result);\n Dispatching is suitable for processing where processing logic for different graph elements does not need to access processing logic of other elements. An example of such logic would be updating diagram elements based on statuses retrieved from tracking/monitoring systems - each element is updated individually. Processors and processor factories Processor package provides means for creating graph element processors and wiring them together so they can interact. One area of where such functionality would be needed is executable diagrams. For example, a flow processor/simulator. Activity processors would need to pass control to connected activities via connection processors. Activity processors may also need to access facilities of their parent processors. The below diagram shows interaction of two nodes via a connection. Connections are bi-directional - source processor may interact with the target processor and vice versa. Some connections may be “pass-through” - just passing interactions without doing any processing. A pass-through connection is depicted below. Graph element processors are wired together with handlers and endpoints: A handler is a java object provided by a processor for receiving interactions from other processors via endpoints. An endpoint is a java object provided to a processor for interacting with other processors. An endpoint may be of the same type as a handler or a handler may be used as an endpoint. This might be the case if processing is performed sequentially in a single JVM. Alternatively, an endpoint may be of different type than the handler it passes interactions to. For example: Endpoint methods may return Futures or CompletionStages of counterpart handler methods - when an endpoint method is invoked it would invoke handler’s method asynchronously. Endpoint methods may take different parameters. E.g. an endpoint method can take InputStream, save it to some storage and pass a URL to the handler method. Processors can also interact by looking up other processors in the processor registry. Endpoints are created by implementations Processors are created in two steps: Processor configs are created by subclasses of ProcessorConfigFactory, e.g. NopEndpointProcessorConfigFactory Processors are created from configs by subclasses of ProcessorFactory overriding createProcessor() method. Client code creates processors by calling createProcessors() method. This method return a registry - Map<Element,ProcessorInfo<P>>. The registry allows the client code to interact with the handler/endpoint/processor wiring created from the graph. TestDrawio.testProcessor() method provides an example of using an anonymous implementation of NopEndpointProcessorFactory for graph processing. Reflection A good deal of processor creation logic is selection of a processor to create for a given graph element in a given situation/context and then “wiring” configuration to the processor. There are two processor factory classes and ReflectiveProcessorWirer class which make the selection/matching/wiring process easier. ReflectiveProcessorFactoryProvider ReflectiveProcessorFactoryProvider invokes methods annotated with Processor annotation to create processors. SyncProcessorFactory is an example of reflective processor factory. Below is one of factory methods: @Processor(\n\ttype = NodeAdapter.class,\n\tvalue = "get() instanceof T(org.nasdanika.models.functionflow.FunctionFlow)")\npublic Object createFunctionFlowProcessor(\n\tNodeProcessorConfig<?,?> config, \n\tboolean parallel, \n\tBiConsumer<Element,BiConsumer<ProcessorInfo<Object>,ProgressMonitor>> infoProvider,\n\tFunction<ProgressMonitor, Object> next,\t\t\n\tProgressMonitor progressMonitor) {\t\n\treturn new FunctionFlowProcessor();\n}\n Capability CapabilityProcessorFactory uses the Nasdanika Capability Framework to delegate processor creation to capability factories. ReflectiveProcessorServiceFactory provides such a capability by collecting reflective targets from capability providers and then using ReflectiveProcessorFactoryProvider mentioned above. This approach provides high level of decoupling between code which executes the graph and code which creates processors. FunctionFlowTests executes a graph loaded from a Drawio diagram. It constructs a processor factory as shown below: CapabilityLoader capabilityLoader = new CapabilityLoader();\t\t\nCapabilityProcessorFactory<Object, BiFunction<Object, ProgressMonitor, Object>> processorFactory = new CapabilityProcessorFactory<Object, BiFunction<Object, ProgressMonitor, Object>>(\n\t\tBiFunction.class, \n\t\tBiFunction.class, \n\t\tBiFunction.class, \n\t\tnull, \n\t\tcapabilityLoader); \n SyncProcessorFactory mentioned above is contributed by SyncCapabilityFactory: @Override\npublic boolean canHandle(Object requirement) {\n\tif (requirement instanceof ReflectiveProcessorFactoryProviderTargetRequirement) {\n\t\tReflectiveProcessorFactoryProviderTargetRequirement<?,?> targetRequirement = (ReflectiveProcessorFactoryProviderTargetRequirement<?,?>) requirement;\n\t\tif (targetRequirement.processorType() == BiFunction.class) { // To account for generic parameters create a non-generic sub-interface binding those parameters.\n\t\t\tProcessorRequirement<?, ?> processorRequiremment = targetRequirement.processorRequirement();\n\t\t\tif (processorRequiremment.handlerType() == BiFunction.class && processorRequiremment.endpointType() == BiFunction.class) {\n\t\t\t\treturn processorRequiremment.requirement() == null; // Customize if needed\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n@Override\npublic CompletionStage<Iterable<CapabilityProvider<Object>>> create(\n\tReflectiveProcessorFactoryProviderTargetRequirement<Object, BiFunction<Object, ProgressMonitor, Object>> requirement,\n\tBiFunction<Object, ProgressMonitor, CompletionStage<Iterable<CapabilityProvider<Object>>>> resolver,\n\tProgressMonitor progressMonitor) {\t\t\n\treturn CompletableFuture.completedStage(Collections.singleton(CapabilityProvider.of(new SyncProcessorFactory())));\t\n}\n canHandle() returns true if the factory can handle the requriement passed to it. create() creates a new instance of SyncProcessorFactory. Note, that create() may request other capabilities. Say, an instsance of OpenAIClient to generate code using chat completions. SyncCapabilityFactory is registered in module-info.java: exports org.nasdanika.models.functionflow.processors.targets.java.sync;\nopens org.nasdanika.models.functionflow.processors.targets.java.sync to org.nasdanika.common; // For loading resources\n\nprovides CapabilityFactory with SyncCapabilityFactory;\n Note that a package containing reflective factories and processors shall be opened to org.nasdanika.common for reflection to work. Wiring Processors created by the above factories are introspected for the following annotations: All processors: ChildProcessor - field a method to inject processor or config of element’s child matching the selector expression. ChildProcessors - field or method to inject a map of children elements to their processor info. ParentProcessor - field or method to inject processor or config of element’s parent. ProcessorElement - field or method to inject the graph element. Registry - field or method to inject the registry - a map of graph elements to their info. RegistryEntry - field or method to inject a matching registry entry. Node processors: IncomingEndpoint - field or method to inject a matching incoming endpoint. IncomingEndpoints - field or method to inject a map of incoming connections to their endpoints completion stages. IncomingHandler - field or method to obtain a handler for an incoming connection. IncomingHandlerConsumers - field or method to inject a map of incoming connections to java.util.function.Consumers of handlers. OutgoingEndpoint - field or method to inject a matching outgoing endpoint. OutgoingEndpoints - field or method to inject a map of outgoing connections to their endpoints completion stages. OutgoingHandler - field or method to obtain a handler for an outgoing connection. OutgoingHandlerConsumers - field or method to inject a map of outgoing connections to consumers of handlers. Connection processors: SourceEndpoint - field or method into which a connection source endpoint is injected. Source endpoint allows the connection processor to interact with the connection source handler. SourceHandler - field or method from which the connection source handler is obtained. TargetEndpoint - field or method into which a connection target endpoint is injected. Target endpoint allows the connection processor to interact with the connection target handler. TargetHandler - Field or method from which the connection target handler is obtained. Element/Node/Connection configuration is declaratively “wired” to processors’ fields and methods. Configuration can also be wired imperatively. Declarative and imperative styles can be used together. Below is an example of using @OutgoingEndpoint annotation by StartProcessor: public class StartProcessor implements BiFunction<Object, ProgressMonitor, Object> {\n\n\tprotected Collection<BiFunction<Object, ProgressMonitor, Object>> outgoingEndpoints = Collections.synchronizedCollection(new ArrayList<>());\t\n\t\n\t@Override\n\tpublic Object apply(Object arg, ProgressMonitor progressMonitor) {\n\t\tMap<BiFunction<Object, ProgressMonitor, Object>, Object> outgoingEndpointsResults = new LinkedHashMap<>();\n\t\tfor (BiFunction<Object, ProgressMonitor, Object> e: outgoingEndpoints) {\n\t\t\toutgoingEndpointsResults.put(e, e.apply(arg, progressMonitor));\n\t\t}\n\t\treturn outgoingEndpointsResults;\n\t}\n\t\n\t@OutgoingEndpoint\n\tpublic void addOutgoingEndpoint(BiFunction<Object, ProgressMonitor, Object> endpoint) {\n\t\toutgoingEndpoints.add(endpoint);\n\t}\n\n}``` Root A B A1 A2 B1 Page-1 Node Processor Node Processor source -> target processor target -> source processor Page-1 Node Processor Node Processor Page-1"},"nsd-cli/nsd/drawio/html-app/site/index.html":{"path":"CLI/nsd/drawio/html-app/site","link-uuid":"090f266c-df29-4fb5-a5f9-e8df11c3a8fe","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd drawio html-app site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>]\r\n [-F=<pageTemplateFile>] [-m=<domian>]\r\n [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]...\r\n [-i[=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/model/html-app/save/index.html":{"path":"CLI/nsd/model/html-app/save","link-uuid":"aecd4efa-4fa1-4118-bea2-8264fc5093e8","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model html-app save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>].\r\n ..\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/rules/list/index.html":{"path":"CLI/nsd/rules/list","link-uuid":"d9fc9fd9-081a-4f69-a0b2-58bf2212e392","title":"list","content":"Usage: nsd rules list [-hrV] [--progress-console] [--progress-data]\r\n [--progress-json] [-o=<output>]\r\n [--progress-output=<progressOutput>] [--exclude-rule\r\n [=<ruleExcludes>...]]... [--exclude-rule-set\r\n [=<ruleSetExcludes>...]]... [--include-rule\r\n [=<ruleIncludes>...]]... [--include-rule-set\r\n [=<ruleSetIncludes>...]]...\r\nLists available rule sets and rules\r\n --exclude-rule[=<ruleExcludes>...]\r\n ID's of rules to exclude\r\n --exclude-rule-set[=<ruleSetExcludes>...]\r\n ID's of rule sets to exclude\r\n -h, --help Show this help message and exit.\r\n --include-rule[=<ruleIncludes>...]\r\n ID's of rules to include\r\n --include-rule-set[=<ruleSetIncludes>...]\r\n ID's of rule sets to include\r\n -o, --output=<output> Output file\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --[no-]rules Output rules\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/gsh/index.html":{"path":"CLI/nsd/gitlab/gsh","link-uuid":"7efa02fb-6135-4beb-b213-0b81d57914f6","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab gsh [-hV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/http-server/index.html":{"path":"CLI/nsd/http-server","link-uuid":"c3bc5c40-d57f-4065-8fa9-1867dfd874c7","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/model/index.html":{"path":"CLI/nsd/model","link-uuid":"186e29ad-5b74-415e-832b-9716cbe8413a","title":"model","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd model [-fhV] [--content-type-resource-factory=<String=Class>]...\r\n [--extension-resource-factory=<String=Class>]...\r\n [--protocol-resource-factory=<String=Class>]... <uri> [COMMAND]\r\nLoads EObject from a URI or file\r\n <uri> EObject URI or file path, resolved relative\r\n to the current directory\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit.\r\nCommands:\r\n ecore-html-app Generates Ecore model documentation html app model\r\n html-app Generates html application model from a drawio document\r\n save Saves model to a file"},"nsd-cli/nsd/launcher/index.html":{"path":"CLI/nsd/launcher","link-uuid":"a8eaa357-5a16-4ce0-a1d4-2ec69088f783","title":"launcher","content":"Version: org.nasdanika.cli@2024.12.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 information\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/rules/site/index.html":{"path":"CLI/nsd/rules/site","link-uuid":"593d870e-fa3a-4e53-8b71-c089a299a62f","title":"site","content":"Usage: nsd rules site [-fhlRV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [--root-action-icon=<rootActionIcon>]\r\n [--root-action-location=<rootActionLocation>]\r\n [--root-action-text=<rootActionText>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e[=<excludes>...]]... [-i\r\n [=<includes>...]]... <model> <output>\r\nGenerates rule set documentation site\r\n <model> Model URI, resolved relative\r\n to the current directory\r\n or looked up in registered rule sets\r\n if -R option is provided\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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -f, --file Mdel parameter is a file path\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\r\n -R, --registered Use registered rule set\r\n with provided URI\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"},"core/persistence/index.html":{"path":"Core/Persistence","link-uuid":"19ccdd4b-8f47-4ab4-9c7d-ab3a3876b97e","title":"Persistence","content":"Sources Javadoc"},"nsd-cli/nsd/drawio/index.html":{"path":"CLI/nsd/drawio","link-uuid":"8b1170c8-d0c8-4ec6-aa61-65cbab137fab","title":"drawio","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd drawio [-fhV] [-p=<String=String>]... [-P=URL]...\r\n [-u=<String=String>]... [-U=URL of URI to URL mapping\r\n resource]... <document> [COMMAND]\r\nLoads Drawio document from a URI or file\r\n <document> Document URI or file path, resolved relative\r\n to the current directory\r\n -f, --file Document parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in the\r\n order of definition, later properties replacing the\r\n former\r\n -u, --uri=<String=String>\r\n URI to URL mapping\r\n Target URLs are resolved\r\n relative to the document URL\r\n -U, --uris=URL of URI to URL mapping resource\r\n URI map resource URL relative to the document file\r\n YAML, JSON, or properties\r\n Type is inferred from the content type header, if it\r\n is present,\r\n or extension\r\n -V, --version Print version information and exit.\r\nCommands:\r\n html-app Generates html application model from a drawio document"},"nsd-cli/nsd/java/junit/jacoco/index.html":{"path":"CLI/nsd/java/junit/jacoco","link-uuid":"ef3da8e0-4c12-4703-9b5c-0b874a2022b9","title":"jacoco","content":"Usage: nsd java junit jacoco [-hV] [-c=<classes>] [-j=<jacoco>]\r\n [-m=<moduleName>]\r\nLoads coverage from jacoco.exec and classes directory\r\n -c, --classes=<classes> Classes directory path relative\r\n to the project directory,\r\n defaults to target/classes\r\n -h, --help Show this help message and exit.\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 -m, --module=<moduleName> Coverage module name\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/gitlab/contribute/index.html":{"path":"CLI/nsd/gitlab/contribute","link-uuid":"85fb33c9-254b-4edf-af0c-2ca3fa21d1e4","title":"contribute","content":"Usage: nsd gitlab contribute [-hV] [-a=<String=String>]... (<authorEmail>\r\n <authorName> [-m=<commitMessage>] [-b=<branch>]\r\n [-f] [-s]) [[-t=<targetBranch>] [--[no-]\r\n allow-collaboration]\r\n [--approvals-before-merge=<approvalsBeforeMerge>]\r\n [--assignee=<Assignee ID>]...\r\n [--merge-request-description=<description>] [--\r\n [no-]discussion-locked] [--label=<labels>]...\r\n [--milestone=<milestoneId>] [--[no-]\r\n remove-source-branch] [--reviewer=<Reviewer\r\n ID>]... [--[no-]squash]\r\n [--merge-request-title=<title>]\r\n [--state-event=<stateEvent>]] [COMMAND]\r\nParent for sub-command contributing via GitLabURIHandler\r\n -a, --alias=<String=String>\r\n Map project alias (key) to project ID or path (value)\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommit\r\n <authorEmail> Commit author eMail\r\n <authorName> Commit author name\r\n -b, --branch=<branch> Branch to commit to\r\n -f, --force Force commit\r\n -m, --commit-message=<commitMessage>\r\n Commit message\r\n -s, --stats With stats\r\nMerge request\r\n --[no-]allow-collaboration\r\n\r\n --approvals-before-merge=<approvalsBeforeMerge>\r\n Number of approvals before merge\r\n --assignee=<Assignee ID>\r\n Assignee ID\r\n --[no-]discussion-locked\r\n\r\n --label=<labels>\r\n --merge-request-description=<description>\r\n\r\n --merge-request-title=<title>\r\n\r\n --milestone=<milestoneId>\r\n Milestone ID\r\n --[no-]remove-source-branch\r\n\r\n --reviewer=<Reviewer ID>\r\n Reviewer ID\r\n --[no-]squash\r\n --state-event=<stateEvent>\r\n Valid values: close, reopen\r\n -t, --target-branch=<targetBranch>\r\n Target branch, defaults to the original branch\r\nCommands:\r\n gsh Groovy Shell\r\n invoke Invokes URI\r\n junit Generates JUnit tests\r\n retrospect Parent for sub-commands contributing based on history"},"core/cli/index.html":{"path":"Core/CLI","link-uuid":"4779ae92-48de-4497-ab6e-16eea5486350","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. Sources Javadoc Medium stories: Beyond PicoCLI Declarative Command Pipelines Contributing sub-commands @SubCommands annotation @ParentCommands annotation Programmatic match Contributing mix-ins @MixIns annotation @ParentCommands annotation Programmatic match Overriding Extended documentation Commands Mix-ins Shell Closing commands Building distributions Downloading dependencies Generating launcher scripts Assembly 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. @ParentCommands annotation In this case the sub-command or mix-in class are annotated with @ParentCommands 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, or implement Adaptable and return non-null value from adaptTo(Class) method. This allows to create declarative command pipelines as explained in the Declarative Command Pipelines Medium story. 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. @ParentCommands annotation See “@ParentCommands 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. Commands The CLI module provides several base command classes: CommandBase - base class with standard help mix-in CommandGroup - base class for commands which don’t have own functionality, only sub-commands ContextCommand - command with options to configure Context DelegatingCommand - options to configure Context and ProgressMonitor and delegate execution to SupplierFactory HelpCommand - outputs usage for the command hierarchy in text, html, action model, or generates a documentation site Mix-ins The module also provides several mix-ins: ContextMixIn - creates and configures Context ProgressMonitorMixIn - creates and configures ProgressMonitor ResourceSetMixIn - creates and configures ResourceSet using CapabilityLoader to add packages, resource and adapter factories, … Shell ShellCommand can be used to execute multiple commands in the same JVM. Closing commands Commands implementing org.nasdanika.common.Closeable, including CommandBase and its subclasses are closed recursively. This functionality can be used to release resources or save state to the permanent storage, e.g. file system. 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 a Maven build. Building a distribution involves the following steps: Downloading modules (dependencies) Generating launcher scripts Building an assembly (zip) All of the above steps are executed by mvn verify or mvn clean verify 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. Assembly Create an assembly file dist.xml similar to the one below in src\\assembly directory: <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"\n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">\n <id>dist</id>\n <formats>\n <format>tar.gz</format>\n <format>tar.bz2</format>\n <format>zip</format>\n </formats>\n <fileSets>\n <fileSet>\n <directory>${project.build.directory}/dist</directory>\n <outputDirectory>/</outputDirectory>\n <useDefaultExcludes>false</useDefaultExcludes>\n </fileSet>\n </fileSets>\n</assembly>\n then add the following plugin definition to pom.xml: <plugin>\n\t<artifactId>maven-assembly-plugin</artifactId>\n\t<version>3.7.1</version>\n\t<configuration>\n\t\t<outputDirectory>${project.build.directory}</outputDirectory>\n\t\t<formats>zip</formats>\n\t\t<appendAssemblyId>false</appendAssemblyId>\n\t\t<finalName>nsd-cli-${project.version}</finalName>\n\t\t<descriptors>\n\t\t\t<descriptor>src/assembly/dist.xml</descriptor>\n\t\t</descriptors>\n\t</configuration>\n <executions>\n <execution>\n <id>create-archive</id>\n <phase>verify</phase>\n <goals>\n <goal>single</goal>\n </goals>\n </execution>\n </executions>\n</plugin>\t\t \t\t\t\n Change the final name to your CLI name. E.g. my-company-cli."},"core/resources/index.html":{"path":"Core/Resources","link-uuid":"0a39397a-4b51-42b9-b95f-eddb24d560f2","title":"Resources","content":"Sources Javadoc"},"practices/index.html":{"link-uuid":"3d6da450-8274-46f6-b188-fb96af0d2d44","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. ↩"},"nsd-cli/nsd/invoke/index.html":{"path":"CLI/nsd/invoke","link-uuid":"340c8501-61e4-4cae-bfd1-fd4a9d10d499","title":"invoke","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd invoke [-fhV] [--progress-console] [--progress-data]\r\n [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... <uri> [<bindings>...]\r\nInvokes URI\r\n <uri> URI to invoke\r\n [<bindings>...] Bindings URIs\r\n -f, --file URI parameter is a file path\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/emf/index.html":{"path":"Core/EMF","link-uuid":"a9ee1151-49c1-4eda-a996-a9e2cef83e1b","title":"EMF","content":"Sources Javadoc"},"nsd-cli/nsd/gitlab/contribute/gsh/index.html":{"path":"CLI/nsd/gitlab/contribute/gsh","link-uuid":"ba83be68-3ccd-4ce0-97df-e3828aeb47dd","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab contribute gsh [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"nsd-cli/nsd/index.html":{"path":"CLI/nsd","link-uuid":"c56f3d25-65af-4e21-b80e-5fe2fb7aa4e9","title":"nsd","content":"Version: org.nasdanika.cli@2024.12.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 drawio Loads Drawio document from a URI or file\r\n gitlab Commands for working with GitLab\r\n gsh Groovy Shell\r\n help Outputs usage for all registred commands\r\n http-server Serves HTTP routes\r\n invoke Invokes URI\r\n java Commands related to Java\r\n model Loads EObject from a URI or file\r\n rules Rules commands\r\n shell Starts an interactive shell"},"nsd-cli/nsd/gitlab/contribute/retrospect/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect","link-uuid":"572a725f-4e5a-4498-93b4-62992db8761c","title":"retrospect","content":"Usage: nsd gitlab contribute retrospect [-hV] [--ref=<ref>] [--since=<since>]\r\n [--until=<until>] [--path=<paths>]...\r\n <project> [COMMAND]\r\nParent for sub-commands contributing based on history\r\n <project> Project ID or path\r\n -h, --help Show this help message and exit.\r\n --path=<paths> Paths of interest\r\n --ref=<ref> Reference - branch, tag, or commit\r\n --since=<since> Since date in ISO8601 format yyyy-MM-dd'T'HH:mm:ssZ\r\n --until=<until> Since date in ISO8601 format yyyy-MM-dd'T'HH:mm:ssZ\r\n -V, --version Print version information and exit.\r\nCommands:\r\n gsh Groovy Shell\r\n invoke Invokes URI"},"nsd-cli/nsd/drawio/html-app/save/index.html":{"path":"CLI/nsd/drawio/html-app/save","link-uuid":"eeec6e75-c768-4c1f-ba70-ab96cfbc886e","title":"save","content":"Version: org.nasdanika.cli@2024.12.0 \r\nUsage: nsd drawio html-app save [-hV] [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--progress-output=<progressOutput>]\r\n [--content-type-resource-factory=<String=Class>]\r\n ...\r\n [--extension-resource-factory=<String=Class>]...\r\n\r\n [--protocol-resource-factory=<String=Class>]...\r\n <output>\r\nSaves model to a file\r\n <output> Output file\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -h, --help Show this help message and exit.\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -V, --version Print version information and exit."},"html/jstree/index.html":{"path":"HTML/JsTree","link-uuid":"7f2a3ace-c615-43e2-aa1f-888eeb173add","title":"JsTree","content":"Sources Javadoc"},"nsd-cli/nsd/model/ecore-html-app/index.html":{"path":"CLI/nsd/model/ecore-html-app","link-uuid":"855e1e23-9b7b-41a9-9f0e-09506d540a2d","title":"ecore-html-app","content":"Version: org.nasdanika.models.ecore.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app [-fhRV] [-P=<insertionIndex>] [-r=<rootLabel>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [--content-type-resource-factory=<String=Class>]\r\n ...\r\n [--extension-resource-factory=<String=Class>]...\r\n [-M=<String=String>]...\r\n [--protocol-resource-factory=<String=Class>]...\r\n [COMMAND]\r\nGenerates Ecore model documentation html app model\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 directory.\r\n YAML, JSON, or properties. In properties dots are\r\n treated as key path separators. Type is inferred from\r\n the content type header, if it is present, or\r\n extension. Contexts are composed in the order of\r\n definition, later context entries shadowing the former\r\n --content-type-resource-factory=<String=Class>\r\n Maps content type to resource factory class\r\n --extension-resource-factory=<String=Class>\r\n Maps extension to resource factory class\r\n -f, --file Root action option is a file path\r\n -h, --help Show this help message and exit.\r\n -M, --context-mount=<String=String>\r\n MappingContext resource URL relative to the current\r\n directory. YAML, JSON, or properties. In properties\r\n dots are treated as key path separators. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Mounts shadow context entries.\r\n -P, --position=<insertionIndex>\r\n Insertion position\r\n Defaults to 0\r\n --protocol-resource-factory=<String=Class>\r\n Maps protocol to resource factory class\r\n -r, --root-label=<rootLabel>\r\n Root label URL or file path, resolved relative\r\n to the current directory\r\n -R, --add-to-root Add labels to the root\r\n even if the principal is present\r\n -V, --version Print version information and exit.\r\nCommands:\r\n save Saves model to a file\r\n site Generates HTML site"},"glossary.html":{"link-uuid":"b79b549b-da76-443d-80d3-d2b025bb0d2c","title":"Glossary","content":"Clear Identifier(s) Hide UUID {{data.value.name}} {{data.value[0].value}} {{item.value}}"},"nsd-cli/nsd/rules/index.html":{"path":"CLI/nsd/rules","link-uuid":"1b9261e4-d4bf-4963-823f-15fe92e20476","title":"rules","content":"Usage: nsd rules [-hV] [COMMAND]\r\nRules commands\r\n -h, --help Show this help message and exit.\r\n -V, --version Print version information and exit.\r\nCommands:\r\n action-model Generates rule set documentation action model\r\n list Lists available rule sets and rules\r\n site Generates rule set documentation site"},"core/exec/index.html":{"path":"Core/Exec","link-uuid":"dc0840f1-98f3-4c3d-b611-95168139c3f1","title":"Exec","content":"Sources Javadoc"},"html/html/index.html":{"path":"HTML/HTML","link-uuid":"965cad88-a835-45e8-8f51-8efdd0b83661","title":"HTML","content":"Sources Javadoc"},"nsd-cli/nsd/gitlab/contribute/junit/index.html":{"path":"CLI/nsd/gitlab/contribute/junit","link-uuid":"2081a7f5-09d4-45b5-ac43-ac17c41694d3","title":"junit","content":"Version: org.nasdanika.models.java.cli@2024.12.0 \r\nUsage: nsd gitlab contribute junit [-fhVw] [--[no-]ai] [--[no-]\r\n comment-response] [--disabled]\r\n [--progress-console] [--progress-data]\r\n [--progress-json]\r\n [--api-endpoint=<apiEndpoint>]\r\n [--class-suffix=<classSuffix>] [-k=<apiKey>]\r\n [-l=<limit>] [-m=<deploymentOrModelName>]\r\n [--package-suffix=<packageSuffix>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<prompt>] [-s=<sources>]\r\n [-t=<coverageType>]\r\n [-v=<apiKeyEnvironmentVariable>] [-e\r\n [=<excludes>...]]... [-i[=<includes>...]]...\r\n <projectURI> <coverageThreshold> <output>\r\n [COMMAND]\r\nGenerates JUnit tests\r\n <projectURI> Project URI\r\n <coverageThreshold> Coverage threshold\r\n <output> Output URI\r\n relative to the project URI\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 --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 --disabled Generate disabled tests\r\n -e, --exclude[=<excludes>...]\r\n Source excludes\r\n Ant pattern\r\n -f Project URI is a file path\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 -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 --package-suffix=<packageSuffix>\r\n Test package suffix\r\n defaults to .tests\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\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 URI path relative\r\n to the project URIy,\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\r\nCommands:\r\n jacoco Loads coverage from jacoco.exec and classes directory"},"nsd-cli/nsd/java/index.html":{"path":"CLI/nsd/java","link-uuid":"6aaf298d-8c20-4324-913e-a04b05260285","title":"java","content":"Version: org.nasdanika.models.java.cli@2024.12.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","link-uuid":"2f9f67bd-cb80-40dc-9863-d29959fe22b3","title":"site","content":"Usage: nsd help site [-hlV] [--progress-console] [--progress-data]\r\n [--progress-json] [-b=<baseDir>] [-m=<domian>]\r\n [-P=<parallelism>] [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [--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 -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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/gitlab/contribute/retrospect/gsh/index.html":{"path":"CLI/nsd/gitlab/contribute/retrospect/gsh","link-uuid":"2a935f00-544b-49e2-9747-5d2f9496f9f4","title":"gsh","content":"Version: org.nasdanika.groovy@2024.12.0 \r\nUsage: nsd gitlab contribute retrospect gsh [-hV] [--progress-console]\r\n [--progress-data] [--progress-json] [--progress-output=<progressOutput>]\r\n [-p=<String=String>]... [-P=URL]... [<args>...]\r\nGroovy Shell\r\n [<args>...] Argument URIs\r\n -h, --help Show this help message and exit.\r\n -p, --property=<String=String>\r\n Property\r\n -P, --properties=URL Properties resource URL relative to the current\r\n directory. YAML, JSON, or properties. Type is\r\n inferred from the content type header, if it is\r\n present, or extension. Properties are loaded in\r\n the order of definition, later properties\r\n replacing the former\r\n --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -V, --version Print version information and exit."},"core/index.html":{"link-uuid":"4546de68-a951-45cd-8fbe-bdfe4ec13404","title":"Core","content":"Sources"},"practices/generic/index.html":{"path":"Practices/Analysis, Visualization & Generation","link-uuid":"9868e662-a7f5-49c6-b57c-e75f4750213e","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 Transformation 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 Transformation Corporation Marketing Finance Uses Operations HR Builds IT Execution environments Binary packages Source Code Application Transformation"},"nsd-cli/nsd/gitlab/index.html":{"path":"CLI/nsd/gitlab","link-uuid":"a2a87981-ae84-4b68-8c52-371646a2165f","title":"gitlab","content":"Usage: nsd gitlab [-hV] [-l=<clientRateLimit>] [-t=<accessToken>] [-u=<url>]\r\n [-w=<clientRateLimitWindow>] [COMMAND]\r\nCommands for working with GitLab\r\n -h, --help Show this help message and exit.\r\n -l, --client-rate-limit=<clientRateLimit>\r\n Client enforced rate limit\r\n use this option if the server limits requests rate,\r\n but does not rate limit headers to the client\r\n only errors if the rate limit is exceeded\r\n -t, --access-token=<accessToken>\r\n GitLab access token, defaults to the value of\r\n GITLAB_ACCESS_TOKEN environment variable\r\n -u, --url=<url> GitLab URL, defaults to the value of\r\n GITLAB_URL environment variable\r\n -V, --version Print version information and exit.\r\n -w, --client-rate-limit-window=<clientRateLimitWindow>\r\n Client enforced rate limit window in seconds\r\n defaults to 10\r\n ignored if the client rate limit is not set\r\nCommands:\r\n contribute Parent for sub-command contributing via GitLabURIHandler\r\n gsh Groovy Shell\r\n invoke Invokes URI"},"core/http/index.html":{"path":"Core/HTTP","link-uuid":"c6fdabaa-635c-4ef6-9238-0fcc6cf8a921","title":"HTTP","content":"Sources Javadoc"},"nsd-cli/nsd/model/ecore-html-app/site/index.html":{"path":"CLI/nsd/model/ecore-html-app/site","link-uuid":"cd60c42f-7211-4300-b694-c248157f795d","title":"site","content":"Version: org.nasdanika.models.app.cli@2024.12.0 \r\nUsage: nsd model ecore-html-app site [-hlV] [--progress-console]\r\n [--progress-data] [--progress-json]\r\n [-b=<baseDir>] [-F=<pageTemplateFile>]\r\n [-m=<domian>] [-P=<parallelism>]\r\n [--progress-output=<progressOutput>]\r\n [-r=<pageErrors>] [-t=<timeout>]\r\n [-T=<pageTemplate>] [-w=<workDir>]\r\n [-c=<String=String>]... [-C=URL]...\r\n [-M=<String=String>]... [-e\r\n [=<excludes>...]]... [-i\r\n [=<includes>...]]... <output>\r\nGenerates HTML site\r\n <output> Output directory relative to the base 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 -e, --exclude[=<excludes>...]\r\n Output directory clean excludes\r\n Ant pattern\r\n -F, --page-template-file=<pageTemplateFile>\r\n Page template file relative\r\n to the current directory\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 -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, --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 --progress-console Output progress to console\r\n --progress-data Output progress data\r\n --progress-json Output progress in JSON\r\n --progress-output=<progressOutput>\r\n Output file for progress monitor\r\n -r, --errors=<pageErrors> Expected number of page errors\r\n -1 for any (not fail on errors)\r\n default is 0\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"},"nsd-cli/nsd/help/index.html":{"path":"CLI/nsd/help","link-uuid":"f460352e-1d31-4ca2-ad0e-56c29428a8c9","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 b8df0eb3b..ab563482d 100644 --- a/docs/search.html +++ b/docs/search.html @@ -38,45 +38,45 @@
- + Nasdanika
-
+
-
- -
+
+ +
-
+
-

Search +

Search

@@ -279,7 +279,7 @@

results.split(' ').includes(node.original['data-nsd-label-uuid']); return tree; }({"core":{"data":[{"a_attr":{"onclick":"window.location='index.html';"},"children":[{"children":[{"children":[{"children":[{"a_attr":{"onclick":"window.location='https://leanpub.com/u/pvlasov';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='https://docs.nasdanika.org/resources/beyond-diagrams-sample.pdf';"},"data-nsd-label-uuid":"8b053630-aa85-4616-b59c-ee45ae090836","id":"58c8fc39-9271-4fda-8bd3-45f699b5da13","text":"Beyond Diagrams","type":"leaf"},{"a_attr":{"onclick":"window.location='https://leanpub.com/java-analysis';"},"data-nsd-label-uuid":"c365b5d6-5a16-4e02-9d26-639d7ce242fb","id":"157ccc27-127e-4a93-ad12-8cc91c3a8fd1","text":"Java Analysis, Visualization, and Generation","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"a0530ff7-119c-4d75-ab66-8c5586d0b152","id":"346bb872-bad4-4f5e-85a7-37c4a5d25035","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":"9868e662-a7f5-49c6-b57c-e75f4750213e","id":"e7f8dc1b-eaf4-44d9-a973-0cd57dd28b94","text":"Analysis, Visualization & Generation","type":"leaf"},{"a_attr":{"onclick":"window.location='practices/java/index.html';"},"data-nsd-label-uuid":"b3ba7a9f-54f5-4c3e-a9bc-6cd85f10387b","id":"e53d4e4b-3d21-4735-91c6-e2e65b923a56","text":"Java Analysis, Visualization & Generation","type":"leaf"},{"a_attr":{"onclick":"window.location='practices/junit/index.html';"},"data-nsd-label-uuid":"78ecbb39-34b1-46a2-b8fe-18d8177ee712","id":"c112f432-95ee-4684-9b8e-16a2b7c9aa0a","text":"JUnit Tests Generation","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"3d6da450-8274-46f6-b188-fb96af0d2d44","id":"ba91c38a-ace4-4ca7-a27e-530ed26331ad","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":"217a9773-d7bf-4884-a30e-0e8535bd3dfd","id":"a9a71035-d3b0-412d-b254-d5b1e761b29f","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"8ace60fd-23a4-485a-af76-9f19e8425f10","id":"0f587c94-0675-4111-9a9a-d6ebdac2b32a","text":"app","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/drawio/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/drawio/html-app/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/drawio/html-app/save/index.html';"},"data-nsd-label-uuid":"eeec6e75-c768-4c1f-ba70-ab96cfbc886e","icon":"https://img.icons8.com/dusk/20/save--v1.png","id":"19073611-cd44-49a9-92b6-e583e8f21dbc","text":"save","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/drawio/html-app/site/index.html';"},"data-nsd-label-uuid":"090f266c-df29-4fb5-a5f9-e8df11c3a8fe","icon":"https://img.icons8.com/material-two-tone/20/web.png","id":"c4eaa75c-3609-46d1-b6c2-79cfe0de6301","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"1a831d5f-8c39-4faa-a8d1-21bc9ca7200e","id":"4be031e2-b202-48b6-89ef-d974575d231f","text":"html-app","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"8b1170c8-d0c8-4ec6-aa61-65cbab137fab","icon":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3QgeT0iMiIgeD0iMiIgd2lkdGg9IjI4IiByeD0iMS4xMiIgaGVpZ2h0PSIyOCIgZmlsbD0iI2YwODcwNSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgZmlsbD0iI2RmNmMwYyIgZD0ibTE2Ljg2MSA5LjE2OCAzLjAyLTMuMTg3IDEwLjExOSAxMC4xMTN2MTIuNzg2YTEuMTE5IDEuMTE5IDAgMCAxIC0xLjEyIDEuMTJoLTE3LjU2NGwtNS4zODUtNS40MDd6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTI1LjI0IDE3Ljk2aC0zLjI5NGwtMy4wNzEtNS4zMmguMmExLjExOSAxLjExOSAwIDAgMCAxLjEyLTEuMTJ2LTQuNzZhMS4xMTkgMS4xMTkgMCAwIDAgLTEuMTItMS4xMmgtNi4xNTVhMS4xMTkgMS4xMTkgMCAwIDAgLTEuMTIgMS4xMnY0Ljc2YTEuMTE5IDEuMTE5IDAgMCAwIDEuMTIgMS4xMmguMjA1bC0zLjA3MSA1LjMyaC0zLjI5NGExLjExOSAxLjExOSAwIDAgMCAtMS4xMiAxLjEydjQuNzZhMS4xMTkgMS4xMTkgMCAwIDAgMS4xMiAxLjEyaDYuMTZhMS4xMTkgMS4xMTkgMCAwIDAgMS4xMi0xLjEydi00Ljc2YTEuMTE5IDEuMTE5IDAgMCAwIC0xLjEyLTEuMTJoLS45MjdsMy4wNzItNS4zMmgxLjg3bDMuMDcxIDUuMzJoLS45MjZhMS4xMTkgMS4xMTkgMCAwIDAgLTEuMTIgMS4xMnY0Ljc2YTEuMTE5IDEuMTE5IDAgMCAwIDEuMTIgMS4xMmg2LjE2YTEuMTE5IDEuMTE5IDAgMCAwIDEuMTItMS4xMnYtNC43NmExLjExOSAxLjExOSAwIDAgMCAtMS4xMi0xLjEyeiIvPjwvc3ZnPg==","id":"0236b7d5-0887-4cad-87a4-8f41e9c537e9","text":"drawio","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/gsh/index.html';"},"data-nsd-label-uuid":"ba83be68-3ccd-4ce0-97df-e3828aeb47dd","icon":"https://docs.nasdanika.org/images/command.svg","id":"4eced594-780c-4844-92f1-c37214c244f3","text":"gsh","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/invoke/index.html';"},"data-nsd-label-uuid":"699a83e8-68d1-4a66-8680-f92146440fe0","icon":"https://docs.nasdanika.org/images/optimization.svg","id":"3069c97a-1abb-40a9-a18a-c7b0b93f3690","text":"invoke","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/junit/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/junit/jacoco/index.html';"},"data-nsd-label-uuid":"3813a50b-3d07-4bfa-8417-a92c7c1659ad","id":"5218c9a8-b341-41ee-90e6-38842b3a2bfa","text":"jacoco","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"2081a7f5-09d4-45b5-ac43-ac17c41694d3","icon":"https://docs.nasdanika.org/images/JUnit.svg","id":"94af0f80-69dc-4e8b-8fb2-57158d4a0f44","text":"junit","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/retrospect/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/retrospect/gsh/index.html';"},"data-nsd-label-uuid":"2a935f00-544b-49e2-9747-5d2f9496f9f4","icon":"https://docs.nasdanika.org/images/command.svg","id":"b6f62867-7d8a-4f3b-9814-91c23e5916a7","text":"gsh","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/contribute/retrospect/invoke/index.html';"},"data-nsd-label-uuid":"d89994fb-3b5e-4e28-8e3a-4e06176b4d73","icon":"https://docs.nasdanika.org/images/optimization.svg","id":"07118327-223f-40c6-8599-0bf097e60963","text":"invoke","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"572a725f-4e5a-4498-93b4-62992db8761c","icon":"https://docs.nasdanika.org/images/retrospective.svg","id":"d83efe31-70d5-495d-94a1-947860466aa9","text":"retrospect","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"85fb33c9-254b-4edf-af0c-2ca3fa21d1e4","icon":"https://docs.nasdanika.org/images/jigsaw.svg","id":"1ce65eeb-437b-48b1-ae76-06379b411ba4","text":"contribute","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/gsh/index.html';"},"data-nsd-label-uuid":"7efa02fb-6135-4beb-b213-0b81d57914f6","icon":"https://docs.nasdanika.org/images/command.svg","id":"659d4150-aa3e-4925-bc32-eb9f60a4fd2c","text":"gsh","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gitlab/invoke/index.html';"},"data-nsd-label-uuid":"38d96a5f-6723-4c9e-8a58-c6e04fa421a6","icon":"https://docs.nasdanika.org/images/optimization.svg","id":"72f079c7-982a-4436-9d8d-30999f666405","text":"invoke","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"a2a87981-ae84-4b68-8c52-371646a2165f","icon":"https://docs.nasdanika.org/images/GitLab.svg","id":"0a054408-7097-41ed-b118-b24f0db3a174","text":"gitlab","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/gsh/index.html';"},"data-nsd-label-uuid":"6930bdd9-91e8-46c8-877d-c9e8203de001","icon":"https://docs.nasdanika.org/images/command.svg","id":"06a06947-b180-48d4-905e-a90c92eb939c","text":"gsh","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":"2f9f67bd-cb80-40dc-9863-d29959fe22b3","id":"958e47cc-0da0-4e9e-8a02-3fbf40401a40","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"f460352e-1d31-4ca2-ad0e-56c29428a8c9","id":"cb81de49-e1c6-420e-b900-5238b745853c","text":"help","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/http-server/index.html';"},"data-nsd-label-uuid":"c3bc5c40-d57f-4065-8fa9-1867dfd874c7","id":"b5cade9d-2a8c-47ec-bbb8-86791818b063","text":"http-server","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/invoke/index.html';"},"data-nsd-label-uuid":"340c8501-61e4-4cae-bfd1-fd4a9d10d499","icon":"https://docs.nasdanika.org/images/optimization.svg","id":"670be251-f129-4a22-9485-4ab5ebbfcef0","text":"invoke","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';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/java/junit/jacoco/index.html';"},"data-nsd-label-uuid":"ef3da8e0-4c12-4703-9b5c-0b874a2022b9","id":"8bb9bba6-1973-4fb9-b6ca-a7dd9a111e90","text":"jacoco","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"9c7cb60b-fa27-471c-bafc-1f1b006a1672","icon":"https://docs.nasdanika.org/images/JUnit.svg","id":"4eea20f5-beae-4a4d-a6fb-2917e79c1c6b","text":"junit","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"6aaf298d-8c20-4324-913e-a04b05260285","icon":"https://docs.nasdanika.org/images/java.svg","id":"bd1bce63-bfa8-401b-a9d1-17d5d9362635","text":"java","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/launcher/index.html';"},"data-nsd-label-uuid":"a8eaa357-5a16-4ce0-a1d4-2ec69088f783","id":"fac22551-80f7-495d-9ad5-953d32198b76","text":"launcher","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/ecore-html-app/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/ecore-html-app/save/index.html';"},"data-nsd-label-uuid":"43e10ad7-4ad7-42b4-a742-d6bf1d6c1433","icon":"https://img.icons8.com/dusk/20/save--v1.png","id":"be7642f3-0bff-49a6-ab2f-5e5680fd01c4","text":"save","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/ecore-html-app/site/index.html';"},"data-nsd-label-uuid":"cd60c42f-7211-4300-b694-c248157f795d","icon":"https://img.icons8.com/material-two-tone/20/web.png","id":"4824517b-9104-467f-9d3a-b5ea3675ffd4","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"855e1e23-9b7b-41a9-9f0e-09506d540a2d","id":"46b3369e-2d06-48d3-b832-2a8eddfffd6f","text":"ecore-html-app","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/html-app/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/html-app/save/index.html';"},"data-nsd-label-uuid":"aecd4efa-4fa1-4118-bea2-8264fc5093e8","icon":"https://img.icons8.com/dusk/20/save--v1.png","id":"3b8ca4b7-7569-4b7d-b2fc-1c818dc405d9","text":"save","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/html-app/site/index.html';"},"data-nsd-label-uuid":"5bd766eb-6711-4178-b0d1-8b0704f9a360","icon":"https://img.icons8.com/material-two-tone/20/web.png","id":"2a70cadd-687a-43f0-a53f-d8540a98ba7e","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"8bb9d4b7-5ff1-4f2d-a87a-097a24bb16d6","icon":"https://img.icons8.com/external-flatart-icons-outline-flatarticons/20/external-html-programming-and-coding-flatart-icons-outline-flatarticons-5.png","id":"0d8c7ca6-7f67-4733-ba3d-0ea33f8b47c5","text":"html-app","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/model/save/index.html';"},"data-nsd-label-uuid":"1c444dee-1ba2-4baf-a27d-da1165441bcb","icon":"https://img.icons8.com/dusk/20/save--v1.png","id":"2b8e7c36-ee33-4f23-89b0-a04222f67f26","text":"save","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"186e29ad-5b74-415e-832b-9716cbe8413a","id":"e27f60a6-5959-4f27-afa6-abbd0021b8ee","text":"model","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/rules/index.html';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='nsd-cli/nsd/rules/action-model/index.html';"},"data-nsd-label-uuid":"4023b714-b637-4102-b913-942751ce6673","id":"f55b4a3c-3c64-4e03-a6ab-59199f5f0187","text":"action-model","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/rules/list/index.html';"},"data-nsd-label-uuid":"d9fc9fd9-081a-4f69-a0b2-58bf2212e392","id":"87a68d94-6ef1-444b-9c45-4c10002b524c","text":"list","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/rules/site/index.html';"},"data-nsd-label-uuid":"593d870e-fa3a-4e53-8b71-c089a299a62f","id":"4bfed8ad-a5d1-48ec-affe-d894f216f7b0","text":"site","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"1b9261e4-d4bf-4963-823f-15fe92e20476","id":"a0db8559-d70e-4451-91af-3d96ba63ea06","text":"rules","type":"leaf"},{"a_attr":{"onclick":"window.location='nsd-cli/nsd/shell/index.html';"},"data-nsd-label-uuid":"4a069308-3ba8-48ee-9223-b74e72b835b3","icon":"https://img.icons8.com/nolan/20/console.png","id":"40a30c94-86f1-447e-959d-5e0e74f701af","text":"shell","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"c56f3d25-65af-4e21-b80e-5fe2fb7aa4e9","id":"7a4fa719-4347-4f78-a2a9-f23188c3a1e0","text":"nsd","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"333aae15-02e4-44fb-8ac9-c37cbfabb909","icon":"/images/command-line.svg","id":"136676a6-81f9-4eee-b29a-5d03693da244","text":"CLI","type":"leaf"},{"a_attr":{"onclick":"window.location='https://github.com/Nasdanika-Models';"},"children":[{"children":[{"a_attr":{"onclick":"window.location='https://html-app.models.nasdanika.org/index.html';"},"data-nsd-label-uuid":"70ae71b2-10ca-4498-8e1b-51db6493d243","id":"178e8cd0-697f-46fa-aff9-d0c3c528df51","text":"App","type":"leaf"},{"a_attr":{"onclick":"window.location='https://architecture.models.nasdanika.org';"},"data-nsd-label-uuid":"f62b19ba-8fd7-467f-9c7d-9fdf9f950d50","id":"e6b6cd46-756d-4123-8c8a-27ff0aa22380","text":"Architecture","type":"leaf"},{"a_attr":{"onclick":"window.location='https://azure.models.nasdanika.org';"},"data-nsd-label-uuid":"a14b7993-1ef3-49e4-b985-e65da9678163","id":"c26252b2-8b5b-47c8-9d46-44fc2104fb62","text":"Azure","type":"leaf"},{"a_attr":{"onclick":"window.location='https://bank.models.nasdanika.org';"},"data-nsd-label-uuid":"7f9fb63d-36a5-4330-a445-34e6795952c9","id":"006bb1b7-de63-4e97-9fc3-ce8c4ca4eb17","text":"Bank","type":"leaf"},{"a_attr":{"onclick":"window.location='https://bootstrap.models.nasdanika.org';"},"data-nsd-label-uuid":"40fbf11f-eb01-43b6-af96-bf18839793d3","id":"15f04e11-5720-4243-8610-796cefc20a24","text":"Bootstrap","type":"leaf"},{"a_attr":{"onclick":"window.location='https://capability.models.nasdanika.org';"},"data-nsd-label-uuid":"49374271-2634-478a-9c3b-93475ec92744","id":"d63745f9-b482-44c0-9546-2bc53aefc2de","text":"Capability","type":"leaf"},{"a_attr":{"onclick":"window.location='https://coverage.models.nasdanika.org';"},"data-nsd-label-uuid":"941f8f85-297d-4cf8-bdc5-0636a4a3fc31","id":"3025a869-b708-4d60-bb43-b7263adefb07","text":"Coverage","type":"leaf"},{"a_attr":{"onclick":"window.location='https://mcda.models.nasdanika.org';"},"data-nsd-label-uuid":"bee6553d-dc73-4d9a-a4e0-a8f4c51dcecb","id":"f0c8455d-9cd2-4d3f-98ed-e7684dad18cc","text":"Decision Analysis","type":"leaf"},{"a_attr":{"onclick":"window.location='https://echarts.models.nasdanika.org';"},"data-nsd-label-uuid":"396e768a-fde5-41fb-a90c-ee5d3922ff16","id":"b66a0e04-b040-4b4a-a98f-01c8b7a8d598","text":"ECharts","type":"leaf"},{"a_attr":{"onclick":"window.location='https://ecore.models.nasdanika.org';"},"data-nsd-label-uuid":"a8f5517a-8c19-40d2-b189-746c07c1efe9","id":"34da5eee-8c99-4aba-bfc0-1fc340b436a0","text":"Ecore","type":"leaf"},{"a_attr":{"onclick":"window.location='https://enterprise.models.nasdanika.org';"},"data-nsd-label-uuid":"e0a45f3a-2d95-456b-ba9b-d6f3208d9b45","id":"5a7e8a1e-7007-4982-926c-8e725f689826","text":"Enterprise","type":"leaf"},{"a_attr":{"onclick":"window.location='https://excel.models.nasdanika.org';"},"data-nsd-label-uuid":"fcb67104-fe98-4a36-b997-51b510ce8ff5","id":"55ef3428-c490-42e5-9f34-80fc92e9f7d8","text":"Excel","type":"leaf"},{"a_attr":{"onclick":"window.location='https://family.models.nasdanika.org';"},"data-nsd-label-uuid":"da31950f-614f-4781-8034-3d788777a288","id":"cbb62b74-d450-4f11-9c66-b29c9a7136ef","text":"Family","type":"leaf"},{"a_attr":{"onclick":"window.location='https://flow.models.nasdanika.org';"},"data-nsd-label-uuid":"c540b90f-2a97-4d33-bbc4-338620d85328","id":"3e0f5faf-5eec-4831-99f1-4035a85e6040","text":"Flow","type":"leaf"},{"a_attr":{"onclick":"window.location='https://function-flow.models.nasdanika.org';"},"data-nsd-label-uuid":"4c44cc81-4f02-4fad-93aa-cd2d7e02d36a","id":"35e8b4aa-d179-42fd-8537-c016ef843d13","text":"Function Flow","type":"leaf"},{"a_attr":{"onclick":"window.location='https://git.models.nasdanika.org';"},"data-nsd-label-uuid":"fefba89e-fc85-4719-968d-490b9da079b6","id":"e9497c02-96eb-4e85-8309-97db8892a958","text":"Git","type":"leaf"},{"a_attr":{"onclick":"window.location='https://gitlab.models.nasdanika.org';"},"data-nsd-label-uuid":"98acfb8b-80a6-4d30-a87f-4dabac070d07","id":"91d16ea5-3830-4cd1-98d8-2a6a728a302d","text":"GitLab","type":"leaf"},{"a_attr":{"onclick":"window.location='https://html-app.models.nasdanika.org';"},"data-nsd-label-uuid":"ca49235e-2248-4ebb-b174-79c1bcf8a16e","id":"a4af01f9-ea13-49d5-8710-84f3514fe671","text":"HTML","type":"leaf"},{"a_attr":{"onclick":"window.location='https://java.models.nasdanika.org';"},"data-nsd-label-uuid":"64d44439-e7aa-4c7e-93a6-8b165be76744","id":"9bd56fbb-e335-4776-9c10-ee154a8742ee","text":"Java","type":"leaf"},{"a_attr":{"onclick":"window.location='https://jira.models.nasdanika.org';"},"data-nsd-label-uuid":"e93a6cd7-cf46-43b8-8a9e-2db7c3bab2f6","id":"a3878f29-b13f-43d3-9ea3-61dba06005bb","text":"Jira","type":"leaf"},{"a_attr":{"onclick":"window.location='https://maven.models.nasdanika.org';"},"data-nsd-label-uuid":"62a16a75-b085-4740-b0bf-515b880e5f51","id":"4c29ad21-9002-4115-9f59-d0717a58b900","text":"Maven","type":"leaf"},{"a_attr":{"onclick":"window.location='https://nature.models.nasdanika.org';"},"data-nsd-label-uuid":"72d6ea6a-d76a-45ca-b100-97b519c70caf","id":"4bfaa18d-67e8-48ff-b59f-41d05d28f0de","text":"Nature","type":"leaf"},{"a_attr":{"onclick":"window.location='https://pdf.models.nasdanika.org';"},"data-nsd-label-uuid":"90b223dd-4f6e-4942-bb79-8381cf2a73db","id":"60e8cdaa-dc48-4eb2-b3ad-a556c852a5b3","text":"PDF","type":"leaf"},{"a_attr":{"onclick":"window.location='https://party.models.nasdanika.org';"},"data-nsd-label-uuid":"208a35aa-b4b2-47ee-9779-9980f977f788","id":"4085cd66-95a1-4e3e-8c9e-d1b58d2a4398","text":"Party","type":"leaf"},{"a_attr":{"onclick":"window.location='https://rules.models.nasdanika.org';"},"data-nsd-label-uuid":"5346f59b-1780-4a91-bc3e-9ff3ff374af4","id":"e0ec2d9b-0193-4418-9aea-54b3163c7590","text":"Rules","type":"leaf"},{"a_attr":{"onclick":"window.location='https://source-engineering.models.nasdanika.org';"},"data-nsd-label-uuid":"1c1463ae-6bf3-4f23-aa11-b6100ae4b78c","id":"ebfce6c6-cc52-4797-a29e-cda62a5d300f","text":"Source Engineering","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"45cfc737-1aeb-4728-b458-03ea301d0d02","id":"b81883de-4326-47b2-9776-d2b686cf2d69","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":"2f238adc-13f1-406c-be82-80390bfffb58","id":"eeccdb04-c45b-4950-b315-e8539a8047e0","text":"Bootstrap","type":"leaf"},{"a_attr":{"onclick":"window.location='html/html/index.html';"},"data-nsd-label-uuid":"965cad88-a835-45e8-8f51-8efdd0b83661","id":"20e6887f-b2e1-49e5-b631-c069432cf6fb","text":"HTML","type":"leaf"},{"a_attr":{"onclick":"window.location='html/jstree/index.html';"},"data-nsd-label-uuid":"7f2a3ace-c615-43e2-aa1f-888eeb173add","id":"3367d8ee-29ea-4124-b5da-b296a3e7351a","text":"JsTree","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"ec620720-90e7-451f-88ea-f12a690f2a19","icon":"/images/html.svg","id":"f041d1ba-82fd-4d31-91b7-c334632fcc4f","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":"4779ae92-48de-4497-ab6e-16eea5486350","icon":"/images/command-line.svg","id":"56516d84-6208-4064-b634-0ec69a33efee","text":"CLI","type":"leaf"},{"a_attr":{"onclick":"window.location='core/capability/index.html';"},"data-nsd-label-uuid":"bbd73087-4469-4887-914a-2fbfc684a44c","id":"04085eb1-7bd9-4775-8a88-818b7901e430","text":"Capability","type":"leaf"},{"a_attr":{"onclick":"window.location='core/common/index.html';"},"data-nsd-label-uuid":"c71bc150-a96c-43bd-9089-f914244c567a","id":"c971f093-4988-4531-87d4-4cfaabaa1f14","text":"Common","type":"leaf"},{"a_attr":{"onclick":"window.location='core/diagram/index.html';"},"data-nsd-label-uuid":"0cd651ce-1699-4b4e-868c-0cd6e6ca7c49","id":"82bf7fb8-8852-48d3-9255-f8dca31f2e5d","text":"Diagram","type":"leaf"},{"a_attr":{"onclick":"window.location='core/drawio/index.html';"},"data-nsd-label-uuid":"d6351d9d-4484-40ad-9287-1ec216cf35ce","id":"fac81b84-39ab-4bc0-859d-b3deed128906","text":"Drawio","type":"leaf"},{"a_attr":{"onclick":"window.location='core/emf/index.html';"},"data-nsd-label-uuid":"a9ee1151-49c1-4eda-a996-a9e2cef83e1b","id":"b6fc7fe7-99c7-4683-b85d-191ef3443731","text":"EMF","type":"leaf"},{"a_attr":{"onclick":"window.location='core/exec/index.html';"},"data-nsd-label-uuid":"dc0840f1-98f3-4c3d-b611-95168139c3f1","id":"8aefebc9-bc2e-4369-8320-d814f40ca1ca","text":"Exec","type":"leaf"},{"a_attr":{"onclick":"window.location='core/graph/index.html';"},"data-nsd-label-uuid":"4dec2691-78b8-4428-90b1-ca57bd1176a2","icon":"/images/data-flow.svg","id":"aee57c2d-f92c-4999-bde1-bb46de9c6635","text":"Graph","type":"leaf"},{"a_attr":{"onclick":"window.location='core/http/index.html';"},"data-nsd-label-uuid":"c6fdabaa-635c-4ef6-9238-0fcc6cf8a921","icon":"/images/http.svg","id":"4da493bc-f963-4cdb-829f-f151f29c99f7","text":"HTTP","type":"leaf"},{"a_attr":{"onclick":"window.location='core/mapping/index.html';"},"data-nsd-label-uuid":"e410c273-a0c1-482c-83ba-0e5f3c610203","icon":"/images/mapping.svg","id":"60f6861e-b11c-4d7f-93b3-982d81a38166","text":"Mapping","type":"leaf"},{"a_attr":{"onclick":"window.location='core/maven/index.html';"},"data-nsd-label-uuid":"0d53ab80-3272-4949-bba4-00a2434c6c4c","id":"33f0bec0-53c4-4dfd-9385-ddf14b418b0b","text":"Maven","type":"leaf"},{"a_attr":{"onclick":"window.location='https://ncore.models.nasdanika.org/';"},"data-nsd-label-uuid":"73f2c4de-2984-4867-af4e-9342bce9086a","id":"8283069c-4d06-4045-aaad-08a5bf17f579","text":"Ncore","type":"leaf"},{"a_attr":{"onclick":"window.location='core/persistence/index.html';"},"data-nsd-label-uuid":"19ccdd4b-8f47-4ab4-9c7d-ab3a3876b97e","id":"b01dfb5c-0f0d-4320-8090-e6bb595f591f","text":"Persistence","type":"leaf"},{"a_attr":{"onclick":"window.location='core/resources/index.html';"},"data-nsd-label-uuid":"0a39397a-4b51-42b9-b95f-eddb24d560f2","id":"b3556a5a-ff85-40ee-8079-425cc31e9c11","text":"Resources","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"4546de68-a951-45cd-8fbe-bdfe4ec13404","icon":"/images/earth.svg","id":"0397eb64-d0e0-4254-b545-f0ad4b50a2bd","text":"Core","type":"leaf"}],"text":"Children"}],"data-nsd-label-uuid":"00c59493-fc17-412b-8121-4402a70fb814","id":"6986c8b0-6e7f-4bfe-aac8-759d17dc9abd","text":"(blank)","type":"leaf"},{"data-nsd-label-uuid":"52e524d7-420d-4f44-8974-028a9871438b","icon":"fas fa-search","id":"f6348a6d-8cb6-413e-b786-d51abb3ee112","text":"Search","type":"leaf"},{"a_attr":{"onclick":"window.location='glossary.html';"},"data-nsd-label-uuid":"b79b549b-da76-443d-80d3-d2b025bb0d2c","id":"3c8a67d2-7c26-4270-ab96-a0d2c6afacf1","text":"Glossary","type":"leaf"}],"text":"Children"},{"children":[{"a_attr":{"onclick":"window.location='https://github.com/Nasdanika/nasdanika.github.io/';"},"data-nsd-label-uuid":"c9dc5df5-7ae3-4b54-9976-ce8a58a3f850","icon":"fab fa-github","id":"52cf1e44-3695-4ae1-af1d-8ba0dcb154b2","text":"Source","type":"leaf"}],"text":"Navigation"}],"data-nsd-label-uuid":"4b254e60-aab3-492a-9868-b3995a73bc46","icon":"https://docs.nasdanika.org/images/nasdanika-logo.png","id":"42d28199-1f6b-4f2b-9269-46389afe0227","text":"Nasdanika","type":"leaf"}]},"search":{"show_only_matches":true},"plugins":["state","search"],"state":{"key":"nsd-site-map-tree"}})); });

@@ -294,7 +294,7 @@

diff --git a/docs/semantic-info.json b/docs/semantic-info.json index 4a9e3a27d..6fbcce99d 100644 --- a/docs/semantic-info.json +++ b/docs/semantic-info.json @@ -1,6 +1,6 @@ [ { - "identifiers": ["uuid:fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4"], + "identifiers": ["uuid:4b254e60-aab3-492a-9868-b3995a73bc46"], "name": "Nasdanika", "icon": "https://docs.nasdanika.org/images/nasdanika-logo.png", "location": "index.html", @@ -12,9 +12,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4"] + "identifiers": ["uuid:4b254e60-aab3-492a-9868-b3995a73bc46"] }, - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"], + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"], "type": { "name": "Action", "ns-uri": "ecore://app.models.nasdanika.org" @@ -23,9 +23,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:6ebb9d63-9456-40fa-acc8-fce4bddbc584"], + "identifiers": ["uuid:a0530ff7-119c-4d75-ab66-8c5586d0b152"], "name": "Books", "location": "https://leanpub.com/u/pvlasov", "type": { @@ -36,11 +36,11 @@ { "container": { "reference": "children", - "identifiers": ["uuid:6ebb9d63-9456-40fa-acc8-fce4bddbc584"] + "identifiers": ["uuid:a0530ff7-119c-4d75-ab66-8c5586d0b152"] }, - "identifiers": ["uuid:9979aba8-2c1a-4e74-b2bb-14a4cfade8d2"], + "identifiers": ["uuid:8b053630-aa85-4616-b59c-ee45ae090836"], "name": "Beyond Diagrams", - "location": "https://leanpub.com/resources/beyond-diagrams-sample.pdf", + "location": "https://docs.nasdanika.org/resources/beyond-diagrams-sample.pdf", "type": { "name": "Link", "ns-uri": "ecore://app.models.nasdanika.org" @@ -49,9 +49,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:6ebb9d63-9456-40fa-acc8-fce4bddbc584"] + "identifiers": ["uuid:a0530ff7-119c-4d75-ab66-8c5586d0b152"] }, - "identifiers": ["uuid:90b154f2-7b19-40e0-99a9-b7f29a1b20f4"], + "identifiers": ["uuid:c365b5d6-5a16-4e02-9d26-639d7ce242fb"], "name": "Java Analysis, Visualization, and Generation", "location": "https://leanpub.com/java-analysis", "type": { @@ -62,9 +62,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:5c45f75b-c116-4a2b-a392-c1f5db57c772"], + "identifiers": ["uuid:3d6da450-8274-46f6-b188-fb96af0d2d44"], "name": "Practices", "location": "practices/index.html", "type": { @@ -75,9 +75,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5c45f75b-c116-4a2b-a392-c1f5db57c772"] + "identifiers": ["uuid:3d6da450-8274-46f6-b188-fb96af0d2d44"] }, - "identifiers": ["uuid:d727b659-9685-456a-a48c-734e1e30697b"], + "identifiers": ["uuid:9868e662-a7f5-49c6-b57c-e75f4750213e"], "name": "Analysis, Visualization & Generation", "location": "practices/generic/index.html", "type": { @@ -88,9 +88,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5c45f75b-c116-4a2b-a392-c1f5db57c772"] + "identifiers": ["uuid:3d6da450-8274-46f6-b188-fb96af0d2d44"] }, - "identifiers": ["uuid:05c18178-0099-49ad-9f37-2de804f5820a"], + "identifiers": ["uuid:b3ba7a9f-54f5-4c3e-a9bc-6cd85f10387b"], "name": "Java Analysis, Visualization & Generation", "location": "practices/java/index.html", "type": { @@ -101,9 +101,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:5c45f75b-c116-4a2b-a392-c1f5db57c772"] + "identifiers": ["uuid:3d6da450-8274-46f6-b188-fb96af0d2d44"] }, - "identifiers": ["uuid:ba54a576-ba48-47cf-aac2-f96938d6a76e"], + "identifiers": ["uuid:78ecbb39-34b1-46a2-b8fe-18d8177ee712"], "name": "JUnit Tests Generation", "location": "practices/junit/index.html", "type": { @@ -114,9 +114,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:8f67c12c-24ad-4219-9dda-be26c6520110"], + "identifiers": ["uuid:333aae15-02e4-44fb-8ac9-c37cbfabb909"], "name": "CLI", "icon": "/images/command-line.svg", "location": "nsd-cli/index.html", @@ -128,7 +128,7 @@ { "container": { "reference": "children", - "identifiers": ["uuid:8f67c12c-24ad-4219-9dda-be26c6520110"] + "identifiers": ["uuid:333aae15-02e4-44fb-8ac9-c37cbfabb909"] }, "identifiers": ["uuid:c56f3d25-65af-4e21-b80e-5fe2fb7aa4e9"], "name": "nsd", @@ -672,9 +672,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"], + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"], "name": "Models", "location": "https://github.com/Nasdanika-Models", "type": { @@ -685,9 +685,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:2e6ac080-cc1f-4af8-a738-ac483a285588"], + "identifiers": ["uuid:70ae71b2-10ca-4498-8e1b-51db6493d243"], "name": "App", "location": "https://html-app.models.nasdanika.org/index.html", "type": { @@ -698,9 +698,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:ce60fa1a-af62-4adb-b8ec-00046400f32b"], + "identifiers": ["uuid:f62b19ba-8fd7-467f-9c7d-9fdf9f950d50"], "name": "Architecture", "location": "https://architecture.models.nasdanika.org", "type": { @@ -711,9 +711,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:d91f8e6e-4825-44d5-8df0-9043dd3db244"], + "identifiers": ["uuid:a14b7993-1ef3-49e4-b985-e65da9678163"], "name": "Azure", "location": "https://azure.models.nasdanika.org", "type": { @@ -724,9 +724,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:e2cdf971-dd39-4c01-ad44-e6eddc6bf02b"], + "identifiers": ["uuid:7f9fb63d-36a5-4330-a445-34e6795952c9"], "name": "Bank", "location": "https://bank.models.nasdanika.org", "type": { @@ -737,9 +737,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:550f33c6-fdaf-428f-a005-8c2b6cda7129"], + "identifiers": ["uuid:40fbf11f-eb01-43b6-af96-bf18839793d3"], "name": "Bootstrap", "location": "https://bootstrap.models.nasdanika.org", "type": { @@ -750,9 +750,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:a72a6eb5-a530-44c9-8b3e-8bd5f3bf6997"], + "identifiers": ["uuid:49374271-2634-478a-9c3b-93475ec92744"], "name": "Capability", "location": "https://capability.models.nasdanika.org", "type": { @@ -763,9 +763,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:a36b729f-3bf4-410b-953e-c4200d2606c9"], + "identifiers": ["uuid:941f8f85-297d-4cf8-bdc5-0636a4a3fc31"], "name": "Coverage", "location": "https://coverage.models.nasdanika.org", "type": { @@ -776,9 +776,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:4002db91-94cd-478d-abe6-d1cad3c563e8"], + "identifiers": ["uuid:bee6553d-dc73-4d9a-a4e0-a8f4c51dcecb"], "name": "Decision Analysis", "location": "https://mcda.models.nasdanika.org", "type": { @@ -789,9 +789,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:c0139ccd-7076-44f4-b1af-209a306d5a23"], + "identifiers": ["uuid:396e768a-fde5-41fb-a90c-ee5d3922ff16"], "name": "ECharts", "location": "https://echarts.models.nasdanika.org", "type": { @@ -802,9 +802,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:1d13e748-42b8-403c-a30e-3381734c8e90"], + "identifiers": ["uuid:a8f5517a-8c19-40d2-b189-746c07c1efe9"], "name": "Ecore", "location": "https://ecore.models.nasdanika.org", "type": { @@ -815,9 +815,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:9974d3db-2214-4e76-88b7-64a39de5b9cc"], + "identifiers": ["uuid:e0a45f3a-2d95-456b-ba9b-d6f3208d9b45"], "name": "Enterprise", "location": "https://enterprise.models.nasdanika.org", "type": { @@ -828,9 +828,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:ea46a91c-7ff1-4671-8563-7c6efbfce95a"], + "identifiers": ["uuid:fcb67104-fe98-4a36-b997-51b510ce8ff5"], "name": "Excel", "location": "https://excel.models.nasdanika.org", "type": { @@ -841,9 +841,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:d1944898-53c8-4f51-a9ff-908877e25c0b"], + "identifiers": ["uuid:da31950f-614f-4781-8034-3d788777a288"], "name": "Family", "location": "https://family.models.nasdanika.org", "type": { @@ -854,9 +854,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:b4bdd289-6790-4f0c-8028-bc976be52da0"], + "identifiers": ["uuid:c540b90f-2a97-4d33-bbc4-338620d85328"], "name": "Flow", "location": "https://flow.models.nasdanika.org", "type": { @@ -867,9 +867,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:5b272756-7b18-4a69-aa9f-15e60ed252fb"], + "identifiers": ["uuid:4c44cc81-4f02-4fad-93aa-cd2d7e02d36a"], "name": "Function Flow", "location": "https://function-flow.models.nasdanika.org", "type": { @@ -880,9 +880,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:1914dae9-d120-40ac-b55e-590b677a8954"], + "identifiers": ["uuid:fefba89e-fc85-4719-968d-490b9da079b6"], "name": "Git", "location": "https://git.models.nasdanika.org", "type": { @@ -893,9 +893,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:b240df69-9d89-4a36-862f-821b59930537"], + "identifiers": ["uuid:98acfb8b-80a6-4d30-a87f-4dabac070d07"], "name": "GitLab", "location": "https://gitlab.models.nasdanika.org", "type": { @@ -906,9 +906,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:6eae84d4-cb45-49ab-8a7f-b78423010b5e"], + "identifiers": ["uuid:ca49235e-2248-4ebb-b174-79c1bcf8a16e"], "name": "HTML", "location": "https://html-app.models.nasdanika.org", "type": { @@ -919,9 +919,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:466d8299-7d77-4865-8f70-230498be045f"], + "identifiers": ["uuid:64d44439-e7aa-4c7e-93a6-8b165be76744"], "name": "Java", "location": "https://java.models.nasdanika.org", "type": { @@ -932,9 +932,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:940fad1c-b6b2-4d4c-8dcf-8eedf944b24e"], + "identifiers": ["uuid:e93a6cd7-cf46-43b8-8a9e-2db7c3bab2f6"], "name": "Jira", "location": "https://jira.models.nasdanika.org", "type": { @@ -945,9 +945,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:97099f7e-15dc-4960-abca-936d8bad21ab"], + "identifiers": ["uuid:62a16a75-b085-4740-b0bf-515b880e5f51"], "name": "Maven", "location": "https://maven.models.nasdanika.org", "type": { @@ -958,9 +958,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:ce9d43c4-11d3-4d53-8371-250960c8e2ba"], + "identifiers": ["uuid:72d6ea6a-d76a-45ca-b100-97b519c70caf"], "name": "Nature", "location": "https://nature.models.nasdanika.org", "type": { @@ -971,9 +971,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:2192e145-1dde-49c1-9103-55d3a6974112"], + "identifiers": ["uuid:90b223dd-4f6e-4942-bb79-8381cf2a73db"], "name": "PDF", "location": "https://pdf.models.nasdanika.org", "type": { @@ -984,9 +984,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:85c6b78d-3398-4b17-bc08-2aeedf4574c3"], + "identifiers": ["uuid:208a35aa-b4b2-47ee-9779-9980f977f788"], "name": "Party", "location": "https://party.models.nasdanika.org", "type": { @@ -997,9 +997,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:a026e67e-6187-4479-9ae7-bee8bf5fe191"], + "identifiers": ["uuid:5346f59b-1780-4a91-bc3e-9ff3ff374af4"], "name": "Rules", "location": "https://rules.models.nasdanika.org", "type": { @@ -1010,9 +1010,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:f341dddd-39dc-4513-8dec-d64dd5bfe312"] + "identifiers": ["uuid:45cfc737-1aeb-4728-b458-03ea301d0d02"] }, - "identifiers": ["uuid:47bf3d1d-e8f8-4e55-ae86-f017edbd2fb8"], + "identifiers": ["uuid:1c1463ae-6bf3-4f23-aa11-b6100ae4b78c"], "name": "Source Engineering", "location": "https://source-engineering.models.nasdanika.org", "type": { @@ -1023,9 +1023,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:54132499-8909-400b-aac1-43cbf2d545d1"], + "identifiers": ["uuid:ec620720-90e7-451f-88ea-f12a690f2a19"], "name": "HTML", "icon": "/images/html.svg", "location": "html/index.html", @@ -1037,9 +1037,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:54132499-8909-400b-aac1-43cbf2d545d1"] + "identifiers": ["uuid:ec620720-90e7-451f-88ea-f12a690f2a19"] }, - "identifiers": ["uuid:ece1521e-f6d1-4300-af1a-ec9f686636d7"], + "identifiers": ["uuid:2f238adc-13f1-406c-be82-80390bfffb58"], "name": "Bootstrap", "location": "html/bootstrap/index.html", "type": { @@ -1050,9 +1050,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:54132499-8909-400b-aac1-43cbf2d545d1"] + "identifiers": ["uuid:ec620720-90e7-451f-88ea-f12a690f2a19"] }, - "identifiers": ["uuid:1a631497-143a-4798-b284-1de34dd191a9"], + "identifiers": ["uuid:965cad88-a835-45e8-8f51-8efdd0b83661"], "name": "HTML", "location": "html/html/index.html", "type": { @@ -1063,9 +1063,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:54132499-8909-400b-aac1-43cbf2d545d1"] + "identifiers": ["uuid:ec620720-90e7-451f-88ea-f12a690f2a19"] }, - "identifiers": ["uuid:256e5f01-4e3b-401b-817f-f0211e68f08a"], + "identifiers": ["uuid:7f2a3ace-c615-43e2-aa1f-888eeb173add"], "name": "JsTree", "location": "html/jstree/index.html", "type": { @@ -1076,9 +1076,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:7ac501fa-517d-4428-972f-7a91ff00e1fa"] + "identifiers": ["uuid:00c59493-fc17-412b-8121-4402a70fb814"] }, - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"], + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"], "name": "Core", "icon": "/images/earth.svg", "location": "core/index.html", @@ -1090,9 +1090,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:078f1c10-01a6-4f00-8a3d-95bd7ac56ea8"], + "identifiers": ["uuid:4779ae92-48de-4497-ab6e-16eea5486350"], "name": "CLI", "icon": "/images/command-line.svg", "location": "core/cli/index.html", @@ -1104,9 +1104,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:854a555f-5c19-4aca-945e-5a16918d44c4"], + "identifiers": ["uuid:bbd73087-4469-4887-914a-2fbfc684a44c"], "name": "Capability", "location": "core/capability/index.html", "type": { @@ -1117,9 +1117,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:78daff3b-b26f-466d-9fb8-cb633c8bec78"], + "identifiers": ["uuid:c71bc150-a96c-43bd-9089-f914244c567a"], "name": "Common", "location": "core/common/index.html", "type": { @@ -1130,9 +1130,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:521cf79a-0d13-469f-8812-f3fe4d1694ef"], + "identifiers": ["uuid:0cd651ce-1699-4b4e-868c-0cd6e6ca7c49"], "name": "Diagram", "location": "core/diagram/index.html", "type": { @@ -1143,9 +1143,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:b22f0146-0b59-4157-91ef-6a34c3508a34"], + "identifiers": ["uuid:d6351d9d-4484-40ad-9287-1ec216cf35ce"], "name": "Drawio", "location": "core/drawio/index.html", "type": { @@ -1156,9 +1156,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:c639f1c2-b4c8-4718-842d-587f39d0a44a"], + "identifiers": ["uuid:a9ee1151-49c1-4eda-a996-a9e2cef83e1b"], "name": "EMF", "location": "core/emf/index.html", "type": { @@ -1169,9 +1169,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:1c81ca9c-4663-4cfe-b02a-753e6b1c95b8"], + "identifiers": ["uuid:dc0840f1-98f3-4c3d-b611-95168139c3f1"], "name": "Exec", "location": "core/exec/index.html", "type": { @@ -1182,9 +1182,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:9ae6aaba-8274-4633-9fe5-add6d814ced1"], + "identifiers": ["uuid:4dec2691-78b8-4428-90b1-ca57bd1176a2"], "name": "Graph", "icon": "/images/data-flow.svg", "location": "core/graph/index.html", @@ -1196,9 +1196,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:b8f674f1-9d3f-4fe7-8aa9-7774f6271e66"], + "identifiers": ["uuid:c6fdabaa-635c-4ef6-9238-0fcc6cf8a921"], "name": "HTTP", "icon": "/images/http.svg", "location": "core/http/index.html", @@ -1210,9 +1210,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:310e8453-7243-45ce-8743-3eda6ec2bc92"], + "identifiers": ["uuid:e410c273-a0c1-482c-83ba-0e5f3c610203"], "name": "Mapping", "icon": "/images/mapping.svg", "location": "core/mapping/index.html", @@ -1224,9 +1224,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:234c2e91-e3b6-4ca5-b0df-678439550f93"], + "identifiers": ["uuid:0d53ab80-3272-4949-bba4-00a2434c6c4c"], "name": "Maven", "location": "core/maven/index.html", "type": { @@ -1237,9 +1237,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:79175fd0-515f-4304-aa76-332a4d707fa9"], + "identifiers": ["uuid:73f2c4de-2984-4867-af4e-9342bce9086a"], "name": "Ncore", "location": "https://ncore.models.nasdanika.org/", "type": { @@ -1250,9 +1250,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:0b67c53b-6a75-4dec-a11e-ca4bd93b3583"], + "identifiers": ["uuid:19ccdd4b-8f47-4ab4-9c7d-ab3a3876b97e"], "name": "Persistence", "location": "core/persistence/index.html", "type": { @@ -1263,9 +1263,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:4fa3bcd8-f85d-4204-aa48-69825a5542e4"] + "identifiers": ["uuid:4546de68-a951-45cd-8fbe-bdfe4ec13404"] }, - "identifiers": ["uuid:39a80721-f157-4a22-941f-62f99126a1b5"], + "identifiers": ["uuid:0a39397a-4b51-42b9-b95f-eddb24d560f2"], "name": "Resources", "location": "core/resources/index.html", "type": { @@ -1276,9 +1276,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4"] + "identifiers": ["uuid:4b254e60-aab3-492a-9868-b3995a73bc46"] }, - "identifiers": ["uuid:6b65e3c0-e862-4729-8e52-c2ce25825643"], + "identifiers": ["uuid:52e524d7-420d-4f44-8974-028a9871438b"], "name": "Search", "icon": "fas fa-search", "location": "search.html", @@ -1290,9 +1290,9 @@ { "container": { "reference": "children", - "identifiers": ["uuid:fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4"] + "identifiers": ["uuid:4b254e60-aab3-492a-9868-b3995a73bc46"] }, - "identifiers": ["uuid:b62c2e33-595d-4119-9c16-74cc9b09b32d"], + "identifiers": ["uuid:b79b549b-da76-443d-80d3-d2b025bb0d2c"], "name": "Glossary", "location": "glossary.html", "type": { @@ -1303,9 +1303,9 @@ { "container": { "reference": "navigation", - "identifiers": ["uuid:fde1df07-721c-43f7-ab3c-9e4ebaa6cdc4"] + "identifiers": ["uuid:4b254e60-aab3-492a-9868-b3995a73bc46"] }, - "identifiers": ["uuid:8b72d621-45a3-4819-8726-f44942303ed5"], + "identifiers": ["uuid:c9dc5df5-7ae3-4b54-9976-ce8a58a3f850"], "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 4bbb3f3cc..956792547 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,342 +2,342 @@ https://docs.nasdanika.org/core/capability/index.html - 2024-12-30T19:44:08.372-05:00 + 2024-12-30T19:48:17.507-05:00 weekly https://docs.nasdanika.org/core/cli/index.html - 2024-12-30T19:44:08.370-05:00 + 2024-12-30T19:48:17.505-05:00 weekly https://docs.nasdanika.org/core/common/index.html - 2024-12-30T19:44:08.373-05:00 + 2024-12-30T19:48:17.508-05:00 weekly https://docs.nasdanika.org/core/diagram/index.html - 2024-12-30T19:44:08.375-05:00 + 2024-12-30T19:48:17.510-05:00 weekly https://docs.nasdanika.org/core/drawio/index.html - 2024-12-30T19:44:08.377-05:00 + 2024-12-30T19:48:17.512-05:00 weekly https://docs.nasdanika.org/core/emf/index.html - 2024-12-30T19:44:08.379-05:00 + 2024-12-30T19:48:17.514-05:00 weekly https://docs.nasdanika.org/core/exec/index.html - 2024-12-30T19:44:08.380-05:00 + 2024-12-30T19:48:17.515-05:00 weekly https://docs.nasdanika.org/core/graph/index.html - 2024-12-30T19:44:08.382-05:00 + 2024-12-30T19:48:17.517-05:00 weekly https://docs.nasdanika.org/core/http/index.html - 2024-12-30T19:44:08.384-05:00 + 2024-12-30T19:48:17.518-05:00 weekly https://docs.nasdanika.org/core/index.html - 2024-12-30T19:44:08.369-05:00 + 2024-12-30T19:48:17.503-05:00 weekly https://docs.nasdanika.org/core/mapping/index.html - 2024-12-30T19:44:08.387-05:00 + 2024-12-30T19:48:17.522-05:00 weekly https://docs.nasdanika.org/core/maven/index.html - 2024-12-30T19:44:08.389-05:00 + 2024-12-30T19:48:17.524-05:00 weekly https://docs.nasdanika.org/core/persistence/index.html - 2024-12-30T19:44:08.390-05:00 + 2024-12-30T19:48:17.525-05:00 weekly https://docs.nasdanika.org/core/resources/index.html - 2024-12-30T19:44:08.391-05:00 + 2024-12-30T19:48:17.527-05:00 weekly https://docs.nasdanika.org/demos/module-graph-full.html - 2024-12-30T11:31:15.611-05:00 + 2024-12-30T19:44:08.790-05:00 weekly https://docs.nasdanika.org/demos/module-graph.html - 2024-12-30T11:31:15.614-05:00 + 2024-12-30T19:44:08.792-05:00 weekly https://docs.nasdanika.org/glossary.html - 2024-12-30T19:44:08.395-05:00 + 2024-12-30T19:48:17.530-05:00 weekly https://docs.nasdanika.org/html/bootstrap/index.html - 2024-12-30T19:44:08.365-05:00 + 2024-12-30T19:48:17.500-05:00 weekly https://docs.nasdanika.org/html/html/index.html - 2024-12-30T19:44:08.366-05:00 + 2024-12-30T19:48:17.501-05:00 weekly https://docs.nasdanika.org/html/index.html - 2024-12-30T19:44:08.364-05:00 + 2024-12-30T19:48:17.499-05:00 weekly https://docs.nasdanika.org/html/jstree/index.html - 2024-12-30T19:44:08.367-05:00 + 2024-12-30T19:48:17.502-05:00 weekly https://docs.nasdanika.org/index.html - 2024-12-30T19:44:08.298-05:00 + 2024-12-30T19:48:17.429-05:00 weekly https://docs.nasdanika.org/nsd-cli/index.html - 2024-12-30T19:44:08.312-05:00 + 2024-12-30T19:48:17.443-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/app/index.html - 2024-12-30T19:44:08.314-05:00 + 2024-12-30T19:48:17.446-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/app/site/index.html - 2024-12-30T19:44:08.315-05:00 + 2024-12-30T19:48:17.447-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/drawio/html-app/index.html - 2024-12-30T19:44:08.318-05:00 + 2024-12-30T19:48:17.450-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/drawio/html-app/save/index.html - 2024-12-30T19:44:08.319-05:00 + 2024-12-30T19:48:17.451-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/drawio/html-app/site/index.html - 2024-12-30T19:44:08.320-05:00 + 2024-12-30T19:48:17.453-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/drawio/index.html - 2024-12-30T19:44:08.316-05:00 + 2024-12-30T19:48:17.449-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/gsh/index.html - 2024-12-30T19:44:08.323-05:00 + 2024-12-30T19:48:17.456-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/index.html - 2024-12-30T19:44:08.322-05:00 + 2024-12-30T19:48:17.455-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/invoke/index.html - 2024-12-30T19:44:08.325-05:00 + 2024-12-30T19:48:17.458-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/junit/index.html - 2024-12-30T19:44:08.326-05:00 + 2024-12-30T19:48:17.459-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/junit/jacoco/index.html - 2024-12-30T19:44:08.327-05:00 + 2024-12-30T19:48:17.460-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/retrospect/gsh/index.html - 2024-12-30T19:44:08.332-05:00 + 2024-12-30T19:48:17.463-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/retrospect/index.html - 2024-12-30T19:44:08.331-05:00 + 2024-12-30T19:48:17.462-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/contribute/retrospect/invoke/index.html - 2024-12-30T19:44:08.333-05:00 + 2024-12-30T19:48:17.465-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/gsh/index.html - 2024-12-30T19:44:08.334-05:00 + 2024-12-30T19:48:17.466-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/index.html - 2024-12-30T19:44:08.321-05:00 + 2024-12-30T19:48:17.454-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gitlab/invoke/index.html - 2024-12-30T19:44:08.336-05:00 + 2024-12-30T19:48:17.468-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/gsh/index.html - 2024-12-30T19:44:08.337-05:00 + 2024-12-30T19:48:17.469-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/help/index.html - 2024-12-30T19:44:08.338-05:00 + 2024-12-30T19:48:17.470-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/help/site/index.html - 2024-12-30T19:44:08.339-05:00 + 2024-12-30T19:48:17.472-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/http-server/index.html - 2024-12-30T19:44:08.341-05:00 + 2024-12-30T19:48:17.474-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/index.html - 2024-12-30T19:44:08.313-05:00 + 2024-12-30T19:48:17.445-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/invoke/index.html - 2024-12-30T19:44:08.342-05:00 + 2024-12-30T19:48:17.475-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/java/index.html - 2024-12-30T19:44:08.343-05:00 + 2024-12-30T19:48:17.476-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/java/junit/index.html - 2024-12-30T19:44:08.344-05:00 + 2024-12-30T19:48:17.478-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/java/junit/jacoco/index.html - 2024-12-30T19:44:08.346-05:00 + 2024-12-30T19:48:17.479-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/launcher/index.html - 2024-12-30T19:44:08.347-05:00 + 2024-12-30T19:48:17.480-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/ecore-html-app/index.html - 2024-12-30T19:44:08.350-05:00 + 2024-12-30T19:48:17.483-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/ecore-html-app/save/index.html - 2024-12-30T19:44:08.351-05:00 + 2024-12-30T19:48:17.484-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/ecore-html-app/site/index.html - 2024-12-30T19:44:08.352-05:00 + 2024-12-30T19:48:17.486-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/html-app/index.html - 2024-12-30T19:44:08.353-05:00 + 2024-12-30T19:48:17.487-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/html-app/save/index.html - 2024-12-30T19:44:08.354-05:00 + 2024-12-30T19:48:17.488-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/html-app/site/index.html - 2024-12-30T19:44:08.355-05:00 + 2024-12-30T19:48:17.489-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/index.html - 2024-12-30T19:44:08.348-05:00 + 2024-12-30T19:48:17.482-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/model/save/index.html - 2024-12-30T19:44:08.357-05:00 + 2024-12-30T19:48:17.491-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/rules/action-model/index.html - 2024-12-30T19:44:08.359-05:00 + 2024-12-30T19:48:17.493-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/rules/index.html - 2024-12-30T19:44:08.358-05:00 + 2024-12-30T19:48:17.492-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/rules/list/index.html - 2024-12-30T19:44:08.360-05:00 + 2024-12-30T19:48:17.495-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/rules/site/index.html - 2024-12-30T19:44:08.361-05:00 + 2024-12-30T19:48:17.496-05:00 weekly https://docs.nasdanika.org/nsd-cli/nsd/shell/index.html - 2024-12-30T19:44:08.363-05:00 + 2024-12-30T19:48:17.497-05:00 weekly https://docs.nasdanika.org/practices/generic/index.html - 2024-12-30T19:44:08.304-05:00 + 2024-12-30T19:48:17.435-05:00 weekly https://docs.nasdanika.org/practices/index.html - 2024-12-30T19:44:08.302-05:00 + 2024-12-30T19:48:17.433-05:00 weekly https://docs.nasdanika.org/practices/java/index.html - 2024-12-30T19:44:08.305-05:00 + 2024-12-30T19:48:17.437-05:00 weekly https://docs.nasdanika.org/practices/junit/index.html - 2024-12-30T19:44:08.310-05:00 + 2024-12-30T19:48:17.442-05:00 weekly https://docs.nasdanika.org/search.html - 2024-12-30T19:44:08.394-05:00 + 2024-12-30T19:48:17.528-05:00 weekly \ No newline at end of file diff --git a/model/nasdanika.drawio b/model/nasdanika.drawio index 5583e5c42..57bc9324a 100644 --- a/model/nasdanika.drawio +++ b/model/nasdanika.drawio @@ -263,7 +263,7 @@ - +