diff --git a/lib/features/modeling/Modeling.js b/lib/features/modeling/Modeling.js index aa841e52..93d43fc0 100644 --- a/lib/features/modeling/Modeling.js +++ b/lib/features/modeling/Modeling.js @@ -9,7 +9,8 @@ var UpdatePropertiesHandler = require('./cmd/UpdatePropertiesHandler'), AddLaneHandler = require('./cmd/AddLaneHandler'), SplitLaneHandler = require('./cmd/SplitLaneHandler'), ResizeLaneHandler = require('./cmd/ResizeLaneHandler'), - UpdateFlowNodeRefsHandler = require('./cmd/UpdateFlowNodeRefsHandler'); + UpdateFlowNodeRefsHandler = require('./cmd/UpdateFlowNodeRefsHandler'), + IdClaimHandler = require('./cmd/IdClaimHandler'); /** @@ -42,6 +43,7 @@ Modeling.prototype.getHandlers = function() { handlers['lane.resize'] = ResizeLaneHandler; handlers['lane.split'] = SplitLaneHandler; handlers['lane.updateRefs'] = UpdateFlowNodeRefsHandler; + handlers['id.updateClaim'] = IdClaimHandler; return handlers; }; @@ -145,3 +147,20 @@ Modeling.prototype.makeProcess = function() { this._commandStack.execute('canvas.updateRoot', context); }; + + +Modeling.prototype.claimId = function(id, moddleElement) { + this._commandStack.execute('id.updateClaim', { + id: id, + element: moddleElement, + claiming: true + }); +}; + + +Modeling.prototype.unclaimId = function(id, moddleElement) { + this._commandStack.execute('id.updateClaim', { + id: id, + element: moddleElement + }); +}; diff --git a/lib/features/modeling/behavior/UnclaimIdBehavior.js b/lib/features/modeling/behavior/UnclaimIdBehavior.js new file mode 100644 index 00000000..da097c89 --- /dev/null +++ b/lib/features/modeling/behavior/UnclaimIdBehavior.js @@ -0,0 +1,28 @@ +'use strict'; + +var forEach = require('lodash/collection/forEach'); + +var inherits = require('inherits'); + +var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); + +function UnclaimIdBehavior(eventBus, modeling) { + + CommandInterceptor.call(this, eventBus); + + this.preExecute('elements.delete', function(event) { + var context = event.context, + elements = context.elements; + + forEach(elements, function(element) { + modeling.unclaimId(element.businessObject.id, element.businessObject); + }); + + }); +} + +inherits(UnclaimIdBehavior, CommandInterceptor); + +UnclaimIdBehavior.$inject = [ 'eventBus', 'modeling' ]; + +module.exports = UnclaimIdBehavior; \ No newline at end of file diff --git a/lib/features/modeling/behavior/index.js b/lib/features/modeling/behavior/index.js index cb76e49d..190b42f3 100644 --- a/lib/features/modeling/behavior/index.js +++ b/lib/features/modeling/behavior/index.js @@ -15,7 +15,8 @@ module.exports = { 'resizeLaneBehavior', 'unsetDefaultFlowBehavior', 'updateFlowNodeRefsBehavior', - 'removeElementBehavior' + 'removeElementBehavior', + 'unclaimIdBehavior' ], appendBehavior: [ 'type', require('./AppendBehavior') ], createBoundaryEventBehavior: [ 'type', require('./CreateBoundaryEventBehavior') ], @@ -32,5 +33,6 @@ module.exports = { resizeLaneBehavior: [ 'type', require('./ResizeLaneBehavior') ], unsetDefaultFlowBehavior: [ 'type', require('./UnsetDefaultFlowBehavior') ], updateFlowNodeRefsBehavior: [ 'type', require('./UpdateFlowNodeRefsBehavior') ], - removeElementBehavior: [ 'type', require('./RemoveElementBehavior') ] + removeElementBehavior: [ 'type', require('./RemoveElementBehavior') ], + unclaimIdBehavior: [ 'type', require('./UnclaimIdBehavior') ] }; diff --git a/lib/features/modeling/cmd/IdClaimHandler.js b/lib/features/modeling/cmd/IdClaimHandler.js new file mode 100644 index 00000000..a0490199 --- /dev/null +++ b/lib/features/modeling/cmd/IdClaimHandler.js @@ -0,0 +1,41 @@ +'use strict'; + + +function IdClaimHandler(moddle) { + this._moddle = moddle; +} + +IdClaimHandler.$inject = [ 'moddle' ]; + +module.exports = IdClaimHandler; + + +IdClaimHandler.prototype.execute = function(context) { + var ids = this._moddle.ids, + id = context.id, + element = context.element, + claiming = context.claiming; + + if (claiming){ + ids.claim(id, element); + } else { + ids.unclaim(id); + } +}; + +/** + * Command revert implementation. + */ +IdClaimHandler.prototype.revert = function(context) { + var ids = this._moddle.ids, + id = context.id, + element = context.element, + claiming = context.claiming; + + if (claiming){ + ids.unclaim(id); + } else { + ids.claim(id, element); + } +}; + diff --git a/lib/features/modeling/cmd/UpdatePropertiesHandler.js b/lib/features/modeling/cmd/UpdatePropertiesHandler.js index 649e1388..43d8c9c5 100644 --- a/lib/features/modeling/cmd/UpdatePropertiesHandler.js +++ b/lib/features/modeling/cmd/UpdatePropertiesHandler.js @@ -65,6 +65,8 @@ UpdatePropertiesHandler.prototype.execute = function(context) { ids.unclaim(businessObject[ID]); elementRegistry.updateId(element, properties[ID]); + + ids.claim(properties[ID], businessObject); } // correctly indicate visual changes on default flow updates @@ -120,6 +122,8 @@ UpdatePropertiesHandler.prototype.revert = function(context) { ids.unclaim(properties[ID]); elementRegistry.updateId(element, oldProperties[ID]); + + ids.claim(oldProperties[ID], businessObject); } return context.changed; diff --git a/test/spec/features/modeling/IdClaimSpec.bpmn b/test/spec/features/modeling/IdClaimSpec.bpmn new file mode 100644 index 00000000..905a5e4d --- /dev/null +++ b/test/spec/features/modeling/IdClaimSpec.bpmn @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/spec/features/modeling/IdClaimSpec.js b/test/spec/features/modeling/IdClaimSpec.js new file mode 100644 index 00000000..39ffdf21 --- /dev/null +++ b/test/spec/features/modeling/IdClaimSpec.js @@ -0,0 +1,50 @@ +'use strict'; + +/* global bootstrapModeler, inject */ + +var modelingModule = require('../../../../lib/features/modeling'), + coreModule = require('../../../../lib/core'); + + +describe('features/modeling - id claim management', function() { + + var testModules = [ coreModule, modelingModule ]; + + var processDiagramXML = require('./IdClaimSpec.bpmn'); + + beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); + + var element, moddleElement, id; + + beforeEach(inject(function(elementRegistry, moddle) { + id = 'StartEvent_2'; + element = elementRegistry.get(id); + moddleElement = element.businessObject; + })); + + + describe('unclaim', function() { + + it('should unclaim id when removing element', inject(function(modeling, moddle) { + // when + modeling.removeElements([ element ]); + + // then + expect(moddle.ids.assigned(id)).to.be.false; + })); + + + it('should revert unclaim action on restoring element', inject(function(modeling, moddle, commandStack) { + // given + modeling.removeElements([ element ]); + + // when + commandStack.undo(); + + // then + expect(moddle.ids.assigned(id)).to.eql(moddleElement); + })); + + }); + +}); diff --git a/test/spec/features/modeling/UpdatePropertiesSpec.js b/test/spec/features/modeling/UpdatePropertiesSpec.js index 7ba983f9..7041813b 100644 --- a/test/spec/features/modeling/UpdatePropertiesSpec.js +++ b/test/spec/features/modeling/UpdatePropertiesSpec.js @@ -146,7 +146,7 @@ describe('features/modeling - update properties', function() { modeling.updateProperties(flowConnection, { id: 'FOO_BAR' }); // then - expect(ids.assigned('FOO_BAR')).to.exist; + expect(ids.assigned('FOO_BAR')).to.eql(flowConnection.businessObject); expect(ids.assigned('SequenceFlow_1')).to.be.false; expect(flowConnection.businessObject.id).to.equal('FOO_BAR'); @@ -275,7 +275,7 @@ describe('features/modeling - update properties', function() { // then expect(ids.assigned('FOO_BAR')).to.be.false; - expect(ids.assigned('SequenceFlow_1')).to.exist; + expect(ids.assigned('SequenceFlow_1')).to.eql(flowConnection.businessObject); expect(flowConnection.businessObject.id).to.equal('SequenceFlow_1'); expect(flowConnection.id).to.equal('SequenceFlow_1'); @@ -409,7 +409,7 @@ describe('features/modeling - update properties', function() { modeling.updateProperties(flowConnection, { id: 'SequenceFlow_1' }); // then - expect(ids.assigned('SequenceFlow_1')).to.exist; + expect(ids.assigned('SequenceFlow_1')).to.eql(flowConnection.businessObject); expect(flowConnection.businessObject.id).to.equal('SequenceFlow_1'); }));