diff --git a/docs/src/.vuepress/client.ts b/docs/src/.vuepress/client.ts
index 0d87bf99c..5d8b1b1b5 100644
--- a/docs/src/.vuepress/client.ts
+++ b/docs/src/.vuepress/client.ts
@@ -4,18 +4,17 @@ import { Layout as ParentLayout } from "vuepress-theme-hope/client";
import Layout from './layouts/PageLayout.vue'
import NotFoundLayout from './layouts/NotFoundLayout.vue'
import BlogLayout from './layouts/BlogLayout.vue';
-import NewsList from "./components/NewsList.vue"; // adjust if path differs
+
export default defineClientConfig({
enhance({ app }) {
- //app.component("NewsList", NewsList);
+
},
layouts: {
ParentLayout,
Layout,
NotFound: NotFoundLayout,
Blog: BlogLayout,
-
},
})
\ No newline at end of file
diff --git a/docs/src/.vuepress/components/NewsList.vue b/docs/src/.vuepress/components/NewsList.vue
deleted file mode 100644
index 09ce2977c..000000000
--- a/docs/src/.vuepress/components/NewsList.vue
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
diff --git a/docs/src/.vuepress/public/assets/linter/architecture.svg b/docs/src/.vuepress/public/assets/linter/architecture.svg
new file mode 100644
index 000000000..c3fc2a41d
--- /dev/null
+++ b/docs/src/.vuepress/public/assets/linter/architecture.svg
@@ -0,0 +1,158 @@
+
diff --git a/docs/src/.vuepress/public/assets/linter/bpmn-linting.svg b/docs/src/.vuepress/public/assets/linter/bpmn-linting.svg
new file mode 100644
index 000000000..00d14c8d7
--- /dev/null
+++ b/docs/src/.vuepress/public/assets/linter/bpmn-linting.svg
@@ -0,0 +1,143 @@
+
+
diff --git a/docs/src/.vuepress/public/assets/linter/fhir-linting.svg b/docs/src/.vuepress/public/assets/linter/fhir-linting.svg
new file mode 100644
index 000000000..901f659dd
--- /dev/null
+++ b/docs/src/.vuepress/public/assets/linter/fhir-linting.svg
@@ -0,0 +1,142 @@
+
+
diff --git a/docs/src/.vuepress/theme.ts b/docs/src/.vuepress/theme.ts
index cb6b474c2..931950b27 100644
--- a/docs/src/.vuepress/theme.ts
+++ b/docs/src/.vuepress/theme.ts
@@ -50,12 +50,13 @@ export default hopeTheme({
text: "Process Development",
icon: "plugin",
prefix: "/process-development/",
- children: ["api-v1/", "api-v2/"]
+ children: ["api-v1/", "api-v2/", "linter-tool/linter-tool"],
},
{
text: "DSF Development",
icon: "info",
- link: "/dsf-development/",
+ prefix: "/dsf-development/",
+ children: ["v2/fhir-ig", "v2/maven"],
},
{
text: "Community",
@@ -306,8 +307,7 @@ export default hopeTheme({
icon: "info",
prefix: "linter-tool/",
children: [
- "linter-tool",
- "validation","phases", "development", "troubleshooting"],
+ "linter-tool", "validation","phases", "development", "troubleshooting", "changelog"],
}
],
"/dsf-development": [
diff --git a/docs/src/process-development/linter-tool/changelog.md b/docs/src/process-development/linter-tool/changelog.md
new file mode 100644
index 000000000..9d4ecb420
--- /dev/null
+++ b/docs/src/process-development/linter-tool/changelog.md
@@ -0,0 +1,30 @@
+---
+title: Changelog
+icon: code
+---
+
+### Version 0.1.1 (Latest)
+- **Bugfix: DSF API v2 Plugin Discovery (`CLASS_LOADING_FAILED`)**:
+ - Fixed a bug where linting a JAR built against **DSF API v2** (`dev.dsf.bpe.v2.ProcessPluginDefinition`) failed with `CLASS_LOADING_FAILED` and the message `Failed to load plugin class: dev/dsf/bpe/v2/AbstractProcessPluginDefinition`
+ - **Root Cause**: The linter's shaded JAR only included `dsf-bpe-process-api-v1`; the v2 API classes were absent at runtime
+ - **Fix**: Added `dsf-bpe-process-api-v2` as a runtime dependency and included it in the shaded CLI JAR
+ - Plugins built against API v1 are unaffected
+ - The "no plugins found" error message now explicitly references both service-loader files:
+ - `META-INF/services/dev.dsf.bpe.v1.ProcessPluginDefinition`
+ - `META-INF/services/dev.dsf.bpe.v2.ProcessPluginDefinition`
+
+### Version 0.1.0
+- Initial release
+- BPMN validation:
+ - Process ID pattern validation (`BPMN_PROCESS_ID_PATTERN_MISMATCH`, `BPMN_PROCESS_ID_EMPTY`)
+ - Process count validation (`BPMN_FILE_NO_PROCESS`, `BPMN_FILE_MULTIPLE_PROCESSES`)
+ - Process history time-to-live validation (`BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING`)
+ - Process executable validation (`BPMN_PROCESS_NOT_EXECUTABLE`)
+ - Task Listener TaskOutput field injections validation for API v2
+ - Task Listener input parameter (`practitionerRole`, `practitioners`) validation for API v2
+- FHIR validation:
+ - ActivityDefinition URL pattern validation (`ACTIVITY_DEFINITION_INVALID_URL_PATTERN`)
+ - Task identifier system and value format validation (`FHIR_TASK_IDENTIFIER_MISSING_SYSTEM`, `FHIR_TASK_IDENTIFIER_INVALID_SYSTEM`, `FHIR_TASK_IDENTIFIER_INVALID_FORMAT`)
+- Plugin configuration validation:
+ - Plugin resource version validation (`PLUGIN_DEFINITION_RESOURCE_VERSION_NULL`)
+- HTML and JSON report generation
\ No newline at end of file
diff --git a/docs/src/process-development/linter-tool/development.md b/docs/src/process-development/linter-tool/development.md
index 8a383984b..6b7daaba4 100644
--- a/docs/src/process-development/linter-tool/development.md
+++ b/docs/src/process-development/linter-tool/development.md
@@ -2,11 +2,9 @@
title: Development
icon: code
---
-## Development
-
### Requirements
-- **Java**: 17 or higher
+- **Java**: 17 or higher (Java 25+ required for API Version 2 validation)
- **Maven**: 3.6 or higher
- **IDE**: IntelliJ IDEA, Eclipse, or VS Code (optional)
@@ -78,7 +76,7 @@ vim linter-core/src/main/java/dev/dsf/linter/service/BpmnLintingService.java
mvn clean package -DskipTests
# 3. Test with a sample plugin
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path test-plugin.jar --html --verbose
# 4. Check the generated report
@@ -99,7 +97,7 @@ git commit -m "Description of changes"
```bash
# Start the linter with debugger enabled
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 \
- -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+ -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --verbose
# Attach debugger from IDE to localhost:5005
diff --git a/docs/src/process-development/linter-tool/linter-tool.md b/docs/src/process-development/linter-tool/linter-tool.md
index 3a0e6cbfc..0413160bb 100644
--- a/docs/src/process-development/linter-tool/linter-tool.md
+++ b/docs/src/process-development/linter-tool/linter-tool.md
@@ -64,11 +64,11 @@ mvn clean package -X
```bash
# Lint a local JAR file
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path your-plugin.jar --html
# Lint a remote JAR file
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path https://github.com/datasharingframework/dsf-process-ping-pong/releases/download/v2.0.0.1/dsf-process-ping-pong-2.0.0.1.jar --html
# View report at: /tmp/dsf-linter-report-/dsf-linter-report/index.html
@@ -78,7 +78,7 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
### Requirements
-- **Java**: 17 or higher
+- **Java**: 17 or higher (Java 25+ required for API Version 2 validation)
- **Maven**: 3.6 or higher
- **Operating System**: Windows, Linux, or macOS
@@ -93,7 +93,7 @@ cd dsf-linter
mvn clean package
# The executable JAR will be at:
-# linter-cli/target/linter-cli-1.0-SNAPSHOT.jar
+# linter-cli/target/linter-cli-0.1.1.jar
```
### Distribution
@@ -102,7 +102,7 @@ The linter is distributed as a single executable JAR file that includes all depe
```bash
# Copy to a convenient location
-cp linter-cli/target/linter-cli-1.0-SNAPSHOT.jar ~/bin/dsf-linter.jar
+cp linter-cli/target/linter-cli-0.1.1.jar ~/bin/dsf-linter.jar
# Use from anywhere
java -jar ~/bin/dsf-linter.jar --path plugin.jar --html
@@ -129,8 +129,8 @@ The linter expects the following structure in the JAR file:
plugin.jar
├── META-INF/
│ └── services/
-│ ├── dev.dsf.bpe.process.ProcessPlugin (v1)
-│ └── dev.dsf.bpe.process.v2.ProcessPlugin (v2)
+│ ├── dev.dsf.bpe.v1.ProcessPluginDefinition (v1)
+│ └── dev.dsf.bpe.v2.ProcessPluginDefinition (v2)
├── bpe/
│ └── *.bpmn (BPMN process definitions)
└── fhir/
@@ -154,11 +154,11 @@ plugin.jar
```bash
# Local JAR file
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path C:\path\to\plugin.jar --html
# Remote JAR file
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path https://github.com/datasharingframework/dsf-process-ping-pong/releases/download/v2.0.0.1/dsf-process-ping-pong-2.0.0.1.jar --html
```
@@ -166,11 +166,11 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
```bash
# Multiple report formats with custom path
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --json --report-path ./reports
# Verbose output (colors enabled by default, use --no-color to disable)
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --verbose
# Lint Maven project (two-step process)
@@ -178,7 +178,7 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
cd /path/to/project && mvn clean package
# Step 2: Lint the resulting JAR
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path /path/to/project/target/my-plugin-1.0.0.jar --html
```
@@ -186,16 +186,16 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
```bash
# GitHub Actions / GitLab CI
-FORCE_COLOR=1 java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+FORCE_COLOR=1 java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --json --verbose
# Jenkins (fail on errors)
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html
# Exit code: 0 = success, 1 = errors
# Don't fail build (gradual adoption)
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --no-fail
```
@@ -243,6 +243,17 @@ Reports are generated in the following structure:
└── plugin-name.json # JSON report (if --json specified)
```
+The default `` resolves to `/dsf-linter-report-/dsf-linter-report`, for example:
+
+```
+/tmp/dsf-linter-report-my-plugin/dsf-linter-report/
+├── index.html
+├── my-plugin.html
+└── my-plugin.json
+```
+
+Use `--report-path` to override this location.
+
### HTML Report
The HTML report provides a comprehensive, human-readable view of all linting results.
@@ -312,8 +323,8 @@ The JSON report provides machine-readable output for CI/CD integration and autom
```json
{
- "version": "2.0.0",
- "timestamp": "2024-01-15T10:30:00Z",
+ "version": "0.1.1",
+ "timestamp": "2025-06-15T10:30:00Z",
"projectPath": "/path/to/plugin.jar",
"executionTimeMs": 2300,
"success": true,
@@ -376,7 +387,7 @@ Each lint item in the JSON report has the following structure:
### Example Console Output
```
-DSF Linter v2.0.0
+DSF Linter v0.1.1
=================================================================
Project: /path/to/plugin.jar
Report: /tmp/dsf-linter-report-plugin/dsf-linter-report
@@ -411,6 +422,7 @@ Summary
```
## Architecture
+
### Project Structure
@@ -418,58 +430,134 @@ Summary
dsf-linter/
├── linter-core/ # Core linting logic
│ ├── src/main/java/dev/dsf/linter/
+│ │ ├── DsfLinter.java # Main orchestrator
│ │ ├── analysis/ # Resource analysis
│ │ │ └── LeftoverResourceDetector.java
│ │ ├── bpmn/ # BPMN parsing & validation
│ │ │ ├── BpmnLinter.java
│ │ │ ├── BpmnModelLinter.java
+│ │ │ ├── BpmnElementLinter.java
+│ │ │ ├── BpmnProcessLinter.java
│ │ │ ├── BpmnTaskLinter.java
│ │ │ ├── BpmnEventLinter.java
+│ │ │ ├── BpmnFieldInjectionLinter.java
│ │ │ ├── BpmnGatewayAndFlowLinter.java
│ │ │ └── BpmnSubProcessLinter.java
+│ │ ├── classloading/ # Dynamic class loading
+│ │ │ ├── ProjectClassLoaderFactory.java
+│ │ │ └── ClassInspector.java
+│ │ ├── constants/ # Constants & configuration
+│ │ │ ├── BpmnElementType.java
+│ │ │ └── DsfApiConstants.java
+│ │ ├── exception/ # Custom exceptions
+│ │ │ ├── ApiVersionUnknownException.java
+│ │ │ ├── MissingServiceRegistrationException.java
+│ │ │ └── ResourceLinterException.java
│ │ ├── fhir/ # FHIR parsing & validation
│ │ │ ├── FhirResourceLinter.java
+│ │ │ ├── FhirFileLinter.java
│ │ │ ├── FhirTaskLinter.java
│ │ │ ├── FhirStructureDefinitionLinter.java
│ │ │ ├── FhirValueSetLinter.java
│ │ │ ├── FhirActivityDefinitionLinter.java
│ │ │ ├── FhirCodeSystemLinter.java
│ │ │ └── FhirQuestionnaireLinter.java
+│ │ ├── input/ # Input handling & JAR processing
+│ │ │ ├── InputResolver.java
+│ │ │ ├── InputType.java
+│ │ │ └── JarHandler.java
+│ │ ├── logger/ # Logging infrastructure
+│ │ │ ├── Logger.java
+│ │ │ ├── ConsoleLogger.java
+│ │ │ ├── Console.java
+│ │ │ ├── LogDecorators.java
+│ │ │ └── LogUtils.java
+│ │ ├── output/ # Lint item definitions & types
+│ │ │ ├── FloatingElementType.java
+│ │ │ ├── FlowElementType.java
+│ │ │ ├── LinterSeverity.java
+│ │ │ ├── LintingType.java
+│ │ │ ├── ProcessingLevel.java
+│ │ │ └── item/ # Lint item base classes
+│ │ │ ├── AbstractLintItem.java
+│ │ │ ├── BpmnElementLintItem.java
+│ │ │ ├── BpmnFlowElementLintItem.java
+│ │ │ ├── BpmnLintItem.java
+│ │ │ ├── FhirElementLintItem.java
+│ │ │ ├── FhirLintItem.java
+│ │ │ ├── LintItem.java
+│ │ │ └── PluginLintItem.java
+│ │ ├── plugin/ # Plugin definition discovery
+│ │ │ ├── EnhancedPluginDefinitionDiscovery.java
+│ │ │ ├── PluginDefinitionDiscovery.java
+│ │ │ └── PluginDiscoveryError.java
+│ │ ├── report/ # Report generation
+│ │ │ ├── HtmlReportGenerator.java
+│ │ │ ├── JsonReportGenerator.java
+│ │ │ ├── LintConsolePrinter.java
+│ │ │ └── LintingReportGenerator.java
│ │ ├── service/ # Linting services
+│ │ │ ├── AbstractResourceLintingService.java
│ │ │ ├── BpmnLintingService.java
│ │ │ ├── FhirLintingService.java
+│ │ │ ├── LintingResult.java
+│ │ │ ├── PluginLintingOrchestrator.java
│ │ │ ├── PluginLintingService.java
-│ │ │ └── PluginLintingOrchestrator.java
-│ │ ├── output/ # Lint item definitions
-│ │ │ └── item/ # Specific lint items (200+ classes)
-│ │ ├── report/ # Report generation
-│ │ │ └── LintingReportGenerator.java
-│ │ ├── input/ # Input handling & JAR processing
-│ │ │ └── InputResolver.java
-│ │ ├── setup/ # Project setup & building
+│ │ │ ├── PluginMetadataLinter.java
+│ │ │ └── ResourceDiscoveryService.java
+│ │ ├── setup/ # Project setup & JAR extraction
│ │ │ └── ProjectSetupHandler.java
-│ │ ├── plugin/ # Plugin definition discovery
-│ │ │ └── PluginDefinitionDiscovery.java
-│ │ ├── classloading/ # Dynamic class loading
-│ │ │ ├── ProjectClassLoaderFactory.java
-│ │ │ └── ClassInspector.java
-│ │ ├── logger/ # Logging infrastructure
-│ │ │ ├── Logger.java
-│ │ │ ├── ConsoleLogger.java
-│ │ │ └── Console.java
-│ │ ├── constants/ # Constants & configuration
-│ │ │ └── DsfApiConstants.java
-│ │ ├── exception/ # Custom exceptions
-│ │ │ ├── ResourceLinterException.java
-│ │ │ └── MissingServiceRegistrationException.java
│ │ └── util/ # Utilities
│ │ ├── api/ # API version detection
+│ │ │ ├── ApiVersion.java
+│ │ │ ├── ApiVersionDetector.java
+│ │ │ ├── ApiVersionHolder.java
+│ │ │ ├── DetectedVersion.java
+│ │ │ ├── DetectionSource.java
+│ │ │ └── PluginVersionUtils.java
+│ │ ├── bpmn/ # BPMN utilities
+│ │ │ ├── BpmnModelUtils.java
+│ │ │ └── linters/ # Element-specific BPMN linters
+│ │ │ ├── BpmnBoundaryEventLinter.java
+│ │ │ ├── BpmnEndEventLinter.java
+│ │ │ ├── BpmnEventLinter.java
+│ │ │ ├── BpmnIntermediateCatchEventLinter.java
+│ │ │ ├── BpmnIntermediateThrowEventLinter.java
+│ │ │ ├── BpmnListenerLinter.java
+│ │ │ ├── BpmnMessageEventImplementationLinter.java
+│ │ │ ├── BpmnMessageLinter.java
+│ │ │ ├── BpmnStartEventLinter.java
+│ │ │ └── BpmnTimerLinter.java
│ │ ├── cache/ # Caching utilities
+│ │ │ └── ConcurrentCache.java
│ │ ├── converter/ # Format converters
+│ │ │ └── JsonXmlConverter.java
│ │ ├── linting/ # Linting utilities
+│ │ │ ├── AbstractFhirInstanceLinter.java
+│ │ │ ├── LintingOutput.java
+│ │ │ ├── LintingUtils.java
+│ │ │ └── PluginLintingUtils.java
│ │ ├── loader/ # Class/service loading
-│ │ ├── maven/ # Maven utilities
+│ │ │ ├── ClassLoaderUtils.java
+│ │ │ └── ServiceLoaderUtils.java
│ │ └── resource/ # Resource management
+│ │ ├── CompositeResourceProvider.java
+│ │ ├── FhirAuthorizationCache.java
+│ │ ├── FhirFileUtils.java
+│ │ ├── FhirResourceEntry.java
+│ │ ├── FhirResourceExtractor.java
+│ │ ├── FhirResourceLocator.java
+│ │ ├── FhirResourceParser.java
+│ │ ├── FileSystemResourceProvider.java
+│ │ ├── JarResourceProvider.java
+│ │ ├── ResourceDiscoveryUtils.java
+│ │ ├── ResourceEntryFactory.java
+│ │ ├── ResourcePathNormalizer.java
+│ │ ├── ResourceProvider.java
+│ │ ├── ResourceResolutionResult.java
+│ │ ├── ResourceResolutionService.java
+│ │ ├── ResourceRootResolver.java
+│ │ └── ResourceType.java
│ ├── src/main/resources/
│ │ ├── logback.xml # Logging configuration
│ │ ├── logback-verbose.xml # Verbose logging configuration
@@ -504,6 +592,23 @@ dsf-linter/
| `BpmnModelLinter` | Validates BPMN model structure and elements |
| `FhirResourceLinter` | Validates FHIR resources using pluggable linters |
+### Design Patterns
+
+The linter uses several design patterns:
+
+- **Template Method Pattern**: Abstract base classes define linting algorithm structure
+- **Strategy Pattern**: Pluggable linters for different resource types
+- **Factory Pattern**: Classloader and service creation
+- **Service Locator Pattern**: Plugin discovery via ServiceLoader
+- **Builder Pattern**: Configuration and result objects
+
+### Thread Safety
+
+- Most components are stateless and thread-safe
+- Classloader isolation ensures no cross-plugin interference
+- Temporary context classloader used for resource access
+- Result objects are immutable
+
## API Reference
### Core Classes
@@ -700,4 +805,4 @@ Discovers plugins and resources.
**Methods**:
```java
DiscoveryResult discover(ProjectContext context)
-```
+```
\ No newline at end of file
diff --git a/docs/src/process-development/linter-tool/phases.md b/docs/src/process-development/linter-tool/phases.md
index ea188f464..2734a33c6 100644
--- a/docs/src/process-development/linter-tool/phases.md
+++ b/docs/src/process-development/linter-tool/phases.md
@@ -2,6 +2,8 @@
title: Linting Phases
icon: config
---
+### Linting Phases
+
The linter executes in five phases:
#### Phase 1: Project Setup
diff --git a/docs/src/process-development/linter-tool/troubleshooting.md b/docs/src/process-development/linter-tool/troubleshooting.md
index 505924539..1cfd0a6dd 100644
--- a/docs/src/process-development/linter-tool/troubleshooting.md
+++ b/docs/src/process-development/linter-tool/troubleshooting.md
@@ -2,6 +2,9 @@
title: Troubleshooting
icon: config
---
+
+## Troubleshooting
+
### "Input must be a JAR file" Error
**Problem**: The linter only accepts JAR files as input.
@@ -9,12 +12,12 @@ icon: config
**Solution**:
```bash
# Wrong - Maven project directly
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path /path/to/project --html
# Correct - Build first, then lint JAR
cd /path/to/project && mvn clean package
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path /path/to/project/target/my-plugin-1.0.0.jar --html
```
@@ -26,11 +29,11 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
```bash
# Windows
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path "C:\Users\Username\project\target\plugin.jar" --html
# Linux/Mac
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path /home/username/project/target/plugin.jar --html
```
@@ -44,7 +47,7 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
ls ~/.m2/settings.xml
# Use verbose mode to see detailed error messages
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --verbose
# Check if dependencies are in the JAR
@@ -58,11 +61,11 @@ jar -tf plugin.jar | grep -i "class"
**Solution**:
```bash
# --html or --json flag must be set
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html # ← Required
# Use absolute path for report directory
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html --report-path $(pwd)/reports
# Check write permissions
@@ -85,7 +88,7 @@ ls -lh test.jar
ping example.com
# Then use the local file
-java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -jar linter-cli/target/linter-cli-0.1.1.jar \
--path test.jar --html
```
@@ -107,11 +110,11 @@ java -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
**Solution**:
```bash
# Increase heap size
-java -Xmx2g -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -Xmx2g -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html
# For very large projects
-java -Xmx4g -Xms1g -jar linter-cli/target/linter-cli-1.0-SNAPSHOT.jar \
+java -Xmx4g -Xms1g -jar linter-cli/target/linter-cli-0.1.1.jar \
--path plugin.jar --html
```
diff --git a/docs/src/process-development/linter-tool/validation.md b/docs/src/process-development/linter-tool/validation.md
index 250ec6ade..934ac9026 100644
--- a/docs/src/process-development/linter-tool/validation.md
+++ b/docs/src/process-development/linter-tool/validation.md
@@ -2,20 +2,116 @@
title: Validation Rules
icon: note
---
-## Validation Rules
-
The linter performs comprehensive validation across multiple dimensions. This section details all validation rules organized by resource type.
-### BPMN Validation
+## Table of Contents
+
+1. [BPMN Validation](#bpmn-validation)
+2. [FHIR Validation](#fhir-resource-validation)
+3. [Plugin Configuration](#plugin-configuration-validation)
+### BPMN Validation
The linter performs comprehensive validation on BPMN 2.0 process definitions using the Camunda BPMN model API.
+
+
**Important:** The linter automatically detects the DSF API version (V1 or V2) from the plugin configuration and applies version-specific validation rules. Many validation rules differ between V1 and V2 API, particularly for:
- Service Task and Send Task implementation classes
- Execution Listeners
- Task Listeners (User Tasks)
- Message Events (Intermediate Throw and End Events)
+#### Process Validation
+
+##### Process ID Pattern Validation
+
+- **Pattern Requirement**:
+ - Process ID must follow the pattern: `domain_processname`
+ - Domain and process name must consist only of alphanumeric characters (a-z, A-Z, 0-9) and hyphens (-)
+ - Exactly one underscore must separate domain and process name
+ - Error: `BPMN_PROCESS_ID_PATTERN_MISMATCH`
+ - Error: `BPMN_PROCESS_ID_EMPTY`
+ - Success: `SUCCESS` when the pattern is matched
+
+- **Valid Examples**:
+ - ✅ `testorg_myprocess`
+ - ✅ `dsf-dev_download-allowlist`
+ - ✅ `example123_process456`
+
+- **Invalid Examples**:
+ - ❌ `myProcess` (missing underscore)
+ - ❌ `test.org_myprocess` (dots not allowed)
+ - ❌ `test_my_process` (multiple underscores not allowed)
+ - ❌ `test_process_name` (only one underscore allowed)
+
+- **Pattern Definition**:
+ ```regex
+ ^(?[a-zA-Z0-9-]+)_(?[a-zA-Z0-9-]+)$
+ ```
+
+- **DSF Framework Reference**:
+ - This validation is based on the DSF Framework requirement defined in:
+ - `dsf-bpe/dsf-bpe-process-api/src/main/java/dev/dsf/bpe/api/plugin/AbstractProcessPlugin.java`
+
+##### Process Count Validation
+
+- **Requirement**:
+ - Each BPMN file must contain **exactly one** process definition
+ - Error: `BPMN_FILE_NO_PROCESS` (when no process is found)
+ - Error: `BPMN_FILE_MULTIPLE_PROCESSES` (when more than one process is found)
+ - Success: `SUCCESS` when exactly one process is found
+
+- **Valid Examples**:
+ - ✅ BPMN file with 1 process definition
+
+- **Invalid Examples**:
+ - ❌ BPMN file with 0 process definitions
+ - ❌ BPMN file with 2 or more process definitions
+
+- **DSF Framework Reference**:
+ - This validation is based on the DSF Framework requirement defined in:
+ - `dsf-bpe/dsf-bpe-process-api/src/main/java/dev/dsf/bpe/api/plugin/AbstractProcessPlugin.java`
+ - DSF validates: `if (processes.size() != 1) { return false; }`
+
+##### Process History Time To Live Validation
+
+- **Requirement**:
+ - Process should have `camunda:historyTimeToLive` attribute set
+ - If not set (null or empty), DSF automatically uses default value `P30D` (30 days)
+ - Warning: `BPMN_PROCESS_HISTORY_TIME_TO_LIVE_MISSING`
+ - Success: `SUCCESS` when historyTimeToLive is explicitly set
+
+- **Valid Examples**:
+ - ✅ ``
+ - ✅ ``
+
+- **Warning Example**:
+ - ⚠️ `` (no historyTimeToLive attribute)
+
+- **DSF Framework Reference**:
+ - DSF Framework sets default at runtime if not specified:
+ - `process.setOperatonHistoryTimeToLiveString("P30D")`
+ - Best practice: Set explicitly in BPMN file
+
+##### Process Executable Validation
+
+- **Requirement**:
+ - Process must have `isExecutable="true"` attribute set
+ - Processes without this attribute cannot be deployed and executed by the process engine
+ - Error: `BPMN_PROCESS_NOT_EXECUTABLE`
+ - Success: `SUCCESS` when isExecutable is true
+
+- **Valid Examples**:
+ - ✅ ``
+
+- **Invalid Examples**:
+ - ❌ `` (no isExecutable attribute, defaults to false)
+ - ❌ ``
+
+- **Reason**:
+ - The process engine only deploys and executes processes marked as executable
+ - Non-executable processes are typically used for documentation or as templates
+
#### Task Validation
##### Service Tasks
@@ -152,17 +248,44 @@ The linter performs comprehensive validation on BPMN 2.0 process definitions usi
- Error: `BpmnSendTaskNoInterfaceClassImplementingLintItem`
- **Field Injection Validation**:
- - Message-related field injections must be valid
- - FHIR resource references must be correct
+ - Same field injections as Message Send Events are validated: `profile`, `messageName`, and `instantiatesCanonical`
+ - `profile` field injection:
+ - Must be non-empty
+ - Error: `BpmnFieldInjectionProfileEmptyLintItem`
+ - Must contain version placeholder `#{version}`
+ - Error: `BpmnFieldInjectionProfileNoVersionPlaceholderLintItem`
+ - Must reference existing StructureDefinition
+ - Error: `BpmnNoStructureDefinitionFoundForMessageLintItem`
+ - `messageName` field injection:
+ - Must be non-empty
+ - Error: `BpmnFieldInjectionMessageValueEmptyLintItem`
+ - Must be a string literal
+ - Error: `BpmnFieldInjectionNotStringLiteralLintItem`
+ - `instantiatesCanonical` field injection:
+ - Must be non-empty
+ - Error: `BpmnFieldInjectionInstantiatesCanonicalEmptyLintItem`
+ - Must end with version placeholder `|#{version}`
+ - Error: `BpmnFieldInjectionInstantiatesCanonicalNoVersionPlaceholderLintItem`
+ - Must reference existing ActivityDefinition
+ - Error: `BpmnNoActivityDefinitionFoundForMessageLintItem`
+ - Unknown field injections are reported
+ - Error: `BpmnUnknownFieldInjectionLintItem`
##### Receive Tasks
- **Name Validation**:
- Task must have a non-empty name
+ - Warning: `BpmnEventNameEmptyLintItem`
- **Message Definition Validation**:
- - Message definition must be valid
- - FHIR message name cross-checks
+ - Message definition must be present and have a non-empty message name
+ - Error: `BpmnMessageStartEventMessageNameEmptyLintItem`
+
+- **FHIR Resource Validation**:
+ - Message name must reference an existing ActivityDefinition
+ - Error: `BpmnNoActivityDefinitionFoundForMessageLintItem`
+ - Message name must reference an existing StructureDefinition
+ - Error: `BpmnNoStructureDefinitionFoundForMessageLintItem`
#### Event Validation
@@ -219,9 +342,17 @@ The linter performs comprehensive validation on BPMN 2.0 process definitions usi
##### Timer Events
-- **Time Expression Validation**:
- - Time cycle/date/duration expressions must be valid
- - Placeholder usage validation
+- **Timer Type Validation**:
+ - At least one of `timeDate`, `timeCycle`, or `timeDuration` must be set
+ - Error: `BpmnFloatingElementLintItem` ("Timer type is empty")
+
+- **Fixed Date Warning**:
+ - `timeDate` expressions are flagged with an informational message to verify if a fixed date is intended
+ - Info: `BpmnFloatingElementLintItem` ("Timer type is a fixed date/time (timeDate)")
+
+- **Placeholder Validation**:
+ - `timeCycle` and `timeDuration` values should contain a placeholder (e.g., `#{interval}`)
+ - Warning: `BpmnFloatingElementLintItem` ("Timer value appears fixed (no placeholder found)")
##### Error Boundary Events
@@ -251,8 +382,25 @@ The linter performs comprehensive validation on BPMN 2.0 process definitions usi
##### Conditional Events
+- **Event Name Validation**:
+ - Conditional Intermediate Catch Event should have a non-empty name
+ - Warning: `BpmnFloatingElementLintItem` ("Conditional Intermediate Catch Event name is empty")
+
+- **Variable Name Validation**:
+ - `camunda:variableName` attribute must not be empty
+ - Error: `BpmnFloatingElementLintItem` ("Conditional Intermediate Catch Event variable name is empty")
+
+- **Variable Events Validation**:
+ - `camunda:variableEvents` attribute must not be empty
+ - Error: `BpmnFloatingElementLintItem` ("Conditional Intermediate Catch Event variableEvents is empty")
+
+- **Condition Type Validation**:
+ - `camunda:conditionType` must be set, or a condition expression must be provided (in which case `"expression"` is assumed)
+ - Error: `BpmnFloatingElementLintItem` ("Conditional Intermediate Catch Event condition type is empty")
+
- **Condition Expression Validation**:
- - Condition expressions must be valid
+ - When condition type is `"expression"`, the condition expression must not be empty
+ - Error: `BpmnFloatingElementLintItem` ("Conditional Intermediate Catch Event condition expression is empty")
#### Gateway and Flow Validation
@@ -335,6 +483,8 @@ The linter performs comprehensive validation on BPMN 2.0 process definitions usi
The linter validates FHIR resources against DSF-specific profiles and HL7 FHIR specifications.
+
+
#### Unparsable FHIR Resources
- **Resource Parsing**:
@@ -401,6 +551,46 @@ Task resources are validated against the DSF Task base profile (`http://dsf.dev/
- `authoredOn` must contain `#{date}`
- Error: `FhirTaskDateNoPlaceholderLintItem`
+##### Task Identifier Validation
+
+- **System Validation**:
+ - Task identifiers must have a valid system element
+ - Expected system: `http://dsf.dev/sid/task-identifier`
+ - Error: `FHIR_TASK_IDENTIFIER_MISSING_SYSTEM` (when system is missing or empty)
+ - Error: `FHIR_TASK_IDENTIFIER_INVALID_SYSTEM` (when system is set but incorrect)
+ - Success: When the system is correctly set to `http://dsf.dev/sid/task-identifier`
+
+- **Value Format Validation**:
+ - Task identifiers with system `http://dsf.dev/sid/task-identifier` must follow a specific format
+ - Format: `{process-url}/{process-version}/{task-example-name}`
+ - Example: `http://test.org/bpe/Process/someProcessName/1.0/someExampleName`
+ - Error: `FHIR_TASK_IDENTIFIER_INVALID_FORMAT`
+ - Success: When the identifier format is valid
+
+- **Pattern Definition**:
+ ```regex
+ ^https?://[^/]+/bpe/Process/[a-zA-Z0-9-]+/(?:\d+\.\d+|#{version})/.+$
+ ```
+ The pattern accepts both actual version numbers (e.g., `1.0`) and placeholders (e.g., `#{version}`) for development-time validation.
+
+- **Valid Examples**:
+ - ✅ System: `http://dsf.dev/sid/task-identifier`
+ - ✅ Value: `http://test.org/bpe/Process/someProcessName/1.0/someExampleName` (with actual version)
+ - ✅ Value: `http://test.org/bpe/Process/someProcessName/#{version}/someExampleName` (with placeholder)
+ - ✅ Value: `https://dsf.dev/bpe/Process/myProcess/2.5/startTask`
+ - ✅ Value: `http://medizininformatik-initiative.de/bpe/Process/coordinateDataSharing/#{version}/coordinateDataSharing`
+
+- **Invalid Examples**:
+ - ❌ System missing or empty
+ - ❌ System: `http://wrong.system/identifier` (wrong system URL)
+ - ❌ Value: `http://test.org/someProcessName/1.0/taskName` (missing `/bpe/Process/` segment)
+ - ❌ Value: `http://test.org/bpe/Process/myProcess/1/taskName` (version must be in `X.Y` format, e.g. `1.0`)
+ - ❌ Empty or blank identifier value
+
+- **DSF Framework Reference**:
+ - Based on the DSF NamingSystem definition: `http://dsf.dev/sid/task-identifier`
+ - See: [DSF Framework Repository](https://github.com/datasharingframework/dsf)
+
##### Task.input Validation
- **Input Presence**:
@@ -576,10 +766,38 @@ ValueSet resources are validated against the DSF ValueSet base profile.
##### URL Validation
-- **URL Format**:
- - URL must be valid
+- **URL Presence**:
+ - URL must be present and non-empty
- Error: `FhirActivityDefinitionInvalidFhirUrlLintItem`
+- **URL Pattern Validation**:
+ - ActivityDefinition URL must follow a specific pattern
+ - Format: `http[s]://domain/bpe/Process/processName`
+ - Example: `http://dsf.dev/bpe/Process/test`
+ - Error: `ACTIVITY_DEFINITION_INVALID_URL_PATTERN`
+ - Success: When the URL pattern is valid
+
+- **Pattern Definition**:
+ ```regex
+ ^http[s]{0,1}://(?(?:(?:[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])\.)+(?:[a-zA-Z0-9]{1,63}))/bpe/Process/(?[a-zA-Z0-9-]+)$
+ ```
+
+- **Valid Examples**:
+ - ✅ `http://dsf.dev/bpe/Process/test`
+ - ✅ `https://example.org/bpe/Process/my-process`
+ - ✅ `http://test.example.com/bpe/Process/process123`
+
+- **Invalid Examples**:
+ - ❌ `http://dsf.dev/Process/test` (missing `/bpe/`)
+ - ❌ `http://dsf.dev/bpe/Process/test_invalid` (underscore not allowed in processName)
+ - ❌ `http://dsf.dev/bpe/Process/` (missing processName)
+ - ❌ `ftp://dsf.dev/bpe/Process/test` (only http/https allowed)
+
+- **DSF Framework Reference**:
+ - Based on the DSF Framework requirement defined in:
+ - `dsf-bpe/dsf-bpe-process-api/src/main/java/dev/dsf/bpe/api/plugin/AbstractProcessPlugin.java`
+ - See: [DSF Framework Repository](https://github.com/datasharingframework/dsf)
+
##### Status Validation
- **Status**:
@@ -745,7 +963,7 @@ ValueSet resources are validated against the DSF ValueSet base profile.
- **V2 API**: Must be registered in `META-INF/services/dev.dsf.bpe.v2.ProcessPluginDefinition`
- Error: `PluginDefinitionMissingServiceLoaderRegistrationLintItem`
- Plugin class must be loadable
- - Error: `PluginDefinitionProcessPluginRessourceNotLoadedLintItem`
+ - Error: `PluginDefinitionProcessPluginResourceNotLoadedLintItem`
#### Resource References
@@ -775,6 +993,34 @@ ValueSet resources are validated against the DSF ValueSet base profile.
- At least one FHIR resource must be defined
- Error: `PluginDefinitionNoFhirResourcesDefinedLintItem`
+#### Version Validation
+
+##### Resource Version Validation
+
+- **Version Pattern Requirement**:
+ - Plugin version must follow the pattern: `d.d.d.d` (e.g., `1.0.0.1`, `2.5.3.10`)
+ - Resource version is derived from the first two numbers (e.g., `1.0` from `1.0.0.1`)
+ - Error: `PLUGIN_DEFINITION_RESOURCE_VERSION_NULL`
+
+- **Valid Examples**:
+ - ✅ Version `1.0.0.1` → Resource Version `1.0`
+ - ✅ Version `2.5.3.10` → Resource Version `2.5`
+
+- **Invalid Examples**:
+ - ❌ Version `1.0.0` (missing fourth number)
+ - ❌ Version `1.0` (only two numbers)
+ - ❌ Version `invalid` (non-numeric)
+
+- **Pattern Definition**:
+ ```regex
+ (?\d+\.\d+)\.\d+\.\d+
+ ```
+
+- **DSF Framework Reference**:
+ - This validation is based on the DSF Framework requirement defined in:
+ - `dsf-bpe/dsf-bpe-process-api-v2/src/main/java/dev/dsf/bpe/v2/ProcessPluginDefinition.java`
+ - The `getResourceVersion()` method extracts the resource version from the plugin version
+
#### Leftover Resource Detection
The linter performs project-level analysis to identify unreferenced resources: