From 5a48b0943b74ed3610c0c8f36fa32c1ad1a59eec Mon Sep 17 00:00:00 2001 From: Serap Aydin Date: Wed, 18 Feb 2026 18:02:47 +0100 Subject: [PATCH 1/3] Linter Documentation update --- .../public/assets/linter/architecture.svg | 158 ++++++++++ .../public/assets/linter/bpmn-linting.svg | 143 +++++++++ .../public/assets/linter/fhir-linting.svg | 142 +++++++++ docs/src/.vuepress/theme.ts | 8 +- .../linter-tool/changelog.md | 30 ++ .../linter-tool/development.md | 8 +- .../linter-tool/linter-tool.md | 189 +++++++++--- .../process-development/linter-tool/phases.md | 2 + .../linter-tool/troubleshooting.md | 23 +- .../linter-tool/validation.md | 274 +++++++++++++++++- 10 files changed, 902 insertions(+), 75 deletions(-) create mode 100644 docs/src/.vuepress/public/assets/linter/architecture.svg create mode 100644 docs/src/.vuepress/public/assets/linter/bpmn-linting.svg create mode 100644 docs/src/.vuepress/public/assets/linter/fhir-linting.svg create mode 100644 docs/src/process-development/linter-tool/changelog.md 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..6e6f6d8f8 --- /dev/null +++ b/docs/src/.vuepress/public/assets/linter/architecture.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + DSF Linter Architecture + + + + + 1 + + Phase 1: Project Setup + ProjectSetupHandler + + + + + + + + 2 + + Phase 2: Discovery + ResourceDiscoveryService + + + + + + + + 3 + + Phase 3: Linting + + + + BPMN Linting Service + + + + FHIR Linting Service + + + + Plugin Linting + + + + Leftover Detector + + + + + + + + 4 + + Phase 4: Report Generation + + + + HTML Reports + + + + JSON Reports + + + + Console Output (LintConsolePrinter) + + + + + + + + 5 + + Phase 5: Summary + Results & Statistics + Execution Time + + + + + Supporting Components: + + + + ClassLoader Management + ProjectClassLoaderFactory + + + + Orchestration + PluginLintingOrchestrator + + + + Output Management + LintingOutput & LintItems + + + + + + + + Input + " Extracted JAR + " Configuration + + + + + + + Processing + " Multi-Plugin Support + " API v1 & v2 + + + + + + + Output + " HTML/JSON Reports + " Success Status + + + + + + + Validation + " ~99 BPMN Checks + " ~118 FHIR Checks + + + + + Key Features: + ✓ Supports single & multi-plugin projects + ✓ Isolated ClassLoader per project + ✓ Comprehensive validation (BPMN, FHIR, Plugins) + ✓ Leftover resource detection + 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 @@ + + + + + + + + + + + + BPMN Linting Overview + + + + + + Input + BPMN Files (.bpmn) + Plugin Context + + + + + BpmnLintingService + extends AbstractResourceLintingService + + + + + BpmnLinter + Parses .bpmn files + + + + + BpmnModelLinter + Orchestrates model validation + + + + + + Delegates to: + + + + + + + BpmnProcessLinter + + • Process ID pattern + • Exactly one process per file + • Executable flag + • History time to live + • Process name + + + + BpmnTaskLinter + + • Service Tasks (class, interface) + • User Tasks (formKey, Questionnaire) + • Send Tasks (FHIR references) + • Receive Tasks (message def.) + + + + BpmnEventLinter + + • Start Events (message, timer) + • End Events (message) + • Intermediate Events + • Boundary Events (error, signal) + + + + BpmnGateway + AndFlowLinter + + • Exclusive/Inclusive gateways + • Event-based gateways + • Sequence flow naming + • Condition expressions + + + + + + + BpmnSubProcessLinter + + • Multi-instance subprocesses + • asyncBefore configuration + + + + BpmnFieldInjectionLinter + + • Profile field validation + • messageName field + • instantiatesCanonical + • FHIR cross-references + + + + BpmnElementLinter + + • Messages (BpmnMessageLinter) + • Listeners (BpmnListenerLinter) + • Timers (BpmnTimerLinter) + + + + + + + LintingResult + BpmnElementLintItem | ~99 Checks | ERROR | WARN | INFO | SUCCESS + + + Shared Utilities: + + + + + + FhirResourceLocator + Cross-reference validation + + + LintingOutput + Collects lint items + + + AbstractLintingService + Template method base + + + ConcurrentCache + Thread-safe caching + 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 @@ + + + + + + + + + + + + FHIR Linting Overview + + + + + + Input + FHIR Files (XML / JSON) + Plugin Context + + + + + FhirLintingService + extends AbstractResourceLintingService + + + + + FhirResourceLinter + ServiceLoader - pluggable linters + + + + + FhirFileLinter + Parses & dispatches by type + + + + + + Dispatches to resource linter: + + + + + + + FhirActivityDefinitionLinter + ~7 checks + + • URL pattern validation + • Status, kind, profile + • Read-access tag + • Process-authorization extension + • Date & version format + + + + FhirTaskLinter + ~38 checks + + • Profile & meta validation + • Status, intent, identifiers (fixed) + • Task.input slice validation + • Cardinality enforcement + • Terminology & authorization refs + + + + FhirStructureDefinitionLinter + ~11 checks + + • URL, version, date + • Snapshot / differential + • Element ID validation + • Slice cardinality + + + + + + + FhirValueSetLinter + ~17 checks + + • URL, name, publisher + • Compose / include validation + • Concept code validation + • Read-access tag + + + + FhirCodeSystemLinter + ~8 checks + + • Code & display validation + • Version & date format + • Element concept validation + + + + FhirQuestionnaireLinter + ~11 checks + + • Meta profile validation + • Read-access tag + • Item linkId, type, text + • Mandatory item validation + + + + + + + LintingResult + FhirElementLintItem | ~118 Checks | ERROR | WARN | INFO | SUCCESS + + + Shared Utilities: + + + + + + FhirAuthorizationCache + Terminology code caching + + + FhirResourceLocator + Locates ActivityDef, Task, SD + + + FhirResourceParser + Parses XML / JSON resources + + + AbstractFhirInstanceLinter + Base class, XPath utilities + 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 +![DSF Linter Architecture](/assets/linter/architecture.svg) ### 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. +![BPMN Linting](/assets/linter/bpmn-linting.svg) + **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. +![FHIR Linting](/assets/linter/fhir-linting.svg) + #### 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: From 13c9265d4eca035b151d1f178f566da767eb7335 Mon Sep 17 00:00:00 2001 From: Serap Aydin Date: Wed, 18 Feb 2026 18:06:05 +0100 Subject: [PATCH 2/3] newslist removed bc its not used --- docs/src/.vuepress/client.ts | 5 ++--- docs/src/.vuepress/components/NewsList.vue | 8 -------- 2 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 docs/src/.vuepress/components/NewsList.vue 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 @@ - - - From 7025f60293da44d077ee536099bddb2191be39bc Mon Sep 17 00:00:00 2001 From: Simon Schweizer Date: Fri, 20 Feb 2026 11:01:18 +0100 Subject: [PATCH 3/3] Update text elements in architecture.svg with bullets --- .../public/assets/linter/architecture.svg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/.vuepress/public/assets/linter/architecture.svg b/docs/src/.vuepress/public/assets/linter/architecture.svg index 6e6f6d8f8..c3fc2a41d 100644 --- a/docs/src/.vuepress/public/assets/linter/architecture.svg +++ b/docs/src/.vuepress/public/assets/linter/architecture.svg @@ -117,8 +117,8 @@ Input - " Extracted JAR - " Configuration + • Extracted JAR + • Configuration @@ -126,8 +126,8 @@ Processing - " Multi-Plugin Support - " API v1 & v2 + • Multi-Plugin Support + • API v1 & v2 @@ -135,8 +135,8 @@ Output - " HTML/JSON Reports - " Success Status + • HTML/JSON Reports + • Success Status @@ -144,8 +144,8 @@ Validation - " ~99 BPMN Checks - " ~118 FHIR Checks + • ~99 BPMN Checks + • ~118 FHIR Checks