From 82c93509a3f9b888a08ddb25c4e56e6f4540179e Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 11:43:49 +0200 Subject: [PATCH 1/7] feat: open BKM with encapsulated logic Related to #704 --- .../src/import/TableTreeWalker.js | 41 +++++---- .../test/helper/DecisionTableEditor.js | 9 +- .../test/helper/DecisionTableViewer.js | 9 +- .../test/spec/ViewerSpec.js | 6 ++ .../dmn-js-decision-table/test/spec/bkm.dmn | 88 +++++++++++++++++++ packages/dmn-js-shared/src/util/ModelUtil.js | 18 ++++ packages/dmn-js/src/Modeler.js | 16 ++-- packages/dmn-js/src/NavigatedViewer.js | 16 ++-- packages/dmn-js/src/Viewer.js | 16 ++-- 9 files changed, 161 insertions(+), 58 deletions(-) create mode 100644 packages/dmn-js-decision-table/test/spec/bkm.dmn diff --git a/packages/dmn-js-decision-table/src/import/TableTreeWalker.js b/packages/dmn-js-decision-table/src/import/TableTreeWalker.js index 90a9bc916..85e3aab22 100644 --- a/packages/dmn-js-decision-table/src/import/TableTreeWalker.js +++ b/packages/dmn-js-decision-table/src/import/TableTreeWalker.js @@ -1,3 +1,4 @@ +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; import { forEach } from 'min-dash'; import { elementToString } from './Util'; @@ -24,35 +25,33 @@ export default function TableTreeWalker(handler, options) { // Semantic handling ////////////////////// - function handleDecision(decision) { + function handleDMNElement(element) { + const table = getBoxedExpression(element); - if (!decision.id) { - decision.id = 'decision'; + if (!table) { + throw new Error(`no table for ${ elementToString(element) }`); } - const table = decision.decisionLogic; - - if (table) { - - if (!table.output) { - throw new Error(`missing output for ${ elementToString(table) }`); - } + handleDecisionTable(table); + } - const ctx = visitTable(table); + function handleDecisionTable(table) { - if (table.input) { - handleClauses(table.input, ctx, table); - } + if (!table.output) { + throw new Error(`missing output for ${ elementToString(table) }`); + } - handleClauses(table.output, ctx, table); + const ctx = visitTable(table); - // if any input or output clauses (columns) were added - // make sure that for each rule the according input/output entry is created - handleRules(table.rule, ctx, table); - } else { - throw new Error(`no table for ${ elementToString(decision) }`); + if (table.input) { + handleClauses(table.input, ctx, table); } + handleClauses(table.output, ctx, table); + + // if any input or output clauses (columns) were added + // make sure that for each rule the according input/output entry is created + handleRules(table.rule, ctx, table); } function handleClauses(clauses, context, definitions) { @@ -81,6 +80,6 @@ export default function TableTreeWalker(handler, options) { // API ////////////////////// return { - handleDecision: handleDecision + handleDecision: handleDMNElement }; } diff --git a/packages/dmn-js-decision-table/test/helper/DecisionTableEditor.js b/packages/dmn-js-decision-table/test/helper/DecisionTableEditor.js index abd1e7632..8e52c3bc4 100644 --- a/packages/dmn-js-decision-table/test/helper/DecisionTableEditor.js +++ b/packages/dmn-js-decision-table/test/helper/DecisionTableEditor.js @@ -1,4 +1,5 @@ import EditingManager from 'dmn-js-shared/lib/base/EditingManager'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import Editor from 'src/Editor'; @@ -12,11 +13,9 @@ export default class DecisionTableEditor extends EditingManager { id: 'decisionTable', constructor: Editor, opens(element) { - return ( - element.$type === 'dmn:Decision' && - element.decisionLogic && - element.decisionLogic.$type === 'dmn:DecisionTable' - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:DecisionTable'); } } ]; diff --git a/packages/dmn-js-decision-table/test/helper/DecisionTableViewer.js b/packages/dmn-js-decision-table/test/helper/DecisionTableViewer.js index 8a3ef0d45..89a69110c 100644 --- a/packages/dmn-js-decision-table/test/helper/DecisionTableViewer.js +++ b/packages/dmn-js-decision-table/test/helper/DecisionTableViewer.js @@ -1,4 +1,5 @@ import Manager from 'dmn-js-shared/lib/base/Manager'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import Viewer from 'src/Viewer'; @@ -12,11 +13,9 @@ export default class DecisionTableViewer extends Manager { id: 'decisionTable', constructor: Viewer, opens(element) { - return ( - element.$type === 'dmn:Decision' && - element.decisionLogic && - element.decisionLogic.$type === 'dmn:DecisionTable' - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:DecisionTable'); } } ]; diff --git a/packages/dmn-js-decision-table/test/spec/ViewerSpec.js b/packages/dmn-js-decision-table/test/spec/ViewerSpec.js index a91620818..e30d331f2 100644 --- a/packages/dmn-js-decision-table/test/spec/ViewerSpec.js +++ b/packages/dmn-js-decision-table/test/spec/ViewerSpec.js @@ -18,6 +18,7 @@ import { import simpleDiagramXML from './simple.dmn'; import complexDiagramXML from './complex.dmn'; +import bkmXML from './bkm.dmn'; describe('DecisionTable', function() { @@ -67,6 +68,11 @@ describe('DecisionTable', function() { }); + it('should open BKM', function() { + return createDecisionTable(bkmXML); + }); + + describe('#attachTo', function() { let decisionTableViewer; diff --git a/packages/dmn-js-decision-table/test/spec/bkm.dmn b/packages/dmn-js-decision-table/test/spec/bkm.dmn new file mode 100644 index 000000000..f6adb4259 --- /dev/null +++ b/packages/dmn-js-decision-table/test/spec/bkm.dmn @@ -0,0 +1,88 @@ + + + + + + + + status + + + "bronze","silver","gold" + + + + + sum + + + + + "ok","notok" + + + + + Bronze is really not that good + + "bronze" + + + + + + "notok" + + + "work on your status first, as bronze you're not going to get anything" + + + + Silver is actually quite okay + + "silver" + + + < 1000 + + + "ok" + + + "you little fish will get what you want" + + + + Same here + + "silver" + + + >= 1000 + + + "notok" + + + "you took too much man, you took too much!" + + + + Gold is really good, try even harder next time though + + "gold" + + + + + + "ok" + + + "you get anything you want" + + + + + + diff --git a/packages/dmn-js-shared/src/util/ModelUtil.js b/packages/dmn-js-shared/src/util/ModelUtil.js index 523afb630..b4f485ee6 100644 --- a/packages/dmn-js-shared/src/util/ModelUtil.js +++ b/packages/dmn-js-shared/src/util/ModelUtil.js @@ -60,3 +60,21 @@ export function isAny(element, types) { return is(element, t); }); } + +/** + * Return logic of a given decision or BKM. + * + * @param {ModdleElement} decisionOrBkm - the decision or business knowledge model + * @returns {ModdleElement|undefined} + */ +export function getBoxedExpression(decisionOrBkm) { + var bo = getBusinessObject(decisionOrBkm); + + if (is(bo, 'dmn:Decision')) { + return bo.get('decisionLogic'); + } else if (is(bo, 'dmn:BusinessKnowledgeModel')) { + var encapsulatedLogic = bo.get('encapsulatedLogic'); + + return encapsulatedLogic && encapsulatedLogic.get('body'); + } +} diff --git a/packages/dmn-js/src/Modeler.js b/packages/dmn-js/src/Modeler.js index 1786d252f..9d031fc61 100644 --- a/packages/dmn-js/src/Modeler.js +++ b/packages/dmn-js/src/Modeler.js @@ -4,7 +4,7 @@ import DrdModeler from 'dmn-js-drd/lib/Modeler'; import DecisionTableEditor from 'dmn-js-decision-table/lib/Editor'; import LiteralExpressionEditor from 'dmn-js-literal-expression/lib/Editor'; -import { is } from 'dmn-js-shared/lib/util/ModelUtil'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import { containsDi } from 'dmn-js-shared/lib/util/DiUtil'; import { find } from 'min-dash'; @@ -27,20 +27,18 @@ export default class Modeler extends EditingManager { id: 'decisionTable', constructor: DecisionTableEditor, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:DecisionTable') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:DecisionTable'); } }, { id: 'literalExpression', constructor: LiteralExpressionEditor, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:LiteralExpression') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; diff --git a/packages/dmn-js/src/NavigatedViewer.js b/packages/dmn-js/src/NavigatedViewer.js index 69321bb06..bb2e82e35 100644 --- a/packages/dmn-js/src/NavigatedViewer.js +++ b/packages/dmn-js/src/NavigatedViewer.js @@ -4,7 +4,7 @@ import DrdNavigatedViewer from 'dmn-js-drd/lib/NavigatedViewer'; import DecisionTableViewer from 'dmn-js-decision-table/lib/Viewer'; import LiteralExpressionViewer from 'dmn-js-literal-expression/lib/Viewer'; -import { is } from 'dmn-js-shared/lib/util/ModelUtil'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import { containsDi } from 'dmn-js-shared/lib/util/DiUtil'; @@ -27,20 +27,18 @@ export default class Viewer extends Manager { id: 'decisionTable', constructor: DecisionTableViewer, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:DecisionTable') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:DecisionTable'); } }, { id: 'literalExpression', constructor: LiteralExpressionViewer, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:LiteralExpression') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; diff --git a/packages/dmn-js/src/Viewer.js b/packages/dmn-js/src/Viewer.js index 13f4696c6..ebbc7800f 100644 --- a/packages/dmn-js/src/Viewer.js +++ b/packages/dmn-js/src/Viewer.js @@ -4,7 +4,7 @@ import DrdViewer from 'dmn-js-drd/lib/Viewer'; import DecisionTableViewer from 'dmn-js-decision-table/lib/Viewer'; import LiteralExpressionViewer from 'dmn-js-literal-expression/lib/Viewer'; -import { is } from 'dmn-js-shared/lib/util/ModelUtil'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import { containsDi } from 'dmn-js-shared/lib/util/DiUtil'; @@ -27,20 +27,18 @@ export default class Viewer extends Manager { id: 'decisionTable', constructor: DecisionTableViewer, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:DecisionTable') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:DecisionTable'); } }, { id: 'literalExpression', constructor: LiteralExpressionViewer, opens(element) { - return ( - is(element, 'dmn:Decision') && - is(element.decisionLogic, 'dmn:LiteralExpression') - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; From d9b31f06ac9ee127c2bbdff9df740148840d5e90 Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 15:44:06 +0200 Subject: [PATCH 2/7] feat(literal-expression): open BKM with encapsulated logic --- .../LiteralExpressionPropertiesComponent.js | 9 +++++---- ...teralExpressionPropertiesEditorComponent.js | 4 +++- .../src/features/modeling/Modeling.js | 5 +++-- .../textarea/components/TextareaComponent.js | 4 +++- .../components/TextareaEditorComponent.js | 3 ++- .../test/helper/LiteralExpressionEditor.js | 10 +++++----- .../test/helper/LiteralExpressionViewer.js | 10 +++++----- .../test/spec/EditorSpec.js | 5 +++++ .../test/spec/ViewerSpec.js | 6 ++++++ .../test/spec/bkm.dmn | 18 ++++++++++++++++++ 10 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 packages/dmn-js-literal-expression/test/spec/bkm.dmn diff --git a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesComponent.js b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesComponent.js index 454fe10fe..a01196d6e 100644 --- a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesComponent.js +++ b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesComponent.js @@ -1,5 +1,6 @@ import { Component } from 'inferno'; +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; export default class LiteralExpressionPropertiesComponent extends Component { constructor(props, context) { @@ -9,10 +10,10 @@ export default class LiteralExpressionPropertiesComponent extends Component { } render() { - const { - decisionLogic: literalExpression, - variable - } = this._viewer.getDecision(); + const decision = this._viewer.getDecision(); + + const literalExpression = getBoxedExpression(decision); + const variable = decision.variable; return (
diff --git a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js index 97e04c1d3..3b9d08aea 100644 --- a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js +++ b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js @@ -3,6 +3,8 @@ import { Component } from 'inferno'; import Input from 'dmn-js-shared/lib/components/Input'; import InputSelect from 'dmn-js-shared/lib/components/InputSelect'; +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; + export default class LiteralExpressionPropertiesComponent extends Component { constructor(props, context) { @@ -110,7 +112,7 @@ class ExpressionLanguage extends Component { _getExpressionLanguage() { const decision = this._viewer.getDecision(); - const literalExpression = decision.decisionLogic; + const literalExpression = getBoxedExpression(decision); return (literalExpression && literalExpression.expressionLanguage) ? literalExpression.expressionLanguage.toLowerCase() diff --git a/packages/dmn-js-literal-expression/src/features/modeling/Modeling.js b/packages/dmn-js-literal-expression/src/features/modeling/Modeling.js index 58d922f86..5286de7de 100644 --- a/packages/dmn-js-literal-expression/src/features/modeling/Modeling.js +++ b/packages/dmn-js-literal-expression/src/features/modeling/Modeling.js @@ -5,6 +5,7 @@ import { import UpdatePropertiesHandler from 'dmn-js-shared/lib/features/modeling/cmd/UpdatePropertiesHandler'; +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; export default class Modeling { @@ -62,7 +63,7 @@ export default class Modeling { editLiteralExpressionText(text) { const decision = this.getDecision(), - literalExpression = decision.decisionLogic; + literalExpression = getBoxedExpression(decision); const context = { element: literalExpression, @@ -76,7 +77,7 @@ export default class Modeling { editExpressionLanguage(expressionLanguage) { const decision = this.getDecision(), - literalExpression = decision.decisionLogic; + literalExpression = getBoxedExpression(decision); const context = { element: literalExpression, diff --git a/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaComponent.js b/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaComponent.js index f8edcd648..c2bd71cdb 100644 --- a/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaComponent.js +++ b/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaComponent.js @@ -1,5 +1,7 @@ import { Component } from 'inferno'; +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; + export default class TextareaComponent extends Component { constructor(props, context) { @@ -9,7 +11,7 @@ export default class TextareaComponent extends Component { } render() { - const { text } = this._viewer.getDecision().decisionLogic; + const { text } = getBoxedExpression(this._viewer.getDecision()); return (
diff --git a/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaEditorComponent.js b/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaEditorComponent.js index 4508b2fa3..f1b3e9658 100644 --- a/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaEditorComponent.js +++ b/packages/dmn-js-literal-expression/src/features/textarea/components/TextareaEditorComponent.js @@ -2,6 +2,7 @@ import { Component } from 'inferno'; import EditableComponent from 'dmn-js-shared/lib/components/EditableComponent'; +import { getBoxedExpression } from 'dmn-js-shared/lib/util/ModelUtil'; export default class TextareaEditorComponent extends Component { constructor(props, context) { @@ -21,7 +22,7 @@ export default class TextareaEditorComponent extends Component { } getLiteralExpression() { - return this._viewer.getDecision().decisionLogic; + return getBoxedExpression(this._viewer.getDecision()); } onElementsChanged() { diff --git a/packages/dmn-js-literal-expression/test/helper/LiteralExpressionEditor.js b/packages/dmn-js-literal-expression/test/helper/LiteralExpressionEditor.js index c4c89009c..fc10888c0 100644 --- a/packages/dmn-js-literal-expression/test/helper/LiteralExpressionEditor.js +++ b/packages/dmn-js-literal-expression/test/helper/LiteralExpressionEditor.js @@ -1,5 +1,7 @@ import EditingManager from 'dmn-js-shared/lib/base/EditingManager'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; + import Editor from 'src/Editor'; @@ -12,11 +14,9 @@ export default class LiteralExpressionEditor extends EditingManager { id: 'literalExpression', constructor: Editor, opens(element) { - return ( - element.$type === 'dmn:Decision' && - element.decisionLogic && - element.decisionLogic.$type === 'dmn:LiteralExpression' - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; diff --git a/packages/dmn-js-literal-expression/test/helper/LiteralExpressionViewer.js b/packages/dmn-js-literal-expression/test/helper/LiteralExpressionViewer.js index 532f339f0..f3a172a3b 100644 --- a/packages/dmn-js-literal-expression/test/helper/LiteralExpressionViewer.js +++ b/packages/dmn-js-literal-expression/test/helper/LiteralExpressionViewer.js @@ -1,5 +1,7 @@ import Manager from 'dmn-js-shared/lib/base/Manager'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; + import Viewer from 'src/Viewer'; @@ -12,11 +14,9 @@ export default class LiteralExpressionViewer extends Manager { id: 'literalExpression', constructor: Viewer, opens(element) { - return ( - element.$type === 'dmn:Decision' && - element.decisionLogic && - element.decisionLogic.$type === 'dmn:LiteralExpression' - ); + const boxedExpression = getBoxedExpression(element); + + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; diff --git a/packages/dmn-js-literal-expression/test/spec/EditorSpec.js b/packages/dmn-js-literal-expression/test/spec/EditorSpec.js index 3c2c195c5..2fc41c0e0 100644 --- a/packages/dmn-js-literal-expression/test/spec/EditorSpec.js +++ b/packages/dmn-js-literal-expression/test/spec/EditorSpec.js @@ -3,6 +3,7 @@ import TestContainer from 'mocha-test-container-support'; import DmnLiteralExpressionEditor from '../helper/LiteralExpressionEditor'; import simpleXML from './empty-literal-expression.dmn'; +import bkmXML from './bkm.dmn'; describe('Editor', function() { @@ -26,4 +27,8 @@ describe('Editor', function() { return createEditor(simpleXML); }); + + it('should open BKM', function() { + return createEditor(bkmXML); + }); }); diff --git a/packages/dmn-js-literal-expression/test/spec/ViewerSpec.js b/packages/dmn-js-literal-expression/test/spec/ViewerSpec.js index a811fb83e..9ce1d04f0 100644 --- a/packages/dmn-js-literal-expression/test/spec/ViewerSpec.js +++ b/packages/dmn-js-literal-expression/test/spec/ViewerSpec.js @@ -16,6 +16,7 @@ import DmnLiteralExpressionViewer from '../helper/LiteralExpressionViewer'; import { domify } from 'min-dom'; import simpleXML from './literal-expression.dmn'; +import bkmXML from './bkm.dmn'; describe('Viewer', function() { @@ -49,6 +50,11 @@ describe('Viewer', function() { }); + it('should open BKM', function() { + return createViewer(bkmXML); + }); + + describe('getDecision', function() { beforeEach(bootstrapViewer(simpleXML, { container: testContainer })); diff --git a/packages/dmn-js-literal-expression/test/spec/bkm.dmn b/packages/dmn-js-literal-expression/test/spec/bkm.dmn new file mode 100644 index 000000000..fac260e57 --- /dev/null +++ b/packages/dmn-js-literal-expression/test/spec/bkm.dmn @@ -0,0 +1,18 @@ + + + + + + + calendar.getSeason(date) + + + + + + + + + + + From 1f7e2b68bb30ba7954594925d78d77ac3596dc34 Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 15:50:54 +0200 Subject: [PATCH 3/7] test: verify BKM works in decision table editor --- packages/dmn-js-decision-table/test/spec/EditorSpec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/dmn-js-decision-table/test/spec/EditorSpec.js b/packages/dmn-js-decision-table/test/spec/EditorSpec.js index 1785a1d43..247af7e7b 100644 --- a/packages/dmn-js-decision-table/test/spec/EditorSpec.js +++ b/packages/dmn-js-decision-table/test/spec/EditorSpec.js @@ -4,6 +4,7 @@ import DmnDecisionTableEditor from '../helper/DecisionTableEditor'; import simpleDiagramXML from './simple.dmn'; import complexDiagramXML from './complex.dmn'; +import bkmXML from './bkm.dmn'; describe('DecisionTable', function() { @@ -48,4 +49,8 @@ describe('DecisionTable', function() { return createDecisionTableEditor(complexDiagramXML); }); + + it('should open BKM', function() { + return createDecisionTableEditor(bkmXML); + }); }); From c08c54584d8b59aa45c52bbe6d1507598847b252 Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 16:31:09 +0200 Subject: [PATCH 4/7] wip: replace --- .../popup-menu/ReplaceMenuProvider.js | 37 ++++++++++++++++--- .../src/features/replace/DrdReplace.js | 31 ++++++++++++++-- .../src/features/replace/ReplaceOptions.js | 32 ++++++++++++++++ 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/packages/dmn-js-drd/src/features/popup-menu/ReplaceMenuProvider.js b/packages/dmn-js-drd/src/features/popup-menu/ReplaceMenuProvider.js index d3b77a64f..552e6f3b6 100644 --- a/packages/dmn-js-drd/src/features/popup-menu/ReplaceMenuProvider.js +++ b/packages/dmn-js-drd/src/features/popup-menu/ReplaceMenuProvider.js @@ -1,4 +1,5 @@ import { + getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; @@ -56,26 +57,52 @@ ReplaceMenuProvider.prototype.getEntries = function(element) { var businessObject = element.businessObject; - var rules = this._rules; + var rules = this._rules, + options, + boxedExpression; if (!rules.allowed('shape.replace', { element: element })) { return []; } if (is(businessObject, 'dmn:Decision')) { + boxedExpression = getBoxedExpression(businessObject); - var options = filter(replaceOptions.DECISION, function(option) { + options = filter(replaceOptions.DECISION, function(option) { var notEmpty = ( option.actionName === 'replace-with-empty-decision' && - businessObject.decisionLogic + boxedExpression ); var notTable = ( option.actionName === 'replace-with-decision-table' && - !is(businessObject.decisionLogic, 'dmn:DecisionTable') + !is(boxedExpression, 'dmn:DecisionTable') ); var notExp = ( option.actionName === 'replace-with-literal-expression' && - !is(businessObject.decisionLogic, 'dmn:LiteralExpression') + !is(boxedExpression, 'dmn:LiteralExpression') + ); + + return notEmpty || notTable || notExp; + }); + + return this._createEntries(element, options); + } + + if (is(businessObject, 'dmn:BusinessKnowledgeModel')) { + boxedExpression = getBoxedExpression(businessObject); + + options = filter(replaceOptions.BKM, function(option) { + var notEmpty = ( + option.actionName === 'replace-with-empty' && + boxedExpression + ); + var notTable = ( + option.actionName === 'replace-with-decision-table' && + !is(boxedExpression, 'dmn:DecisionTable') + ); + var notExp = ( + option.actionName === 'replace-with-literal-expression' && + !is(boxedExpression, 'dmn:LiteralExpression') ); return notEmpty || notTable || notExp; diff --git a/packages/dmn-js-drd/src/features/replace/DrdReplace.js b/packages/dmn-js-drd/src/features/replace/DrdReplace.js index 03250a503..e94576972 100644 --- a/packages/dmn-js-drd/src/features/replace/DrdReplace.js +++ b/packages/dmn-js-drd/src/features/replace/DrdReplace.js @@ -1,3 +1,5 @@ +import { is } from 'dmn-js-shared/lib/util/ModelUtil'; + /** * This module takes care of replacing DRD elements */ @@ -34,7 +36,6 @@ export default function DrdReplace(drdFactory, replace, selection, modeling) { if (target.table) { var table = drdFactory.create('dmn:DecisionTable'); - newBusinessObject.decisionLogic = table; table.$parent = newBusinessObject; var output = drdFactory.create('dmn:OutputClause'); @@ -53,11 +54,15 @@ export default function DrdReplace(drdFactory, replace, selection, modeling) { inputExpression.$parent = input; table.input = [ input ]; + + setBoxedExpression(newBusinessObject, table, drdFactory); } if (target.expression) { - newBusinessObject.decisionLogic = drdFactory.create('dmn:LiteralExpression'); - newBusinessObject.variable = drdFactory.create('dmn:InformationItem'); + var literalExpression = drdFactory.create('dmn:LiteralExpression'), + variable = drdFactory.create('dmn:InformationItem'); + + setBoxedExpression(newBusinessObject, literalExpression, drdFactory, variable); } return replace.replaceElement(element, newElement, hints); @@ -72,3 +77,23 @@ DrdReplace.$inject = [ 'selection', 'modeling' ]; + +// helper ////////////////////////////////////////////////////////////// +function setBoxedExpression(bo, expression, drdFactory, variable) { + if (is(bo, 'dmn:Decision')) { + bo.decisionLogic = expression; + expression.$parent = bo; + } else if (is(bo, 'dmn:BusinessKnowledgeModel')) { + var encapsulatedLogic = drdFactory.create('dmn:FunctionDefinition', { + body: expression }); + + bo.encapsulatedLogic = expression; + encapsulatedLogic.$parent = bo; + expression.$parent = encapsulatedLogic; + } + + if (variable) { + bo.variable = variable; + variable.$parent = bo; + } +} \ No newline at end of file diff --git a/packages/dmn-js-drd/src/features/replace/ReplaceOptions.js b/packages/dmn-js-drd/src/features/replace/ReplaceOptions.js index 3ae6f1c6f..630e6e8f4 100644 --- a/packages/dmn-js-drd/src/features/replace/ReplaceOptions.js +++ b/packages/dmn-js-drd/src/features/replace/ReplaceOptions.js @@ -30,5 +30,37 @@ export default { expression: true } } + ], + BKM: [ + { + label: 'Empty', + actionName: 'replace-with-empty', + className: 'dmn-icon-clear', + target: { + type: 'dmn:BusinessKnowledgeModel', + table: false, + expression: false + } + }, + { + label: 'Decision Table', + actionName: 'replace-with-decision-table', + className: 'dmn-icon-decision-table', + target: { + type: 'dmn:BusinessKnowledgeModel', + table: true, + expression: false + } + }, + { + label: 'Literal Expression', + actionName: 'replace-with-literal-expression', + className: 'dmn-icon-literal-expression', + target: { + type: 'dmn:BusinessKnowledgeModel', + table: false, + expression: true + } + } ] }; From 63048ea79344e4049c9174c637612f5fbe2b142f Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 16:40:50 +0200 Subject: [PATCH 5/7] more wip --- .../src/features/drill-down/DrillDown.js | 16 +++++----------- .../src/features/replace/DrdReplace.js | 2 +- .../dmn-js-shared/src/base/EditingManager.js | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/dmn-js-drd/src/features/drill-down/DrillDown.js b/packages/dmn-js-drd/src/features/drill-down/DrillDown.js index ce338d45a..b4c4920f2 100644 --- a/packages/dmn-js-drd/src/features/drill-down/DrillDown.js +++ b/packages/dmn-js-drd/src/features/drill-down/DrillDown.js @@ -1,4 +1,4 @@ -import { is } from 'dmn-js-shared/lib/util/ModelUtil'; +import { getBoxedExpression, is } from 'dmn-js-shared/lib/util/ModelUtil'; import { domify, @@ -11,23 +11,17 @@ var PROVIDERS = [ { className: 'dmn-icon-decision-table', matches: function(el) { - var businessObject = el.businessObject; + var boxedExpression = getBoxedExpression(el); - return ( - is(businessObject, 'dmn:Decision') && - is(businessObject.decisionLogic, 'dmn:DecisionTable') - ); + return is(boxedExpression, 'dmn:DecisionTable'); } }, { className: 'dmn-icon-literal-expression', matches: function(el) { - var businessObject = el.businessObject; + var boxedExpression = getBoxedExpression(el); - return ( - is(businessObject, 'dmn:Decision') && - is(businessObject.decisionLogic, 'dmn:LiteralExpression') - ); + return is(boxedExpression, 'dmn:LiteralExpression'); } } ]; diff --git a/packages/dmn-js-drd/src/features/replace/DrdReplace.js b/packages/dmn-js-drd/src/features/replace/DrdReplace.js index e94576972..0540db471 100644 --- a/packages/dmn-js-drd/src/features/replace/DrdReplace.js +++ b/packages/dmn-js-drd/src/features/replace/DrdReplace.js @@ -87,7 +87,7 @@ function setBoxedExpression(bo, expression, drdFactory, variable) { var encapsulatedLogic = drdFactory.create('dmn:FunctionDefinition', { body: expression }); - bo.encapsulatedLogic = expression; + bo.encapsulatedLogic = encapsulatedLogic; encapsulatedLogic.$parent = bo; expression.$parent = encapsulatedLogic; } diff --git a/packages/dmn-js-shared/src/base/EditingManager.js b/packages/dmn-js-shared/src/base/EditingManager.js index a2e98ae07..e6b432238 100644 --- a/packages/dmn-js-shared/src/base/EditingManager.js +++ b/packages/dmn-js-shared/src/base/EditingManager.js @@ -27,7 +27,7 @@ export default class EditingManager extends Manager { viewer.on('elements.changed', ({ elements }) => { var viewsChanged = elements.some(function(e) { - return isAny(e, [ 'dmn:Decision', 'dmn:Definitions' ]); + return isAny(e, [ 'dmn:Decision', 'dmn:Definitions', 'dmn:BusinessKnowledgeModel' ]); }); if (viewsChanged) { From 15b15d7b87285da2ddad439a9dc23d35461e355b Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 17:03:56 +0200 Subject: [PATCH 6/7] wip: view drd --- .../src/features/view-drd/ViewDrd.js | 29 ++----------------- .../dmn-js-shared/src/base/EditingManager.js | 7 ++++- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/packages/dmn-js-decision-table/src/features/view-drd/ViewDrd.js b/packages/dmn-js-decision-table/src/features/view-drd/ViewDrd.js index c77083d2f..14a85c46b 100644 --- a/packages/dmn-js-decision-table/src/features/view-drd/ViewDrd.js +++ b/packages/dmn-js-decision-table/src/features/view-drd/ViewDrd.js @@ -3,7 +3,6 @@ import ViewDrdComponent from './components/ViewDrdComponent'; export default class ViewDrd { constructor(components, eventBus, injector, sheet) { this._injector = injector; - this._sheet = sheet; components.onGetComponent('table.before', () => { if (this.canViewDrd()) { @@ -14,9 +13,7 @@ export default class ViewDrd { eventBus.on('showDrd', () => { const parent = injector.get('_parent', false); - const root = sheet.getRoot(); - - const definitions = getDefinitions(root); + const definitions = parent.getDefinitions(); if (!definitions) { return; @@ -36,30 +33,10 @@ export default class ViewDrd { return false; } - const root = this._sheet.getRoot(); - - const definitions = getDefinitions(root); + const definitions = parent.getDefinitions(); return !!parent.getView(definitions); } } -ViewDrd.$inject = [ 'components', 'eventBus', 'injector', 'sheet' ]; - - -// helpers ////////////////////// - -function getDefinitions(root) { - const { businessObject } = root; - - // root might not have business object - if (!businessObject) { - return; - } - - const decision = businessObject.$parent; - - const definitions = decision.$parent; - - return definitions; -} \ No newline at end of file +ViewDrd.$inject = [ 'components', 'eventBus', 'injector' ]; diff --git a/packages/dmn-js-shared/src/base/EditingManager.js b/packages/dmn-js-shared/src/base/EditingManager.js index e6b432238..0aa56c1cf 100644 --- a/packages/dmn-js-shared/src/base/EditingManager.js +++ b/packages/dmn-js-shared/src/base/EditingManager.js @@ -4,6 +4,11 @@ import Ids from 'ids'; import { isAny } from '../util/ModelUtil'; +const VIEWABLE_ELEMENTS = [ + 'dmn:Decision', + 'dmn:Definitions', + 'dmn:BusinessKnowledgeModel' +]; export default class EditingManager extends Manager { @@ -27,7 +32,7 @@ export default class EditingManager extends Manager { viewer.on('elements.changed', ({ elements }) => { var viewsChanged = elements.some(function(e) { - return isAny(e, [ 'dmn:Decision', 'dmn:Definitions', 'dmn:BusinessKnowledgeModel' ]); + return isAny(e, VIEWABLE_ELEMENTS); }); if (viewsChanged) { From 7c674004e99553bc7fbfaad35af9977ba9c054f9 Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Mon, 4 Jul 2022 17:16:40 +0200 Subject: [PATCH 7/7] wip --- .../DecisionTablePropertiesEditorComponent.js | 14 +++++++++- .../src/features/modeling/Modeling.js | 26 ++++++++++++------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/packages/dmn-js-decision-table/src/features/decision-table-properties/components/DecisionTablePropertiesEditorComponent.js b/packages/dmn-js-decision-table/src/features/decision-table-properties/components/DecisionTablePropertiesEditorComponent.js index 2a92a7a8f..a5fa292bb 100644 --- a/packages/dmn-js-decision-table/src/features/decision-table-properties/components/DecisionTablePropertiesEditorComponent.js +++ b/packages/dmn-js-decision-table/src/features/decision-table-properties/components/DecisionTablePropertiesEditorComponent.js @@ -2,6 +2,8 @@ import { Component } from 'inferno'; import EditableComponent from 'dmn-js-shared/lib/components/EditableComponent'; +import { getBusinessObject, is } from 'dmn-js-shared/lib/util/ModelUtil'; + import { inject, mixin, @@ -40,7 +42,7 @@ export default class DecisionTablePropertiesComponent extends Component { } getBusinessObject() { - return this.sheet.getRoot().businessObject.$parent; + return getDMNElement(this.sheet.getRoot().businessObject.$parent); } onElementsChanged = () => { @@ -122,3 +124,13 @@ function NullComponent() { function resetScroll(event) { event.target.scroll(0, 0); } + +function getDMNElement(root) { + let parent = getBusinessObject(root).$parent; + + while (parent && !is(parent, 'dmn:DMNElement')) { + parent = parent.$parent; + } + + return parent; +} diff --git a/packages/dmn-js-decision-table/src/features/modeling/Modeling.js b/packages/dmn-js-decision-table/src/features/modeling/Modeling.js index 073365cac..46949c102 100644 --- a/packages/dmn-js-decision-table/src/features/modeling/Modeling.js +++ b/packages/dmn-js-decision-table/src/features/modeling/Modeling.js @@ -7,6 +7,8 @@ import UpdatePropertiesHandler from 'dmn-js-shared/lib/features/modeling/cmd/UpdatePropertiesHandler'; import IdClaimHandler from './cmd/IdClaimHandler'; +import { getBusinessObject, is } from 'dmn-js-shared/lib/util/ModelUtil'; + export default class Modeling extends BaseModeling { @@ -32,12 +34,10 @@ export default class Modeling extends BaseModeling { } editDecisionTableName(name) { - const root = this._sheet.getRoot(), - businessObject = root.businessObject, - parentBusinessObject = businessObject.$parent; + const parentElement = getDMNElement(this._sheet.getRoot()); const context = { - element: parentBusinessObject, + element: parentElement, properties: { name } @@ -47,12 +47,10 @@ export default class Modeling extends BaseModeling { } editDecisionTableId(id) { - const root = this._sheet.getRoot(), - businessObject = root.businessObject, - parentBusinessObject = businessObject.$parent; + const parentElement = getDMNElement(this._sheet.getRoot()); const context = { - element: parentBusinessObject, + element: parentElement, properties: { id } @@ -189,4 +187,14 @@ export default class Modeling extends BaseModeling { } } -Modeling.$inject = [ 'eventBus', 'elementFactory', 'commandStack', 'sheet' ]; \ No newline at end of file +Modeling.$inject = [ 'eventBus', 'elementFactory', 'commandStack', 'sheet' ]; + +function getDMNElement(root) { + let parent = getBusinessObject(root).$parent; + + while (parent && !is(parent, 'dmn:DMNElement')) { + parent = parent.$parent; + } + + return parent; +}