From b233ab957cd62aa253c863ff992027f024cd0c72 Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Mon, 27 Apr 2015 16:50:09 +0200 Subject: [PATCH] feat(snapping): add bpmn-specific move snapping This commit adds message flow + collaboration specific snapping by subclassing the diagram-js provided default Snapping implementation. * Add collaboration snapping * Rename lib/util/{Name}.js -> lib/util/{Name}Util.js Closes #255 --- lib/Modeler.js | 1 - lib/draw/BpmnRenderer.js | 4 +- .../label-editing/LabelEditingProvider.js | 29 ++-- lib/features/modeling/BpmnLayouter.js | 2 +- lib/features/modeling/BpmnUpdater.js | 34 ++-- lib/features/modeling/ElementFactory.js | 2 +- lib/features/modeling/LabelSupport.js | 2 +- lib/features/modeling/ModelingUtil.js | 24 +-- .../modeling/behavior/CreateBehavior.js | 4 +- .../modeling/behavior/DropBehavior.js | 2 +- .../modeling/behavior/RemoveBehavior.js | 5 +- lib/features/modeling/rules/BpmnRules.js | 10 +- lib/features/snapping/BpmnSnapping.js | 150 ++++++++++++++++-- lib/features/snapping/index.js | 4 +- lib/import/BpmnImporter.js | 4 +- lib/util/Di.js | 16 -- lib/util/DiUtil.js | 21 +++ lib/util/{Label.js => LabelUtil.js} | 0 lib/util/ModelUtil.js | 31 ++++ .../spec/features/modeling/AppendShapeSpec.js | 2 +- .../modeling/behavior/DropBehaviorSpec.js | 2 +- 21 files changed, 235 insertions(+), 114 deletions(-) delete mode 100644 lib/util/Di.js create mode 100644 lib/util/DiUtil.js rename lib/util/{Label.js => LabelUtil.js} (100%) create mode 100644 lib/util/ModelUtil.js diff --git a/lib/Modeler.js b/lib/Modeler.js index 507c52a5..8f78accb 100644 --- a/lib/Modeler.js +++ b/lib/Modeler.js @@ -64,7 +64,6 @@ Modeler.prototype._interactionModules = [ Modeler.prototype._modelingModules = [ // modeling components require('diagram-js/lib/features/keyboard'), - require('diagram-js/lib/features/snapping'), require('diagram-js/lib/features/move'), require('diagram-js/lib/features/bendpoints'), require('diagram-js/lib/features/resize'), diff --git a/lib/draw/BpmnRenderer.js b/lib/draw/BpmnRenderer.js index bbe20ff8..40077f89 100644 --- a/lib/draw/BpmnRenderer.js +++ b/lib/draw/BpmnRenderer.js @@ -11,7 +11,7 @@ var inherits = require('inherits'), var DefaultRenderer = require('diagram-js/lib/draw/Renderer'), TextUtil = require('diagram-js/lib/util/Text'), - DiUtil = require('../util/Di'); + DiUtil = require('../util/DiUtil'); var createLine = DefaultRenderer.createLine; @@ -869,7 +869,7 @@ function BpmnRenderer(events, styles, pathMap) { var lane = renderer('bpmn:Lane')(p, element); - var expandedPool = DiUtil.isExpandedPool(getSemantic(element)); + var expandedPool = DiUtil.isExpanded(element); if (expandedPool) { drawLine(p, [ diff --git a/lib/features/label-editing/LabelEditingProvider.js b/lib/features/label-editing/LabelEditingProvider.js index 956bc06c..c046ff56 100644 --- a/lib/features/label-editing/LabelEditingProvider.js +++ b/lib/features/label-editing/LabelEditingProvider.js @@ -2,8 +2,10 @@ var UpdateLabelHandler = require('./cmd/UpdateLabelHandler'); -var LabelUtil = require('./LabelUtil'), - DiUtil = require('../../util/Di'); +var LabelUtil = require('./LabelUtil'); + +var is = require('../../util/ModelUtil').is, + isExpanded = require('../../util/DiUtil').isExpanded; var MIN_BOUNDS = { @@ -46,11 +48,14 @@ function LabelEditingProvider(eventBus, canvas, directEditing, commandStack, inj eventBus.on('create.end', 500, function(e) { var element = e.shape, - businessObject = element.businessObject; + canExecute = e.context.canExecute; - if (businessObject.$instanceOf('bpmn:Task') || - businessObject.$instanceOf('bpmn:TextAnnotation') || - (businessObject.$instanceOf('bpmn:SubProcess') && !businessObject.di.isExpanded)) { + if (!canExecute) { + return; + } + + if (is(element, 'bpmn:Task') || is(element, 'bpmn:TextAnnotation') || + (is(element, 'bpmn:SubProcess') && !isExpanded(element))) { directEditing.activate(element); } @@ -68,9 +73,6 @@ module.exports = LabelEditingProvider; LabelEditingProvider.prototype.activate = function(element) { - var semantic = element.businessObject, - di = semantic.di; - var text = LabelUtil.getLabel(element); if (text === undefined) { @@ -79,9 +81,8 @@ LabelEditingProvider.prototype.activate = function(element) { var bbox = this.getEditingBBox(element); - // adjust for expanded pools / lanes - if ((semantic.$instanceOf('bpmn:Participant') && DiUtil.isExpandedPool(semantic)) || - semantic.$instanceOf('bpmn:Lane')) { + // adjust for expanded pools AND lanes + if ((is(element, 'bpmn:Participant') && isExpanded(element)) || is(element, 'bpmn:Lane')) { bbox.width = MIN_BOUNDS.width; bbox.height = MIN_BOUNDS.height; @@ -90,8 +91,8 @@ LabelEditingProvider.prototype.activate = function(element) { bbox.y = bbox.mid.y - bbox.height / 2; } - // adjust for sub processes - if (semantic.$instanceOf('bpmn:SubProcess') && DiUtil.isExpanded(semantic, di)) { + // adjust for expanded sub processes + if (is(element, 'bpmn:SubProcess') && isExpanded(element)) { bbox.height = MIN_BOUNDS.height; diff --git a/lib/features/modeling/BpmnLayouter.js b/lib/features/modeling/BpmnLayouter.js index 7f50fae7..ecbf0507 100644 --- a/lib/features/modeling/BpmnLayouter.js +++ b/lib/features/modeling/BpmnLayouter.js @@ -8,7 +8,7 @@ var BaseLayouter = require('diagram-js/lib/layout/BaseLayouter'), LayoutUtil = require('diagram-js/lib/layout/LayoutUtil'), ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout'); -var is = require('./ModelingUtil').is; +var is = require('../../util/ModelUtil').is; function BpmnLayouter() {} diff --git a/lib/features/modeling/BpmnUpdater.js b/lib/features/modeling/BpmnUpdater.js index b73bf175..29893111 100644 --- a/lib/features/modeling/BpmnUpdater.js +++ b/lib/features/modeling/BpmnUpdater.js @@ -1,12 +1,13 @@ 'use strict'; -var isArray = require('lodash/lang/isArray'), - assign = require('lodash/object/assign'), - forEach = require('lodash/collection/forEach'); +var assign = require('lodash/object/assign'), + inherits = require('inherits'); var Collections = require('diagram-js/lib/util/Collections'), Model = require('diagram-js/lib/model'); +var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); + /** * A handler responsible for updating the underlying BPMN 2.0 XML + DI @@ -14,7 +15,8 @@ var Collections = require('diagram-js/lib/util/Collections'), */ function BpmnUpdater(eventBus, bpmnFactory, connectionDocking) { - this._eventBus = eventBus; + CommandInterceptor.call(this, eventBus); + this._bpmnFactory = bpmnFactory; var self = this; @@ -122,6 +124,8 @@ function BpmnUpdater(eventBus, bpmnFactory, connectionDocking) { ], updateConnectionWaypoints); } +inherits(BpmnUpdater, CommandInterceptor); + module.exports = BpmnUpdater; BpmnUpdater.$inject = [ 'eventBus', 'bpmnFactory', 'connectionDocking']; @@ -330,24 +334,4 @@ BpmnUpdater.prototype._getLabel = function(di) { } return di.label; -}; - -BpmnUpdater.prototype.pre = function(commands, callback) { - this.on(commands, 'preExecute', callback); -}; - -BpmnUpdater.prototype.executed = function(commands, callback) { - this.on(commands, 'executed', callback); -}; - -BpmnUpdater.prototype.reverted = function(commands, callback) { - this.on(commands, 'reverted', callback); -}; - -BpmnUpdater.prototype.on = function(commands, suffix, callback) { - commands = isArray(commands) ? commands : [ commands ]; - - forEach(commands, function(c) { - this._eventBus.on('commandStack.' + c + '.' + suffix, callback); - }, this); -}; +}; \ No newline at end of file diff --git a/lib/features/modeling/ElementFactory.js b/lib/features/modeling/ElementFactory.js index 8387acc5..b074b5d3 100644 --- a/lib/features/modeling/ElementFactory.js +++ b/lib/features/modeling/ElementFactory.js @@ -4,7 +4,7 @@ var assign = require('lodash/object/assign'), inherits = require('inherits'); var BaseElementFactory = require('diagram-js/lib/core/ElementFactory'), - LabelUtil = require('../../util/Label'); + LabelUtil = require('../../util/LabelUtil'); /** diff --git a/lib/features/modeling/LabelSupport.js b/lib/features/modeling/LabelSupport.js index d4a913c0..dd6bf489 100644 --- a/lib/features/modeling/LabelSupport.js +++ b/lib/features/modeling/LabelSupport.js @@ -3,7 +3,7 @@ var assign = require('lodash/object/assign'), forEach = require('lodash/collection/forEach'); -var LabelUtil = require('../../util/Label'); +var LabelUtil = require('../../util/LabelUtil'); var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelMid = LabelUtil.getExternalLabelMid; diff --git a/lib/features/modeling/ModelingUtil.js b/lib/features/modeling/ModelingUtil.js index 426a8d59..7aeac50e 100644 --- a/lib/features/modeling/ModelingUtil.js +++ b/lib/features/modeling/ModelingUtil.js @@ -31,26 +31,4 @@ function getSharedParent(a, b) { }); } -module.exports.getSharedParent = getSharedParent; - -/** - * Is an element of the given BPMN type? - * - * @param {djs.model.Base|ModdleElement} element - * @param {String} type - * @return {Boolean} - */ -function is(element, type) { - var bo = getBusinessObject(element); - - return bo && bo.$instanceOf(type); -} - -module.exports.is = is; - - -function getBusinessObject(element) { - return (element && element.businessObject) || element; -} - -module.exports.getBusinessObject = getBusinessObject; \ No newline at end of file +module.exports.getSharedParent = getSharedParent; \ No newline at end of file diff --git a/lib/features/modeling/behavior/CreateBehavior.js b/lib/features/modeling/behavior/CreateBehavior.js index f574d29e..0db1e246 100644 --- a/lib/features/modeling/behavior/CreateBehavior.js +++ b/lib/features/modeling/behavior/CreateBehavior.js @@ -4,6 +4,7 @@ var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); +var is = require('../../../util/ModelUtil').is; /** * BPMN specific create behavior @@ -24,8 +25,7 @@ function CreateBehavior(eventBus, modeling) { shape = context.shape, position = context.position; - if (parent.businessObject.$instanceOf('bpmn:Process') && - shape.businessObject.$instanceOf('bpmn:Participant')) { + if (is(parent, 'bpmn:Process') && is(shape, 'bpmn:Participant')) { // this is going to detach the process root // and set the returned collaboration element diff --git a/lib/features/modeling/behavior/DropBehavior.js b/lib/features/modeling/behavior/DropBehavior.js index bbbae2e6..1a80dfdf 100644 --- a/lib/features/modeling/behavior/DropBehavior.js +++ b/lib/features/modeling/behavior/DropBehavior.js @@ -5,7 +5,7 @@ var forEach = require('lodash/collection/forEach'), var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); -var is = require('../ModelingUtil').is, +var is = require('../../../util/ModelUtil').is, getSharedParent = require('../ModelingUtil').getSharedParent; diff --git a/lib/features/modeling/behavior/RemoveBehavior.js b/lib/features/modeling/behavior/RemoveBehavior.js index 99491d8c..f8a8455f 100644 --- a/lib/features/modeling/behavior/RemoveBehavior.js +++ b/lib/features/modeling/behavior/RemoveBehavior.js @@ -4,6 +4,9 @@ var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); +var is = require('../../../util/ModelUtil').is; + + /** * BPMN specific remove behavior */ @@ -24,7 +27,7 @@ function RemoveBehavior(eventBus, modeling) { // activate the behavior if the shape to be removed // is a participant - if (shape.businessObject.$instanceOf('bpmn:Participant')) { + if (is(shape, 'bpmn:Participant')) { context.collaborationRoot = parent; } }, true); diff --git a/lib/features/modeling/rules/BpmnRules.js b/lib/features/modeling/rules/BpmnRules.js index 836b6563..7f721cb7 100644 --- a/lib/features/modeling/rules/BpmnRules.js +++ b/lib/features/modeling/rules/BpmnRules.js @@ -6,8 +6,9 @@ var groupBy = require('lodash/collection/groupBy'), inherits = require('inherits'); var getParents = require('../ModelingUtil').getParents, - is = require('../ModelingUtil').is, - getBusinessObject = require('../ModelingUtil').getBusinessObject; + is = require('../../../util/ModelUtil').is, + getBusinessObject = require('../../../util/ModelUtil').getBusinessObject, + isExpanded = require('../../../util/DiUtil').isExpanded; var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider'); @@ -164,11 +165,6 @@ function getScopeParent(element) { return bo; } -function isExpanded(element) { - var bo = getBusinessObject(element); - return bo.di.isExpanded; -} - function isSameScope(a, b) { var scopeParentA = getScopeParent(a), scopeParentB = getScopeParent(b); diff --git a/lib/features/snapping/BpmnSnapping.js b/lib/features/snapping/BpmnSnapping.js index 685937a2..a630ea5a 100644 --- a/lib/features/snapping/BpmnSnapping.js +++ b/lib/features/snapping/BpmnSnapping.js @@ -1,7 +1,23 @@ 'use strict'; +var inherits = require('inherits'); + +var forEach = require('lodash/collection/forEach'); + var getBoundingBox = require('diagram-js/lib/util/Elements').getBBox; +var Snapping = require('diagram-js/lib/features/snapping/Snapping'), + SnapUtil = require('diagram-js/lib/features/snapping/SnapUtil'); + +var is = require('../../util/ModelUtil').is; + +var mid = SnapUtil.mid, + topLeft = SnapUtil.topLeft, + bottomRight = SnapUtil.bottomRight; + +var round = Math.round; + + /** * BPMN specific snapping functionality * @@ -13,8 +29,12 @@ var getBoundingBox = require('diagram-js/lib/util/Elements').getBBox; */ function BpmnSnapping(eventBus, canvas) { + // instantiate super + Snapping.call(this, eventBus, canvas); + + /** - * Drop articipant on process <> process elements snapping + * Drop participant on process <> process elements snapping */ function initParticipantSnapping(context, shape, elements) { @@ -55,27 +75,24 @@ function BpmnSnapping(eventBus, canvas) { }; var snapTopLeft = snapBox, - snapBottomRight = { - x: snapBox.x + snapBox.width, - y: snapBox.y + snapBox.height - }; + snapBottomRight = bottomRight(snapBox); if (currentTopLeft.x >= snapTopLeft.x) { event.x = snapTopLeft.x + 30 + shapeHalfWidth; - event.snapping = true; + event.snapped = true; } else if (currentBottomRight.x <= snapBottomRight.x) { event.x = snapBottomRight.x - 30 - shapeHalfWidth; - event.snapping = true; + event.snapped = true; } if (currentTopLeft.y >= snapTopLeft.y) { event.y = snapTopLeft.y + shapeHalfHeight; - event.snapping = true; + event.snapped = true; } else if (currentBottomRight.y <= snapBottomRight.y) { event.y = snapBottomRight.y - shapeHalfHeight; - event.snapping = true; + event.snapped = true; } } @@ -86,8 +103,7 @@ function BpmnSnapping(eventBus, canvas) { rootElement = canvas.getRootElement(); // snap participant around existing elements (if any) - if (shape.businessObject.$instanceOf('bpmn:Participant') && - rootElement.businessObject.$instanceOf('bpmn:Process')) { + if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) { initParticipantSnapping(context, shape, rootElement.children); } @@ -99,12 +115,120 @@ function BpmnSnapping(eventBus, canvas) { shape = context.shape, participantSnapBox = context.participantSnapBox; - if (!event.snapping && participantSnapBox) { + if (!event.snapped && participantSnapBox) { snapParticipant(participantSnapBox, shape, event); } }); } +inherits(BpmnSnapping, Snapping); + BpmnSnapping.$inject = [ 'eventBus', 'canvas' ]; -module.exports = BpmnSnapping; \ No newline at end of file +module.exports = BpmnSnapping; + + +BpmnSnapping.prototype.initSnap = function(event) { + + var context = event.context, + shape = context.shape, + shapeMid, + shapeBounds, + shapeTopLeft, + shapeBottomRight, + snapContext; + + + snapContext = Snapping.prototype.initSnap.call(this, event); + + if (is(shape, 'bpmn:Participant')) { + // assign higher priority for outer snaps on participants + snapContext.setSnapLocations([ 'top-left', 'bottom-right', 'mid' ]); + } + + + if (shape) { + + shapeMid = mid(shape, event); + + shapeBounds = { + width: shape.width, + height: shape.height, + x: isNaN(shape.x) ? round(shapeMid.x - shape.width / 2) : shape.x, + y: isNaN(shape.y) ? round(shapeMid.y - shape.height / 2) : shape.y, + }; + + shapeTopLeft = topLeft(shapeBounds); + shapeBottomRight = bottomRight(shapeBounds); + + snapContext.setSnapOrigin('top-left', { + x: shapeTopLeft.x - event.x, + y: shapeTopLeft.y - event.y + }); + + snapContext.setSnapOrigin('bottom-right', { + x: shapeBottomRight.x - event.x, + y: shapeBottomRight.y - event.y + }); + + + forEach(shape.outgoing, function(c) { + var docking = c.waypoints[0]; + + docking = docking.original || docking; + + snapContext.setSnapOrigin(c.id + '-docking', { + x: docking.x - event.x, + y: docking.y - event.y + }); + }); + + forEach(shape.incoming, function(c) { + var docking = c.waypoints[c.waypoints.length - 1]; + + docking = docking.original || docking; + + snapContext.setSnapOrigin(c.id + '-docking', { + x: docking.x - event.x, + y: docking.y - event.y + }); + }); + } +}; + + +BpmnSnapping.prototype.addTargetSnaps = function(snapPoints, shape, target) { + + var siblings = this.getSiblings(shape, target); + + + forEach(siblings, function(s) { + snapPoints.add('mid', mid(s)); + + if (is(s, 'bpmn:Participant')) { + snapPoints.add('top-left', topLeft(s)); + snapPoints.add('bottom-right', bottomRight(s)); + } + }); + + forEach(shape.incoming, function(c) { + + if (siblings.indexOf(c.source) === -1) { + snapPoints.add('mid', mid(c.source)); + + var docking = c.waypoints[0]; + snapPoints.add(c.id + '-docking', docking.original || docking); + } + }); + + + forEach(shape.outgoing, function(c) { + + if (siblings.indexOf(c.target) === -1) { + snapPoints.add('mid', mid(c.target)); + + var docking = c.waypoints[c.waypoints.length - 1]; + snapPoints.add(c.id + '-docking', docking.original || docking); + } + }); +}; \ No newline at end of file diff --git a/lib/features/snapping/index.js b/lib/features/snapping/index.js index 0cef69b0..cbe1b135 100644 --- a/lib/features/snapping/index.js +++ b/lib/features/snapping/index.js @@ -1,4 +1,4 @@ module.exports = { - __init__: [ 'bpmnSnapping' ], - bpmnSnapping: [ 'type', require('./BpmnSnapping') ] + __init__: [ 'snapping' ], + snapping: [ 'type', require('./BpmnSnapping') ] }; \ No newline at end of file diff --git a/lib/import/BpmnImporter.js b/lib/import/BpmnImporter.js index 3fba3152..be3c5c10 100644 --- a/lib/import/BpmnImporter.js +++ b/lib/import/BpmnImporter.js @@ -3,11 +3,11 @@ var assign = require('lodash/object/assign'), map = require('lodash/collection/map'); -var LabelUtil = require('../util/Label'); +var LabelUtil = require('../util/LabelUtil'); var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelBounds = LabelUtil.getExternalLabelBounds, - isExpanded = require('../util/Di').isExpanded, + isExpanded = require('../util/DiUtil').isExpanded, elementToString = require('./Util').elementToString; diff --git a/lib/util/Di.js b/lib/util/Di.js deleted file mode 100644 index cfc6d3d4..00000000 --- a/lib/util/Di.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -module.exports.isExpandedPool = function(semantic) { - return !!semantic.processRef; -}; - -module.exports.isExpanded = function(semantic) { - - // Is type expanded by default? - var isDefaultExpanded = !(semantic.$instanceOf('bpmn:SubProcess') || semantic.$instanceOf('bpmn:CallActivity')); - - // For non default expanded types -> evaluate the expanded flag - var isExpanded = isDefaultExpanded || semantic.di.isExpanded; - - return isExpanded; -}; diff --git a/lib/util/DiUtil.js b/lib/util/DiUtil.js new file mode 100644 index 00000000..09453978 --- /dev/null +++ b/lib/util/DiUtil.js @@ -0,0 +1,21 @@ +'use strict'; + +var is = require('./ModelUtil').is, + getBusinessObject = require('./ModelUtil').getBusinessObject; + +module.exports.isExpanded = function(element) { + + if (is(element, 'bpmn:CallActivity')) { + return false; + } + + if (is(element, 'bpmn:SubProcess')) { + return getBusinessObject(element).di.isExpanded; + } + + if (is(element, 'bpmn:Participant')) { + return !!getBusinessObject(element).processRef; + } + + return true; +}; diff --git a/lib/util/Label.js b/lib/util/LabelUtil.js similarity index 100% rename from lib/util/Label.js rename to lib/util/LabelUtil.js diff --git a/lib/util/ModelUtil.js b/lib/util/ModelUtil.js new file mode 100644 index 00000000..7dc0056d --- /dev/null +++ b/lib/util/ModelUtil.js @@ -0,0 +1,31 @@ +'use strict'; + +/** + * Is an element of the given BPMN type? + * + * @param {djs.model.Base|ModdleElement} element + * @param {String} type + * + * @return {Boolean} + */ +function is(element, type) { + var bo = getBusinessObject(element); + + return bo && bo.$instanceOf(type); +} + +module.exports.is = is; + + +/** + * Return the business object for a given element. + * + * @param {djs.model.Base|ModdleElement} element + * + * @return {ModdleElement} + */ +function getBusinessObject(element) { + return (element && element.businessObject) || element; +} + +module.exports.getBusinessObject = getBusinessObject; diff --git a/test/spec/features/modeling/AppendShapeSpec.js b/test/spec/features/modeling/AppendShapeSpec.js index 138fac96..cb0cd2e8 100644 --- a/test/spec/features/modeling/AppendShapeSpec.js +++ b/test/spec/features/modeling/AppendShapeSpec.js @@ -10,7 +10,7 @@ var modelingModule = require('../../../../lib/features/modeling'), coreModule = require('../../../../lib/core'); -var LabelUtil = require('../../../../lib/util/Label'); +var LabelUtil = require('../../../../lib/util/LabelUtil'); describe('features/modeling - append shape', function() { diff --git a/test/spec/features/modeling/behavior/DropBehaviorSpec.js b/test/spec/features/modeling/behavior/DropBehaviorSpec.js index 5336d902..cd5753f8 100644 --- a/test/spec/features/modeling/behavior/DropBehaviorSpec.js +++ b/test/spec/features/modeling/behavior/DropBehaviorSpec.js @@ -4,7 +4,7 @@ var TestHelper = require('../../../../TestHelper'); /* global bootstrapModeler, inject */ -var is = require('../../../../../lib/features/modeling/ModelingUtil').is, +var is = require('../../../../../lib/util/ModelUtil').is, find = require('lodash/collection/find'); var modelingModule = require('../../../../../lib/features/modeling'),