├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ ├── codeql-analysis.yml │ ├── dependency-review.yml │ ├── javadoc-publish.yml │ ├── jib-publish.yml │ ├── publish.yml │ ├── scorecards.yml │ ├── update-gradle-wrapper.yml │ └── validate-gradle-wrapper.yml ├── .gitignore ├── .lgtm.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── SECURITY.md ├── camunda-modeler-plugin ├── .gitignore ├── .npmignore ├── client │ ├── dmn-js-extension │ │ ├── DmnCheckJsExtension.js │ │ └── index.js │ └── index.js ├── index.js ├── package-lock.json ├── package.json ├── style │ └── style.css └── webpack.config.js ├── checkerframework └── stubs │ ├── jparsec.astub │ └── jsonobject.astub ├── cli ├── pom.xml └── src │ ├── main │ └── java │ │ └── de │ │ └── redsix │ │ └── dmncheck │ │ └── cli │ │ └── Main.java │ └── test │ └── java │ └── de │ └── redsix │ └── dmncheck │ └── cli │ └── MainTest.java ├── core ├── pom.xml └── src │ ├── main │ └── java │ │ └── de │ │ └── redsix │ │ └── dmncheck │ │ ├── drg │ │ └── RequirementGraph.java │ │ ├── package-info.java │ │ ├── result │ │ ├── Severity.java │ │ └── ValidationResult.java │ │ └── validators │ │ └── core │ │ ├── GenericValidator.java │ │ ├── RequirementGraphValidator.java │ │ ├── SimpleValidator.java │ │ ├── ValidationContext.java │ │ └── Validator.java │ └── test │ └── java │ └── de │ └── redsix │ └── dmncheck │ ├── drg │ └── RequirementGraphTest.java │ └── validators │ └── core │ └── GenericValidatorTest.java ├── docs ├── _config.yml └── index.md ├── gradle-plugin ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ ├── java │ └── de │ │ └── redsix │ │ └── dmncheck │ │ ├── DmnCheckExtension.java │ │ ├── DmnCheckGradlePlugin.java │ │ └── DmnCheckTask.java │ └── resources │ └── META-INF │ └── gradle-plugins │ └── de.redsix.dmncheck.plugin.properties ├── maven-plugin ├── pom.xml └── src │ ├── main │ └── java │ │ └── de │ │ └── redsix │ │ └── dmncheck │ │ └── CheckerMain.java │ └── test │ ├── java │ └── de │ │ └── redsix │ │ └── dmncheck │ │ └── CheckerMainTest.java │ └── resources │ ├── empty-as-well.dmn │ └── empty.dmn ├── plugin-base ├── pom.xml └── src │ ├── main │ └── java │ │ └── de │ │ └── redsix │ │ └── dmncheck │ │ └── plugin │ │ ├── PluginBase.java │ │ └── PrettyPrintValidationResults.java │ └── test │ ├── java │ └── de │ │ └── redsix │ │ └── dmncheck │ │ └── plugin │ │ └── PluginBaseTest.java │ └── resources │ ├── cyclic-diagram.dmn │ ├── decision-requirement-diagram.dmn │ ├── diagram-with-a-loop.dmn │ ├── dish-decision-1-3.dmn │ ├── dish-decision.dmn │ ├── duplicate_collect.dmn │ ├── duplicate_unique.dmn │ ├── empty.dmn │ └── no-decision.dmn ├── pom.xml ├── server ├── pom.xml └── src │ └── main │ └── java │ └── de │ └── redsix │ └── dmncheck │ └── server │ ├── NonValidatingDmnParser.java │ └── ValidationServer.java └── validators ├── checkerframework └── stubs │ ├── jparsec.astub │ └── jsonobject.astub ├── pom.xml └── src ├── main └── java │ └── de │ └── redsix │ └── dmncheck │ ├── feel │ ├── ExpressionType.java │ ├── ExpressionTypeParser.java │ ├── FeelExpression.java │ ├── FeelParser.java │ ├── FeelTypecheck.java │ ├── Operator.java │ └── Subsumption.java │ ├── util │ ├── Either.java │ ├── Expression.java │ ├── ProjectClassLoader.java │ ├── TopLevelExpressionLanguage.java │ ├── TriFunction.java │ ├── Util.java │ └── ValidatorLoader.java │ └── validators │ ├── AggregationOutputTypeValidator.java │ ├── AggregationValidator.java │ ├── ConflictingRuleValidator.java │ ├── ConnectedRequirementGraphValidator.java │ ├── DecisionIdAndNameValidator.java │ ├── DefinitionsIdAndNameValidator.java │ ├── DuplicateColumnLabelValidator.java │ ├── DuplicateRuleValidator.java │ ├── ElementTypeDeclarationValidator.java │ ├── IdAndNameValidator.java │ ├── InputDataIdAndNameValidator.java │ ├── InputEntryTypeValidator.java │ ├── InputTypeDeclarationValidator.java │ ├── InputValuesTypeValidator.java │ ├── ItemDefinitionAllowedValuesTypeValidator.java │ ├── ItemDefinitionIdAndNameValidator.java │ ├── KnowledgeSourceIdAndNameValidator.java │ ├── NoDecisionPresentValidator.java │ ├── OutputEntryTypeValidator.java │ ├── OutputTypeDeclarationValidator.java │ ├── OutputValuesTypeValidator.java │ ├── RequirementGraphLeafValidator.java │ ├── ShadowedRuleValidator.java │ └── TypeValidator.java └── test └── java └── de └── redsix └── dmncheck ├── feel ├── ExpressionTypeParserTest.java ├── FeelExpressionTest.java ├── FeelParserTest.java ├── FeelTypecheckTest.java └── SubsumptionTest.java ├── util └── ExpressionTest.java └── validators ├── AggregationOutputTypeValidatorTest.java ├── AggregationValidatorTest.java ├── ConflictingRuleValidatorTest.java ├── ConnectedRequirementGraphValidatorTest.java ├── DecisionIdAndNameValidatorTest.java ├── DefinitionsIdAndNameValidatorTest.java ├── DuplicateColumnLabelValidatorTest.java ├── DuplicateRuleValidatorTest.java ├── InputDataIdAndNameValidatorTest.java ├── InputEntryTypeValidatorTest.java ├── InputTypeDeclarationValidatorTest.java ├── InputValuesTypeValidatorTest.java ├── ItemDefinitionAllowedValuesTypeValidatorTest.java ├── ItemDefinitionIdAndNameValidatorTest.java ├── KnowledgeSourceIdAndNameValidatorTest.java ├── NoDecisionPresentValidatorTest.java ├── OutputEntryTypeValidatorTest.java ├── OutputTypeDeclarationValidatorTest.java ├── OutputValuesTypeValidatorTest.java ├── RequirementGraphLeafValidatorTest.java ├── ShadowedRuleValidatorTest.java └── util ├── TestEnum.java ├── WithDecisionTable.java ├── WithDefinitions.java ├── WithItemDefinition.java └── WithRequirementGraph.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "monthly" 8 | 9 | - package-ecosystem: "maven" 10 | directory: "/" 11 | schedule: 12 | interval: "monthly" 13 | open-pull-requests-limit: 10 14 | 15 | - package-ecosystem: "gradle" 16 | directory: "/gradle-plugin" 17 | schedule: 18 | interval: "monthly" 19 | 20 | - package-ecosystem: "maven" 21 | directory: "/" 22 | schedule: 23 | interval: "monthly" 24 | # Setting open-pull-requests-limit to 0 means that dependabot will not 25 | # update regular dependencies on this target branch, but still provide 26 | # security updates for our gomod dependencies 27 | open-pull-requests-limit: 0 28 | target-branch: "release/1.3.x" 29 | 30 | - package-ecosystem: "gradle" 31 | directory: "/gradle-plugin" 32 | schedule: 33 | interval: "monthly" 34 | # Setting open-pull-requests-limit to 0 means that dependabot will not 35 | # update regular dependencies on this target branch, but still provide 36 | # security updates for our gomod dependencies 37 | open-pull-requests-limit: 0 38 | target-branch: "release/1.3.x" 39 | 40 | - package-ecosystem: "maven" 41 | directory: "/" 42 | schedule: 43 | interval: "monthly" 44 | # Setting open-pull-requests-limit to 0 means that dependabot will not 45 | # update regular dependencies on this target branch, but still provide 46 | # security updates for our gomod dependencies 47 | open-pull-requests-limit: 0 48 | target-branch: "release/1.2.x" 49 | 50 | - package-ecosystem: "gradle" 51 | directory: "/gradle-plugin" 52 | schedule: 53 | interval: "monthly" 54 | # Setting open-pull-requests-limit to 0 means that dependabot will not 55 | # update regular dependencies on this target branch, but still provide 56 | # security updates for our gomod dependencies 57 | open-pull-requests-limit: 0 58 | target-branch: "release/1.2.x" 59 | 60 | 61 | - package-ecosystem: npm 62 | directory: /camunda-modeler-plugin 63 | schedule: 64 | interval: daily 65 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - 'release/*' 8 | pull_request: 9 | types: [ opened, synchronize, reopened ] 10 | 11 | pull_request_target: 12 | types: [ opened, synchronize, reopened ] 13 | 14 | jobs: 15 | build-dmn-check: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Harden Runner 21 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 22 | with: 23 | egress-policy: audit 24 | 25 | - name: Checkout 26 | if: ${{ github.event_name != 'pull_request_target' }} 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | fetch-depth: 0 # Disabling shallow clone is recommended for improving relevancy of reporting 30 | - name: Checkout PR 31 | if: ${{ github.event_name == 'pull_request_target' }} 32 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 33 | with: 34 | ref: ${{ github.event.pull_request.head.sha }} 35 | fetch-depth: 0 # Disabling shallow clone is recommended for improving relevancy of reporting 36 | - name: Set up JDK 37 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 38 | with: 39 | java-version: '17' 40 | distribution: 'adopt' 41 | cache: maven 42 | - name: Build with Maven 43 | run: mvn clean install -P checkerframework 44 | 45 | 46 | sonarcloud: 47 | runs-on: ubuntu-latest 48 | # If the PR is coming from a fork (pull_request_target), ensure it's opened by "dependabot[bot]". 49 | # Otherwise, clone it normally. 50 | if: | 51 | (github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]') || 52 | (github.event_name != 'pull_request_target' && github.actor != 'dependabot[bot]') 53 | steps: 54 | - name: Harden Runner 55 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 56 | with: 57 | egress-policy: audit 58 | allowed-endpoints: sonarcloud.io:443 59 | 60 | - name: Checkout 61 | if: ${{ github.event_name != 'pull_request_target' }} 62 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 63 | - name: Checkout PR 64 | if: ${{ github.event_name == 'pull_request_target' }} 65 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 66 | with: 67 | ref: ${{ github.event.pull_request.head.sha }} 68 | - name: Set up JDK 69 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 70 | with: 71 | java-version: '17' 72 | distribution: 'adopt' 73 | - env: 74 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 75 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 76 | run: mvn -B verify jacoco:report org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=red6_dmn-check 77 | 78 | 79 | build-gradle-plugin: 80 | runs-on: ubuntu-latest 81 | needs: build-dmn-check 82 | steps: 83 | - name: Harden Runner 84 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 85 | with: 86 | egress-policy: audit 87 | 88 | - name: Checkout 89 | if: ${{ github.event_name != 'pull_request_target' }} 90 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 91 | with: 92 | fetch-depth: 0 # Disabling shallow clone is recommended for improving relevancy of reporting 93 | - name: Checkout PR 94 | if: ${{ github.event_name == 'pull_request_target' }} 95 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 96 | with: 97 | ref: ${{ github.event.pull_request.head.sha }} 98 | fetch-depth: 0 # Disabling shallow clone is recommended for improving relevancy of reporting 99 | - name: Set up JDK 100 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 101 | with: 102 | java-version: '17' 103 | distribution: 'adopt' 104 | cache: maven 105 | - name: Build with Gradle 106 | run: cd gradle-plugin && ./gradlew build 107 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # ******** NOTE ******** 12 | 13 | name: "CodeQL" 14 | 15 | on: 16 | push: 17 | branches: 18 | - master 19 | - 'release/*' 20 | pull_request: 21 | # The branches below must be a subset of the branches above 22 | branches: 23 | - master 24 | - 'release/*' 25 | schedule: 26 | - cron: '20 19 * * 1' 27 | 28 | permissions: 29 | contents: read 30 | 31 | jobs: 32 | analyze: 33 | permissions: 34 | actions: read # for github/codeql-action/init to get workflow details 35 | contents: read # for actions/checkout to fetch code 36 | security-events: write # for github/codeql-action/autobuild to send a status report 37 | name: Analyze 38 | runs-on: ubuntu-latest 39 | 40 | strategy: 41 | fail-fast: false 42 | matrix: 43 | language: [ 'java', 'javascript' ] 44 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 45 | # Learn more... 46 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 47 | 48 | steps: 49 | - name: Harden Runner 50 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 51 | with: 52 | egress-policy: audit 53 | 54 | - name: Checkout repository 55 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 56 | 57 | - name: Set up JDK 58 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 59 | with: 60 | java-version: '17' 61 | distribution: 'adopt' 62 | 63 | # Initializes the CodeQL tools for scanning. 64 | - name: Initialize CodeQL 65 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 66 | with: 67 | languages: ${{ matrix.language }} 68 | # If you wish to specify custom queries, you can do so here or in a config file. 69 | # By default, queries listed here will override any specified in a config file. 70 | # Prefix the list here with "+" to use these queries and those in the config file. 71 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 72 | 73 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 74 | # If this step fails, then you should remove it and run the build manually (see below) 75 | - name: Autobuild 76 | uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 77 | 78 | # ℹ️ Command-line programs to run using the OS shell. 79 | # 📚 https://git.io/JvXDl 80 | 81 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 82 | # and modify them (or add more) to build your code if your project 83 | # uses a compiled language 84 | 85 | #- run: | 86 | # make bootstrap 87 | # make release 88 | 89 | - name: Perform CodeQL Analysis 90 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 91 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Harden Runner 18 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 19 | with: 20 | egress-policy: audit 21 | 22 | - name: 'Checkout Repository' 23 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | - name: 'Dependency Review' 25 | uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 26 | -------------------------------------------------------------------------------- /.github/workflows/javadoc-publish.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Javadoc 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | paths: 9 | - "**.java" 10 | 11 | jobs: 12 | publish: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Harden Runner 16 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 17 | with: 18 | egress-policy: audit 19 | 20 | - name: Deploy JavaDoc 🚀 21 | uses: MathieuSoysal/Javadoc-publisher.yml@fda475b197081ba1eca7a1dfadf0c017080a1623 # v3.0.2 22 | with: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | javadoc-branch: javadoc 25 | java-version: 17 26 | target-folder: javadoc 27 | -------------------------------------------------------------------------------- /.github/workflows/jib-publish.yml: -------------------------------------------------------------------------------- 1 | name: JIB container publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | release: 8 | types: [ created ] 9 | 10 | jobs: 11 | publish: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Harden Runner 15 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 16 | with: 17 | egress-policy: audit 18 | 19 | - name: JIB container build and publish 20 | uses: MathieuSoysal/jib-container-publish.yml@8df13913445f036bf93d0450669dbfbac2cac541 # main 21 | with: 22 | PASSWORD: ${{ secrets.GITHUB_TOKEN }} 23 | java-version: 17 24 | module: cli 25 | main-class: de.redsix.dmncheck.cli.Main -------------------------------------------------------------------------------- /.github/workflows/scorecards.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | # For Branch-Protection check. Only the default branch is supported. See 8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 9 | branch_protection_rule: 10 | # To guarantee Maintained check is occasionally updated. See 11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 12 | schedule: 13 | - cron: '20 7 * * 2' 14 | push: 15 | branches: ["master"] 16 | 17 | # Declare default permissions as read only. 18 | permissions: read-all 19 | 20 | jobs: 21 | analysis: 22 | name: Scorecard analysis 23 | runs-on: ubuntu-latest 24 | permissions: 25 | # Needed to upload the results to code-scanning dashboard. 26 | security-events: write 27 | # Needed to publish results and get a badge (see publish_results below). 28 | id-token: write 29 | contents: read 30 | actions: read 31 | 32 | steps: 33 | - name: Harden Runner 34 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 35 | with: 36 | egress-policy: audit 37 | 38 | - name: "Checkout code" 39 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 40 | with: 41 | persist-credentials: false 42 | 43 | - name: "Run analysis" 44 | uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 45 | with: 46 | results_file: results.sarif 47 | results_format: sarif 48 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 49 | # - you want to enable the Branch-Protection check on a *public* repository, or 50 | # - you are installing Scorecards on a *private* repository 51 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. 52 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 53 | 54 | # Public repositories: 55 | # - Publish results to OpenSSF REST API for easy access by consumers 56 | # - Allows the repository to include the Scorecard badge. 57 | # - See https://github.com/ossf/scorecard-action#publishing-results. 58 | # For private repositories: 59 | # - `publish_results` will always be set to `false`, regardless 60 | # of the value entered here. 61 | publish_results: true 62 | 63 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF 64 | # format to the repository Actions tab. 65 | - name: "Upload artifact" 66 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 67 | with: 68 | name: SARIF file 69 | path: results.sarif 70 | retention-days: 5 71 | 72 | # Upload the results to GitHub's code scanning dashboard. 73 | - name: "Upload to code-scanning" 74 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 75 | with: 76 | sarif_file: results.sarif 77 | -------------------------------------------------------------------------------- /.github/workflows/update-gradle-wrapper.yml: -------------------------------------------------------------------------------- 1 | name: Update Gradle Wrapper 2 | on: 3 | schedule: 4 | - cron: '0 0 1 * *' 5 | 6 | jobs: 7 | update-gradle-wrapper: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Harden Runner 11 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 12 | with: 13 | egress-policy: audit 14 | 15 | - name: checkout 16 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 17 | 18 | - name: update gradle 19 | id: gradleUpdate 20 | uses: EdwarDDay/upgrade-gradle-action@3b3788a65fe8c6d24ee63acbf09a3d59e39b4f0b # v1.5.0 21 | with: 22 | working-directory: gradle-plugin 23 | 24 | - name: create pull request 25 | uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 26 | with: 27 | commit-message: "Update gradle to ${{ steps.gradleUpdate.outputs.gradle-version }}" 28 | branch: "gradle_update/version_${{ steps.gradleUpdate.outputs.gradle-version }}" 29 | delete-branch: true 30 | title: "Update gradle to ${{ steps.gradleUpdate.outputs.gradle-version }}" 31 | body: | 32 | ${{ steps.gradleUpdate.outputs.version-information }} 33 | 34 | Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action 35 | labels: "dependencies,gradle" -------------------------------------------------------------------------------- /.github/workflows/validate-gradle-wrapper.yml: -------------------------------------------------------------------------------- 1 | name: "Validate Gradle Wrapper" 2 | on: [push] 3 | 4 | permissions: 5 | contents: read 6 | 7 | jobs: 8 | validation: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Harden Runner 12 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 13 | with: 14 | egress-policy: audit 15 | 16 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 17 | - uses: gradle/wrapper-validation-action@f9c9c575b8b21b6485636a91ffecd10e558c62f6 # v3.5.0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/** 2 | *.iml 3 | target/** 4 | */target/** 5 | gradle-plugin/.idea -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | java: 3 | index: 4 | java_version: "17" 5 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Currently the following versions do get security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 1.3.x | :white_check_mark: | 10 | | < 1.3 | :x: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | Please report any vulnerability to pascal.wittmann@red6-es.de. 15 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and not Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Stores VSCode versions used for testing VSCode extensions 107 | .vscode-test 108 | 109 | # Intellij Idea 110 | *.iml 111 | .idea 112 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/.npmignore: -------------------------------------------------------------------------------- 1 | !dist 2 | client 3 | webpack.config.js -------------------------------------------------------------------------------- /camunda-modeler-plugin/client/dmn-js-extension/DmnCheckJsExtension.js: -------------------------------------------------------------------------------- 1 | function DmnCheckJsExtension(eventBus, drd, elementRegistry, moddle, overlays, canvas) { 2 | 3 | const messages = document.createElement("div"); 4 | messages.classList.add('message-box'); 5 | messages.id = "message-box"; 6 | messages.style.display = "none"; 7 | canvas.getContainer().parentNode.appendChild(messages); 8 | 9 | eventBus.on('import.done', function() { 10 | validate(); 11 | }); 12 | 13 | 14 | eventBus.on('elements.changed', function() { 15 | validate(); 16 | }); 17 | 18 | function validate() { 19 | const map = {}; 20 | 21 | moddle.toXML(drd._definitions, {}).then((result) => { 22 | log("Start validation."); 23 | 24 | xml = result.xml; 25 | 26 | fetch('http://localhost:42000/validate', { 27 | method: "POST", 28 | body: xml 29 | }).then(res => { 30 | res.text().then(function (results) { 31 | 32 | log("Request complete! response:", results); 33 | 34 | messages.textContent = ""; 35 | 36 | JSON.parse(results).items.forEach(result => { 37 | const shape = elementRegistry.get(result.drgElementId); 38 | 39 | if (typeof shape !== "undefined") { 40 | overlays.add(shape, 'badge', { 41 | position: { 42 | bottom: 0, 43 | left: 21 * map[result.drgElementId] 44 | }, 45 | html: '
' 46 | }); 47 | 48 | map[result.drgElementId] = ~~map[result.drgElementId] + 1; 49 | } else { 50 | messages.textContent = result.message; 51 | } 52 | }); 53 | 54 | if (messages.textContent !== "") { 55 | messages.style.display = "block"; 56 | } 57 | }) 58 | }); 59 | 60 | log("Validation finished."); 61 | }); 62 | } 63 | } 64 | 65 | 66 | 67 | function log(...args) { 68 | console.log('[DmnCheckJsExtension]', ...args); 69 | } 70 | 71 | DmnCheckJsExtension.$inject = ['eventBus', 'drd', 'elementRegistry', 'moddle', 'overlays', 'canvas']; 72 | 73 | module.exports = DmnCheckJsExtension; 74 | 75 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/client/dmn-js-extension/index.js: -------------------------------------------------------------------------------- 1 | import DmnCheckPlugin from './DmnCheckJsExtension'; 2 | 3 | export default { 4 | __init__: [ 'dmnCheckPlugin' ], 5 | dmnCheckPlugin: [ 'type', DmnCheckPlugin ] 6 | }; 7 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/client/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | registerDmnJSPlugin, 3 | } from 'camunda-modeler-plugin-helpers'; 4 | 5 | import DmnExtensionModule from './dmn-js-extension'; 6 | 7 | registerDmnJSPlugin(DmnExtensionModule, 'drd'); 8 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH 3 | * under one or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information regarding copyright 5 | * ownership. 6 | * 7 | * Camunda licenses this file to you under the MIT; you may not use this file 8 | * except in compliance with the MIT License. 9 | */ 10 | 11 | 'use strict'; 12 | 13 | module.exports = { 14 | name: 'dmn-check Plugin', 15 | script: './dist/client.js', 16 | style: './style/style.css' 17 | }; 18 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dmn-test-plugin", 3 | "version": "1.0.0", 4 | "description": "The Camunda Modeler dmn-check plug-in", 5 | "main": "index.js", 6 | "scripts": { 7 | "all": "run-s bundle", 8 | "bundle": "webpack", 9 | "dev": "webpack -w", 10 | "prepublishOnly": "run-s bundle" 11 | }, 12 | "keywords": [ 13 | "camunda", 14 | "modeler", 15 | "plugin", 16 | "dmn-check" 17 | ], 18 | "devDependencies": { 19 | "camunda-modeler-plugin-helpers": "^5.1.0", 20 | "npm-run-all": "^4.1.5", 21 | "webpack": "^5.99.9", 22 | "webpack-cli": "^6.0.1" 23 | }, 24 | "dependencies": { 25 | "min-dash": "^4.2.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/style/style.css: -------------------------------------------------------------------------------- 1 | .badge { 2 | position:relative; 3 | } 4 | .badge:after { 5 | content:'🞩'; 6 | position:absolute; 7 | top:-10px; 8 | right:-10px; 9 | font-size:1.2em; 10 | color:white; 11 | width:20px; 12 | height:20px; 13 | text-align:center; 14 | line-height:20px; 15 | border-radius:50%; 16 | box-shadow:0 0 1px #333; 17 | } 18 | 19 | .badge-warning:after { 20 | background: orange; 21 | } 22 | 23 | .badge-error:after { 24 | background: red; 25 | } 26 | 27 | .message-box { 28 | font-size: 1.5em; 29 | position: absolute; 30 | bottom: 20px; 31 | left: 20px; 32 | background: red; 33 | color: white; 34 | } 35 | -------------------------------------------------------------------------------- /camunda-modeler-plugin/webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH 3 | * under one or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information regarding copyright 5 | * ownership. 6 | * 7 | * Camunda licenses this file to you under the MIT; you may not use this file 8 | * except in compliance with the MIT License. 9 | */ 10 | 11 | const path = require('path'); 12 | 13 | module.exports = { 14 | mode: 'development', 15 | entry: './client/index.js', 16 | output: { 17 | path: path.resolve(__dirname, 'dist'), 18 | filename: 'client.js' 19 | }, 20 | devtool: 'cheap-module-source-map' 21 | }; -------------------------------------------------------------------------------- /checkerframework/stubs/jparsec.astub: -------------------------------------------------------------------------------- 1 | import org.checkerframework.checker.regex.qual.Regex; 2 | package org.jparsec.pattern; 3 | public final class Patterns { 4 | public static Pattern regex(@Regex String s); 5 | } 6 | -------------------------------------------------------------------------------- /checkerframework/stubs/jsonobject.astub: -------------------------------------------------------------------------------- 1 | import org.checkerframework.checker.nullness.qual.Nullable; 2 | package org.json; 3 | 4 | public class JSONObject { 5 | public JSONObject put(String key, @Nullable Object value) throws JSONException; 6 | } 7 | -------------------------------------------------------------------------------- /cli/pom.xml: -------------------------------------------------------------------------------- 1 | 2 |1) A message that describes the validation result 2) A severity indicating how severe the result is 3) A reference 9 | * to the DMN element that caused result 10 | * 11 | *
In this context a validation result always describes an error or a warning. There is currently no way to express 12 | * positive validation results, except returning no validation results at all. 13 | */ 14 | public class ValidationResult { 15 | 16 | private final Severity severity; 17 | private final String message; 18 | private final ModelElementInstance element; 19 | 20 | private ValidationResult(final String message, final ModelElementInstance element, final Severity severity) { 21 | this.message = message; 22 | this.element = element; 23 | this.severity = severity; 24 | } 25 | 26 | public Severity getSeverity() { 27 | return severity; 28 | } 29 | 30 | public String getMessage() { 31 | return message; 32 | } 33 | 34 | public ModelElementInstance getElement() { 35 | return element; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return message; 41 | } 42 | 43 | public static final Builder.MessageStep init = message -> (new Builder.SeverityStep() { 44 | 45 | private Severity severity = Severity.ERROR; 46 | 47 | @Override 48 | public Builder.BuildStep element(ModelElementInstance element) { 49 | return new Builder.BuildStep() { 50 | 51 | @Override 52 | public ModelElementInstance getElement() { 53 | return element; 54 | } 55 | 56 | @Override 57 | public Severity getSeverity() { 58 | return severity; 59 | } 60 | 61 | @Override 62 | public String getMessage() { 63 | return message; 64 | } 65 | 66 | @Override 67 | public ValidationResult build() { 68 | return new ValidationResult(message, element, severity); 69 | } 70 | }; 71 | } 72 | 73 | @Override 74 | public Severity getSeverity() { 75 | return severity; 76 | } 77 | 78 | @Override 79 | public Builder.ElementStep severity(Severity severity) { 80 | this.severity = severity; 81 | return this; 82 | } 83 | 84 | @Override 85 | public String getMessage() { 86 | return message; 87 | } 88 | }); 89 | 90 | public static final class Builder { 91 | 92 | @FunctionalInterface 93 | public interface MessageStep { 94 | SeverityStep message(String message); 95 | } 96 | 97 | public interface SeverityStep extends ElementStep { 98 | ElementStep severity(Severity severity); 99 | 100 | String getMessage(); 101 | } 102 | 103 | public interface ElementStep { 104 | BuildStep element(ModelElementInstance element); 105 | 106 | Severity getSeverity(); 107 | 108 | String getMessage(); 109 | } 110 | 111 | public interface BuildStep { 112 | ModelElementInstance getElement(); 113 | 114 | Severity getSeverity(); 115 | 116 | String getMessage(); 117 | 118 | ValidationResult build(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /core/src/main/java/de/redsix/dmncheck/validators/core/GenericValidator.java: -------------------------------------------------------------------------------- 1 | package de.redsix.dmncheck.validators.core; 2 | 3 | import de.redsix.dmncheck.result.ValidationResult; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | import org.camunda.bpm.model.dmn.DmnModelInstance; 9 | import org.camunda.bpm.model.xml.instance.ModelElementInstance; 10 | 11 | /** 12 | * Generic validator that facilitates writing validations directly on the structure of the DMN model instance. 13 | * 14 | *
Note: We are using the Camunda implementation of the DMN model (...). 16 | * 17 | *
To write a validation using this validator you have to specify: 18 | * 19 | *
1) The element type (T) that is validated 2) The element type (S) that is used to check whether the validation is 20 | * applicable 21 | * 22 | *
The validator collects all elements of type S and checks whether the validation is applicable. It then applies the
23 | * validation on all child elements of type T.
24 | *
25 | * @param A validation context can be used to track global assumptions about the DMN model instance.
44 | *
45 | * @param element Element under validation
46 | * @param validationContext Validation Context
47 | * @return A list of validation results
48 | */
49 | protected abstract List Note: Reading from the validation context is cached.
16 | */
17 | public class ValidationContext {
18 |
19 | private static class Memoizer Every validation for dmn-check has to implement this interface.
11 | */
12 | public interface Validator {
13 |
14 | /**
15 | * Validates the given DMN model instance and returns the validation results as a list.
16 | *
17 | * @param dmnModelInstance DMN model instance used for validation
18 | * @return A possibly empty list of validation results
19 | */
20 | List Class used to check whether the validation is applicable
26 | * @param
29 | implements Validator {
30 |
31 | /**
32 | * Checks whether the validation is applicable for an element of type S taking account of the validation context.
33 | *
34 | * @param element Element used to check applicability of the validation
35 | * @param validationContext Validation Context
36 | * @return Whether the validation is applicable
37 | */
38 | protected abstract boolean isApplicable(final S element, ValidationContext validationContext);
39 |
40 | /**
41 | * Validates a given element of type T.
42 | *
43 | * getClassUsedToCheckApplicability();
57 |
58 | /**
59 | * Auxiliary method to determine the class for the validation.
60 | *
61 | * @return Class used for validation
62 | */
63 | protected abstract Class elements = dmnModelInstance.getModelElementsByType(getClassUsedToCheckApplicability());
69 | return elements.stream()
70 | .filter(element -> isApplicable(element, validationContext))
71 | .flatMap(this::getElementsUnderValidation)
72 | .flatMap(element -> validate(element, validationContext).stream())
73 | .collect(Collectors.toList());
74 | }
75 |
76 | private Stream