@bpmn-ld/bpmn-ld 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +125 -2
- package/contexts/combined.jsonld +3 -0
- package/contexts/core.jsonld +170 -0
- package/contexts/di.jsonld +37 -0
- package/dist/analyze/analyze.d.ts +3 -0
- package/dist/analyze/analyze.js +11 -0
- package/dist/analyze/findings.d.ts +8 -0
- package/dist/analyze/findings.js +1 -0
- package/dist/analyze/report.d.ts +3 -0
- package/dist/analyze/report.js +9 -0
- package/dist/analyze/rules/ad-hoc-completion-condition.d.ts +2 -0
- package/dist/analyze/rules/ad-hoc-completion-condition.js +7 -0
- package/dist/analyze/rules/cannot-reach-end.d.ts +2 -0
- package/dist/analyze/rules/cannot-reach-end.js +28 -0
- package/dist/analyze/rules/compensation-association.d.ts +2 -0
- package/dist/analyze/rules/compensation-association.js +13 -0
- package/dist/analyze/rules/dead-end.d.ts +2 -0
- package/dist/analyze/rules/dead-end.js +13 -0
- package/dist/analyze/rules/end-event.d.ts +2 -0
- package/dist/analyze/rules/end-event.js +8 -0
- package/dist/analyze/rules/error-catch.d.ts +2 -0
- package/dist/analyze/rules/error-catch.js +14 -0
- package/dist/analyze/rules/escalation-catch.d.ts +2 -0
- package/dist/analyze/rules/escalation-catch.js +14 -0
- package/dist/analyze/rules/gateway-cardinality.d.ts +3 -0
- package/dist/analyze/rules/gateway-cardinality.js +17 -0
- package/dist/analyze/rules/index.d.ts +4 -0
- package/dist/analyze/rules/index.js +21 -0
- package/dist/analyze/rules/instantiating-gateway.d.ts +2 -0
- package/dist/analyze/rules/instantiating-gateway.js +14 -0
- package/dist/analyze/rules/non-interrupting-start.d.ts +2 -0
- package/dist/analyze/rules/non-interrupting-start.js +14 -0
- package/dist/analyze/rules/reachability.d.ts +2 -0
- package/dist/analyze/rules/reachability.js +25 -0
- package/dist/analyze/rules/rule.d.ts +7 -0
- package/dist/analyze/rules/rule.js +1 -0
- package/dist/analyze/rules/signal-catch.d.ts +2 -0
- package/dist/analyze/rules/signal-catch.js +12 -0
- package/dist/analyze/rules/split-join-pairing.d.ts +3 -0
- package/dist/analyze/rules/split-join-pairing.js +50 -0
- package/dist/analyze/rules/start-event.d.ts +2 -0
- package/dist/analyze/rules/start-event.js +8 -0
- package/dist/analyze/rules/task-message-flow.d.ts +2 -0
- package/dist/analyze/rules/task-message-flow.js +19 -0
- package/dist/analyze/scope-graph.d.ts +56 -0
- package/dist/analyze/scope-graph.js +89 -0
- package/dist/analyze-cli.d.ts +1 -0
- package/dist/analyze-cli.js +5 -0
- package/dist/analyze-run.d.ts +12 -0
- package/dist/analyze-run.js +85 -0
- package/dist/bpmn-ld-cli.d.ts +1 -0
- package/dist/bpmn-ld-cli.js +90 -0
- package/dist/build-cli.d.ts +1 -0
- package/dist/build-cli.js +2 -0
- package/dist/build.d.ts +3 -0
- package/dist/build.js +38 -0
- package/dist/check-xml/check.d.ts +3 -0
- package/dist/check-xml/check.js +11 -0
- package/dist/check-xml/lint.d.ts +2 -0
- package/dist/check-xml/lint.js +47 -0
- package/dist/check-xml/moddle.d.ts +6 -0
- package/dist/check-xml/moddle.js +23 -0
- package/dist/check-xml/types.d.ts +20 -0
- package/dist/check-xml/types.js +1 -0
- package/dist/check-xml/xsd.d.ts +2 -0
- package/dist/check-xml/xsd.js +25 -0
- package/dist/check-xml-cli.d.ts +1 -0
- package/dist/check-xml-cli.js +5 -0
- package/dist/check-xml-run.d.ts +10 -0
- package/dist/check-xml-run.js +77 -0
- package/dist/convert/analyze-output.d.ts +3 -0
- package/dist/convert/analyze-output.js +8 -0
- package/dist/convert/convert.d.ts +19 -0
- package/dist/convert/convert.js +96 -0
- package/dist/convert/errors.d.ts +5 -0
- package/dist/convert/errors.js +8 -0
- package/dist/convert/extensions.d.ts +23 -0
- package/dist/convert/extensions.js +103 -0
- package/dist/convert/mapping-check.d.ts +15 -0
- package/dist/convert/mapping-check.js +66 -0
- package/dist/convert/mapping.d.ts +52 -0
- package/dist/convert/mapping.js +273 -0
- package/dist/convert/namespaces.d.ts +2 -0
- package/dist/convert/namespaces.js +19 -0
- package/dist/convert/validate-output.d.ts +2 -0
- package/dist/convert/validate-output.js +28 -0
- package/dist/convert/warnings.d.ts +9 -0
- package/dist/convert/warnings.js +67 -0
- package/dist/convert/xml-reader.d.ts +11 -0
- package/dist/convert/xml-reader.js +84 -0
- package/dist/convert-cli.d.ts +1 -0
- package/dist/convert-cli.js +5 -0
- package/dist/convert-run.d.ts +10 -0
- package/dist/convert-run.js +125 -0
- package/dist/coverage-cli.d.ts +1 -0
- package/dist/coverage-cli.js +8 -0
- package/dist/coverage-mappings.d.ts +3 -0
- package/dist/coverage-mappings.js +34 -0
- package/dist/coverage-scope.d.ts +11 -0
- package/dist/coverage-scope.js +187 -0
- package/dist/coverage-xsd.d.ts +15 -0
- package/dist/coverage-xsd.js +55 -0
- package/dist/coverage.d.ts +35 -0
- package/dist/coverage.js +152 -0
- package/dist/docs-cli.d.ts +1 -0
- package/dist/docs-cli.js +18 -0
- package/dist/docs.d.ts +8 -0
- package/dist/docs.js +136 -0
- package/dist/eval/checks.d.ts +19 -0
- package/dist/eval/checks.js +252 -0
- package/dist/eval/regenerate.d.ts +10 -0
- package/dist/eval/regenerate.js +48 -0
- package/dist/eval-regenerate-cli.d.ts +1 -0
- package/dist/eval-regenerate-cli.js +16 -0
- package/dist/export/data.d.ts +10 -0
- package/dist/export/data.js +127 -0
- package/dist/export/diagram.d.ts +8 -0
- package/dist/export/diagram.js +112 -0
- package/dist/export/element.d.ts +27 -0
- package/dist/export/element.js +175 -0
- package/dist/export/export.d.ts +22 -0
- package/dist/export/export.js +124 -0
- package/dist/export/extensions.d.ts +18 -0
- package/dist/export/extensions.js +122 -0
- package/dist/export/layout-export.d.ts +4 -0
- package/dist/export/layout-export.js +25 -0
- package/dist/export/mapping-check.d.ts +39 -0
- package/dist/export/mapping-check.js +175 -0
- package/dist/export/normalize.d.ts +3 -0
- package/dist/export/normalize.js +67 -0
- package/dist/export-cli.d.ts +1 -0
- package/dist/export-cli.js +5 -0
- package/dist/export-run.d.ts +10 -0
- package/dist/export-run.js +157 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/install-skill-run.d.ts +8 -0
- package/dist/install-skill-run.js +30 -0
- package/dist/install-skill.d.ts +23 -0
- package/dist/install-skill.js +76 -0
- package/dist/layout/collaboration.d.ts +36 -0
- package/dist/layout/collaboration.js +152 -0
- package/dist/layout/di.d.ts +15 -0
- package/dist/layout/di.js +52 -0
- package/dist/layout/extract.d.ts +2 -0
- package/dist/layout/extract.js +99 -0
- package/dist/layout/lanes.d.ts +30 -0
- package/dist/layout/lanes.js +112 -0
- package/dist/layout/layering.d.ts +7 -0
- package/dist/layout/layering.js +53 -0
- package/dist/layout/layout.d.ts +12 -0
- package/dist/layout/layout.js +299 -0
- package/dist/layout/model.d.ts +52 -0
- package/dist/layout/model.js +10 -0
- package/dist/layout/placement.d.ts +25 -0
- package/dist/layout/placement.js +256 -0
- package/dist/layout/standalone.d.ts +8 -0
- package/dist/layout/standalone.js +50 -0
- package/dist/layout-cli.d.ts +1 -0
- package/dist/layout-cli.js +5 -0
- package/dist/layout-run.d.ts +9 -0
- package/dist/layout-run.js +105 -0
- package/dist/loader.d.ts +5 -0
- package/dist/loader.js +7 -0
- package/dist/namespace.d.ts +5 -0
- package/dist/namespace.js +5 -0
- package/dist/ontology.d.ts +19 -0
- package/dist/ontology.js +94 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.js +2 -0
- package/dist/render/geometry.d.ts +40 -0
- package/dist/render/geometry.js +81 -0
- package/dist/render/renderer.d.ts +31 -0
- package/dist/render/renderer.js +369 -0
- package/dist/render/symbols.d.ts +10 -0
- package/dist/render/symbols.js +26 -0
- package/dist/render/text.d.ts +20 -0
- package/dist/render/text.js +28 -0
- package/dist/render-cli.d.ts +1 -0
- package/dist/render-cli.js +7 -0
- package/dist/render-run.d.ts +9 -0
- package/dist/render-run.js +161 -0
- package/dist/render.d.ts +4 -0
- package/dist/render.js +4 -0
- package/dist/schema-overrides.d.ts +14 -0
- package/dist/schema-overrides.js +36 -0
- package/dist/schema-validate.d.ts +5 -0
- package/dist/schema-validate.js +8 -0
- package/dist/schema.d.ts +6 -0
- package/dist/schema.js +114 -0
- package/dist/shacl.d.ts +15 -0
- package/dist/shacl.js +37 -0
- package/dist/validate-cli.d.ts +1 -0
- package/dist/validate-cli.js +5 -0
- package/dist/validate-run.d.ts +8 -0
- package/dist/validate-run.js +58 -0
- package/dist/validate.d.ts +11 -0
- package/dist/validate.js +94 -0
- package/dist/versioning-cli.d.ts +1 -0
- package/dist/versioning-cli.js +18 -0
- package/dist/versioning.d.ts +17 -0
- package/dist/versioning.js +45 -0
- package/ontology/core.ttl +993 -0
- package/ontology/di.ttl +167 -0
- package/package.json +76 -4
- package/schema/bpmn-ld.schema.json +15230 -0
- package/shapes/core.shapes.ttl +398 -0
- package/skills/bpmn-ld/SKILL.md +154 -0
- package/skills/bpmn-ld/evals/models/order-approval-di.jsonld +296 -0
- package/skills/bpmn-ld/evals/models/refund-di.bpmn +82 -0
- package/skills/bpmn-ld/evals/models/refund.bpmn +18 -0
- package/skills/bpmn-ld/evals/outputs/explain-collaboration.md +22 -0
- package/skills/bpmn-ld/evals/outputs/explain-order-approval.md +24 -0
- package/skills/bpmn-ld/evals/outputs/explain-refund.md +17 -0
- package/skills/bpmn-ld/evals/outputs/generate-activity-compensation.jsonld +39 -0
- package/skills/bpmn-ld/evals/outputs/generate-ad-hoc-sub-process.jsonld +52 -0
- package/skills/bpmn-ld/evals/outputs/generate-boundary-event.jsonld +27 -0
- package/skills/bpmn-ld/evals/outputs/generate-collaboration.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-conditions.jsonld +93 -0
- package/skills/bpmn-ld/evals/outputs/generate-diagram-properties.jsonld +340 -0
- package/skills/bpmn-ld/evals/outputs/generate-error.jsonld +217 -0
- package/skills/bpmn-ld/evals/outputs/generate-escalation.jsonld +231 -0
- package/skills/bpmn-ld/evals/outputs/generate-event-definition-ref.jsonld +67 -0
- package/skills/bpmn-ld/evals/outputs/generate-event-sub-process.jsonld +54 -0
- package/skills/bpmn-ld/evals/outputs/generate-exclusive-choice.jsonld +32 -0
- package/skills/bpmn-ld/evals/outputs/generate-instantiating-gateway.jsonld +24 -0
- package/skills/bpmn-ld/evals/outputs/generate-lane-partition.jsonld +46 -0
- package/skills/bpmn-ld/evals/outputs/generate-link-event.expect.json +11 -0
- package/skills/bpmn-ld/evals/outputs/generate-link-event.jsonld +57 -0
- package/skills/bpmn-ld/evals/outputs/generate-loop.jsonld +30 -0
- package/skills/bpmn-ld/evals/outputs/generate-message.jsonld +61 -0
- package/skills/bpmn-ld/evals/outputs/generate-parallel-branches.jsonld +25 -0
- package/skills/bpmn-ld/evals/outputs/generate-process-attributes.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-script-task.jsonld +18 -0
- package/skills/bpmn-ld/evals/outputs/generate-signal.jsonld +178 -0
- package/skills/bpmn-ld/evals/outputs/generate-sub-process.jsonld +31 -0
- package/skills/bpmn-ld/evals/outputs/generate-targeted-compensation.jsonld +40 -0
- package/skills/bpmn-ld/evals/outputs/generate-task-implementation.jsonld +18 -0
- package/skills/bpmn-ld/evals/outputs/generate-task-message-references.jsonld +49 -0
- package/skills/bpmn-ld/evals/outputs/generate-transaction.jsonld +48 -0
- package/skills/bpmn-ld/evals/outputs/modify-order-approval.jsonld +376 -0
- package/skills/bpmn-ld/evals/outputs/modify-refund.jsonld +373 -0
- package/skills/bpmn-ld/evals/outputs/order-approval.jsonld +29 -0
- package/skills/bpmn-ld/evals/outputs/refine-order-approval.jsonld +377 -0
- package/skills/bpmn-ld/evals/prompts/explain-collaboration.md +3 -0
- package/skills/bpmn-ld/evals/prompts/explain-order-approval.md +3 -0
- package/skills/bpmn-ld/evals/prompts/explain-refund.md +3 -0
- package/skills/bpmn-ld/evals/prompts/generate-activity-compensation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-ad-hoc-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-boundary-event.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-collaboration.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-conditions.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-diagram-properties.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-error.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-escalation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-event-definition-ref.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-event-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-exclusive-choice.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-instantiating-gateway.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-lane-partition.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-link-event.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-loop.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-message.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-parallel-branches.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-process-attributes.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-script-task.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-signal.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-sub-process.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-targeted-compensation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-task-implementation.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-task-message-references.md +1 -0
- package/skills/bpmn-ld/evals/prompts/generate-transaction.md +1 -0
- package/skills/bpmn-ld/evals/prompts/modify-order-approval.md +4 -0
- package/skills/bpmn-ld/evals/prompts/modify-refund.md +4 -0
- package/skills/bpmn-ld/evals/prompts/order-approval.md +1 -0
- package/skills/bpmn-ld/evals/prompts/refine-order-approval.md +8 -0
- package/skills/bpmn-ld/examples/positive/activity-compensation.jsonld +39 -0
- package/skills/bpmn-ld/examples/positive/ad-hoc-sub-process.jsonld +52 -0
- package/skills/bpmn-ld/examples/positive/boundary-event.jsonld +27 -0
- package/skills/bpmn-ld/examples/positive/collaboration.jsonld +49 -0
- package/skills/bpmn-ld/examples/positive/conditions.jsonld +93 -0
- package/skills/bpmn-ld/examples/positive/diagram-properties.jsonld +340 -0
- package/skills/bpmn-ld/examples/positive/error.jsonld +208 -0
- package/skills/bpmn-ld/examples/positive/escalation.jsonld +231 -0
- package/skills/bpmn-ld/examples/positive/event-definition-ref.jsonld +142 -0
- package/skills/bpmn-ld/examples/positive/event-sub-process.jsonld +54 -0
- package/skills/bpmn-ld/examples/positive/exclusive-choice.jsonld +32 -0
- package/skills/bpmn-ld/examples/positive/instantiating-gateway.jsonld +24 -0
- package/skills/bpmn-ld/examples/positive/lane-partition.jsonld +46 -0
- package/skills/bpmn-ld/examples/positive/link-event.expect.json +10 -0
- package/skills/bpmn-ld/examples/positive/link-event.jsonld +138 -0
- package/skills/bpmn-ld/examples/positive/loop.jsonld +30 -0
- package/skills/bpmn-ld/examples/positive/message.jsonld +60 -0
- package/skills/bpmn-ld/examples/positive/order-approval.jsonld +29 -0
- package/skills/bpmn-ld/examples/positive/parallel-branches.jsonld +25 -0
- package/skills/bpmn-ld/examples/positive/process-attributes.jsonld +49 -0
- package/skills/bpmn-ld/examples/positive/script-task.jsonld +18 -0
- package/skills/bpmn-ld/examples/positive/signal.jsonld +150 -0
- package/skills/bpmn-ld/examples/positive/sub-process.jsonld +31 -0
- package/skills/bpmn-ld/examples/positive/targeted-compensation.jsonld +40 -0
- package/skills/bpmn-ld/examples/positive/task-implementation.jsonld +18 -0
- package/skills/bpmn-ld/examples/positive/task-message-references.jsonld +151 -0
- package/skills/bpmn-ld/examples/positive/transaction.jsonld +48 -0
- package/skills/bpmn-ld/references/clarification-and-refinement.md +60 -0
- package/skills/bpmn-ld/references/common-mistakes.md +110 -0
- package/skills/bpmn-ld/references/explain-and-document.md +36 -0
- package/skills/bpmn-ld/references/modify-existing-model.md +49 -0
- package/skills/bpmn-ld/references/patterns.md +292 -0
- package/skills/bpmn-ld/references/render-output.md +1 -0
- package/skills/bpmn-ld/references/rule-catalogue.md +183 -0
- package/skills/bpmn-ld/references/vocabulary-summary.md +65 -0
- package/skills/bpmn-ld/template.jsonld +14 -0
- package/templates/combined.jsonld +3 -0
- package/templates/core.jsonld +170 -0
- package/templates/core.shapes.ttl +398 -0
- package/templates/core.ttl +993 -0
- package/templates/di.jsonld +37 -0
- package/templates/di.ttl +167 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { BPMN_NAMESPACES, MODEL_NAMESPACE, XSI_NAMESPACE } from "./mapping.js";
|
|
2
|
+
import { loadContextTerms } from "./mapping-check.js";
|
|
3
|
+
const ATTRIBUTE_NAMESPACE = /^\{(.*)\}(.*)$/;
|
|
4
|
+
const ABSOLUTE_NAMESPACE = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
5
|
+
const GENERAL_DELIMITER = /[:/?#[\]@]$/;
|
|
6
|
+
const XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
|
|
7
|
+
const RESERVED_PREFIXES = ["xml", "xmlns", "xsi"];
|
|
8
|
+
const MIXED_CONTENT = "text content cannot be represented next to attributes or child elements";
|
|
9
|
+
export const isExtensionNamespace = (namespace) => ABSOLUTE_NAMESPACE.test(namespace) && !BPMN_NAMESPACES.includes(namespace) && namespace !== XSI_NAMESPACE && namespace !== XML_NAMESPACE;
|
|
10
|
+
const isIgnoredNamespace = (namespace) => namespace === XSI_NAMESPACE || namespace === XML_NAMESPACE;
|
|
11
|
+
export const isExtensionAttribute = (key) => {
|
|
12
|
+
const match = ATTRIBUTE_NAMESPACE.exec(key);
|
|
13
|
+
return match !== null && isExtensionNamespace(match[1]);
|
|
14
|
+
};
|
|
15
|
+
const walkDeclarations = (element, visit) => {
|
|
16
|
+
element.declarations.forEach(([prefix, namespace]) => visit(prefix, namespace));
|
|
17
|
+
element.children.forEach((child) => walkDeclarations(child, visit));
|
|
18
|
+
};
|
|
19
|
+
export class Prefixes {
|
|
20
|
+
hints = new Map();
|
|
21
|
+
declared = new Set();
|
|
22
|
+
terms = new Set(Object.keys(loadContextTerms()));
|
|
23
|
+
byNamespace = new Map();
|
|
24
|
+
byPrefix = new Map();
|
|
25
|
+
generated = 0;
|
|
26
|
+
constructor(root) {
|
|
27
|
+
walkDeclarations(root, (prefix, namespace) => {
|
|
28
|
+
this.declared.add(prefix);
|
|
29
|
+
if (prefix !== "")
|
|
30
|
+
this.hints.set(namespace, [...(this.hints.get(namespace) ?? []), prefix]);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
available(prefix) {
|
|
34
|
+
return !RESERVED_PREFIXES.includes(prefix) && !this.terms.has(prefix) && !this.byPrefix.has(prefix);
|
|
35
|
+
}
|
|
36
|
+
prefixFor(namespace) {
|
|
37
|
+
const known = this.byNamespace.get(namespace);
|
|
38
|
+
if (known !== undefined)
|
|
39
|
+
return known;
|
|
40
|
+
let prefix = (this.hints.get(namespace) ?? []).find((hint) => this.available(hint));
|
|
41
|
+
while (prefix === undefined) {
|
|
42
|
+
const candidate = `ns${++this.generated}`;
|
|
43
|
+
if (this.available(candidate) && !this.declared.has(candidate))
|
|
44
|
+
prefix = candidate;
|
|
45
|
+
}
|
|
46
|
+
this.byNamespace.set(namespace, prefix);
|
|
47
|
+
this.byPrefix.set(prefix, namespace);
|
|
48
|
+
return prefix;
|
|
49
|
+
}
|
|
50
|
+
context() {
|
|
51
|
+
return Object.fromEntries([...this.byPrefix].map(([prefix, namespace]) => [prefix, GENERAL_DELIMITER.test(namespace) ? namespace : { "@id": namespace, "@prefix": true }]));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const add = (target, name, value) => {
|
|
55
|
+
const existing = target[name];
|
|
56
|
+
target[name] = existing === undefined ? value : [...(Array.isArray(existing) ? existing : [existing]), value];
|
|
57
|
+
};
|
|
58
|
+
const addAttributes = (target, element, prefixes, unqualified) => {
|
|
59
|
+
for (const [key, value] of Object.entries(element.attributes)) {
|
|
60
|
+
const match = ATTRIBUTE_NAMESPACE.exec(key);
|
|
61
|
+
if (match) {
|
|
62
|
+
if (isExtensionNamespace(match[1]))
|
|
63
|
+
add(target, `${prefixes.prefixFor(match[1])}:${match[2]}`, value);
|
|
64
|
+
}
|
|
65
|
+
else if (unqualified)
|
|
66
|
+
add(target, `${prefixes.prefixFor(element.namespace)}:${key}`, value);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const addChildren = (target, element, prefixes) => {
|
|
70
|
+
for (const child of element.children) {
|
|
71
|
+
if (isExtensionNamespace(child.namespace))
|
|
72
|
+
add(target, `${prefixes.prefixFor(child.namespace)}:${child.name}`, valueOf(child, prefixes));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const valueOf = (element, prefixes) => {
|
|
76
|
+
const properties = {};
|
|
77
|
+
addAttributes(properties, element, prefixes, true);
|
|
78
|
+
addChildren(properties, element, prefixes);
|
|
79
|
+
return Object.keys(properties).length === 0 ? element.text : properties;
|
|
80
|
+
};
|
|
81
|
+
const containers = (element) => element.children.filter((child) => child.namespace === MODEL_NAMESPACE && child.name === "extensionElements");
|
|
82
|
+
export const extensionProperties = (element, prefixes) => {
|
|
83
|
+
const properties = {};
|
|
84
|
+
addAttributes(properties, element, prefixes, false);
|
|
85
|
+
for (const container of containers(element))
|
|
86
|
+
addChildren(properties, container, prefixes);
|
|
87
|
+
return properties;
|
|
88
|
+
};
|
|
89
|
+
const rejected = (child) => ({ kind: "foreign-namespace", construct: child.name, location: child.location });
|
|
90
|
+
const unrepresentable = (element) => {
|
|
91
|
+
const warnings = [];
|
|
92
|
+
const hasProperties = Object.keys(element.attributes).some((key) => !ATTRIBUTE_NAMESPACE.test(key) || isExtensionAttribute(key)) || element.children.some((child) => isExtensionNamespace(child.namespace));
|
|
93
|
+
if (hasProperties && element.text !== "")
|
|
94
|
+
warnings.push({ ...rejected(element), message: MIXED_CONTENT });
|
|
95
|
+
for (const key of Object.keys(element.attributes)) {
|
|
96
|
+
const match = ATTRIBUTE_NAMESPACE.exec(key);
|
|
97
|
+
if (match && !isExtensionNamespace(match[1]) && !isIgnoredNamespace(match[1])) {
|
|
98
|
+
warnings.push({ kind: "foreign-namespace", construct: `${element.name}@${match[2]}`, location: `${element.location}/@${match[2]}` });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [...warnings, ...element.children.flatMap((child) => (isExtensionNamespace(child.namespace) ? unrepresentable(child) : [rejected(child)]))];
|
|
102
|
+
};
|
|
103
|
+
export const extensionWarnings = (container) => container.children.flatMap((child) => (isExtensionNamespace(child.namespace) ? unrepresentable(child) : [rejected(child)]));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Store } from "n3";
|
|
2
|
+
import type { ElementMapping } from "./mapping.ts";
|
|
3
|
+
export interface MappingTables {
|
|
4
|
+
elements: Record<string, ElementMapping>;
|
|
5
|
+
containment: Record<string, Record<string, string>>;
|
|
6
|
+
}
|
|
7
|
+
export interface MappingProblem {
|
|
8
|
+
term: string;
|
|
9
|
+
kind: "class" | "property";
|
|
10
|
+
where: string;
|
|
11
|
+
reason: "not-in-context" | "not-in-ontology";
|
|
12
|
+
}
|
|
13
|
+
export declare const CONTEXT_FILES: string[];
|
|
14
|
+
export declare const loadContextTerms: () => Record<string, string>;
|
|
15
|
+
export declare const checkMapping: (tables: MappingTables, store: Store, context: Record<string, string>) => MappingProblem[];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { ROOT } from "../paths.js";
|
|
4
|
+
import { declaredClasses, declaredProperties } from "../ontology.js";
|
|
5
|
+
export const CONTEXT_FILES = ["contexts/core.jsonld", "contexts/di.jsonld"];
|
|
6
|
+
export const loadContextTerms = () => {
|
|
7
|
+
const raw = {};
|
|
8
|
+
for (const file of CONTEXT_FILES) {
|
|
9
|
+
Object.assign(raw, JSON.parse(readFileSync(join(ROOT, file), "utf8"))["@context"]);
|
|
10
|
+
}
|
|
11
|
+
const expand = (value) => {
|
|
12
|
+
const [prefix, local] = value.split(":");
|
|
13
|
+
const base = raw[prefix];
|
|
14
|
+
return typeof base === "string" && local !== undefined ? `${base}${local}` : value;
|
|
15
|
+
};
|
|
16
|
+
const terms = {};
|
|
17
|
+
for (const [term, entry] of Object.entries(raw)) {
|
|
18
|
+
const id = typeof entry === "string" ? entry : entry["@id"];
|
|
19
|
+
if (id !== undefined && !id.startsWith("@"))
|
|
20
|
+
terms[term] = expand(id);
|
|
21
|
+
}
|
|
22
|
+
return terms;
|
|
23
|
+
};
|
|
24
|
+
const usedTerms = (tables) => {
|
|
25
|
+
const used = [];
|
|
26
|
+
const property = (term, where) => used.push({ term, kind: "property", where });
|
|
27
|
+
for (const [element, mapping] of Object.entries(tables.elements)) {
|
|
28
|
+
used.push({ term: mapping.type, kind: "class", where: `${element}.type` });
|
|
29
|
+
for (const [attribute, term] of Object.entries(mapping.attributes)) {
|
|
30
|
+
if (attribute !== "id")
|
|
31
|
+
property(term, `${element}.attributes.${attribute}`);
|
|
32
|
+
}
|
|
33
|
+
for (const field of ["singles", "textChildren", "textLists"]) {
|
|
34
|
+
for (const [child, term] of Object.entries(mapping[field] ?? {}))
|
|
35
|
+
property(term, `${element}.${field}.${child}`);
|
|
36
|
+
}
|
|
37
|
+
for (const lookup of mapping.lookups ?? [])
|
|
38
|
+
property(lookup.term, `${element}.lookups.${lookup.attribute}`);
|
|
39
|
+
for (const term of mapping.booleans ?? [])
|
|
40
|
+
property(term, `${element}.booleans`);
|
|
41
|
+
for (const term of mapping.numbers ?? [])
|
|
42
|
+
property(term, `${element}.numbers`);
|
|
43
|
+
if (mapping.bodyTerm !== undefined)
|
|
44
|
+
property(mapping.bodyTerm, `${element}.bodyTerm`);
|
|
45
|
+
}
|
|
46
|
+
for (const [element, children] of Object.entries(tables.containment)) {
|
|
47
|
+
for (const [child, term] of Object.entries(children))
|
|
48
|
+
property(term, `containment.${element}.${child}`);
|
|
49
|
+
}
|
|
50
|
+
return used;
|
|
51
|
+
};
|
|
52
|
+
export const checkMapping = (tables, store, context) => {
|
|
53
|
+
const classes = declaredClasses(store);
|
|
54
|
+
const properties = declaredProperties(store);
|
|
55
|
+
const problems = [];
|
|
56
|
+
for (const { term, kind, where } of usedTerms(tables)) {
|
|
57
|
+
const iri = context[term];
|
|
58
|
+
if (iri === undefined) {
|
|
59
|
+
problems.push({ term, kind, where, reason: "not-in-context" });
|
|
60
|
+
}
|
|
61
|
+
else if (!(kind === "class" ? classes : properties).has(iri)) {
|
|
62
|
+
problems.push({ term, kind, where, reason: "not-in-ontology" });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return problems;
|
|
66
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const MODEL_NAMESPACE = "http://www.omg.org/spec/BPMN/20100524/MODEL";
|
|
2
|
+
export declare const DI_NAMESPACE = "http://www.omg.org/spec/BPMN/20100524/DI";
|
|
3
|
+
export declare const DC_NAMESPACE = "http://www.omg.org/spec/DD/20100524/DC";
|
|
4
|
+
export declare const DD_NAMESPACE = "http://www.omg.org/spec/DD/20100524/DI";
|
|
5
|
+
export declare const XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance";
|
|
6
|
+
export declare const BPMN_NAMESPACES: string[];
|
|
7
|
+
export declare const REFERENCE_ATTRIBUTES: string[];
|
|
8
|
+
export declare const REFERENCE_CHILDREN: string[];
|
|
9
|
+
export interface ElementMapping {
|
|
10
|
+
consumed?: string[];
|
|
11
|
+
type: string;
|
|
12
|
+
attributes: Record<string, string>;
|
|
13
|
+
booleans?: string[];
|
|
14
|
+
hashPrefixed?: string[];
|
|
15
|
+
numbers?: string[];
|
|
16
|
+
textChildren?: Record<string, string>;
|
|
17
|
+
textLists?: Record<string, string>;
|
|
18
|
+
lookups?: Lookup[];
|
|
19
|
+
bodyTerm?: string;
|
|
20
|
+
singles?: Record<string, string>;
|
|
21
|
+
anonymous?: boolean;
|
|
22
|
+
requiresBody?: boolean;
|
|
23
|
+
requiresChild?: string;
|
|
24
|
+
derivedChildIds?: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
export interface Lookup {
|
|
27
|
+
attribute: string;
|
|
28
|
+
root: string;
|
|
29
|
+
from: string;
|
|
30
|
+
term: string;
|
|
31
|
+
exportOnly?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare const ELEMENT_MAPPINGS: Record<string, ElementMapping>;
|
|
34
|
+
export declare const ELEMENT_NAMESPACES: Record<string, string>;
|
|
35
|
+
export declare const isEmptyRequired: (element: {
|
|
36
|
+
name: string;
|
|
37
|
+
text: string;
|
|
38
|
+
children: {
|
|
39
|
+
name: string;
|
|
40
|
+
}[];
|
|
41
|
+
}) => boolean;
|
|
42
|
+
export declare const concreteElement: <T extends {
|
|
43
|
+
namespace: string;
|
|
44
|
+
name: string;
|
|
45
|
+
attributes: Record<string, string>;
|
|
46
|
+
}>(element: T) => T;
|
|
47
|
+
export declare const isMapped: (element: {
|
|
48
|
+
namespace: string;
|
|
49
|
+
name: string;
|
|
50
|
+
}) => boolean;
|
|
51
|
+
export declare const CONTAINMENT: Record<string, Record<string, string>>;
|
|
52
|
+
export declare const ROOT_ELEMENTS: string[];
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
export const MODEL_NAMESPACE = "http://www.omg.org/spec/BPMN/20100524/MODEL";
|
|
2
|
+
export const DI_NAMESPACE = "http://www.omg.org/spec/BPMN/20100524/DI";
|
|
3
|
+
export const DC_NAMESPACE = "http://www.omg.org/spec/DD/20100524/DC";
|
|
4
|
+
export const DD_NAMESPACE = "http://www.omg.org/spec/DD/20100524/DI";
|
|
5
|
+
export const XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance";
|
|
6
|
+
export const BPMN_NAMESPACES = [MODEL_NAMESPACE, DI_NAMESPACE, DC_NAMESPACE, DD_NAMESPACE];
|
|
7
|
+
export const REFERENCE_ATTRIBUTES = [
|
|
8
|
+
"sourceRef",
|
|
9
|
+
"targetRef",
|
|
10
|
+
"attachedToRef",
|
|
11
|
+
"processRef",
|
|
12
|
+
"default",
|
|
13
|
+
"errorRef",
|
|
14
|
+
"activityRef",
|
|
15
|
+
"escalationRef",
|
|
16
|
+
"messageRef",
|
|
17
|
+
"operationRef",
|
|
18
|
+
"itemRef",
|
|
19
|
+
"signalRef",
|
|
20
|
+
"structureRef",
|
|
21
|
+
"evaluatesToTypeRef",
|
|
22
|
+
"partitionElementRef",
|
|
23
|
+
"bpmnElement",
|
|
24
|
+
"sourceElement",
|
|
25
|
+
"targetElement",
|
|
26
|
+
];
|
|
27
|
+
export const REFERENCE_CHILDREN = ["flowNodeRef", "operationRef", "source", "target", "eventDefinitionRef"];
|
|
28
|
+
const named = { id: "id", name: "name" };
|
|
29
|
+
const withDefault = { ...named, default: "default" };
|
|
30
|
+
const implementedTasks = ["businessRuleTask", "userTask"];
|
|
31
|
+
const tasks = ["manualTask", "receiveTask", "scriptTask", "sendTask", "serviceTask", ...implementedTasks];
|
|
32
|
+
const withImplementation = { ...withDefault, implementation: "implementation" };
|
|
33
|
+
const gateways = ["exclusiveGateway", "parallelGateway", "inclusiveGateway", "eventBasedGateway", "complexGateway"];
|
|
34
|
+
const defaultableGateways = ["exclusiveGateway", "inclusiveGateway", "complexGateway"];
|
|
35
|
+
const events = ["startEvent", "endEvent", "intermediateCatchEvent", "intermediateThrowEvent", "implicitThrowEvent", "boundaryEvent"];
|
|
36
|
+
const definitions = [
|
|
37
|
+
"message",
|
|
38
|
+
"timer",
|
|
39
|
+
"error",
|
|
40
|
+
"signal",
|
|
41
|
+
"escalation",
|
|
42
|
+
"conditional",
|
|
43
|
+
"link",
|
|
44
|
+
"compensate",
|
|
45
|
+
"cancel",
|
|
46
|
+
"terminate",
|
|
47
|
+
].map((kind) => `${kind}EventDefinition`);
|
|
48
|
+
const capitalize = (name) => name[0].toUpperCase() + name.slice(1);
|
|
49
|
+
const typed = (names, attributes = named, type) => Object.fromEntries(names.map((name) => [name, { type: type ?? capitalize(name), attributes }]));
|
|
50
|
+
const expression = {
|
|
51
|
+
type: "FormalExpression",
|
|
52
|
+
attributes: { language: "language", evaluatesToTypeRef: "evaluatesToTypeRef" },
|
|
53
|
+
consumed: [`{${XSI_NAMESPACE}}type`],
|
|
54
|
+
bodyTerm: "body",
|
|
55
|
+
anonymous: true,
|
|
56
|
+
requiresBody: true,
|
|
57
|
+
};
|
|
58
|
+
const eventReferences = { eventDefinitionRef: "eventDefinitionRef" };
|
|
59
|
+
export const ELEMENT_MAPPINGS = {
|
|
60
|
+
process: {
|
|
61
|
+
type: "Process",
|
|
62
|
+
attributes: { ...named, isExecutable: "isExecutable", processType: "processType", isClosed: "isClosed" },
|
|
63
|
+
booleans: ["isExecutable", "isClosed"],
|
|
64
|
+
},
|
|
65
|
+
subProcess: {
|
|
66
|
+
type: "SubProcess",
|
|
67
|
+
attributes: { ...withDefault, triggeredByEvent: "triggeredByEvent" },
|
|
68
|
+
booleans: ["triggeredByEvent"],
|
|
69
|
+
},
|
|
70
|
+
adHocSubProcess: {
|
|
71
|
+
type: "AdHocSubProcess",
|
|
72
|
+
attributes: { ...withDefault, triggeredByEvent: "triggeredByEvent", ordering: "ordering", cancelRemainingInstances: "cancelRemainingInstances" },
|
|
73
|
+
booleans: ["triggeredByEvent", "cancelRemainingInstances"],
|
|
74
|
+
singles: { completionCondition: "completionCondition" },
|
|
75
|
+
},
|
|
76
|
+
transaction: {
|
|
77
|
+
type: "Transaction",
|
|
78
|
+
attributes: { ...withDefault, triggeredByEvent: "triggeredByEvent", method: "method" },
|
|
79
|
+
booleans: ["triggeredByEvent"],
|
|
80
|
+
hashPrefixed: ["method"],
|
|
81
|
+
},
|
|
82
|
+
...typed(["laneSet", "childLaneSet"], { id: "id" }, "LaneSet"),
|
|
83
|
+
lane: {
|
|
84
|
+
type: "Lane",
|
|
85
|
+
attributes: { ...named, partitionElementRef: "partitionElementRef" },
|
|
86
|
+
textLists: { flowNodeRef: "flowNodeRef" },
|
|
87
|
+
singles: { childLaneSet: "childLaneSet", partitionElement: "partitionElement" },
|
|
88
|
+
},
|
|
89
|
+
collaboration: { type: "Collaboration", attributes: { ...named, isClosed: "isClosed" }, booleans: ["isClosed"] },
|
|
90
|
+
participant: { type: "Participant", attributes: { ...named, processRef: "processRef" } },
|
|
91
|
+
association: {
|
|
92
|
+
type: "Association",
|
|
93
|
+
attributes: { ...named, sourceRef: "sourceRef", targetRef: "targetRef", associationDirection: "associationDirection" },
|
|
94
|
+
},
|
|
95
|
+
messageFlow: {
|
|
96
|
+
type: "MessageFlow",
|
|
97
|
+
attributes: { ...named, sourceRef: "sourceRef", targetRef: "targetRef", messageRef: "messageRef" },
|
|
98
|
+
},
|
|
99
|
+
message: { type: "Message", attributes: { ...named, itemRef: "itemRef" } },
|
|
100
|
+
signal: { type: "Signal", attributes: { ...named, structureRef: "structureRef" } },
|
|
101
|
+
error: { type: "Error", attributes: { ...named, errorCode: "errorCode", structureRef: "structureRef" } },
|
|
102
|
+
escalation: { type: "Escalation", attributes: { ...named, escalationCode: "escalationCode", structureRef: "structureRef" } },
|
|
103
|
+
task: { type: "ManualTask", attributes: withDefault },
|
|
104
|
+
...typed(["manualTask"], withDefault),
|
|
105
|
+
...typed(implementedTasks, withImplementation),
|
|
106
|
+
scriptTask: {
|
|
107
|
+
type: "ScriptTask",
|
|
108
|
+
attributes: { ...withDefault, scriptFormat: "scriptFormat" },
|
|
109
|
+
textChildren: { script: "script" },
|
|
110
|
+
},
|
|
111
|
+
serviceTask: { type: "ServiceTask", attributes: { ...withImplementation, operationRef: "operationRef" } },
|
|
112
|
+
sendTask: { type: "SendTask", attributes: { ...withImplementation, messageRef: "messageRef", operationRef: "operationRef" } },
|
|
113
|
+
receiveTask: {
|
|
114
|
+
type: "ReceiveTask",
|
|
115
|
+
attributes: { ...withImplementation, instantiate: "instantiate", messageRef: "messageRef", operationRef: "operationRef" },
|
|
116
|
+
booleans: ["instantiate"],
|
|
117
|
+
},
|
|
118
|
+
...typed(events),
|
|
119
|
+
startEvent: {
|
|
120
|
+
type: "StartEvent",
|
|
121
|
+
attributes: { ...named, isInterrupting: "isInterrupting", parallelMultiple: "parallelMultiple" },
|
|
122
|
+
booleans: ["isInterrupting", "parallelMultiple"],
|
|
123
|
+
},
|
|
124
|
+
intermediateCatchEvent: {
|
|
125
|
+
type: "IntermediateCatchEvent",
|
|
126
|
+
attributes: { ...named, parallelMultiple: "parallelMultiple" },
|
|
127
|
+
booleans: ["parallelMultiple"],
|
|
128
|
+
},
|
|
129
|
+
...typed(gateways, { ...named, gatewayDirection: "gatewayDirection" }),
|
|
130
|
+
eventBasedGateway: {
|
|
131
|
+
type: "EventBasedGateway",
|
|
132
|
+
attributes: { ...named, gatewayDirection: "gatewayDirection", instantiate: "instantiate", eventGatewayType: "eventGatewayType" },
|
|
133
|
+
booleans: ["instantiate"],
|
|
134
|
+
},
|
|
135
|
+
...typed(defaultableGateways, { ...named, gatewayDirection: "gatewayDirection", default: "default" }),
|
|
136
|
+
complexGateway: {
|
|
137
|
+
type: "ComplexGateway",
|
|
138
|
+
attributes: { ...named, gatewayDirection: "gatewayDirection", default: "default" },
|
|
139
|
+
singles: { activationCondition: "activationCondition" },
|
|
140
|
+
},
|
|
141
|
+
...typed(definitions),
|
|
142
|
+
conditionalEventDefinition: {
|
|
143
|
+
type: "ConditionalEventDefinition",
|
|
144
|
+
attributes: named,
|
|
145
|
+
singles: { condition: "condition" },
|
|
146
|
+
},
|
|
147
|
+
messageEventDefinition: {
|
|
148
|
+
type: "MessageEventDefinition",
|
|
149
|
+
attributes: { ...named, messageRef: "messageRef" },
|
|
150
|
+
textChildren: { operationRef: "operationRef" },
|
|
151
|
+
},
|
|
152
|
+
linkEventDefinition: {
|
|
153
|
+
type: "LinkEventDefinition",
|
|
154
|
+
attributes: named,
|
|
155
|
+
textLists: { source: "source" },
|
|
156
|
+
textChildren: { target: "target" },
|
|
157
|
+
},
|
|
158
|
+
signalEventDefinition: { type: "SignalEventDefinition", attributes: { ...named, signalRef: "signalRef" } },
|
|
159
|
+
boundaryEvent: {
|
|
160
|
+
type: "BoundaryEvent",
|
|
161
|
+
attributes: { ...named, attachedToRef: "attachedToRef", cancelActivity: "cancelActivity", parallelMultiple: "parallelMultiple" },
|
|
162
|
+
booleans: ["cancelActivity", "parallelMultiple"],
|
|
163
|
+
},
|
|
164
|
+
timerEventDefinition: {
|
|
165
|
+
type: "TimerEventDefinition",
|
|
166
|
+
attributes: named,
|
|
167
|
+
textChildren: { timeDate: "timeDate", timeDuration: "timeDuration", timeCycle: "timeCycle" },
|
|
168
|
+
},
|
|
169
|
+
errorEventDefinition: {
|
|
170
|
+
type: "ErrorEventDefinition",
|
|
171
|
+
attributes: { ...named, errorRef: "errorRef" },
|
|
172
|
+
lookups: [{ attribute: "errorRef", root: "error", from: "errorCode", term: "errorCode", exportOnly: true }],
|
|
173
|
+
},
|
|
174
|
+
escalationEventDefinition: {
|
|
175
|
+
type: "EscalationEventDefinition",
|
|
176
|
+
attributes: { ...named, escalationRef: "escalationRef" },
|
|
177
|
+
lookups: [{ attribute: "escalationRef", root: "escalation", from: "escalationCode", term: "escalationCode", exportOnly: true }],
|
|
178
|
+
},
|
|
179
|
+
compensateEventDefinition: {
|
|
180
|
+
type: "CompensateEventDefinition",
|
|
181
|
+
attributes: { ...named, waitForCompletion: "waitForCompletion", activityRef: "activityRef" },
|
|
182
|
+
booleans: ["waitForCompletion"],
|
|
183
|
+
},
|
|
184
|
+
sequenceFlow: {
|
|
185
|
+
type: "SequenceFlow",
|
|
186
|
+
attributes: { ...named, sourceRef: "sourceRef", targetRef: "targetRef", isImmediate: "isImmediate" },
|
|
187
|
+
booleans: ["isImmediate"],
|
|
188
|
+
singles: { conditionExpression: "conditionExpression" },
|
|
189
|
+
},
|
|
190
|
+
conditionExpression: expression,
|
|
191
|
+
completionCondition: expression,
|
|
192
|
+
condition: expression,
|
|
193
|
+
activationCondition: expression,
|
|
194
|
+
};
|
|
195
|
+
const diagramInterchange = {
|
|
196
|
+
BPMNDiagram: { type: "BPMNDiagram", attributes: { id: "id", name: "name", resolution: "resolution" }, numbers: ["resolution"], singles: { BPMNPlane: "plane" }, derivedChildIds: { plane: "Plane_" } },
|
|
197
|
+
BPMNPlane: { type: "BPMNPlane", attributes: { id: "id", bpmnElement: "bpmnElement" } },
|
|
198
|
+
BPMNShape: {
|
|
199
|
+
type: "BPMNShape",
|
|
200
|
+
attributes: { id: "id", bpmnElement: "bpmnElement", isExpanded: "isExpanded", isHorizontal: "isHorizontal", isMarkerVisible: "isMarkerVisible", isMessageVisible: "isMessageVisible" },
|
|
201
|
+
booleans: ["isExpanded", "isHorizontal", "isMarkerVisible", "isMessageVisible"],
|
|
202
|
+
singles: { Bounds: "bounds", BPMNLabel: "label" },
|
|
203
|
+
},
|
|
204
|
+
BPMNEdge: {
|
|
205
|
+
type: "BPMNEdge",
|
|
206
|
+
attributes: { id: "id", bpmnElement: "bpmnElement", sourceElement: "sourceElement", targetElement: "targetElement", messageVisibleKind: "messageVisibleKind" },
|
|
207
|
+
singles: { BPMNLabel: "label" },
|
|
208
|
+
},
|
|
209
|
+
BPMNLabel: { type: "BPMNLabel", attributes: {}, singles: { Bounds: "bounds" }, anonymous: true, requiresChild: "Bounds" },
|
|
210
|
+
Bounds: {
|
|
211
|
+
type: "Bounds",
|
|
212
|
+
attributes: { x: "x", y: "y", width: "width", height: "height" },
|
|
213
|
+
numbers: ["x", "y", "width", "height"],
|
|
214
|
+
},
|
|
215
|
+
waypoint: { type: "Point", attributes: { x: "x", y: "y" }, numbers: ["x", "y"] },
|
|
216
|
+
};
|
|
217
|
+
Object.assign(ELEMENT_MAPPINGS, diagramInterchange);
|
|
218
|
+
for (const name of events) {
|
|
219
|
+
const mapping = ELEMENT_MAPPINGS[name];
|
|
220
|
+
ELEMENT_MAPPINGS[name] = { ...mapping, textLists: { ...mapping.textLists, ...eventReferences } };
|
|
221
|
+
}
|
|
222
|
+
const activityAttributes = { isForCompensation: "isForCompensation", startQuantity: "startQuantity", completionQuantity: "completionQuantity" };
|
|
223
|
+
for (const name of [...tasks, "task", "subProcess", "adHocSubProcess", "transaction"]) {
|
|
224
|
+
const mapping = ELEMENT_MAPPINGS[name];
|
|
225
|
+
ELEMENT_MAPPINGS[name] = {
|
|
226
|
+
...mapping,
|
|
227
|
+
attributes: { ...mapping.attributes, ...activityAttributes },
|
|
228
|
+
booleans: [...(mapping.booleans ?? []), "isForCompensation"],
|
|
229
|
+
numbers: [...(mapping.numbers ?? []), "startQuantity", "completionQuantity"],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export const ELEMENT_NAMESPACES = {
|
|
233
|
+
BPMNDiagram: DI_NAMESPACE,
|
|
234
|
+
BPMNPlane: DI_NAMESPACE,
|
|
235
|
+
BPMNShape: DI_NAMESPACE,
|
|
236
|
+
BPMNEdge: DI_NAMESPACE,
|
|
237
|
+
BPMNLabel: DI_NAMESPACE,
|
|
238
|
+
Bounds: DC_NAMESPACE,
|
|
239
|
+
waypoint: DD_NAMESPACE,
|
|
240
|
+
};
|
|
241
|
+
export const isEmptyRequired = (element) => {
|
|
242
|
+
const mapping = ELEMENT_MAPPINGS[element.name];
|
|
243
|
+
return ((mapping?.requiresBody === true && element.text === "") ||
|
|
244
|
+
(mapping?.requiresChild !== undefined && !element.children.some((child) => child.name === mapping.requiresChild)));
|
|
245
|
+
};
|
|
246
|
+
const XSI_TYPE = `{${XSI_NAMESPACE}}type`;
|
|
247
|
+
export const concreteElement = (element) => {
|
|
248
|
+
const declared = element.name === "partitionElement" && element.namespace === MODEL_NAMESPACE ? element.attributes[XSI_TYPE] : undefined;
|
|
249
|
+
const local = declared?.slice(declared.indexOf(":") + 1);
|
|
250
|
+
const name = local !== undefined && /^t[A-Z]/.test(local) ? local[1].toLowerCase() + local.slice(2) : undefined;
|
|
251
|
+
return name !== undefined && name in ELEMENT_MAPPINGS && ELEMENT_NAMESPACES[name] === undefined ? { ...element, name } : element;
|
|
252
|
+
};
|
|
253
|
+
export const isMapped = (element) => element.namespace === (ELEMENT_NAMESPACES[element.name] ?? MODEL_NAMESPACE) && element.name in ELEMENT_MAPPINGS;
|
|
254
|
+
const eventContainment = Object.fromEntries(definitions.map((name) => [name, "eventDefinitions"]));
|
|
255
|
+
const container = {
|
|
256
|
+
...Object.fromEntries([...tasks, "task", ...events, ...gateways, "subProcess", "adHocSubProcess", "transaction", "sequenceFlow"].map((name) => [name, "flowElements"])),
|
|
257
|
+
laneSet: "laneSets",
|
|
258
|
+
association: "artifacts",
|
|
259
|
+
};
|
|
260
|
+
const planeContainment = { BPMNShape: "planeElements", BPMNEdge: "planeElements" };
|
|
261
|
+
export const CONTAINMENT = {
|
|
262
|
+
process: container,
|
|
263
|
+
subProcess: container,
|
|
264
|
+
adHocSubProcess: container,
|
|
265
|
+
transaction: container,
|
|
266
|
+
collaboration: { participant: "participants", messageFlow: "messageFlows" },
|
|
267
|
+
BPMNPlane: planeContainment,
|
|
268
|
+
BPMNEdge: { waypoint: "waypoints" },
|
|
269
|
+
laneSet: { lane: "lanes" },
|
|
270
|
+
childLaneSet: { lane: "lanes" },
|
|
271
|
+
...Object.fromEntries(events.map((event) => [event, eventContainment])),
|
|
272
|
+
};
|
|
273
|
+
export const ROOT_ELEMENTS = ["message", "signal", "error", "escalation", ...definitions, "collaboration", "process", "BPMNDiagram"];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ConversionError } from "./errors.js";
|
|
2
|
+
import { BPMN_NAMESPACES } from "./mapping.js";
|
|
3
|
+
const BPMN_FAMILY = /^https?:\/\/(?:www\.|schema\.)?omg\.org\/(?:spec\/(?:BPMN|DD)\/\d|bpmn)/i;
|
|
4
|
+
const ATTRIBUTE_NAMESPACE = /^\{(.*)\}(.*)$/;
|
|
5
|
+
const isUnrecognisedBpmn = (namespace) => BPMN_FAMILY.test(namespace) && !BPMN_NAMESPACES.includes(namespace);
|
|
6
|
+
const reject = (namespace, construct, location) => {
|
|
7
|
+
throw new ConversionError("unrecognised-bpmn-namespace", `unrecognised BPMN namespace ${namespace} on ${construct} at ${location}; supported namespaces are ${BPMN_NAMESPACES.join(", ")}`);
|
|
8
|
+
};
|
|
9
|
+
export const assertSupportedNamespaces = (element) => {
|
|
10
|
+
if (isUnrecognisedBpmn(element.namespace))
|
|
11
|
+
reject(element.namespace, element.name, element.location);
|
|
12
|
+
for (const key of Object.keys(element.attributes)) {
|
|
13
|
+
const match = ATTRIBUTE_NAMESPACE.exec(key);
|
|
14
|
+
if (match && isUnrecognisedBpmn(match[1]))
|
|
15
|
+
reject(match[1], `${element.name}@${match[2]}`, `${element.location}/@${match[2]}`);
|
|
16
|
+
}
|
|
17
|
+
for (const child of element.children)
|
|
18
|
+
assertSupportedNamespaces(child);
|
|
19
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { ROOT } from "../paths.js";
|
|
5
|
+
import { compileSchema, validateWithSchema } from "../schema-validate.js";
|
|
6
|
+
import { validateShacl } from "../shacl.js";
|
|
7
|
+
import { validateExample } from "../validate.js";
|
|
8
|
+
export const validateConverted = async (document) => {
|
|
9
|
+
const errors = validateWithSchema(document, compileSchema()).map((e) => `schema: ${e}`);
|
|
10
|
+
const local = { ...document, "@context": [join(ROOT, "contexts/combined.jsonld"), document["@context"][1]] };
|
|
11
|
+
const directory = mkdtempSync(join(tmpdir(), "convert-"));
|
|
12
|
+
try {
|
|
13
|
+
const file = join(directory, "out.jsonld");
|
|
14
|
+
writeFileSync(file, JSON.stringify(local));
|
|
15
|
+
const structural = await validateExample(file);
|
|
16
|
+
errors.push(...structural.errors);
|
|
17
|
+
if (structural.valid) {
|
|
18
|
+
const shacl = await validateShacl(file);
|
|
19
|
+
shacl.violations.forEach((v) => errors.push(`shacl: ${v.focusNode} violates ${v.sourceShape}`));
|
|
20
|
+
if (!shacl.conforms && shacl.violations.length === 0)
|
|
21
|
+
errors.push("shacl: validation failed");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
rmSync(directory, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
return errors;
|
|
28
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type XmlElement } from "./xml-reader.ts";
|
|
2
|
+
export type WarningKind = "foreign-namespace" | "unsupported" | "dangling-reference";
|
|
3
|
+
export interface Warning {
|
|
4
|
+
kind: WarningKind;
|
|
5
|
+
construct: string;
|
|
6
|
+
location: string;
|
|
7
|
+
message?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const collectWarnings: (root: XmlElement) => Warning[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { BPMN_NAMESPACES, CONTAINMENT, concreteElement, ELEMENT_MAPPINGS, isEmptyRequired, isMapped, MODEL_NAMESPACE, REFERENCE_ATTRIBUTES, REFERENCE_CHILDREN, ROOT_ELEMENTS, XSI_NAMESPACE, } from "./mapping.js";
|
|
2
|
+
import { extensionWarnings, isExtensionAttribute } from "./extensions.js";
|
|
3
|
+
import { collectIds } from "./xml-reader.js";
|
|
4
|
+
const ATTRIBUTE_NAMESPACE = /^\{(.*)\}(.*)$/;
|
|
5
|
+
const XML_NAMESPACES = [XSI_NAMESPACE, "xml", "http://www.w3.org/XML/1998/namespace"];
|
|
6
|
+
const mappedAttributes = (element) => {
|
|
7
|
+
const mapping = isMapped(element) ? ELEMENT_MAPPINGS[element.name] : undefined;
|
|
8
|
+
return new Set([...Object.keys(mapping?.attributes ?? {}), ...(mapping?.consumed ?? []), ...(mapping?.lookups ?? []).map((lookup) => lookup.attribute)]);
|
|
9
|
+
};
|
|
10
|
+
const consumedRoots = new Set(Object.values(ELEMENT_MAPPINGS).flatMap((mapping) => (mapping.lookups ?? []).map((lookup) => lookup.root)));
|
|
11
|
+
const isHandledChild = (parent, child) => {
|
|
12
|
+
if (parent.name === "definitions")
|
|
13
|
+
return (isMapped(child) && ROOT_ELEMENTS.includes(child.name)) || (child.namespace === MODEL_NAMESPACE && consumedRoots.has(child.name));
|
|
14
|
+
const mapping = ELEMENT_MAPPINGS[parent.name];
|
|
15
|
+
if (child.namespace === MODEL_NAMESPACE && child.name === "extensionElements")
|
|
16
|
+
return true;
|
|
17
|
+
if (child.namespace === MODEL_NAMESPACE && (child.name in (mapping.textChildren ?? {}) || child.name in (mapping.textLists ?? {})))
|
|
18
|
+
return true;
|
|
19
|
+
return isMapped(concreteElement(child)) && (child.name in (mapping.singles ?? {}) || child.name in (CONTAINMENT[parent.name] ?? {}));
|
|
20
|
+
};
|
|
21
|
+
const attributeWarnings = (element, ids) => {
|
|
22
|
+
const allowed = mappedAttributes(element);
|
|
23
|
+
return Object.keys(element.attributes).flatMap((key) => {
|
|
24
|
+
if (allowed.has(key)) {
|
|
25
|
+
const dangling = REFERENCE_ATTRIBUTES.includes(key) && !ids.has(element.attributes[key]);
|
|
26
|
+
return dangling ? [{ kind: "dangling-reference", construct: `${element.name}@${key}`, location: `${element.location}/@${key}` }] : [];
|
|
27
|
+
}
|
|
28
|
+
if (isMapped(element) && isExtensionAttribute(key))
|
|
29
|
+
return [];
|
|
30
|
+
const foreign = ATTRIBUTE_NAMESPACE.exec(key);
|
|
31
|
+
if (foreign && XML_NAMESPACES.includes(foreign[1]))
|
|
32
|
+
return [];
|
|
33
|
+
const location = `${element.location}/@${foreign ? foreign[2] : key}`;
|
|
34
|
+
if (foreign)
|
|
35
|
+
return [{ kind: "foreign-namespace", construct: `${element.name}@${foreign[2]}`, location }];
|
|
36
|
+
return [{ kind: "unsupported", construct: `${element.name}@${key}`, location }];
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
const dropped = (element) => element.name === "extensionElements" && element.namespace === MODEL_NAMESPACE
|
|
40
|
+
? element.children.map((child) => ({ kind: "foreign-namespace", construct: child.name, location: child.location }))
|
|
41
|
+
: [
|
|
42
|
+
{
|
|
43
|
+
kind: BPMN_NAMESPACES.includes(element.namespace) ? "unsupported" : "foreign-namespace",
|
|
44
|
+
construct: element.name,
|
|
45
|
+
location: element.location,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
const childWarnings = (parent, child, ids) => {
|
|
49
|
+
if (!isHandledChild(parent, child))
|
|
50
|
+
return dropped(child);
|
|
51
|
+
if (isMapped(concreteElement(child)))
|
|
52
|
+
return walk(concreteElement(child), ids);
|
|
53
|
+
if (child.name === "extensionElements")
|
|
54
|
+
return extensionWarnings(child);
|
|
55
|
+
const dangling = REFERENCE_CHILDREN.includes(child.name) && !ids.has(child.text);
|
|
56
|
+
return dangling ? [{ kind: "dangling-reference", construct: child.name, location: child.location }] : [];
|
|
57
|
+
};
|
|
58
|
+
const lossyWarnings = (element) => {
|
|
59
|
+
const lossy = isMapped(element) && (element.name === "task" || isEmptyRequired(element));
|
|
60
|
+
return lossy ? [{ kind: "unsupported", construct: element.name, location: element.location }] : [];
|
|
61
|
+
};
|
|
62
|
+
const walk = (element, ids) => [
|
|
63
|
+
...lossyWarnings(element),
|
|
64
|
+
...attributeWarnings(element, ids),
|
|
65
|
+
...element.children.flatMap((child) => childWarnings(element, child, ids)),
|
|
66
|
+
];
|
|
67
|
+
export const collectWarnings = (root) => walk(root, collectIds(root));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface XmlElement {
|
|
2
|
+
namespace: string;
|
|
3
|
+
name: string;
|
|
4
|
+
attributes: Record<string, string>;
|
|
5
|
+
declarations: [string, string][];
|
|
6
|
+
children: XmlElement[];
|
|
7
|
+
text: string;
|
|
8
|
+
location: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const readXml: (xml: string) => XmlElement;
|
|
11
|
+
export declare const collectIds: (element: XmlElement, ids?: Set<string>) => Set<string>;
|