Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7b9df67
Initial version of UxReporter part of openfasttrace WIP, not working.
Feb 3, 2025
9639ada
Collector implementation and test of the coverages of SpecItems
Feb 7, 2025
cf796a3
First running version of the UX generators that outputs a JavaScript …
Feb 9, 2025
60bc1e6
First running version of the UX generators that outputs a JavaScript …
Feb 9, 2025
1cffd9a
Various fixes, initial working version of the UxReporter.
Feb 26, 2025
8883f26
Added support for title
Feb 26, 2025
f7cad54
Fixed generating missing requirements
Feb 27, 2025
5edb943
Added uncoveredIndex
Feb 28, 2025
3411fcf
Added uncovered specitem index list to ux-generator output
Mar 1, 2025
4017db8
Added OpenFastTrace-UX comment to the main README.md
Mar 6, 2025
8fa494b
Added OpenFastTrace-UX comment to the user documentation.
Mar 6, 2025
880ac8d
Added support for setting the projectName via an environment variable
Mar 9, 2025
f11db4e
Added support for setting the projectName via an environment variable…
Mar 9, 2025
4bd126d
Added support for project name to the UX reporter
Mar 9, 2025
30f6419
Added calculation of type, uncovered status and tag Count
Mar 13, 2025
b328118
Increased covered for UxReporter to 97%
Mar 16, 2025
85be76a
Fixed imports in module-info.java of ux reporter.
Dec 25, 2025
962a0bb
Added package-info.java to ux reporter describing the whole output fo…
Dec 25, 2025
c4a2a53
Enhanced the ux reporter by including wrong links information in the …
Dec 25, 2025
b4f3bfe
Increased to openfasttrace version to 4.3.0 to reflect the changes in…
Dec 25, 2025
fdc477c
Added UX reporter ouztput format specification
Dec 26, 2025
bf751ae
Fixed off-by-one failure in text generator. Added normalization of id…
Dec 30, 2025
7080230
Improved variable naming in getWrongLinkTypeByTargets
Dec 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"${workspaceFolder}/reporter/plaintext/src",
"${workspaceFolder}/reporter/html/src",
"${workspaceFolder}/reporter/aspec/src",
"${workspaceFolder}/reporter/ux/src",
"${workspaceFolder}/product/src/test/java",
"${workspaceFolder}/api/src",
"${workspaceFolder}/exporter/specobject/src",
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Below you see a screenshot of an HTML tracing report where OFT traces itself. Yo

<img src="doc/images/oft_screenshot_tracing_report.png" style="box-shadow: 5px 10px 18px #888888;" alt="OFT HTML tracing report">

In addition to the HTML tracing report an interactive requirement browser and analysis tool is integrated into OpenFastTrace.

## Project Information

[![Build](https://github.com/itsallcode/openfasttrace/actions/workflows/build.yml/badge.svg)](https://github.com/itsallcode/openfasttrace/actions/workflows/build.yml)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ public class ReportSettings
private final ColorScheme colorScheme;
private final DetailsSectionDisplay detailsSectionDisplay;

private ReportSettings(final Builder builder)
/**
* Settings for a reporter.
*
* @param builder builder for a reporter
*/
protected ReportSettings(final Builder builder)
{
this.verbosity = builder.verbosity;
this.showOrigin = builder.showOrigin;
Expand Down Expand Up @@ -121,7 +126,10 @@ public static class Builder
private ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS;
private ColorScheme colorScheme = ColorScheme.BLACK_AND_WHITE;

private Builder()
/**
* Create the builder
*/
protected Builder()
{
// empty by intention
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/resources/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Commands:
convert Convert to a different requirements format

Tracing options:
-o, --output-format Report format, one of "plain", "html", "aspec"
-o, --output-format Report format, one of "plain", "html", "aspec", "ux"
Defaults to "plain"
-v, --report-verbosity Set how verbose the output is. Ranges from
"quiet" to "all".
Expand Down
13 changes: 13 additions & 0 deletions doc/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,18 @@ While plain text reports are perfect for debugging your tracing chain, sometimes
oft trace -o html
```

### Interactive requirement analyisis

Besides a basic HTML visualization of requirements OpenFastTrace also provides an interactive requirement browsing and requirement analysis frontend in the form of a responsive HTML page similar to the HTML report.

The UX reporter:

```
oft trace -o ux
```

generates an input file for the OpenFastTrace-UX HTML frontend [OpenFastTrace-UX](https://github.com/poldi2015/openfasttrace-ux).

### Understanding and Fixing Broken Requirement Branches

Requirements — or specification items as we call them more broadly — in OFT are internally organized in a graph. If you haven't heard of that term, don't worry. In most cases it is close enough to think of the relationships between the specification items like a forest where the highest level of the specification are tree trunks from which details branch out into big branches, twigs and eventually leaves.
Expand Down Expand Up @@ -568,6 +580,7 @@ One of:
* `plain`
* `html`
* `aspec`
* `ux`

Defaults to `plain`.

Expand Down
156 changes: 156 additions & 0 deletions doc/ux_report_output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# UX reporter output format

## Overview

The UX reporter output format is the native output format of the openfasttrace ux-reporter.
It is the input format for OpenFastTrace UX.

## Data Structure

The generated JavaScript object follows this structure:

```javascript
window.specitem = {
project: { /* project metadata */ },
specitems: [ /* array of specification items */ ]
}
```

## Project Metadata

The `project` object contains high-level information about the specification project:

| Field | Type | Description |
|-------|------|-------------|
| `projectName` | string | Name of the project |
| `types` | string[] | Array of artifact types (e.g., "itest", "feat", "req", "arch", "utest") |
| `tags` | string[] | Array of all tags used in the project |
| `status` | string[] | Array of possible item statuses ("approved", "proposed", "draft", "rejected") |
| `wrongLinkNames` | string[] | Array of wrong link type names ("version", "orphaned", "unwanted") |
| `item_count` | number | Total number of specification items |
| `item_covered` | number | Number of items that are covered |
| `item_uncovered` | number | Number of items that are uncovered |
| `type_count` | number[] | Count of items per type (indexed by type array) |
| `uncovered_count` | number[] | Count of uncovered items per type |
| `status_count` | number[] | Count of items per status |
| `tag_count` | number[] | Count of items per tag |

## Specitems Array Entries

Each entry in the `specitems` array represents a single specification item with the following structure:

### Basic Properties

| Field | Type | Description |
|-------|------|-------------|
| `index` | number | Unique sequential index of the item in the array |
| `type` | number | Index into the `types` array indicating the item type |
| `title` | string | Full title of the specification item |
| `name` | string | Short name identifier of the item |
| `id` | string | Full unique identifier in format "type:name[:version]" |
| `tags` | number[] | Array of indices into the `tags` array |
| `version` | number | Revision number of the specification item |
| `status` | number | Index into the `status` array |

### Content Properties

| Field | Type | Description |
|-------|------|-------------|
| `content` | string | Description/content of the specification item |
| `comments` | string | Additional comments for the item |
| `path` | string[] | File path components where the item is defined |
| `sourceFile` | string | Source file path where the item is located |
| `sourceLine` | number | Line number in the source file (0 if not available) |

### Traceability Properties

| Field | Type | Description |
|-------|------|-------------|
| `provides` | number[] | Array of type indices that this item provides coverage for |
| `needs` | number[] | Array of type indices that this item needs coverage from |
| `covered` | number[] | Array of Coverage enum IDs per type (0=NONE, 1=UNCOVERED, 2=COVERED, 3=MISSING) |
| `uncovered` | number[] | Array of type indices that are uncovered or missing for this item |
| `covering` | number[] | Array of indices of items that this item covers |
| `coveredBy` | number[] | Array of indices of items that cover this item |
| `depends` | number[] | Array of indices of items that this item depends on |

### Link Validation Properties

| Field | Type | Description |
|-------|------|-------------|
| `wrongLinkTypes` | number[] | Array of indices into `wrongLinkNames` for invalid link types |
| `wrongLinkTargets` | string[] | Array of invalid link targets with format "target[reason]" |

## Example Entry

```javascript
{
index: 0,
type: 2,
title: 'Title fea~fea1',
name: 'fea1',
id: 'fea:fea1',
tags: [],
version: 1,
content: 'Descriptive text for fea~fea1',
provides: [],
needs: [3],
covered: [0, 0, 2, 2, 1, 3],
uncovered: [4, 5],
covering: [],
coveredBy: [1, 2],
depends: [],
status: 0,
path: [],
sourceFile: '',
sourceLine: 0,
comments: '',
wrongLinkTypes: [],
wrongLinkTargets: []
}
```

## Data Interpretation

### Index-Based References

Most numeric arrays in the specitems use indices to reference:
- **Type indices**: Reference the `project.types` array
- **Tag indices**: Reference the `project.tags` array
- **Status indices**: Reference the `project.status` array
- **Item indices**: Reference other items in the `specitems` array
- **Wrong link type indices**: Reference the `project.wrongLinkNames` array

### Coverage Arrays

The `covered` array contains Coverage enum IDs per type, where each position corresponds to a specItem type in the `project.types` array. The Coverage enum values are:
- **0 = NONE**: No coverage relationship exists for this type
- **1 = UNCOVERED**: The specItem is not fully covered
- **2 = COVERED**: The specItem is fully covered
- **3 = MISSING**: These coverage type are needed by this specItems or specItems that cover this specItem (deep coverage) but are not covered

For example, if `project.types = ["itest", "feat", "fea", "req", "arch", "utest"]` and `covered = [0, 0, 2, 2, 1, 3]`, this means:
- itest: NONE (no coverage relationship)
- feat: NONE (no coverage relationship)
- fea: COVERED (coverage is complete)
- req: COVERED (coverage is complete)
- arch: UNCOVERED (coverage required but missing)
- utest: MISSING (coverage exists but has issues)

### Wrong Link Targets Format

Wrong link targets are formatted as `"target[reason]"` where:
- `target` is the invalid link target specification
- `reason` explains why the link is invalid (e.g., "orphaned", "unwanted coverage", "outdated coverage")

Example: `"itest:itest_wrong_type[unwanted coverage]"`

## Usage Notes

- All string values are properly escaped for JavaScript (quotes, HTML entities)
- Long content strings are automatically wrapped across multiple lines with string concatenation
- Empty arrays and strings indicate no data for that property
- The data structure is designed for efficient lookup and filtering in web interfaces
- Indices provide memory-efficient references while maintaining data integrity

This data structure enables comprehensive traceability analysis and visualization in OpenFastTrace-UX applications.
1 change: 1 addition & 0 deletions oft-self-trace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ if $oft_script trace \
"$base_dir/reporter/plaintext/src" \
"$base_dir/reporter/html/src" \
"$base_dir/reporter/aspec/src" \
"$base_dir/reporter/ux/src" \
"$base_dir/product/src/test/java" \
"$base_dir/api/src" \
"$base_dir/exporter/specobject/src" \
Expand Down
10 changes: 8 additions & 2 deletions parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<description>Free requirement tracking suite</description>
<url>https://github.com/itsallcode/openfasttrace</url>
<properties>
<revision>4.1.0</revision>
<revision>4.3.0</revision>
<java.version>17</java.version>
<junit.version>5.11.4</junit.version>
<maven.surefire.version>3.5.2</maven.surefire.version>
Expand Down Expand Up @@ -186,6 +186,12 @@
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-reporter-ux</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-testutil</artifactId>
Expand Down Expand Up @@ -378,7 +384,7 @@
</doclint>
<serialwarn>true</serialwarn>
<failOnError>true</failOnError>
<failOnWarnings>true</failOnWarnings>
<failOnWarnings>false</failOnWarnings>
<verbose>false</verbose>
<additionalJOptions>
<additionalJOption>-html5</additionalJOption>
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<module>reporter/plaintext</module>
<module>reporter/html</module>
<module>reporter/aspec</module>
<module>reporter/ux</module>
<module>testutil</module>
</modules>
<build>
Expand Down
4 changes: 4 additions & 0 deletions product/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-reporter-aspec</artifactId>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-reporter-ux</artifactId>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-testutil</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void exporterAvailable(final String format)

@ParameterizedTest
@CsvSource(
{ "aspec", "html", "plain" })
{ "aspec", "html", "plain", "ux" })
void reporterAvailable(final String format)
{
if (!reporterLoader.isFormatSupported(format))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.itsallcode.openfasttrace.report.aspec.ASpecReporterFactory;
import org.itsallcode.openfasttrace.report.html.HtmlReporterFactory;
import org.itsallcode.openfasttrace.report.plaintext.PlaintextReporterFactory;
import org.itsallcode.openfasttrace.report.ux.UxReporterFactory;
import org.junit.jupiter.api.Test;

/**
Expand Down Expand Up @@ -83,9 +84,10 @@ void testReporterFactoriesRegistered()
final ReporterContext context = new ReporterContext(null);
final List<ReporterFactory> services = getRegisteredServices(ReporterFactory.class,
context);
assertThat(services, hasSize(3));
assertThat(services, hasSize(4));
assertThat(services, containsInAnyOrder(instanceOf(PlaintextReporterFactory.class),
instanceOf(ASpecReporterFactory.class),
instanceOf(UxReporterFactory.class),
instanceOf(HtmlReporterFactory.class)));
for (final ReporterFactory factory : services)
{
Expand Down
32 changes: 32 additions & 0 deletions reporter/ux/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>openfasttrace-reporter-ux</artifactId>
<name>OpenFastTrace UX Reporter</name>
<parent>
<relativePath>../../parent/pom.xml</relativePath>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-parent</artifactId>
<version>${revision}</version>
</parent>
<properties>
<project.build.outputTimestamp>${reproducible.build.timestamp}</project.build.outputTimestamp>
</properties>
<dependencies>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-api</artifactId>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-testutil</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.itsallcode.openfasttrace</groupId>
<artifactId>openfasttrace-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
17 changes: 17 additions & 0 deletions reporter/ux/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* This provides an interactive HTML requirement browser.
*
* @provides org.itsallcode.openfasttrace.api.report.ReporterFactory
*/
module org.itsallcode.openfasttrace.report.ux
{
requires transitive org.itsallcode.openfasttrace.api;
requires java.logging;
requires java.desktop;
requires jdk.jfr;
requires java.xml.crypto;
requires java.xml;

provides org.itsallcode.openfasttrace.api.report.ReporterFactory
with org.itsallcode.openfasttrace.report.ux.UxReporterFactory;
}
Loading