This is an automated email from the ASF dual-hosted git repository.

tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new 9469381265b NO-ISSUE: DMN Editor: Unable to "unhide" a hidden Decision 
Service Node (#2371)
9469381265b is described below

commit 9469381265b1567e4758a41a2de6e1ab5a224776
Author: Kbowers <[email protected]>
AuthorDate: Tue Jun 4 00:03:22 2024 +0200

    NO-ISSUE: DMN Editor: Unable to "unhide" a hidden Decision Service Node 
(#2371)
    
    Co-authored-by: Luiz Motta <[email protected]>
---
 .../dmn-editor/src/autolayout/AutoLayoutHook.ts    | 220 ---------
 .../dmn-editor/src/autolayout/AutolayoutButton.tsx |  41 +-
 .../{autoLayout.ts => autoLayoutInfo.ts}           |  87 ++--
 packages/dmn-editor/src/diagram/Diagram.tsx        | 310 ++++++++----
 .../dmn-editor/src/diagram/DiagramCommands.tsx     |  56 ++-
 packages/dmn-editor/src/diagram/nodes/Nodes.tsx    |   8 +-
 .../mutations/addExistingDecisionServiceToDrd.ts   | 540 ++++++++++++++++-----
 packages/dmn-editor/src/mutations/addOrGetDrd.ts   |   4 +-
 packages/dmn-editor/src/mutations/addShape.ts      |  17 +-
 .../src/mutations/applyAutoLayoutToDrd.ts          | 225 +++++++++
 packages/dmn-editor/src/mutations/deleteImport.ts  |  14 +-
 packages/dmn-editor/src/mutations/deleteNode.ts    | 113 ++---
 packages/dmn-editor/src/mutations/resizeNode.ts    |  15 +-
 .../mutations/updateDecisionServiceDividerLine.ts  |  37 +-
 ...ainingDecisionServiceHrefsByDecisionHrefs.ts.ts |  12 +-
 packages/dmn-editor/src/xml/xmlHrefs.ts            |  21 +
 16 files changed, 1122 insertions(+), 598 deletions(-)

diff --git a/packages/dmn-editor/src/autolayout/AutoLayoutHook.ts 
b/packages/dmn-editor/src/autolayout/AutoLayoutHook.ts
deleted file mode 100644
index 1034b2dcced..00000000000
--- a/packages/dmn-editor/src/autolayout/AutoLayoutHook.ts
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import * as Elk from "elkjs/lib/elk.bundled.js";
-import { useCallback } from "react";
-import { PositionalNodeHandleId } from 
"../diagram/connections/PositionalNodeHandles";
-import { EdgeType, NodeType } from "../diagram/connections/graphStructure";
-import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
-import { addEdge } from "../mutations/addEdge";
-import { repositionNode } from "../mutations/repositionNode";
-import { resizeNode } from "../mutations/resizeNode";
-import { updateDecisionServiceDividerLine } from 
"../mutations/updateDecisionServiceDividerLine";
-import { AutolayoutParentNode, FAKE_MARKER, visitNodeAndNested } from 
"./autoLayout";
-import { State } from "../store/Store";
-import { DmnDiagramNodeData } from "../diagram/nodes/Nodes";
-import { DmnDiagramEdgeData } from "../diagram/edges/Edges";
-import { DMNDI15__DMNShape } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
-import { XmlQName } from "@kie-tools/xml-parser-ts/dist/qNames";
-import * as RF from "reactflow";
-import { Normalized } from "../normalization/normalize";
-
-export function useAutoLayout() {
-  return useCallback(
-    ({
-      s,
-      autolayouted,
-      parentNodesById,
-      nodesById,
-      edgesById,
-      edges,
-      dmnShapesByHref,
-    }: {
-      s: State;
-      autolayouted: {
-        isHorizontal: boolean;
-        nodes: Elk.ElkNode[] | undefined;
-        edges: Elk.ElkExtendedEdge[] | undefined;
-      };
-      parentNodesById: Map<string, AutolayoutParentNode>;
-      nodesById: Map<string, RF.Node<DmnDiagramNodeData, string | undefined>>;
-      edgesById: Map<string, RF.Edge<DmnDiagramEdgeData>>;
-      edges: RF.Edge<DmnDiagramEdgeData>[];
-      dmnShapesByHref: Map<
-        string,
-        Normalized<DMNDI15__DMNShape> & {
-          index: number;
-          dmnElementRefQName: XmlQName;
-        }
-      >;
-    }) => {
-      // 7. Update all nodes positions skipping empty groups, which will be 
positioned manually after all nodes are done being repositioned.
-      const autolayoutedElkNodesById = new Map<string, Elk.ElkNode>();
-
-      for (const topLevelElkNode of autolayouted.nodes ?? []) {
-        visitNodeAndNested(topLevelElkNode, { x: 100, y: 100 }, (elkNode, 
positionOffset) => {
-          if (elkNode.id.includes(FAKE_MARKER)) {
-            return;
-          }
-
-          autolayoutedElkNodesById.set(elkNode.id, elkNode);
-
-          const nodeId = elkNode.id;
-          const node = nodesById.get(nodeId)!;
-
-          repositionNode({
-            definitions: s.dmn.model.definitions,
-            drdIndex: s.computed(s).getDrdIndex(),
-            controlWaypointsByEdge: new Map(),
-            change: {
-              nodeType: node.type as NodeType,
-              type: "absolute",
-              position: {
-                x: elkNode.x! + positionOffset.x,
-                y: elkNode.y! + positionOffset.y,
-              },
-              selectedEdges: [...edgesById.keys()],
-              shapeIndex: node.data?.shape.index,
-              sourceEdgeIndexes: edges.flatMap((e) =>
-                e.source === nodeId && e.data?.dmnEdge ? 
[e.data.dmnEdge.index] : []
-              ),
-              targetEdgeIndexes: edges.flatMap((e) =>
-                e.target === nodeId && e.data?.dmnEdge ? 
[e.data.dmnEdge.index] : []
-              ),
-            },
-          });
-        });
-      }
-
-      // 8. Resize all nodes using the sizes calculated by ELK.
-      for (const topLevelElkNode of autolayouted.nodes ?? []) {
-        visitNodeAndNested(topLevelElkNode, { x: 0, y: 0 }, (elkNode) => {
-          if (elkNode.id.includes(FAKE_MARKER)) {
-            return;
-          }
-
-          const nodeId = elkNode.id;
-          const node = nodesById.get(nodeId)!;
-
-          resizeNode({
-            definitions: s.dmn.model.definitions,
-            drdIndex: s.computed(s).getDrdIndex(),
-            __readonly_dmnShapesByHref: dmnShapesByHref,
-            snapGrid: s.diagram.snapGrid,
-            change: {
-              index: node.data.index,
-              isExternal: !!node.data.dmnObjectQName.prefix,
-              nodeType: node.type as NodeType,
-              dimension: {
-                "@_width": elkNode.width!,
-                "@_height": elkNode.height!,
-              },
-              shapeIndex: node.data?.shape.index,
-              sourceEdgeIndexes: edges.flatMap((e) =>
-                e.source === nodeId && e.data?.dmnEdge ? 
[e.data.dmnEdge.index] : []
-              ),
-              targetEdgeIndexes: edges.flatMap((e) =>
-                e.target === nodeId && e.data?.dmnEdge ? 
[e.data.dmnEdge.index] : []
-              ),
-            },
-          });
-        });
-      }
-
-      // 9. Updating Decision Service divider lines after all nodes are 
repositioned and resized.
-      for (const [parentNodeId] of parentNodesById) {
-        const parentNode = nodesById.get(parentNodeId);
-        if (parentNode?.type !== NODE_TYPES.decisionService) {
-          continue;
-        }
-
-        const elkNode = autolayoutedElkNodesById.get(parentNodeId);
-        if (!elkNode) {
-          throw new Error(`Couldn't find Decision Service with id 
${parentNode.id} at the autolayouted nodes map`);
-        }
-
-        /**
-         * The second children of a Decision Service elkNode is a node 
representing the Encapsulated section.
-         * It's Y position will be exactly where the divider line should be.
-         */
-        const dividerLinerLocalYPosition = elkNode.children?.[1]?.y;
-        if (!dividerLinerLocalYPosition) {
-          throw new Error(
-            `Couldn't find second child (which represents the Encapuslated 
Decision section) of Decision Service with id ${parentNode.id} at the 
autolayouted nodes map`
-          );
-        }
-
-        updateDecisionServiceDividerLine({
-          definitions: s.dmn.model.definitions,
-          drdIndex: s.computed(s).getDrdIndex(),
-          __readonly_dmnShapesByHref: dmnShapesByHref,
-          drgElementIndex: parentNode.data.index,
-          shapeIndex: parentNode.data.shape.index,
-          snapGrid: s.diagram.snapGrid,
-          localYPosition: dividerLinerLocalYPosition,
-        });
-      }
-
-      // 10. Update the edges. Edges always go from top to bottom, removing 
waypoints.
-      for (const elkEdge of autolayouted.edges ?? []) {
-        if (elkEdge.id.includes(FAKE_MARKER)) {
-          continue;
-        }
-
-        const edge = edgesById.get(elkEdge.id)!;
-
-        const sourceNode = nodesById.get(elkEdge.sources[0])!;
-        const targetNode = nodesById.get(elkEdge.targets[0])!;
-
-        // If the target is an external node, we don't have to create the edge.
-        if (targetNode.data.dmnObjectQName.prefix) {
-          continue;
-        }
-
-        addEdge({
-          definitions: s.dmn.model.definitions,
-          drdIndex: s.computed(s).getDrdIndex(),
-          edge: {
-            autoPositionedEdgeMarker: undefined,
-            type: edge.type as EdgeType,
-            targetHandle: PositionalNodeHandleId.Bottom,
-            sourceHandle: PositionalNodeHandleId.Top,
-          },
-          sourceNode: {
-            type: sourceNode.type as NodeType,
-            href: sourceNode.id,
-            data: sourceNode.data,
-            bounds: sourceNode.data.shape["dc:Bounds"]!,
-            shapeId: sourceNode.data.shape["@_id"],
-          },
-          targetNode: {
-            type: targetNode.type as NodeType,
-            href: targetNode.id,
-            data: targetNode.data,
-            bounds: targetNode.data.shape["dc:Bounds"]!,
-            index: targetNode.data.index,
-            shapeId: targetNode.data.shape["@_id"],
-          },
-          keepWaypoints: false,
-        });
-      }
-    },
-    []
-  );
-}
diff --git a/packages/dmn-editor/src/autolayout/AutolayoutButton.tsx 
b/packages/dmn-editor/src/autolayout/AutolayoutButton.tsx
index af4d703a8ab..c1a09f169eb 100644
--- a/packages/dmn-editor/src/autolayout/AutolayoutButton.tsx
+++ b/packages/dmn-editor/src/autolayout/AutolayoutButton.tsx
@@ -19,17 +19,15 @@
 
 import * as React from "react";
 import OptimizeIcon from "@patternfly/react-icons/dist/js/icons/optimize-icon";
-import { useAutoLayout } from "./AutoLayoutHook";
 import { useDmnEditorStoreApi } from "../store/StoreContext";
-import { autoLayout } from "./autoLayout";
+import { getAutoLayoutedInfo } from "./autoLayoutInfo";
 import { useExternalModels } from 
"../includedModels/DmnEditorDependenciesContext";
+import { applyAutoLayoutToDrd } from "../mutations/applyAutoLayoutToDrd";
 
 export function AutolayoutButton() {
   const dmnEditorStoreApi = useDmnEditorStoreApi();
   const { externalModelsByNamespace } = useExternalModels();
 
-  const applyAutoLayout = useAutoLayout();
-
   const onClick = React.useCallback(async () => {
     const state = dmnEditorStoreApi.getState();
     const snapGrid = state.diagram.snapGrid;
@@ -39,27 +37,30 @@ export function AutolayoutButton() {
     const drgEdges = 
state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges;
     const isAlternativeInputDataShape = 
state.computed(state).isAlternativeInputDataShape();
 
-    const { autolayouted, parentNodesById } = await autoLayout({
-      snapGrid,
-      nodesById,
-      edgesById,
-      nodes,
-      drgEdges,
-      isAlternativeInputDataShape,
+    const { __readonly_autoLayoutedInfo, __readonly_parentNodesById } = await 
getAutoLayoutedInfo({
+      __readonly_snapGrid: snapGrid,
+      __readonly_nodesById: nodesById,
+      __readonly_edgesById: edgesById,
+      __readonly_nodes: nodes,
+      __readonly_drgEdges: drgEdges,
+      __readonly_isAlternativeInputDataShape: isAlternativeInputDataShape,
     });
 
     dmnEditorStoreApi.setState((s) => {
-      applyAutoLayout({
-        s,
-        dmnShapesByHref: s.computed(s).indexedDrd().dmnShapesByHref,
-        edges: s.computed(s).getDiagramData(externalModelsByNamespace).edges,
-        edgesById: 
s.computed(s).getDiagramData(externalModelsByNamespace).edgesById,
-        nodesById: 
s.computed(s).getDiagramData(externalModelsByNamespace).nodesById,
-        autolayouted: autolayouted,
-        parentNodesById: parentNodesById,
+      applyAutoLayoutToDrd({
+        state: s,
+        __readonly_dmnShapesByHref: s.computed(s).indexedDrd().dmnShapesByHref,
+        __readonly_edges: 
s.computed(s).getDiagramData(externalModelsByNamespace).edges,
+        __readonly_edgesById: 
s.computed(s).getDiagramData(externalModelsByNamespace).edgesById,
+        __readonly_nodesById: 
s.computed(s).getDiagramData(externalModelsByNamespace).nodesById,
+        __readonly_autoLayoutedInfo,
+        __readonly_parentNodesById,
+        __readonly_drdIndex: s.computed(s).getDrdIndex(),
+        __readonly_dmnObjectNamespace: s.dmn.model.definitions["@_namespace"],
+        __readonly_externalDmnsIndex: 
s.computed(s).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
       });
     });
-  }, [applyAutoLayout, dmnEditorStoreApi, externalModelsByNamespace]);
+  }, [dmnEditorStoreApi, externalModelsByNamespace]);
 
   return (
     <button className={"kie-dmn-editor--autolayout-panel-toggle-button"} 
onClick={onClick} title={"Autolayout (beta)"}>
diff --git a/packages/dmn-editor/src/autolayout/autoLayout.ts 
b/packages/dmn-editor/src/autolayout/autoLayoutInfo.ts
similarity index 84%
rename from packages/dmn-editor/src/autolayout/autoLayout.ts
rename to packages/dmn-editor/src/autolayout/autoLayoutInfo.ts
index ebb672d10c3..74cd1b79ba2 100644
--- a/packages/dmn-editor/src/autolayout/autoLayout.ts
+++ b/packages/dmn-editor/src/autolayout/autoLayoutInfo.ts
@@ -20,15 +20,16 @@
 import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
 import { DC__Bounds } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import ELK, * as Elk from "elkjs/lib/elk.bundled.js";
+import { Edge, Node } from "reactflow";
 import { NodeType } from "../diagram/connections/graphStructure";
+import { DmnDiagramEdgeData } from "../diagram/edges/Edges";
 import { DrgEdge, getAdjMatrix, traverse } from "../diagram/graph/graph";
 import { getContainmentRelationship } from "../diagram/maths/DmnMaths";
 import { DEFAULT_NODE_SIZES, MIN_NODE_SIZES } from 
"../diagram/nodes/DefaultSizes";
+import { DmnDiagramNodeData } from "../diagram/nodes/Nodes";
 import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
 import { SnapGrid } from "../store/Store";
-import { DmnDiagramEdgeData } from "../diagram/edges/Edges";
-import { Edge, Node } from "reactflow";
-import { DmnDiagramNodeData } from "../diagram/nodes/Nodes";
+import { addNamespaceToHref, parseXmlHref } from "../xml/xmlHrefs";
 
 const elk = new ELK();
 
@@ -77,20 +78,20 @@ export interface AutolayoutParentNode {
 
 export const FAKE_MARKER = "__$FAKE$__";
 
-export async function autoLayout({
-  snapGrid,
-  nodesById,
-  edgesById,
-  nodes,
-  drgEdges,
-  isAlternativeInputDataShape,
+export async function getAutoLayoutedInfo({
+  __readonly_snapGrid,
+  __readonly_nodesById,
+  __readonly_edgesById,
+  __readonly_nodes,
+  __readonly_drgEdges,
+  __readonly_isAlternativeInputDataShape,
 }: {
-  snapGrid: SnapGrid;
-  nodesById: Map<string, Node<DmnDiagramNodeData, string | undefined>>;
-  edgesById: Map<string, Edge<DmnDiagramEdgeData>>;
-  nodes: Node<DmnDiagramNodeData, string | undefined>[];
-  drgEdges: DrgEdge[];
-  isAlternativeInputDataShape: boolean;
+  __readonly_snapGrid: SnapGrid;
+  __readonly_nodesById: Map<string, Node<DmnDiagramNodeData, string | 
undefined>>;
+  __readonly_edgesById: Map<string, Edge<DmnDiagramEdgeData>>;
+  __readonly_nodes: Node<DmnDiagramNodeData, string | undefined>[];
+  __readonly_drgEdges: DrgEdge[];
+  __readonly_isAlternativeInputDataShape: boolean;
 }) {
   const parentNodesById = new Map<string, AutolayoutParentNode>();
   const nodeParentsById = new Map<string, Set<string>>();
@@ -101,21 +102,28 @@ export async function autoLayout({
    */
   const fakeEdgesForElk = new Set<Elk.ElkExtendedEdge>();
 
-  const adjMatrix = getAdjMatrix(drgEdges);
+  const adjMatrix = getAdjMatrix(__readonly_drgEdges);
 
   // 1. First we populate the `parentNodesById` map so that we know exactly 
what parent nodes we're dealing with. Decision Service nodes have two fake 
nodes to represent Output and Encapsulated sections.
-  for (const node of nodes) {
+  for (const node of __readonly_nodes) {
     const dependencies = new Set<string>();
     const dependents = new Set<string>();
 
     if (node.data?.dmnObject?.__$$element === "decisionService") {
-      const outputs = new Set([...(node.data.dmnObject.outputDecision ?? 
[]).map((s) => s["@_href"])]);
-      const encapsulated = new 
Set([...(node.data.dmnObject.encapsulatedDecision ?? []).map((s) => 
s["@_href"])]);
+      const { namespace } = parseXmlHref(node.id);
+      const outputs = new Set([
+        ...(node.data.dmnObject.outputDecision ?? []).map((s) => 
addNamespaceToHref({ href: s["@_href"], namespace })),
+      ]);
+      const encapsulated = new Set([
+        ...(node.data.dmnObject.encapsulatedDecision ?? []).map((s) =>
+          addNamespaceToHref({ href: s["@_href"], namespace })
+        ),
+      ]);
 
       const idOfFakeNodeForOutputSection = `${node.id}${FAKE_MARKER}dsOutput`;
       const idOfFakeNodeForEncapsulatedSection = 
`${node.id}${FAKE_MARKER}dsEncapsulated`;
 
-      const dsSize = MIN_NODE_SIZES[NODE_TYPES.decisionService]({ snapGrid });
+      const dsSize = MIN_NODE_SIZES[NODE_TYPES.decisionService]({ snapGrid: 
__readonly_snapGrid });
       parentNodesById.set(node.id, {
         elkNode: {
           id: node.id,
@@ -174,7 +182,7 @@ export async function autoLayout({
         targets: [idOfFakeNodeForOutputSection],
       });
     } else if (node.data?.dmnObject?.__$$element === "group") {
-      const groupSize = DEFAULT_NODE_SIZES[NODE_TYPES.group]({ snapGrid });
+      const groupSize = DEFAULT_NODE_SIZES[NODE_TYPES.group]({ snapGrid: 
__readonly_snapGrid });
       const groupBounds = node.data.shape["dc:Bounds"];
       parentNodesById.set(node.id, {
         decisionServiceSection: "n/a",
@@ -195,10 +203,10 @@ export async function autoLayout({
           isInside: getContainmentRelationship({
             bounds: bounds!,
             container: groupBounds!,
-            snapGrid,
-            isAlternativeInputDataShape,
+            snapGrid: __readonly_snapGrid,
+            isAlternativeInputDataShape: 
__readonly_isAlternativeInputDataShape,
             containerMinSizes: MIN_NODE_SIZES[NODE_TYPES.group],
-            boundsMinSizes: MIN_NODE_SIZES[nodesById.get(id)?.type as 
NodeType],
+            boundsMinSizes: MIN_NODE_SIZES[__readonly_nodesById.get(id)?.type 
as NodeType],
           }).isInside,
           decisionServiceSection: "n/a",
         }),
@@ -209,13 +217,16 @@ export async function autoLayout({
   }
 
   // 2. Then we map all the nodes to elkNodes, including the parents. We 
mutate parents on the fly when iterating over the nodes list.
-  const elkNodes = nodes.flatMap((node) => {
+  const elkNodes = __readonly_nodes.flatMap((node) => {
     const parent = parentNodesById.get(node.id);
     if (parent) {
       return [];
     }
 
-    const defaultSize = DEFAULT_NODE_SIZES[node.type as NodeType]({ snapGrid, 
isAlternativeInputDataShape });
+    const defaultSize = DEFAULT_NODE_SIZES[node.type as NodeType]({
+      snapGrid: __readonly_snapGrid,
+      isAlternativeInputDataShape: __readonly_isAlternativeInputDataShape,
+    });
     const elkNode: Elk.ElkNode = {
       id: node.id,
       width: node.data.shape["dc:Bounds"]?.["@_width"] ?? 
defaultSize["@_width"],
@@ -271,7 +282,7 @@ export async function autoLayout({
       parentNode.dependents.add(n);
     });
 
-    const p = nodesById.get(parentNode.elkNode.id);
+    const p = __readonly_nodesById.get(parentNode.elkNode.id);
     if (p?.type === NODE_TYPES.group && parentNode.elkNode.children?.length 
=== 0) {
       continue; // Ignore empty group nodes.
     } else {
@@ -280,13 +291,13 @@ export async function autoLayout({
   }
 
   // 4. After we have all containment and hierarchical relationships defined, 
we can add the fake edges so that ELK creates the structure correctly.
-  for (const node of nodes) {
+  for (const node of __readonly_nodes) {
     const parentNodes = [...parentNodesById.values()];
 
     const dependents = parentNodes.filter((p) => p.hasDependencyTo({ id: 
node.id }));
     for (const dependent of dependents) {
       // Not all nodes are present in all DRD
-      if (nodesById.has(node.id) && nodesById.has(dependent.elkNode.id)) {
+      if (__readonly_nodesById.has(node.id) && 
__readonly_nodesById.has(dependent.elkNode.id)) {
         fakeEdgesForElk.add({
           id: `${generateUuid()}${FAKE_MARKER}__fake`,
           sources: [node.id],
@@ -296,7 +307,7 @@ export async function autoLayout({
 
       for (const p of nodeParentsById.get(node.id) ?? []) {
         // Not all nodes are present in all DRD
-        if (nodesById.has(p) && nodesById.has(dependent.elkNode.id)) {
+        if (__readonly_nodesById.has(p) && 
__readonly_nodesById.has(dependent.elkNode.id)) {
           fakeEdgesForElk.add({
             id: `${generateUuid()}${FAKE_MARKER}__fake`,
             sources: [p],
@@ -309,7 +320,7 @@ export async function autoLayout({
     const dependencies = parentNodes.filter((p) => p.isDependencyOf({ id: 
node.id }));
     for (const dependency of dependencies) {
       // Not all nodes are present in all DRD
-      if (nodesById.has(node.id) && nodesById.has(dependency.elkNode.id)) {
+      if (__readonly_nodesById.has(node.id) && 
__readonly_nodesById.has(dependency.elkNode.id)) {
         fakeEdgesForElk.add({
           id: `${generateUuid()}${FAKE_MARKER}__fake`,
           sources: [dependency.elkNode.id],
@@ -319,7 +330,7 @@ export async function autoLayout({
 
       for (const p of nodeParentsById.get(node.id) ?? []) {
         // Not all nodes are present in all DRD
-        if (nodesById.has(p) && nodesById.has(dependency.elkNode.id)) {
+        if (__readonly_nodesById.has(p) && 
__readonly_nodesById.has(dependency.elkNode.id)) {
           fakeEdgesForElk.add({
             id: `${generateUuid()}${FAKE_MARKER}__fake`,
             sources: [dependency.elkNode.id],
@@ -333,9 +344,9 @@ export async function autoLayout({
   // 5. Concatenate real and fake edges to pass to ELK.
   const elkEdges = [
     ...fakeEdgesForElk,
-    ...[...edgesById.values()].flatMap((e) => {
+    ...[...__readonly_edgesById.values()].flatMap((e) => {
       // Not all nodes are present in all DRD
-      if (nodesById.has(e.source) && nodesById.has(e.target)) {
+      if (__readonly_nodesById.has(e.source) && 
__readonly_nodesById.has(e.target)) {
         return {
           id: e.id,
           sources: [e.source],
@@ -348,10 +359,10 @@ export async function autoLayout({
   ];
 
   // 6. Run ELK.
-  const autolayouted = await runElk(elkNodes, elkEdges, ELK_OPTIONS);
+  const autoLayoutedInfo = await runElk(elkNodes, elkEdges, ELK_OPTIONS);
   return {
-    autolayouted,
-    parentNodesById,
+    __readonly_autoLayoutedInfo: autoLayoutedInfo,
+    __readonly_parentNodesById: parentNodesById,
   };
 }
 
diff --git a/packages/dmn-editor/src/diagram/Diagram.tsx 
b/packages/dmn-editor/src/diagram/Diagram.tsx
index 5c47b7f4e2d..2081dbb94bd 100644
--- a/packages/dmn-editor/src/diagram/Diagram.tsx
+++ b/packages/dmn-editor/src/diagram/Diagram.tsx
@@ -26,6 +26,7 @@ import {
   DC__Dimension,
   DMN15__tDecisionService,
   DMN15__tDefinitions,
+  DMNDI15__DMNDiagram,
 } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { buildXmlQName } from "@kie-tools/xml-parser-ts/dist/qNames";
 import { Button, ButtonVariant } from 
"@patternfly/react-core/dist/js/components/Button";
@@ -112,16 +113,20 @@ import {
 import { useExternalModels } from 
"../includedModels/DmnEditorDependenciesContext";
 import { xmlHrefToQName } from "../xml/xmlHrefToQName";
 import {
+  addAutoGeneratedDecisionServiceToDrd,
+  addConflictingDecisionServiceToDrd,
+  StrategyForAddingDecisionServiceToDrd,
   addExistingDecisionServiceToDrd,
+  getStrategyToAddExistingDecisionServiceToDrd,
   getDecisionServicePropertiesRelativeToThisDmn,
 } from "../mutations/addExistingDecisionServiceToDrd";
 import { updateExpressionWidths } from "../mutations/updateExpressionWidths";
 import { DiagramCommands } from "./DiagramCommands";
-import { autoLayout } from "../autolayout/autoLayout";
-import { useAutoLayout } from "../autolayout/AutoLayoutHook";
+import { getAutoLayoutedInfo } from "../autolayout/autoLayoutInfo";
 import { autoGenerateDrd } from "../normalization/autoGenerateDrd";
 import { Normalized, normalize } from "../normalization/normalize";
 import OptimizeIcon from "@patternfly/react-icons/dist/js/icons/optimize-icon";
+import { applyAutoLayoutToDrd } from "../mutations/applyAutoLayoutToDrd";
 
 const isFirefox = typeof (window as any).InstallTrigger !== "undefined"; // 
See 
https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browsers
 
@@ -289,7 +294,7 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
     }, []);
 
     const onDrop = useCallback(
-      (e: React.DragEvent) => {
+      async (e: React.DragEvent) => {
         e.preventDefault();
 
         if (!container.current || !reactFlowInstance) {
@@ -341,50 +346,101 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
 
           // --------- This is where we draw the line between the diagram and 
the model.
 
-          dmnEditorStoreApi.setState((state) => {
-            const externalDmnsIndex = state
-              .computed(state)
-              
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns;
+          const state = dmnEditorStoreApi.getState();
+          const externalDmnsIndex = state
+            .computed(state)
+            .getExternalModelTypesByNamespace(externalModelsByNamespace).dmns;
 
-            const externalNodeDmn = 
externalDmnsIndex.get(externalNode.externalDrgElementNamespace);
-            const externalDrgElement = 
(externalNodeDmn?.model.definitions.drgElement ?? []).find(
-              (e) => e["@_id"] === externalNode.externalDrgElementId
+          const externalNodeDmn = 
externalDmnsIndex.get(externalNode.externalDrgElementNamespace);
+          const externalDrgElement = 
(externalNodeDmn?.model.definitions.drgElement ?? []).find(
+            (e) => e["@_id"] === externalNode.externalDrgElementId
+          );
+          if (!externalNodeDmn || !externalDrgElement) {
+            throw new Error(
+              `Can't find DRG element with id 
'${externalNode.externalDrgElementId}' on/or model with namespace 
'${externalNode.externalDrgElementNamespace}'.`
             );
-            if (!externalNodeDmn || !externalDrgElement) {
-              throw new Error(
-                `Can't find DRG element with id 
'${externalNode.externalDrgElementId}' on/or model with namespace 
'${externalNode.externalDrgElementNamespace}'.`
-              );
-            }
+          }
 
-            const externalNodeType = 
getNodeTypeFromDmnObject(externalDrgElement)!;
+          const externalNodeType = 
getNodeTypeFromDmnObject(externalDrgElement)!;
 
-            const defaultExternalNodeDimensions = 
DEFAULT_NODE_SIZES[externalNodeType]({
-              snapGrid: state.diagram.snapGrid,
-              isAlternativeInputDataShape: 
state.computed(state).isAlternativeInputDataShape(),
-            });
+          const defaultExternalNodeDimensions = 
DEFAULT_NODE_SIZES[externalNodeType]({
+            snapGrid: state.diagram.snapGrid,
+            isAlternativeInputDataShape: 
state.computed(state).isAlternativeInputDataShape(),
+          });
 
-            const namespaceName = getXmlNamespaceDeclarationName({
-              rootElement: state.dmn.model.definitions,
-              namespace: externalNode.externalDrgElementNamespace,
-            });
+          const externalNodeHref = buildXmlHref({
+            namespace: externalNode.externalDrgElementNamespace,
+            id: externalNode.externalDrgElementId,
+          });
 
-            const externalNodeHref = buildXmlHref({
-              namespace: externalNode.externalDrgElementNamespace,
-              id: externalNode.externalDrgElementId,
+          if (externalDrgElement.__$$element === "decisionService") {
+            // Create a dereferencedState to enables us to edit the object 
without changing the original state
+            // After we finish applying the changes it will be used to set the 
new state.
+            const { computed, ...internalState } = state;
+            const dereferencedState: State = { computed, 
...JSON.parse(JSON.stringify(internalState)) };
+            const drdIndex = 
dereferencedState.computed(dereferencedState).getDrdIndex();
+
+            const {
+              strategyForAddingDecisionServiceToDrd,
+              indexedDrdContainingDecisionServiceDepiction,
+              decisionServiceHrefRelativeToThisDmn,
+              containedDecisionHrefsRelativeToThisDmn,
+            } = getStrategyToAddExistingDecisionServiceToDrd({
+              __readonly_definitions: dereferencedState.dmn.model.definitions,
+              __readonly_drgElement: externalDrgElement,
+              __readonly_decisionServiceNamespace: 
externalNodeDmn.model.definitions["@_namespace"],
+              __readonly_drdIndex: drdIndex,
+              __readonly_externalDmnsIndex: externalDmnsIndex,
+              __readonly_indexedDrd: 
dereferencedState.computed(dereferencedState).indexedDrd(),
+              __readonly_namespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
             });
 
-            if (externalDrgElement.__$$element === "decisionService") {
+            if (strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.CONFLICT) {
+              addConflictingDecisionServiceToDrd({
+                definitions: dereferencedState.dmn.model.definitions,
+                __readonly_drdIndex: drdIndex,
+                __readonly_dropPoint: dropPoint,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+              });
+            } else if (strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.AUTO_GENERATE) {
+              await addAutoGeneratedDecisionServiceToDrd({
+                state: dereferencedState,
+                __readonly_decisionServiceNamespace: 
externalNodeDmn.model.definitions["@_namespace"],
+                __readonly_drdIndex: drdIndex,
+                __readonly_externalDmnsIndex: externalDmnsIndex,
+                __readonly_containedDecisionHrefsRelativeToThisDmn: 
containedDecisionHrefsRelativeToThisDmn,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+                __readonly_snapGrid: dereferencedState.diagram.snapGrid,
+                __readonly_dropPoint: dropPoint,
+                __readonly_externalModelsByNamespace: 
externalModelsByNamespace,
+                __readonly_isAlternativeInputDataShape: dereferencedState
+                  .computed(dereferencedState)
+                  .isAlternativeInputDataShape(),
+              });
+            } else if (
+              strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.COPY_FROM_ANOTHER_DRD
+            ) {
               addExistingDecisionServiceToDrd({
-                decisionService: externalDrgElement,
-                decisionServiceNamespace: 
externalNodeDmn.model.definitions["@_namespace"],
-                drdIndex: state.computed(state).getDrdIndex(),
-                dropPoint,
-                externalDmnsIndex,
-                thisDmnsDefinitions: state.dmn.model.definitions,
-                thisDmnsIndexedDrd: state.computed(state).indexedDrd(),
-                thisDmnsNamespace: state.dmn.model.definitions["@_namespace"],
+                definitions: dereferencedState.dmn.model.definitions,
+                __readonly_decisionServiceNamespace: 
externalNodeDmn.model.definitions["@_namespace"],
+                __readonly_drdIndex: drdIndex,
+                __readonly_externalDmnsIndex: dereferencedState
+                  .computed(dereferencedState)
+                  
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
+                __readonly_indexedDrd: 
dereferencedState.computed(dereferencedState).indexedDrd(),
+                __readonly_indexedDrdContainingDecisionServiceDepiction: 
indexedDrdContainingDecisionServiceDepiction!,
+                __readonly_containedDecisionHrefsRelativeToThisDmn: 
containedDecisionHrefsRelativeToThisDmn,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+                __readonly_dropPoint: dropPoint,
+                __readonly_namespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
               });
-            } else {
+            }
+            dmnEditorStoreApi.setState((state) => {
+              state.dmn.model = 
JSON.parse(JSON.stringify(dereferencedState.dmn.model));
+              state.diagram._selectedNodes = [externalNodeHref];
+            });
+          } else {
+            dmnEditorStoreApi.setState((state) => {
               const externalNodeType = 
getNodeTypeFromDmnObject(externalDrgElement)!;
               addShape({
                 definitions: state.dmn.model.definitions,
@@ -401,41 +457,95 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
                   },
                 },
               });
-            }
-            state.diagram._selectedNodes = [externalNodeHref];
-          });
-
+              state.diagram._selectedNodes = [externalNodeHref];
+            });
+          }
           console.debug(`DMN DIAGRAM: Adding external node`, 
JSON.stringify(externalNode));
         } else if (e.dataTransfer.getData(MIME_TYPE_FOR_DMN_EDITOR_DRG_NODE)) {
           const drgElement = 
JSON.parse(e.dataTransfer.getData(MIME_TYPE_FOR_DMN_EDITOR_DRG_NODE)) as 
Unpacked<
             Normalized<DMN15__tDefinitions>["drgElement"]
           >;
 
-          dmnEditorStoreApi.setState((state) => {
-            const nodeType = getNodeTypeFromDmnObject(drgElement);
-            if (nodeType === undefined) {
-              throw new Error("DMN DIAGRAM: It wasn't possible to determine 
the node type");
-            }
+          const nodeType = getNodeTypeFromDmnObject(drgElement);
+          if (nodeType === undefined) {
+            throw new Error("DMN DIAGRAM: It wasn't possible to determine the 
node type");
+          }
 
-            const defaultNodeDimensions = DEFAULT_NODE_SIZES[nodeType]({
-              snapGrid: state.diagram.snapGrid,
-              isAlternativeInputDataShape: 
state.computed(state).isAlternativeInputDataShape(),
-            });
+          if (drgElement.__$$element === "decisionService") {
+            const { computed, ...state } = dmnEditorStoreApi.getState();
+            const dereferencedState: State = { computed, 
...JSON.parse(JSON.stringify(state)) };
+
+            const drdIndex = 
dereferencedState.computed(dereferencedState).getDrdIndex();
+            const externalDmnsIndex = dereferencedState
+              .computed(dereferencedState)
+              
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns;
 
-            if (drgElement.__$$element === "decisionService") {
+            const {
+              strategyForAddingDecisionServiceToDrd,
+              indexedDrdContainingDecisionServiceDepiction,
+              decisionServiceHrefRelativeToThisDmn,
+              containedDecisionHrefsRelativeToThisDmn,
+            } = getStrategyToAddExistingDecisionServiceToDrd({
+              __readonly_definitions: dereferencedState.dmn.model.definitions,
+              __readonly_drgElement: drgElement,
+              __readonly_decisionServiceNamespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
+              __readonly_drdIndex: drdIndex,
+              __readonly_externalDmnsIndex: externalDmnsIndex,
+              __readonly_indexedDrd: 
dereferencedState.computed(dereferencedState).indexedDrd(),
+              __readonly_namespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
+            });
+            if (strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.CONFLICT) {
+              addConflictingDecisionServiceToDrd({
+                definitions: dereferencedState.dmn.model.definitions,
+                __readonly_drdIndex: drdIndex,
+                __readonly_dropPoint: dropPoint,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+              });
+            } else if (strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.AUTO_GENERATE) {
+              await addAutoGeneratedDecisionServiceToDrd({
+                state: dereferencedState,
+                __readonly_decisionServiceNamespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
+                __readonly_drdIndex: drdIndex,
+                __readonly_externalDmnsIndex: externalDmnsIndex,
+                __readonly_containedDecisionHrefsRelativeToThisDmn: 
containedDecisionHrefsRelativeToThisDmn,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+                __readonly_snapGrid: dereferencedState.diagram.snapGrid,
+                __readonly_dropPoint: dropPoint,
+                __readonly_externalModelsByNamespace: 
externalModelsByNamespace,
+                __readonly_isAlternativeInputDataShape: dereferencedState
+                  .computed(dereferencedState)
+                  .isAlternativeInputDataShape(),
+              });
+            } else if (
+              strategyForAddingDecisionServiceToDrd === 
StrategyForAddingDecisionServiceToDrd.COPY_FROM_ANOTHER_DRD
+            ) {
               addExistingDecisionServiceToDrd({
-                decisionService: drgElement,
-                decisionServiceNamespace: 
state.dmn.model.definitions["@_namespace"],
-                drdIndex: state.computed(state).getDrdIndex(),
-                dropPoint,
-                externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace)
-                  .dmns,
-                thisDmnsDefinitions: state.dmn.model.definitions,
-                thisDmnsIndexedDrd: state.computed(state).indexedDrd(),
-                thisDmnsNamespace: state.dmn.model.definitions["@_namespace"],
+                definitions: dereferencedState.dmn.model.definitions,
+                __readonly_decisionServiceNamespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
+                __readonly_drdIndex: drdIndex,
+                __readonly_externalDmnsIndex: dereferencedState
+                  .computed(dereferencedState)
+                  
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
+                __readonly_indexedDrd: 
dereferencedState.computed(dereferencedState).indexedDrd(),
+                __readonly_indexedDrdContainingDecisionServiceDepiction: 
indexedDrdContainingDecisionServiceDepiction!,
+                __readonly_containedDecisionHrefsRelativeToThisDmn: 
containedDecisionHrefsRelativeToThisDmn,
+                __readonly_decisionServiceHrefRelativeToThisDmn: 
decisionServiceHrefRelativeToThisDmn,
+                __readonly_dropPoint: dropPoint,
+                __readonly_namespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
               });
-            } else {
+            }
+            dmnEditorStoreApi.setState((state) => {
+              state.dmn.model = 
JSON.parse(JSON.stringify(dereferencedState.dmn.model));
+            });
+          } else {
+            dmnEditorStoreApi.setState((state) => {
               const nodeType = getNodeTypeFromDmnObject(drgElement)!;
+
+              const defaultNodeDimensions = DEFAULT_NODE_SIZES[nodeType]({
+                snapGrid: state.diagram.snapGrid,
+                isAlternativeInputDataShape: 
state.computed(state).isAlternativeInputDataShape(),
+              });
+
               addShape({
                 definitions: state.dmn.model.definitions,
                 drdIndex: state.computed(state).getDrdIndex(),
@@ -455,13 +565,12 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
                   },
                 },
               });
-            }
-          });
-
+            });
+          }
           console.debug(`DMN DIAGRAM: Adding DRG node`, 
JSON.stringify(drgElement));
         }
       },
-      [container, reactFlowInstance, dmnEditorStoreApi, 
externalModelsByNamespace]
+      [container, dmnEditorStoreApi, externalModelsByNamespace, 
reactFlowInstance]
     );
 
     const ongoingConnection = useDmnEditorStore((s) => 
s.diagram.ongoingConnection);
@@ -643,6 +752,10 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
                       drdIndex: state.computed(state).getDrdIndex(),
                       __readonly_dmnShapesByHref: 
state.computed(state).indexedDrd().dmnShapesByHref,
                       snapGrid: state.diagram.snapGrid,
+                      __readonly_dmnObjectNamespace: 
node.data.dmnObjectNamespace,
+                      __readonly_externalDmnsIndex: state
+                        .computed(state)
+                        
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
                       change: {
                         isExternal: !!node.data.dmnObjectQName.prefix,
                         nodeType: node.type as NodeType,
@@ -717,7 +830,11 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
 
                     for (let i = 0; i < 
containedDecisionHrefsRelativeToThisDmn.length; i++) {
                       const diagramData = 
state.computed(state).getDiagramData(externalModelsByNamespace);
-                      const nestedNode = 
diagramData.nodesById.get(containedDecisionHrefsRelativeToThisDmn[i])!;
+                      const nestedNode = 
diagramData.nodesById.get(containedDecisionHrefsRelativeToThisDmn[i]);
+                      if (nestedNode?.data?.shape === undefined) {
+                        // In case we have an incomple depiction of the 
decision service in the current DRD
+                        continue;
+                      }
                       const snappedNestedNodeShapeWithAppliedDelta = 
snapShapePosition(
                         state.diagram.snapGrid,
                         offsetShapePosition(nestedNode.data.shape, delta)
@@ -748,16 +865,18 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
                 console.debug(`DMN DIAGRAM: 'onNodesChange' --> remove 
'${change.id}'`);
                 const node = 
state.computed(state).getDiagramData(externalModelsByNamespace).nodesById.get(change.id)!;
                 deleteNode({
-                  drgEdges: 
state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges,
                   definitions: state.dmn.model.definitions,
-                  drdIndex: state.computed(state).getDrdIndex(),
-                  dmnObjectNamespace: node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
-                  dmnObjectQName: node.data.dmnObjectQName,
-                  dmnObjectId: node.data.dmnObject?.["@_id"],
-                  nodeNature: nodeNatures[node.type as NodeType],
+                  __readonly_drgEdges: 
state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges,
+                  __readonly_drdIndex: state.computed(state).getDrdIndex(),
+                  __readonly_dmnObjectNamespace:
+                    node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
+                  __readonly_dmnObjectQName: node.data.dmnObjectQName,
+                  __readonly_dmnObjectId: node.data.dmnObject?.["@_id"],
+                  __readonly_nodeNature: nodeNatures[node.type as NodeType],
                   mode: NodeDeletionMode.FROM_DRG_AND_ALL_DRDS,
-                  externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace)
-                    .dmns,
+                  __readonly_externalModelTypesByNamespace: state
+                    .computed(state)
+                    
.getExternalModelTypesByNamespace(externalModelsByNamespace),
                 });
                 state.dispatch(state).diagram.setNodeStatus(node.id, {
                   selected: false,
@@ -1126,10 +1245,15 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
       showEmptyState && nodes.length === 0 && 
drgElementsWithoutVisualRepresentationOnCurrentDrdLength === 0;
 
     const canAutoGenerateDrd = useDmnEditorStore((s) => 
s.diagram.autoLayout.canAutoGenerateDrd);
+    const drdsLength = useDmnEditorStore((s) => 
s.dmn.model.definitions["dmndi:DMNDI"]?.["dmndi:DMNDiagram"]?.length);
+
+    const showAutoGenerateDrdModal = useMemo(() => {
+      return canAutoGenerateDrd && drdsLength === undefined;
+    }, [canAutoGenerateDrd, drdsLength]);
 
     return (
       <>
-        {nodes.length === 0 && canAutoGenerateDrd && <DmnDiagramWithoutDrd />}
+        {showAutoGenerateDrdModal && <DmnDiagramWithoutDrd />}
         {isEmptyStateShowing && !canAutoGenerateDrd && <DmnDiagramEmptyState 
setShowEmptyState={setShowEmptyState} />}
         <DiagramContainerContextProvider container={container}>
           <svg style={{ position: "absolute", top: 0, left: 0 }}>
@@ -1201,7 +1325,6 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
 function DmnDiagramWithoutDrd() {
   const dmnEditorStoreApi = useDmnEditorStoreApi();
   const { externalModelsByNamespace } = useExternalModels();
-  const applyAutoLayout = useAutoLayout();
 
   return (
     <Bullseye
@@ -1281,25 +1404,30 @@ function DmnDiagramWithoutDrd() {
                 const dmnShapesByHref = 
dereferencedState.computed(dereferencedState).indexedDrd().dmnShapesByHref;
 
                 // Auto layout the new DRD
-                const { autolayouted, parentNodesById } = await autoLayout({
-                  snapGrid,
-                  nodesById,
-                  edgesById,
-                  nodes,
-                  drgEdges,
-                  isAlternativeInputDataShape,
+                const { __readonly_autoLayoutedInfo, 
__readonly_parentNodesById } = await getAutoLayoutedInfo({
+                  __readonly_snapGrid: snapGrid,
+                  __readonly_nodesById: nodesById,
+                  __readonly_edgesById: edgesById,
+                  __readonly_nodes: nodes,
+                  __readonly_drgEdges: drgEdges,
+                  __readonly_isAlternativeInputDataShape: 
isAlternativeInputDataShape,
                 });
 
                 dmnEditorStoreApi.setState((s) => {
                   s.diagram.autoLayout.canAutoGenerateDrd = false;
-                  applyAutoLayout({
-                    s: dereferencedState,
-                    dmnShapesByHref,
-                    edges: edges,
-                    edgesById: edgesById,
-                    nodesById: nodesById,
-                    autolayouted: autolayouted,
-                    parentNodesById: parentNodesById,
+                  applyAutoLayoutToDrd({
+                    state: dereferencedState,
+                    __readonly_dmnShapesByHref: dmnShapesByHref,
+                    __readonly_edges: edges,
+                    __readonly_edgesById: edgesById,
+                    __readonly_nodesById: nodesById,
+                    __readonly_autoLayoutedInfo,
+                    __readonly_parentNodesById,
+                    __readonly_drdIndex: 
dereferencedState.computed(dereferencedState).getDrdIndex(),
+                    __readonly_dmnObjectNamespace: 
dereferencedState.dmn.model.definitions["@_namespace"],
+                    __readonly_externalDmnsIndex: dereferencedState
+                      .computed(dereferencedState)
+                      
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
                   });
                   s.dmn.model = dereferencedState.dmn.model;
                 });
diff --git a/packages/dmn-editor/src/diagram/DiagramCommands.tsx 
b/packages/dmn-editor/src/diagram/DiagramCommands.tsx
index cabb6654d24..af73112a7e5 100644
--- a/packages/dmn-editor/src/diagram/DiagramCommands.tsx
+++ b/packages/dmn-editor/src/diagram/DiagramCommands.tsx
@@ -148,16 +148,18 @@ export function DiagramCommands(props: {}) {
             .forEach((node: RF.Node<DmnDiagramNodeData>) => {
               if (copiedNodesById.has(node.id)) {
                 deleteNode({
-                  drgEdges: 
state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges,
+                  __readonly_drgEdges: 
state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges,
                   definitions: state.dmn.model.definitions,
-                  drdIndex: state.computed(state).getDrdIndex(),
-                  dmnObjectNamespace: node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
-                  dmnObjectQName: node.data.dmnObjectQName,
-                  dmnObjectId: node.data.dmnObject?.["@_id"],
-                  nodeNature: nodeNatures[node.type as NodeType],
+                  __readonly_drdIndex: state.computed(state).getDrdIndex(),
+                  __readonly_dmnObjectNamespace:
+                    node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
+                  __readonly_dmnObjectQName: node.data.dmnObjectQName,
+                  __readonly_dmnObjectId: node.data.dmnObject?.["@_id"],
+                  __readonly_nodeNature: nodeNatures[node.type as NodeType],
                   mode: NodeDeletionMode.FROM_DRG_AND_ALL_DRDS,
-                  externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace)
-                    .dmns,
+                  __readonly_externalModelTypesByNamespace: state
+                    .computed(state)
+                    
.getExternalModelTypesByNamespace(externalModelsByNamespace),
                 });
                 state.dispatch(state).diagram.setNodeStatus(node.id, {
                   selected: false,
@@ -365,23 +367,25 @@ export function DiagramCommands(props: {}) {
           if (
             (selectedNodeIds.has(edge.source) &&
               canRemoveNodeFromDrdOnly({
-                externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace)
-                  .dmns,
+                __readonly_externalDmnsIndex: state
+                  .computed(state)
+                  
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
                 definitions: state.dmn.model.definitions,
-                drdIndex: state.computed(state).getDrdIndex(),
-                dmnObjectNamespace:
+                __readonly_drdIndex: state.computed(state).getDrdIndex(),
+                __readonly_dmnObjectNamespace:
                   nodesById.get(edge.source)!.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
-                dmnObjectId: 
nodesById.get(edge.source)!.data.dmnObject?.["@_id"],
+                __readonly_dmnObjectId: 
nodesById.get(edge.source)!.data.dmnObject?.["@_id"],
               })) ||
             (selectedNodeIds.has(edge.target) &&
               canRemoveNodeFromDrdOnly({
-                externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace)
-                  .dmns,
+                __readonly_externalDmnsIndex: state
+                  .computed(state)
+                  
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
                 definitions: state.dmn.model.definitions,
-                drdIndex: state.computed(state).getDrdIndex(),
-                dmnObjectNamespace:
+                __readonly_drdIndex: state.computed(state).getDrdIndex(),
+                __readonly_dmnObjectNamespace:
                   nodesById.get(edge.target)!.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
-                dmnObjectId: 
nodesById.get(edge.target)!.data.dmnObject?.["@_id"],
+                __readonly_dmnObjectId: 
nodesById.get(edge.target)!.data.dmnObject?.["@_id"],
               }))
           ) {
             deleteEdge({
@@ -400,14 +404,16 @@ export function DiagramCommands(props: {}) {
             continue;
           }
           const { deletedDmnShapeOnCurrentDrd: deletedShape } = deleteNode({
-            drgEdges: [], // Deleting from DRD only.
             definitions: state.dmn.model.definitions,
-            externalDmnsIndex: 
state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
-            drdIndex: state.computed(state).getDrdIndex(),
-            dmnObjectNamespace: node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
-            dmnObjectQName: node.data.dmnObjectQName,
-            dmnObjectId: node.data.dmnObject?.["@_id"],
-            nodeNature: nodeNatures[node.type as NodeType],
+            __readonly_drgEdges: [], // Deleting from DRD only.
+            __readonly_externalModelTypesByNamespace: state
+              .computed(state)
+              .getExternalModelTypesByNamespace(externalModelsByNamespace),
+            __readonly_drdIndex: state.computed(state).getDrdIndex(),
+            __readonly_dmnObjectNamespace: node.data.dmnObjectNamespace ?? 
state.dmn.model.definitions["@_namespace"],
+            __readonly_dmnObjectQName: node.data.dmnObjectQName,
+            __readonly_dmnObjectId: node.data.dmnObject?.["@_id"],
+            __readonly_nodeNature: nodeNatures[node.type as NodeType],
             mode: NodeDeletionMode.FROM_CURRENT_DRD_ONLY,
           });
 
diff --git a/packages/dmn-editor/src/diagram/nodes/Nodes.tsx 
b/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
index b95c96b4bd5..724e8a7a4a0 100644
--- a/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
+++ b/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
@@ -869,7 +869,7 @@ export const DecisionServiceNode = React.memo(
 
     const ref = useRef<SVGRectElement>(null);
     const isExternal = !!dmnObjectQName.prefix;
-
+    const { externalModelsByNamespace } = useExternalModels();
     const snapGrid = useDmnEditorStore((s) => s.diagram.snapGrid);
     const enableCustomNodeStyles = useDmnEditorStore((s) => 
s.diagram.overlays.enableCustomNodeStyles);
     const isHovered = useIsHovered(ref);
@@ -959,6 +959,10 @@ export const DecisionServiceNode = React.memo(
               drdIndex: state.computed(state).getDrdIndex(),
               __readonly_dmnShapesByHref: 
state.computed(state).indexedDrd().dmnShapesByHref,
               drgElementIndex: index,
+              __readonly_dmnObjectNamespace: dmnObjectNamespace,
+              __readonly_externalDmnsIndex: state
+                .computed(state)
+                
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
               shapeIndex: shape.index,
               localYPosition: e.y,
               snapGrid: state.diagram.snapGrid,
@@ -975,7 +979,7 @@ export const DecisionServiceNode = React.memo(
       return () => {
         selection.on(".drag", null);
       };
-    }, [decisionService, dmnEditorStoreApi, id, index, shape.index]);
+    }, [decisionService, dmnEditorStoreApi, dmnObjectNamespace, 
externalModelsByNamespace, id, index, shape.index]);
 
     const { fontCssProperties, shapeStyle } = useNodeStyle({
       dmnStyle: shape["di:Style"],
diff --git 
a/packages/dmn-editor/src/mutations/addExistingDecisionServiceToDrd.ts 
b/packages/dmn-editor/src/mutations/addExistingDecisionServiceToDrd.ts
index 279dcabbf0b..3dcedc844c1 100644
--- a/packages/dmn-editor/src/mutations/addExistingDecisionServiceToDrd.ts
+++ b/packages/dmn-editor/src/mutations/addExistingDecisionServiceToDrd.ts
@@ -17,74 +17,91 @@
  * under the License.
  */
 
+import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
 import {
   DMN15__tDecisionService,
   DMN15__tDefinitions,
 } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
-import { DECISION_SERVICE_COLLAPSED_DIMENSIONS } from 
"../diagram/nodes/DefaultSizes";
+import { ExternalModelsIndex } from "../DmnEditor";
+import { getAutoLayoutedInfo } from "../autolayout/autoLayoutInfo";
+import { DECISION_SERVICE_COLLAPSED_DIMENSIONS, MIN_NODE_SIZES } from 
"../diagram/nodes/DefaultSizes";
 import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
-import { Computed } from "../store/Store";
+import { Normalized } from "../normalization/normalize";
+import { Computed, SnapGrid, State } from "../store/Store";
 import { computeContainingDecisionServiceHrefsByDecisionHrefs } from 
"../store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts";
+import { computeDiagramData } from "../store/computed/computeDiagramData";
+import { computeExternalModelsByType } from 
"../store/computed/computeExternalModelsByType";
 import { computeIndexedDrd } from "../store/computed/computeIndexes";
 import { xmlHrefToQName } from "../xml/xmlHrefToQName";
 import { buildXmlHref, parseXmlHref } from "../xml/xmlHrefs";
+import { addOrGetDrd } from "./addOrGetDrd";
 import { addShape } from "./addShape";
+import { applyAutoLayoutToDrd } from "./applyAutoLayoutToDrd";
 import { repositionNode } from "./repositionNode";
-import { Normalized } from "../normalization/normalize";
-import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
+
+export enum StrategyForAddingDecisionServiceToDrd {
+  AUTO_GENERATE,
+  CONFLICT,
+  COPY_FROM_ANOTHER_DRD,
+}
 
 /**
  * When adding a Decision Service to a DRD, we need to bring all its 
encapsulated and output Decisions with it,
  * copying their layout from other DRDs, or formatting with autolayout.
+ * This method returns the strategy to be used when adding a Decision Service.
+ * The strategy should be used to call one of three methods:
+ *  - AUTO_GENERATE: addAutoGeneratedDecisionServiceToDrd
+ *  - CONFLICT: addConflictingDecisionServiceToDrd
+ *  - COPY_FROM_ANOTHER_DRD: addExistingDecisionServiceToDrd
  */
-export function addExistingDecisionServiceToDrd({
-  decisionServiceNamespace,
-  decisionService,
-  externalDmnsIndex,
-  thisDmnsNamespace,
-  thisDmnsDefinitions,
-  thisDmnsIndexedDrd,
-  drdIndex,
-  dropPoint,
+export function getStrategyToAddExistingDecisionServiceToDrd({
+  __readonly_definitions,
+  __readonly_decisionServiceNamespace,
+  __readonly_drgElement,
+  __readonly_externalDmnsIndex,
+  __readonly_namespace,
+  __readonly_indexedDrd,
+  __readonly_drdIndex,
 }: {
-  decisionServiceNamespace: string;
-  decisionService: Normalized<DMN15__tDecisionService>;
-  externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
-  thisDmnsNamespace: string;
-  thisDmnsDefinitions: Normalized<DMN15__tDefinitions>;
-  thisDmnsIndexedDrd: ReturnType<Computed["indexedDrd"]>;
-  drdIndex: number;
-  dropPoint: { x: number; y: number };
+  __readonly_definitions: Normalized<DMN15__tDefinitions>;
+  __readonly_decisionServiceNamespace: string;
+  __readonly_drgElement: Normalized<DMN15__tDecisionService>;
+  __readonly_externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
+  __readonly_namespace: string;
+  __readonly_indexedDrd: ReturnType<Computed["indexedDrd"]>;
+  __readonly_drdIndex: number;
 }) {
   const decisionServiceDmnDefinitions =
-    !decisionServiceNamespace || decisionServiceNamespace === thisDmnsNamespace
-      ? thisDmnsDefinitions
-      : externalDmnsIndex.get(decisionServiceNamespace)?.model.definitions;
+    !__readonly_decisionServiceNamespace || 
__readonly_decisionServiceNamespace === __readonly_namespace
+      ? __readonly_definitions
+      : 
__readonly_externalDmnsIndex.get(__readonly_decisionServiceNamespace)?.model.definitions;
   if (!decisionServiceDmnDefinitions) {
-    throw new Error(`DMN MUTATION: Can't find definitions for model with 
namespace ${decisionServiceNamespace}`);
+    throw new Error(
+      `DMN MUTATION: Can't find definitions for model with namespace 
${__readonly_decisionServiceNamespace}`
+    );
   }
   const { decisionServiceNamespaceForHref, 
containedDecisionHrefsRelativeToThisDmn } =
     getDecisionServicePropertiesRelativeToThisDmn({
-      thisDmnsNamespace,
-      decisionServiceNamespace,
-      decisionService,
+      thisDmnsNamespace: __readonly_namespace,
+      decisionServiceNamespace: __readonly_decisionServiceNamespace,
+      decisionService: __readonly_drgElement,
     });
 
   const decisionServiceHrefRelativeToThisDmn = buildXmlHref({
     namespace: decisionServiceNamespaceForHref,
-    id: decisionService["@_id"]!,
+    id: __readonly_drgElement["@_id"]!,
   });
 
   const containingDecisionServiceHrefsByDecisionHrefsRelativeToThisDmn =
     computeContainingDecisionServiceHrefsByDecisionHrefs({
-      thisDmnsNamespace,
-      drgElementsNamespace: decisionServiceNamespace,
+      thisDmnsNamespace: __readonly_namespace,
+      drgElementsNamespace: __readonly_decisionServiceNamespace,
       drgElements: decisionServiceDmnDefinitions.drgElement,
     });
 
   const doesThisDrdHaveConflictingDecisionService = 
containedDecisionHrefsRelativeToThisDmn.some((decisionHref) =>
     
(containingDecisionServiceHrefsByDecisionHrefsRelativeToThisDmn.get(decisionHref)
 ?? []).some((d) =>
-      thisDmnsIndexedDrd.dmnShapesByHref.has(d)
+      __readonly_indexedDrd.dmnShapesByHref.has(d)
     )
   );
 
@@ -92,34 +109,21 @@ export function addExistingDecisionServiceToDrd({
     // There's already, in this DRD, a Decision Service in expanded form that 
contains a Decision that is contained by the Decision Service we're adding.
     // As the DMN specification doesn't allow two copies of the same DRG 
element to be depicted in the same DRD, we can't add the Decision Service in 
expanded form.
     // To not disallow depicting the Decision Service in this DRD, though, we 
add it in collpased form.
-    addShape({
-      definitions: thisDmnsDefinitions,
-      drdIndex,
-      nodeType: NODE_TYPES.decisionService,
-      shape: {
-        "@_id": generateUuid(),
-        "@_dmnElementRef": 
xmlHrefToQName(decisionServiceHrefRelativeToThisDmn, thisDmnsDefinitions),
-        "@_isCollapsed": true,
-        "dc:Bounds": {
-          "@_x": dropPoint.x,
-          "@_y": dropPoint.y,
-          "@_width": DECISION_SERVICE_COLLAPSED_DIMENSIONS.width,
-          "@_height": DECISION_SERVICE_COLLAPSED_DIMENSIONS.height,
-        },
-      },
-    });
-    return;
+    return {
+      strategyForAddingDecisionServiceToDrd: 
StrategyForAddingDecisionServiceToDrd.CONFLICT,
+      decisionServiceHrefRelativeToThisDmn,
+      containedDecisionHrefsRelativeToThisDmn,
+    };
   }
 
   const drds = 
decisionServiceDmnDefinitions["dmndi:DMNDI"]?.["dmndi:DMNDiagram"] ?? [];
-
   let indexedDrd: ReturnType<Computed["indexedDrd"]> | undefined;
   for (let i = 0; i < drds.length; i++) {
-    if (thisDmnsNamespace === decisionServiceNamespace && i === drdIndex) {
+    if (__readonly_namespace === __readonly_decisionServiceNamespace && i === 
__readonly_drdIndex) {
       continue; // Skip the current DRD!
     }
 
-    const _indexedDrd = computeIndexedDrd(thisDmnsNamespace, 
decisionServiceDmnDefinitions, i);
+    const _indexedDrd = computeIndexedDrd(__readonly_namespace, 
decisionServiceDmnDefinitions, i);
     const dsShape = 
_indexedDrd.dmnShapesByHref.get(decisionServiceHrefRelativeToThisDmn);
     const hasCompleteExpandedDepictionOfDecisionService =
       dsShape &&
@@ -132,97 +136,381 @@ export function addExistingDecisionServiceToDrd({
     }
   }
 
-  if (!indexedDrd) {
-    // There's no DRD which inclues a complete expanded depiction of the 
Decision Service. Let's proceed with auto-layout.
-    // TODO: Tiago
+  if (indexedDrd === undefined) {
+    return {
+      strategyForAddingDecisionServiceToDrd: 
StrategyForAddingDecisionServiceToDrd.AUTO_GENERATE,
+      decisionServiceHrefRelativeToThisDmn,
+      containedDecisionHrefsRelativeToThisDmn,
+    };
   } else {
-    // Let's copy the expanded depiction of the Decision Service from `drd`.
-    // Adding or moving nodes that already exist in the current DRD to inside 
the Decision Service.
-    // The positions need all be relative to the Decision Service node, of 
course.
-    const dsShapeOnOtherDrd = 
indexedDrd.dmnShapesByHref.get(decisionServiceHrefRelativeToThisDmn);
-    if (
-      dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_x"] === undefined ||
-      dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] === undefined
-    ) {
+    return {
+      strategyForAddingDecisionServiceToDrd: 
StrategyForAddingDecisionServiceToDrd.COPY_FROM_ANOTHER_DRD,
+      indexedDrdContainingDecisionServiceDepiction: indexedDrd,
+      decisionServiceHrefRelativeToThisDmn,
+      containedDecisionHrefsRelativeToThisDmn,
+    };
+  }
+}
+
+export function addConflictingDecisionServiceToDrd({
+  definitions,
+  __readonly_drdIndex,
+  __readonly_dropPoint,
+  __readonly_decisionServiceHrefRelativeToThisDmn,
+}: {
+  definitions: Normalized<DMN15__tDefinitions>;
+  __readonly_drdIndex: number;
+  __readonly_dropPoint: { x: number; y: number };
+  __readonly_decisionServiceHrefRelativeToThisDmn: string;
+}) {
+  addShape({
+    definitions: definitions,
+    drdIndex: __readonly_drdIndex,
+    nodeType: NODE_TYPES.decisionService,
+    shape: {
+      "@_id": generateUuid(),
+      "@_dmnElementRef": 
xmlHrefToQName(__readonly_decisionServiceHrefRelativeToThisDmn, definitions),
+      "@_isCollapsed": true,
+      "dc:Bounds": {
+        "@_x": __readonly_dropPoint.x,
+        "@_y": __readonly_dropPoint.y,
+        "@_width": DECISION_SERVICE_COLLAPSED_DIMENSIONS.width,
+        "@_height": DECISION_SERVICE_COLLAPSED_DIMENSIONS.height,
+      },
+    },
+  });
+}
+
+export async function addAutoGeneratedDecisionServiceToDrd({
+  state,
+  __readonly_decisionServiceNamespace,
+  __readonly_externalDmnsIndex,
+  __readonly_drdIndex,
+  __readonly_snapGrid,
+  __readonly_decisionServiceHrefRelativeToThisDmn,
+  __readonly_containedDecisionHrefsRelativeToThisDmn,
+  __readonly_dropPoint,
+  __readonly_isAlternativeInputDataShape,
+  __readonly_externalModelsByNamespace,
+}: {
+  state: State;
+  __readonly_decisionServiceNamespace: string;
+  __readonly_externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
+  __readonly_drdIndex: number;
+  __readonly_snapGrid: SnapGrid;
+  __readonly_decisionServiceHrefRelativeToThisDmn: string;
+  __readonly_containedDecisionHrefsRelativeToThisDmn: string[];
+  __readonly_dropPoint: { x: number; y: number };
+  __readonly_isAlternativeInputDataShape: boolean;
+  __readonly_externalModelsByNamespace: ExternalModelsIndex | undefined;
+}) {
+  const drds = 
state.dmn.model.definitions["dmndi:DMNDI"]?.["dmndi:DMNDiagram"];
+  // Create a Dummy DRD
+  // In case the model doesn't have a DRD, the Dummy DRD will be the new DRD.
+  // Otherwise, the Dummy DRD will be the next index.
+  const dummyDrdIndex = drds?.length === undefined ? 0 : drds.length;
+  addOrGetDrd({
+    definitions: state.dmn.model.definitions,
+    drdIndex: dummyDrdIndex,
+  });
+
+  // Add the Decision Service
+  const minNodeSize = MIN_NODE_SIZES[NODE_TYPES.decisionService]({
+    snapGrid: __readonly_snapGrid,
+  });
+  addShape({
+    definitions: state.dmn.model.definitions,
+    drdIndex: dummyDrdIndex,
+    nodeType: NODE_TYPES.decisionService,
+    shape: {
+      "@_id": generateUuid(),
+      "@_dmnElementRef": 
xmlHrefToQName(__readonly_decisionServiceHrefRelativeToThisDmn, 
state.dmn.model.definitions),
+      "dc:Bounds": {
+        "@_x": 0, // Auto-layout will be applied;
+        "@_y": 0, // Auto-layout will be applied;
+        ...minNodeSize,
+      },
+    },
+  });
+
+  // Add all Encapsulated and Output Decisions
+  for (const decisionHref of 
__readonly_containedDecisionHrefsRelativeToThisDmn) {
+    const decisionNs = parseXmlHref(decisionHref).namespace;
+    const decisionDmnDefinitions =
+      !decisionNs || decisionNs === state.dmn.model.definitions["@_namespace"]
+        ? state.dmn.model.definitions
+        : __readonly_externalDmnsIndex.get(decisionNs)?.model.definitions;
+    if (!decisionDmnDefinitions) {
       throw new Error(
-        `DMN MUTATION: Complete DMNShape for Decision Service with href 
${decisionServiceHrefRelativeToThisDmn} should've existed on the indexed DRD.`
+        `DMN MUTATION: Can't find definitions for model with namespace 
${__readonly_decisionServiceNamespace}`
       );
     }
-
+    const minNodeSize = MIN_NODE_SIZES[NODE_TYPES.decision]({
+      snapGrid: __readonly_snapGrid,
+    });
     addShape({
-      definitions: thisDmnsDefinitions,
-      drdIndex,
-      nodeType: NODE_TYPES.decisionService,
+      definitions: state.dmn.model.definitions,
+      drdIndex: dummyDrdIndex,
+      nodeType: NODE_TYPES.decision,
       shape: {
         "@_id": generateUuid(),
-        "@_dmnElementRef": 
xmlHrefToQName(decisionServiceHrefRelativeToThisDmn, thisDmnsDefinitions),
+        "@_dmnElementRef": xmlHrefToQName(decisionHref, 
state.dmn.model.definitions),
         "dc:Bounds": {
-          "@_x": dropPoint.x,
-          "@_y": dropPoint.y,
-          "@_width": dsShapeOnOtherDrd["dc:Bounds"]["@_width"],
-          "@_height": dsShapeOnOtherDrd["dc:Bounds"]["@_height"],
+          "@_x": 0, // Auto-layout will be applied;
+          "@_y": 0, // Auto-layout will be applied;
+          ...minNodeSize,
         },
       },
     });
+  }
+
+  // Compute the external model types by namespace after autogenerating the 
Decision Service
+  const externalModelTypesByNamespace = computeExternalModelsByType(
+    state.dmn.model.definitions.import,
+    __readonly_externalModelsByNamespace
+  );
+
+  // Compute the Dummy DRD indexed drd after autogenerating the Decision 
Service
+  const dummyIndexedDrd = computeIndexedDrd(
+    state.dmn.model.definitions["@_namespace"],
+    state.dmn.model.definitions,
+    dummyDrdIndex
+  );
+
+  // Compute the Dummy DRD diagram data after autogenerating the Decision 
Service
+  const { nodes, nodesById, edges, edgesById, drgEdges } = computeDiagramData(
+    state.diagram,
+    state.dmn.model.definitions,
+    externalModelTypesByNamespace,
+    dummyIndexedDrd,
+    __readonly_isAlternativeInputDataShape
+  );
+
+  // Get the auto-layout info
+  const { __readonly_autoLayoutedInfo, __readonly_parentNodesById } = await 
getAutoLayoutedInfo({
+    __readonly_snapGrid,
+    __readonly_nodesById: nodesById,
+    __readonly_edgesById: edgesById,
+    __readonly_nodes: nodes,
+    __readonly_drgEdges: drgEdges,
+    __readonly_isAlternativeInputDataShape: 
__readonly_isAlternativeInputDataShape,
+  });
+
+  // Apply the auto-layouted info to the Dummy DRD
+  applyAutoLayoutToDrd({
+    state,
+    __readonly_dmnShapesByHref: dummyIndexedDrd.dmnShapesByHref,
+    __readonly_edges: edges,
+    __readonly_edgesById: edgesById,
+    __readonly_nodesById: nodesById,
+    __readonly_autoLayoutedInfo,
+    __readonly_parentNodesById,
+    __readonly_drdIndex: dummyDrdIndex,
+    __readonly_dmnObjectNamespace: __readonly_decisionServiceNamespace,
+    __readonly_externalDmnsIndex: externalModelTypesByNamespace.dmns,
+  });
+
+  // Save DS shape before applying the autolayout
+  const { "@_x": dsShapeX, "@_y": dsShapeY } = 
dummyIndexedDrd.dmnShapesByHref.get(
+    __readonly_decisionServiceHrefRelativeToThisDmn
+  )!["dc:Bounds"]!;
+  // Reposition the auto generated Decision Service to the drop point
+  repositionNode({
+    definitions: state.dmn.model.definitions,
+    drdIndex: dummyDrdIndex,
+    controlWaypointsByEdge: new Map(),
+    change: {
+      nodeType: NODE_TYPES.decisionService,
+      type: "absolute",
+      position: { x: __readonly_dropPoint.x, y: __readonly_dropPoint.y },
+      shapeIndex: 
dummyIndexedDrd.dmnShapesByHref.get(__readonly_decisionServiceHrefRelativeToThisDmn)?.index
 ?? 0,
+      selectedEdges: [],
+      sourceEdgeIndexes: [],
+      targetEdgeIndexes: [],
+    },
+  });
+
+  // Relatively reposition the auto generated Decisions to the drop point
+  for (const decisionHref of 
__readonly_containedDecisionHrefsRelativeToThisDmn) {
+    const currentDecisionShape = 
dummyIndexedDrd.dmnShapesByHref.get(decisionHref);
+
+    const x = __readonly_dropPoint.x + 
currentDecisionShape!["dc:Bounds"]!["@_x"] - dsShapeX;
+    const y = __readonly_dropPoint.y + 
currentDecisionShape!["dc:Bounds"]!["@_y"] - dsShapeY;
+
+    if (currentDecisionShape) {
+      repositionNode({
+        definitions: state.dmn.model.definitions,
+        drdIndex: dummyDrdIndex,
+        controlWaypointsByEdge: new Map(),
+        change: {
+          nodeType: NODE_TYPES.decision,
+          type: "absolute",
+          position: { x, y },
+          shapeIndex: currentDecisionShape.index,
+          selectedEdges: [],
+          sourceEdgeIndexes: [],
+          targetEdgeIndexes: [],
+        },
+      });
+    }
+  }
+
+  // Copy the DS and Decisions to current DRD and remove Dummy DRD;
+  if (dummyDrdIndex !== __readonly_drdIndex) {
+    // The auto generated shape.
+    const dsShape = 
dummyIndexedDrd.dmnShapesByHref.get(__readonly_decisionServiceHrefRelativeToThisDmn)!;
+    drds![__readonly_drdIndex]["dmndi:DMNDiagramElement"] ??= [];
+    drds?.[__readonly_drdIndex]["dmndi:DMNDiagramElement"]?.push({ ...dsShape, 
__$$element: "dmndi:DMNShape" });
+    for (const decisionHref of 
__readonly_containedDecisionHrefsRelativeToThisDmn) {
+      const decisionShape = dummyIndexedDrd.dmnShapesByHref.get(decisionHref)!;
+      drds?.[__readonly_drdIndex]["dmndi:DMNDiagramElement"]?.push({
+        ...decisionShape,
+        __$$element: "dmndi:DMNShape",
+      });
+    }
+    drds?.pop(); // Remove Dummy DRD;
+  } else {
+    // In this case Dummy DRD is the current DRD
+  }
+}
+
+export function addExistingDecisionServiceToDrd({
+  definitions,
+  __readonly_decisionServiceNamespace,
+  __readonly_externalDmnsIndex,
+  __readonly_namespace,
+  __readonly_indexedDrd,
+  __readonly_indexedDrdContainingDecisionServiceDepiction,
+  __readonly_drdIndex,
+  __readonly_dropPoint,
+  __readonly_decisionServiceHrefRelativeToThisDmn,
+  __readonly_containedDecisionHrefsRelativeToThisDmn,
+}: {
+  definitions: Normalized<DMN15__tDefinitions>;
+  __readonly_decisionServiceNamespace: string;
+  __readonly_externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
+  __readonly_namespace: string;
+  __readonly_indexedDrd: ReturnType<Computed["indexedDrd"]>;
+  __readonly_indexedDrdContainingDecisionServiceDepiction: 
ReturnType<Computed["indexedDrd"]>;
+  __readonly_drdIndex: number;
+  __readonly_dropPoint: { x: number; y: number };
+  __readonly_decisionServiceHrefRelativeToThisDmn: string;
+  __readonly_containedDecisionHrefsRelativeToThisDmn: string[];
+}) {
+  // Let's copy the expanded depiction of the Decision Service from `drd`.
+  // Adding or moving nodes that already exist in the current DRD to inside 
the Decision Service.
+  // The positions need all be relative to the Decision Service node, of 
course.
+  const dsShapeOnOtherDrd = 
__readonly_indexedDrdContainingDecisionServiceDepiction.dmnShapesByHref.get(
+    __readonly_decisionServiceHrefRelativeToThisDmn
+  );
+  if (
+    dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_x"] === undefined ||
+    dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] === undefined
+  ) {
+    throw new Error(
+      `DMN MUTATION: Complete DMNShape for Decision Service with href 
${__readonly_decisionServiceHrefRelativeToThisDmn} should've existed on the 
indexed DRD.`
+    );
+  }
+
+  const dsDividirLineOnOtherDrd = 
dsShapeOnOtherDrd["dmndi:DMNDecisionServiceDividerLine"];
+  const decisionServiceDividerLineWaypoint = [
+    {
+      "@_x": __readonly_dropPoint.x,
+      "@_y":
+        (dsDividirLineOnOtherDrd?.["di:waypoint"]?.[0]["@_y"] ?? 0) -
+        (dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] ?? 0) +
+        __readonly_dropPoint.y,
+    },
+    {
+      "@_x":
+        (dsDividirLineOnOtherDrd?.["di:waypoint"]?.[1]["@_x"] ?? 0) -
+        (dsDividirLineOnOtherDrd?.["di:waypoint"]?.[0]["@_x"] ?? 0) +
+        __readonly_dropPoint.x,
+      "@_y":
+        (dsDividirLineOnOtherDrd?.["di:waypoint"]?.[0]["@_y"] ?? 0) -
+        (dsShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] ?? 0) +
+        __readonly_dropPoint.y,
+    },
+  ];
+  addShape({
+    definitions: definitions,
+    drdIndex: __readonly_drdIndex,
+    nodeType: NODE_TYPES.decisionService,
+    shape: {
+      "@_id": generateUuid(),
+      "@_dmnElementRef": 
xmlHrefToQName(__readonly_decisionServiceHrefRelativeToThisDmn, definitions),
+      "dc:Bounds": {
+        "@_x": __readonly_dropPoint.x,
+        "@_y": __readonly_dropPoint.y,
+        "@_width": dsShapeOnOtherDrd["dc:Bounds"]["@_width"],
+        "@_height": dsShapeOnOtherDrd["dc:Bounds"]["@_height"],
+      },
+    },
+    decisionServiceDividerLineWaypoint,
+  });
 
-    for (const decisionHref of containedDecisionHrefsRelativeToThisDmn) {
-      const decisionShapeOnOtherDrd = 
indexedDrd.dmnShapesByHref.get(decisionHref);
-      if (
-        decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_x"] === undefined ||
-        decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] === undefined ||
-        decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_width"] === undefined ||
-        decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_height"] === undefined
-      ) {
+  for (const decisionHref of 
__readonly_containedDecisionHrefsRelativeToThisDmn) {
+    const decisionShapeOnOtherDrd =
+      
__readonly_indexedDrdContainingDecisionServiceDepiction.dmnShapesByHref.get(decisionHref);
+    if (
+      decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_x"] === undefined ||
+      decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_y"] === undefined ||
+      decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_width"] === undefined ||
+      decisionShapeOnOtherDrd?.["dc:Bounds"]?.["@_height"] === undefined
+    ) {
+      throw new Error(
+        `DMN MUTATION: Complete DMNShape for Decision with href 
${decisionHref} should've existed on the indexed DRD.`
+      );
+    }
+
+    const x =
+      __readonly_dropPoint.x + (decisionShapeOnOtherDrd["dc:Bounds"]["@_x"] - 
dsShapeOnOtherDrd["dc:Bounds"]["@_x"]);
+    const y =
+      __readonly_dropPoint.y + (decisionShapeOnOtherDrd["dc:Bounds"]["@_y"] - 
dsShapeOnOtherDrd["dc:Bounds"]["@_y"]);
+
+    const existingDecisionShape = 
__readonly_indexedDrd.dmnShapesByHref.get(decisionHref);
+    if (existingDecisionShape) {
+      repositionNode({
+        definitions: definitions,
+        drdIndex: __readonly_drdIndex,
+        controlWaypointsByEdge: new Map(),
+        change: {
+          nodeType: NODE_TYPES.decision,
+          type: "absolute",
+          position: { x, y },
+          shapeIndex: existingDecisionShape.index,
+          selectedEdges: [],
+          sourceEdgeIndexes: [],
+          targetEdgeIndexes: [],
+        },
+      });
+    } else {
+      const decisionNs = parseXmlHref(decisionHref).namespace;
+      const decisionDmnDefinitions =
+        !decisionNs || decisionNs === __readonly_namespace
+          ? definitions
+          : __readonly_externalDmnsIndex.get(decisionNs)?.model.definitions;
+      if (!decisionDmnDefinitions) {
         throw new Error(
-          `DMN MUTATION: Complete DMNShape for Decision with href 
${decisionHref} should've existed on the indexed DRD.`
+          `DMN MUTATION: Can't find definitions for model with namespace 
${__readonly_decisionServiceNamespace}`
         );
       }
 
-      const x = dropPoint.x + (decisionShapeOnOtherDrd["dc:Bounds"]["@_x"] - 
dsShapeOnOtherDrd["dc:Bounds"]["@_x"]);
-      const y = dropPoint.y + (decisionShapeOnOtherDrd["dc:Bounds"]["@_y"] - 
dsShapeOnOtherDrd["dc:Bounds"]["@_y"]);
-
-      const existingDecisionShape = 
thisDmnsIndexedDrd.dmnShapesByHref.get(decisionHref);
-      if (existingDecisionShape) {
-        repositionNode({
-          definitions: thisDmnsDefinitions,
-          drdIndex,
-          controlWaypointsByEdge: new Map(),
-          change: {
-            nodeType: NODE_TYPES.decision,
-            type: "absolute",
-            position: { x, y },
-            shapeIndex: existingDecisionShape.index,
-            selectedEdges: [],
-            sourceEdgeIndexes: [],
-            targetEdgeIndexes: [],
-          },
-        });
-      } else {
-        const decisionNs = parseXmlHref(decisionHref).namespace;
-        const decisionDmnDefinitions =
-          !decisionNs || decisionNs === thisDmnsNamespace
-            ? thisDmnsDefinitions
-            : externalDmnsIndex.get(decisionNs)?.model.definitions;
-        if (!decisionDmnDefinitions) {
-          throw new Error(`DMN MUTATION: Can't find definitions for model with 
namespace ${decisionServiceNamespace}`);
-        }
-
-        addShape({
-          definitions: thisDmnsDefinitions,
-          drdIndex,
-          nodeType: NODE_TYPES.decision,
-          shape: {
-            "@_id": generateUuid(),
-            "@_dmnElementRef": xmlHrefToQName(decisionHref, 
thisDmnsDefinitions),
-            "dc:Bounds": {
-              "@_x": x,
-              "@_y": y,
-              "@_width": decisionShapeOnOtherDrd["dc:Bounds"]["@_width"],
-              "@_height": decisionShapeOnOtherDrd["dc:Bounds"]["@_height"],
-            },
+      addShape({
+        definitions: definitions,
+        drdIndex: __readonly_drdIndex,
+        nodeType: NODE_TYPES.decision,
+        shape: {
+          "@_id": generateUuid(),
+          "@_dmnElementRef": xmlHrefToQName(decisionHref, definitions),
+          "dc:Bounds": {
+            "@_x": x,
+            "@_y": y,
+            "@_width": decisionShapeOnOtherDrd["dc:Bounds"]["@_width"],
+            "@_height": decisionShapeOnOtherDrd["dc:Bounds"]["@_height"],
           },
-        });
-      }
+        },
+      });
     }
   }
 }
diff --git a/packages/dmn-editor/src/mutations/addOrGetDrd.ts 
b/packages/dmn-editor/src/mutations/addOrGetDrd.ts
index 4247ba79b03..6cf19f7928c 100644
--- a/packages/dmn-editor/src/mutations/addOrGetDrd.ts
+++ b/packages/dmn-editor/src/mutations/addOrGetDrd.ts
@@ -32,7 +32,7 @@ export function addOrGetDrd({
   definitions: Normalized<DMN15__tDefinitions>;
   drdIndex: number;
 }) {
-  const defaultName = getDefaultDrdName({ drdIndex });
+  const drdName = getDefaultDrdName({ drdIndex: drdIndex });
 
   // diagram
   definitions["dmndi:DMNDI"] ??= {};
@@ -41,7 +41,7 @@ export function addOrGetDrd({
 
   const defaultDiagram = 
definitions["dmndi:DMNDI"]["dmndi:DMNDiagram"][drdIndex];
   defaultDiagram["@_id"] ??= generateUuid();
-  defaultDiagram["@_name"] ??= defaultName;
+  defaultDiagram["@_name"] ??= drdName;
   defaultDiagram["@_useAlternativeInputDataShape"] ??= false;
   defaultDiagram["dmndi:DMNDiagramElement"] ??= [];
 
diff --git a/packages/dmn-editor/src/mutations/addShape.ts 
b/packages/dmn-editor/src/mutations/addShape.ts
index 9c5e795e412..fd716e34ae6 100644
--- a/packages/dmn-editor/src/mutations/addShape.ts
+++ b/packages/dmn-editor/src/mutations/addShape.ts
@@ -17,29 +17,42 @@
  * under the License.
  */
 
-import { DMN15__tDefinitions, DMNDI15__DMNShape } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
+import {
+  DC__Point,
+  DMN15__tDefinitions,
+  DMNDI15__DMNDecisionServiceDividerLine,
+  DMNDI15__DMNShape,
+} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { NodeType } from "../diagram/connections/graphStructure";
 import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
 import { Normalized } from "../normalization/normalize";
 import { addOrGetDrd } from "./addOrGetDrd";
 import { getCentralizedDecisionServiceDividerLine } from 
"./updateDecisionServiceDividerLine";
+import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
 
 export function addShape({
   definitions,
   drdIndex,
   nodeType,
   shape,
+  decisionServiceDividerLineWaypoint: decisionServiceDividerLineWaypoint,
 }: {
   definitions: Normalized<DMN15__tDefinitions>;
   drdIndex: number;
   nodeType: NodeType;
   shape: Normalized<DMNDI15__DMNShape>;
+  decisionServiceDividerLineWaypoint?: DC__Point[];
 }) {
   const { diagramElements } = addOrGetDrd({ definitions, drdIndex });
   diagramElements.push({
     __$$element: "dmndi:DMNShape",
     ...(nodeType === NODE_TYPES.decisionService
-      ? { "dmndi:DMNDecisionServiceDividerLine": 
getCentralizedDecisionServiceDividerLine(shape["dc:Bounds"]!) }
+      ? {
+          "dmndi:DMNDecisionServiceDividerLine":
+            decisionServiceDividerLineWaypoint !== undefined
+              ? { "@_id": generateUuid(), "di:waypoint": 
[...decisionServiceDividerLineWaypoint] }
+              : getCentralizedDecisionServiceDividerLine(shape["dc:Bounds"]!),
+        }
       : {}),
     ...shape,
   });
diff --git a/packages/dmn-editor/src/mutations/applyAutoLayoutToDrd.ts 
b/packages/dmn-editor/src/mutations/applyAutoLayoutToDrd.ts
new file mode 100644
index 00000000000..0f3786a1b83
--- /dev/null
+++ b/packages/dmn-editor/src/mutations/applyAutoLayoutToDrd.ts
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DMNDI15__DMNShape } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
+import { XmlQName } from "@kie-tools/xml-parser-ts/dist/qNames";
+import * as Elk from "elkjs/lib/elk.bundled.js";
+import * as RF from "reactflow";
+import { EdgeType, NodeType } from "../diagram/connections/graphStructure";
+import { PositionalNodeHandleId } from 
"../diagram/connections/PositionalNodeHandles";
+import { DmnDiagramEdgeData } from "../diagram/edges/Edges";
+import { DmnDiagramNodeData } from "../diagram/nodes/Nodes";
+import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
+import { addEdge } from "../mutations/addEdge";
+import { repositionNode } from "../mutations/repositionNode";
+import { resizeNode } from "../mutations/resizeNode";
+import { updateDecisionServiceDividerLine } from 
"../mutations/updateDecisionServiceDividerLine";
+import { Normalized } from "../normalization/normalize";
+import { State } from "../store/Store";
+import { AutolayoutParentNode, FAKE_MARKER, visitNodeAndNested } from 
"../autolayout/autoLayoutInfo";
+import { ExternalDmnsIndex } from "../DmnEditor";
+
+export function applyAutoLayoutToDrd({
+  state,
+  __readonly_autoLayoutedInfo,
+  __readonly_parentNodesById,
+  __readonly_nodesById,
+  __readonly_edgesById,
+  __readonly_edges,
+  __readonly_dmnShapesByHref,
+  __readonly_drdIndex,
+  __readonly_dmnObjectNamespace,
+  __readonly_externalDmnsIndex,
+}: {
+  state: State;
+  __readonly_autoLayoutedInfo: {
+    isHorizontal: boolean;
+    nodes: Elk.ElkNode[] | undefined;
+    edges: Elk.ElkExtendedEdge[] | undefined;
+  };
+  __readonly_parentNodesById: Map<string, AutolayoutParentNode>;
+  __readonly_nodesById: Map<string, RF.Node<DmnDiagramNodeData, string | 
undefined>>;
+  __readonly_edgesById: Map<string, RF.Edge<DmnDiagramEdgeData>>;
+  __readonly_edges: RF.Edge<DmnDiagramEdgeData>[];
+  __readonly_dmnShapesByHref: Map<
+    string,
+    Normalized<DMNDI15__DMNShape> & {
+      index: number;
+      dmnElementRefQName: XmlQName;
+    }
+  >;
+  __readonly_drdIndex: number;
+  __readonly_dmnObjectNamespace: string | undefined;
+  __readonly_externalDmnsIndex: ExternalDmnsIndex;
+}) {
+  // 7. Update all nodes positions skipping empty groups, which will be 
positioned manually after all nodes are done being repositioned.
+  const autolayoutedElkNodesById = new Map<string, Elk.ElkNode>();
+
+  for (const topLevelElkNode of __readonly_autoLayoutedInfo.nodes ?? []) {
+    visitNodeAndNested(topLevelElkNode, { x: 100, y: 100 }, (elkNode, 
positionOffset) => {
+      if (elkNode.id.includes(FAKE_MARKER)) {
+        return;
+      }
+
+      autolayoutedElkNodesById.set(elkNode.id, elkNode);
+
+      const nodeId = elkNode.id;
+      const node = __readonly_nodesById.get(nodeId)!;
+
+      repositionNode({
+        definitions: state.dmn.model.definitions,
+        drdIndex: __readonly_drdIndex,
+        controlWaypointsByEdge: new Map(),
+        change: {
+          nodeType: node.type as NodeType,
+          type: "absolute",
+          position: {
+            x: elkNode.x! + positionOffset.x,
+            y: elkNode.y! + positionOffset.y,
+          },
+          selectedEdges: [...__readonly_edgesById.keys()],
+          shapeIndex: node.data?.shape.index,
+          sourceEdgeIndexes: __readonly_edges.flatMap((e) =>
+            e.source === nodeId && e.data?.dmnEdge ? [e.data.dmnEdge.index] : 
[]
+          ),
+          targetEdgeIndexes: __readonly_edges.flatMap((e) =>
+            e.target === nodeId && e.data?.dmnEdge ? [e.data.dmnEdge.index] : 
[]
+          ),
+        },
+      });
+    });
+  }
+
+  // 8. Resize all nodes using the sizes calculated by ELK.
+  for (const topLevelElkNode of __readonly_autoLayoutedInfo.nodes ?? []) {
+    visitNodeAndNested(topLevelElkNode, { x: 0, y: 0 }, (elkNode) => {
+      if (elkNode.id.includes(FAKE_MARKER)) {
+        return;
+      }
+
+      const nodeId = elkNode.id;
+      const node = __readonly_nodesById.get(nodeId)!;
+
+      resizeNode({
+        definitions: state.dmn.model.definitions,
+        drdIndex: __readonly_drdIndex,
+        __readonly_dmnShapesByHref: __readonly_dmnShapesByHref,
+        snapGrid: state.diagram.snapGrid,
+        __readonly_dmnObjectNamespace,
+        __readonly_externalDmnsIndex,
+        change: {
+          index: node.data.index,
+          isExternal: !!node.data.dmnObjectQName.prefix,
+          nodeType: node.type as NodeType,
+          dimension: {
+            "@_width": elkNode.width!,
+            "@_height": elkNode.height!,
+          },
+          shapeIndex: node.data?.shape.index,
+          sourceEdgeIndexes: __readonly_edges.flatMap((e) =>
+            e.source === nodeId && e.data?.dmnEdge ? [e.data.dmnEdge.index] : 
[]
+          ),
+          targetEdgeIndexes: __readonly_edges.flatMap((e) =>
+            e.target === nodeId && e.data?.dmnEdge ? [e.data.dmnEdge.index] : 
[]
+          ),
+        },
+      });
+    });
+  }
+
+  // 9. Updating Decision Service divider lines after all nodes are 
repositioned and resized.
+  for (const [parentNodeId] of __readonly_parentNodesById) {
+    const parentNode = __readonly_nodesById.get(parentNodeId);
+    if (parentNode?.type !== NODE_TYPES.decisionService) {
+      continue;
+    }
+
+    const elkNode = autolayoutedElkNodesById.get(parentNodeId);
+    if (!elkNode) {
+      throw new Error(`Couldn't find Decision Service with id ${parentNode.id} 
at the autolayouted nodes map`);
+    }
+
+    /**
+     * The second children of a Decision Service elkNode is a node 
representing the Encapsulated section.
+     * It's Y position will be exactly where the divider line should be.
+     */
+    const dividerLinerLocalYPosition = elkNode.children?.[1]?.y;
+    if (!dividerLinerLocalYPosition) {
+      throw new Error(
+        `Couldn't find second child (which represents the Encapuslated 
Decision section) of Decision Service with id ${parentNode.id} at the 
autolayouted nodes map`
+      );
+    }
+
+    updateDecisionServiceDividerLine({
+      definitions: state.dmn.model.definitions,
+      drdIndex: __readonly_drdIndex,
+      __readonly_dmnShapesByHref,
+      __readonly_dmnObjectNamespace,
+      __readonly_externalDmnsIndex,
+      drgElementIndex: parentNode.data.index,
+      shapeIndex: parentNode.data.shape.index,
+      snapGrid: state.diagram.snapGrid,
+      localYPosition: dividerLinerLocalYPosition,
+    });
+  }
+
+  // 10. Update the edges. Edges always go from top to bottom, removing 
waypoints.
+  for (const elkEdge of __readonly_autoLayoutedInfo.edges ?? []) {
+    if (elkEdge.id.includes(FAKE_MARKER)) {
+      continue;
+    }
+
+    const edge = __readonly_edgesById.get(elkEdge.id)!;
+
+    const sourceNode = __readonly_nodesById.get(elkEdge.sources[0])!;
+    const targetNode = __readonly_nodesById.get(elkEdge.targets[0])!;
+
+    // If the target is an external node, we don't have to create the edge.
+    if (targetNode.data.dmnObjectQName.prefix) {
+      continue;
+    }
+
+    addEdge({
+      definitions: state.dmn.model.definitions,
+      drdIndex: __readonly_drdIndex,
+      edge: {
+        autoPositionedEdgeMarker: undefined,
+        type: edge.type as EdgeType,
+        targetHandle: PositionalNodeHandleId.Bottom,
+        sourceHandle: PositionalNodeHandleId.Top,
+      },
+      sourceNode: {
+        type: sourceNode.type as NodeType,
+        href: sourceNode.id,
+        data: sourceNode.data,
+        bounds: sourceNode.data.shape["dc:Bounds"]!,
+        shapeId: sourceNode.data.shape["@_id"],
+      },
+      targetNode: {
+        type: targetNode.type as NodeType,
+        href: targetNode.id,
+        data: targetNode.data,
+        bounds: targetNode.data.shape["dc:Bounds"]!,
+        index: targetNode.data.index,
+        shapeId: targetNode.data.shape["@_id"],
+      },
+      keepWaypoints: false,
+    });
+  }
+}
diff --git a/packages/dmn-editor/src/mutations/deleteImport.ts 
b/packages/dmn-editor/src/mutations/deleteImport.ts
index ca2617e3260..34aa40bcc7a 100644
--- a/packages/dmn-editor/src/mutations/deleteImport.ts
+++ b/packages/dmn-editor/src/mutations/deleteImport.ts
@@ -61,13 +61,13 @@ export function deleteImport({
     externalNodesByNamespace.get(deletedImport["@_namespace"])?.forEach((node) 
=> {
       deleteNode({
         definitions,
-        drgEdges: drgEdges,
-        drdIndex: 0,
-        nodeNature: nodeNatures[node.type! as NodeType],
-        dmnObjectId: node.data.dmnObject?.["@_id"],
-        dmnObjectQName: node.data.dmnObjectQName,
-        dmnObjectNamespace: node.data.dmnObjectNamespace!,
-        externalDmnsIndex: __readonly_externalModelTypesByNamespace.dmns,
+        __readonly_drgEdges: drgEdges,
+        __readonly_drdIndex: 0,
+        __readonly_nodeNature: nodeNatures[node.type! as NodeType],
+        __readonly_dmnObjectId: node.data.dmnObject?.["@_id"],
+        __readonly_dmnObjectQName: node.data.dmnObjectQName,
+        __readonly_dmnObjectNamespace: node.data.dmnObjectNamespace!,
+        __readonly_externalModelTypesByNamespace,
         mode: NodeDeletionMode.FROM_DRG_AND_ALL_DRDS,
       });
     });
diff --git a/packages/dmn-editor/src/mutations/deleteNode.ts 
b/packages/dmn-editor/src/mutations/deleteNode.ts
index 5a732691650..5f4affe9fa4 100644
--- a/packages/dmn-editor/src/mutations/deleteNode.ts
+++ b/packages/dmn-editor/src/mutations/deleteNode.ts
@@ -31,6 +31,7 @@ import { Computed } from "../store/Store";
 import { computeContainingDecisionServiceHrefsByDecisionHrefs } from 
"../store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts";
 import { xmlHrefToQName } from "../xml/xmlHrefToQName";
 import { Normalized } from "../normalization/normalize";
+import { NodeDmnObjects } from "../diagram/nodes/Nodes";
 
 export enum NodeDeletionMode {
   FROM_DRG_AND_ALL_DRDS,
@@ -39,23 +40,23 @@ export enum NodeDeletionMode {
 
 export function deleteNode({
   definitions,
-  drgEdges,
-  drdIndex,
-  nodeNature,
-  dmnObjectId,
-  dmnObjectQName,
-  dmnObjectNamespace,
-  externalDmnsIndex,
+  __readonly_drgEdges,
+  __readonly_drdIndex,
+  __readonly_nodeNature,
+  __readonly_dmnObjectId,
+  __readonly_dmnObjectNamespace,
+  __readonly_dmnObjectQName,
+  __readonly_externalModelTypesByNamespace,
   mode,
 }: {
   definitions: Normalized<DMN15__tDefinitions>;
-  drgEdges: DrgEdge[];
-  drdIndex: number;
-  nodeNature: NodeNature;
-  externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
-  dmnObjectNamespace: string;
-  dmnObjectId: string | undefined;
-  dmnObjectQName: XmlQName;
+  __readonly_drgEdges: DrgEdge[];
+  __readonly_drdIndex: number;
+  __readonly_nodeNature: NodeNature;
+  __readonly_externalModelTypesByNamespace: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>;
+  __readonly_dmnObjectId: string | undefined;
+  __readonly_dmnObjectNamespace: string;
+  __readonly_dmnObjectQName: XmlQName;
   mode: NodeDeletionMode;
 }): {
   deletedDmnObject: Unpacked<Normalized<DMN15__tDefinitions>["drgElement" | 
"artifact"]> | undefined;
@@ -65,10 +66,10 @@ export function deleteNode({
     mode === NodeDeletionMode.FROM_CURRENT_DRD_ONLY &&
     !canRemoveNodeFromDrdOnly({
       definitions,
-      drdIndex,
-      dmnObjectNamespace,
-      dmnObjectId,
-      externalDmnsIndex,
+      __readonly_drdIndex,
+      __readonly_dmnObjectNamespace,
+      __readonly_dmnObjectId,
+      __readonly_externalDmnsIndex: 
__readonly_externalModelTypesByNamespace.dmns,
     })
   ) {
     console.warn("DMN MUTATION: Cannot hide a Decision that's contained by a 
Decision Service from a DRD.");
@@ -78,14 +79,18 @@ export function deleteNode({
   if (mode === NodeDeletionMode.FROM_DRG_AND_ALL_DRDS) {
     // Delete Edges
     // A DRD doesn't necessarily renders all edges of the DRG, so we need to 
look for what DRG edges to delete when deleting a node from any DRD.
-    const nodeId = buildXmlHref({ namespace: dmnObjectNamespace, id: 
dmnObjectId! });
-    for (let i = 0; i < drgEdges.length; i++) {
-      const drgEdge = drgEdges[i];
+    const nodeId = buildXmlHref({
+      namespace:
+        __readonly_dmnObjectNamespace === definitions["@_namespace"] ? 
undefined : __readonly_dmnObjectNamespace,
+      id: __readonly_dmnObjectId!,
+    });
+    for (let i = 0; i < __readonly_drgEdges.length; i++) {
+      const drgEdge = __readonly_drgEdges[i];
       // Only delete edges that end at or start from the node being deleted.
       if (drgEdge.sourceId === nodeId || drgEdge.targetId === nodeId) {
         deleteEdge({
           definitions,
-          drdIndex,
+          drdIndex: __readonly_drdIndex,
           mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS,
           edge: {
             id: drgEdge.id,
@@ -108,61 +113,61 @@ export function deleteNode({
     }
   }
 
-  let dmnObject: Unpacked<Normalized<DMN15__tDefinitions>["drgElement" | 
"artifact"]> | undefined;
+  let deletedDmnObject: Unpacked<Normalized<DMN15__tDefinitions>["drgElement" 
| "artifact"]> | undefined;
 
   // External or unknown nodes don't have a dmnObject associated with it, just 
the shape..
-  if (!dmnObjectQName.prefix) {
+  if (!__readonly_dmnObjectQName.prefix) {
     // Delete the dmnObject itself
-    if (nodeNature === NodeNature.ARTIFACT) {
+    if (__readonly_nodeNature === NodeNature.ARTIFACT) {
       if (mode === NodeDeletionMode.FROM_DRG_AND_ALL_DRDS) {
-        const nodeIndex = (definitions.artifact ?? []).findIndex((a) => 
a["@_id"] === dmnObjectId);
-        dmnObject = definitions.artifact?.splice(nodeIndex, 1)?.[0];
+        const nodeIndex = (definitions.artifact ?? []).findIndex((a) => 
a["@_id"] === __readonly_dmnObjectId);
+        deletedDmnObject = definitions.artifact?.splice(nodeIndex, 1)?.[0];
       } else {
         throw new Error(`DMN MUTATION: Can't hide an artifact node.`);
       }
-    } else if (nodeNature === NodeNature.DRG_ELEMENT) {
-      const nodeIndex = (definitions.drgElement ?? []).findIndex((d) => 
d["@_id"] === dmnObjectId);
-      dmnObject =
+    } else if (__readonly_nodeNature === NodeNature.DRG_ELEMENT) {
+      const nodeIndex = (definitions.drgElement ?? []).findIndex((d) => 
d["@_id"] === __readonly_dmnObjectId);
+      deletedDmnObject =
         mode === NodeDeletionMode.FROM_DRG_AND_ALL_DRDS
           ? definitions.drgElement?.splice(nodeIndex, 1)?.[0]
           : definitions.drgElement?.[nodeIndex];
-    } else if (nodeNature === NodeNature.UNKNOWN) {
+    } else if (__readonly_nodeNature === NodeNature.UNKNOWN) {
       // Ignore. There's no dmnObject here.
     } else {
-      throw new Error(`DMN MUTATION: Unknown node nature '${nodeNature}'.`);
+      throw new Error(`DMN MUTATION: Unknown node nature 
'${__readonly_nodeNature}'.`);
     }
 
-    if (!dmnObject && nodeNature !== NodeNature.UNKNOWN) {
+    if (!deletedDmnObject && __readonly_nodeNature !== NodeNature.UNKNOWN) {
       /**
        * We do not want to throw error in case of `nodeNature` equals to 
`NodeNature.UNKNOWN`.
        * In such scenario it is expected `dmnObject` is undefined as we can 
not pair `dmnObject` with the `DMNShape`.
        * However we are still able to delete at least the selected `DMNShape` 
from the diagram.
        */
-      throw new Error(`DMN MUTATION: Can't delete DMN object that doesn't 
exist: ID=${dmnObjectId}`);
+      throw new Error(`DMN MUTATION: Can't delete DMN object that doesn't 
exist: ID=${__readonly_dmnObjectId}`);
     }
   }
 
-  const shapeDmnElementRef = buildXmlQName(dmnObjectQName);
+  const shapeDmnElementRef = buildXmlQName(__readonly_dmnObjectQName);
 
   // Deleting the DMNShape's
   let deletedDmnShapeOnCurrentDrd: Normalized<DMNDI15__DMNShape> | undefined;
 
-  const deletedIdsOnDmnObjectTree = dmnObject
+  const deletedIdsOnDmnObjectTree = deletedDmnObject
     ? getNewDmnIdRandomizer()
-        .ack({ json: [dmnObject], type: "DMN15__tDefinitions", attr: 
"drgElement" })
+        .ack({ json: [deletedDmnObject], type: "DMN15__tDefinitions", attr: 
"drgElement" })
         .getOriginalIds()
     : new Set<string>();
 
   const drdCount = (definitions["dmndi:DMNDI"]?.["dmndi:DMNDiagram"] ?? 
[]).length;
   for (let i = 0; i < drdCount; i++) {
-    if (mode === NodeDeletionMode.FROM_CURRENT_DRD_ONLY && i !== drdIndex) {
+    if (mode === NodeDeletionMode.FROM_CURRENT_DRD_ONLY && i !== 
__readonly_drdIndex) {
       continue;
     }
 
     const { diagramElements, widthsExtension } = addOrGetDrd({ definitions, 
drdIndex: i });
     const dmnShapeIndex = (diagramElements ?? []).findIndex((d) => 
d["@_dmnElementRef"] === shapeDmnElementRef);
     if (dmnShapeIndex >= 0) {
-      if (i === drdIndex) {
+      if (i === __readonly_drdIndex) {
         deletedDmnShapeOnCurrentDrd = diagramElements[dmnShapeIndex];
       }
 
@@ -178,40 +183,40 @@ export function deleteNode({
   repopulateInputDataAndDecisionsOnAllDecisionServices({ definitions });
 
   return {
-    deletedDmnObject: mode === NodeDeletionMode.FROM_DRG_AND_ALL_DRDS ? 
dmnObject : undefined,
+    deletedDmnObject: mode === NodeDeletionMode.FROM_DRG_AND_ALL_DRDS ? 
deletedDmnObject : undefined,
     deletedDmnShapeOnCurrentDrd,
   };
 }
 
 export function canRemoveNodeFromDrdOnly({
   definitions,
-  drdIndex,
-  dmnObjectNamespace,
-  dmnObjectId,
-  externalDmnsIndex,
+  __readonly_drdIndex,
+  __readonly_dmnObjectNamespace,
+  __readonly_dmnObjectId,
+  __readonly_externalDmnsIndex,
 }: {
-  dmnObjectNamespace: string;
-  dmnObjectId: string | undefined;
   definitions: Normalized<DMN15__tDefinitions>;
-  drdIndex: number;
-  externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
+  __readonly_dmnObjectNamespace: string;
+  __readonly_dmnObjectId: string | undefined;
+  __readonly_drdIndex: number;
+  __readonly_externalDmnsIndex: 
ReturnType<Computed["getExternalModelTypesByNamespace"]>["dmns"];
 }) {
-  const { diagramElements } = addOrGetDrd({ definitions, drdIndex });
+  const { diagramElements } = addOrGetDrd({ definitions, drdIndex: 
__readonly_drdIndex });
 
   const dmnObjectHref = buildXmlHref({
-    namespace: dmnObjectNamespace === definitions["@_namespace"] ? "" : 
dmnObjectNamespace,
-    id: dmnObjectId!,
+    namespace: __readonly_dmnObjectNamespace === definitions["@_namespace"] ? 
undefined : __readonly_dmnObjectNamespace,
+    id: __readonly_dmnObjectId!,
   });
 
   const drgElements =
-    definitions["@_namespace"] === dmnObjectNamespace
+    definitions["@_namespace"] === __readonly_dmnObjectNamespace
       ? definitions.drgElement ?? []
-      : 
externalDmnsIndex.get(dmnObjectNamespace)?.model.definitions.drgElement ?? [];
+      : 
__readonly_externalDmnsIndex.get(__readonly_dmnObjectNamespace)?.model.definitions.drgElement
 ?? [];
 
   const containingDecisionServiceHrefsByDecisionHrefsRelativeToThisDmn =
     computeContainingDecisionServiceHrefsByDecisionHrefs({
       thisDmnsNamespace: definitions["@_namespace"],
-      drgElementsNamespace: dmnObjectNamespace,
+      drgElementsNamespace: __readonly_dmnObjectNamespace,
       drgElements,
     });
 
diff --git a/packages/dmn-editor/src/mutations/resizeNode.ts 
b/packages/dmn-editor/src/mutations/resizeNode.ts
index 6199148f5d3..ee991a1cc90 100644
--- a/packages/dmn-editor/src/mutations/resizeNode.ts
+++ b/packages/dmn-editor/src/mutations/resizeNode.ts
@@ -34,11 +34,14 @@ import { SnapGrid } from "../store/Store";
 import { addOrGetDrd } from "./addOrGetDrd";
 import { DECISION_SERVICE_DIVIDER_LINE_PADDING } from 
"./updateDecisionServiceDividerLine";
 import { Normalized } from "../normalization/normalize";
+import { ExternalDmnsIndex } from "../DmnEditor";
 
 export function resizeNode({
   definitions,
   drdIndex,
   __readonly_dmnShapesByHref,
+  __readonly_dmnObjectNamespace,
+  __readonly_externalDmnsIndex,
   snapGrid,
   change,
 }: {
@@ -46,6 +49,8 @@ export function resizeNode({
   drdIndex: number;
   __readonly_dmnShapesByHref: Map<string, Normalized<DMNDI15__DMNShape> & { 
index: number }>;
   snapGrid: SnapGrid;
+  __readonly_dmnObjectNamespace: string | undefined;
+  __readonly_externalDmnsIndex: ExternalDmnsIndex;
   change: {
     nodeType: NodeType;
     isExternal: boolean;
@@ -68,7 +73,15 @@ export function resizeNode({
 
   const limit = { x: 0, y: 0 };
   if (change.nodeType === NODE_TYPES.decisionService) {
-    const ds = definitions.drgElement![change.index] as 
Normalized<DMN15__tDecisionService>;
+    const externalDmn = 
__readonly_externalDmnsIndex.get(__readonly_dmnObjectNamespace ?? "");
+
+    const ds =
+      externalDmn === undefined
+        ? (definitions.drgElement![change.index] as 
Normalized<DMN15__tDecisionService>)
+        : (externalDmn.model.definitions.drgElement![change.index] as 
Normalized<DMN15__tDecisionService>);
+    if (!ds) {
+      throw new Error("DMN MUTATION: Cannot reposition divider line of 
non-existent Decision Service");
+    }
 
     const dividerLineY =
       
shape["dmndi:DMNDecisionServiceDividerLine"]?.["di:waypoint"]?.[0]?.["@_y"] ?? 
shapeBounds["@_y"];
diff --git 
a/packages/dmn-editor/src/mutations/updateDecisionServiceDividerLine.ts 
b/packages/dmn-editor/src/mutations/updateDecisionServiceDividerLine.ts
index 5b0b3d2c684..d92ca3a67d1 100644
--- a/packages/dmn-editor/src/mutations/updateDecisionServiceDividerLine.ts
+++ b/packages/dmn-editor/src/mutations/updateDecisionServiceDividerLine.ts
@@ -31,6 +31,8 @@ import { SnapGrid } from "../store/Store";
 import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
 import { Normalized } from "../normalization/normalize";
 import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
+import { addNamespaceToHref } from "../xml/xmlHrefs";
+import { ExternalDmnsIndex } from "../DmnEditor";
 
 export const DECISION_SERVICE_DIVIDER_LINE_PADDING = 100;
 
@@ -38,6 +40,8 @@ export function updateDecisionServiceDividerLine({
   definitions,
   drdIndex,
   __readonly_dmnShapesByHref,
+  __readonly_dmnObjectNamespace,
+  __readonly_externalDmnsIndex,
   shapeIndex,
   localYPosition,
   drgElementIndex,
@@ -46,6 +50,8 @@ export function updateDecisionServiceDividerLine({
   definitions: Normalized<DMN15__tDefinitions>;
   drdIndex: number;
   __readonly_dmnShapesByHref: Map<string, Normalized<DMNDI15__DMNShape> & { 
index: number }>;
+  __readonly_dmnObjectNamespace: string | undefined;
+  __readonly_externalDmnsIndex: ExternalDmnsIndex;
   shapeIndex: number;
   localYPosition: number;
   drgElementIndex: number;
@@ -59,7 +65,12 @@ export function updateDecisionServiceDividerLine({
     throw new Error("DMN MUTATION: Cannot reposition divider line of 
non-existent shape bounds");
   }
 
-  const ds = definitions.drgElement![drgElementIndex] as 
Normalized<DMN15__tDecisionService>;
+  const externalDmn = 
__readonly_externalDmnsIndex.get(__readonly_dmnObjectNamespace ?? "");
+
+  const ds =
+    externalDmn === undefined
+      ? (definitions.drgElement![drgElementIndex] as 
Normalized<DMN15__tDecisionService>)
+      : (externalDmn.model.definitions.drgElement![drgElementIndex] as 
Normalized<DMN15__tDecisionService>);
   if (!ds) {
     throw new Error("DMN MUTATION: Cannot reposition divider line of 
non-existent Decision Service");
   }
@@ -71,14 +82,32 @@ export function updateDecisionServiceDividerLine({
   const snappedDimensions = snapShapeDimensions(snapGrid, shape, 
decisionServiceMinSizes);
 
   const upperLimit = (ds.outputDecision ?? []).reduce((acc, od) => {
+    // For external Decision Services, the Output Decision will have the 
relative namespace. e.g. without namespace.
+    const href =
+      __readonly_dmnObjectNamespace !== undefined
+        ? addNamespaceToHref({
+            href: od["@_href"],
+            namespace:
+              definitions["@_namespace"] === __readonly_dmnObjectNamespace ? 
undefined : __readonly_dmnObjectNamespace,
+          })
+        : od["@_href"];
     const v =
-      snapShapePosition(snapGrid, 
__readonly_dmnShapesByHref.get(od["@_href"])!).y +
-      snapShapeDimensions(snapGrid, 
__readonly_dmnShapesByHref.get(od["@_href"])!, decisionMinSizes).height;
+      snapShapePosition(snapGrid, __readonly_dmnShapesByHref.get(href)!).y +
+      snapShapeDimensions(snapGrid, __readonly_dmnShapesByHref.get(href)!, 
decisionMinSizes).height;
     return v > acc ? v : acc;
   }, snappedPosition.y + DECISION_SERVICE_DIVIDER_LINE_PADDING);
 
   const lowerLimit = (ds.encapsulatedDecision ?? []).reduce((acc, ed) => {
-    const v = snapShapePosition(snapGrid, 
__readonly_dmnShapesByHref.get(ed["@_href"])!).y;
+    // For external Decision Services, the Encapsulated Decision will have the 
relative namespace. e.g. without namespace.
+    const href =
+      __readonly_dmnObjectNamespace !== undefined
+        ? addNamespaceToHref({
+            href: ed["@_href"],
+            namespace:
+              definitions["@_namespace"] === __readonly_dmnObjectNamespace ? 
undefined : __readonly_dmnObjectNamespace,
+          })
+        : ed["@_href"];
+    const v = snapShapePosition(snapGrid, 
__readonly_dmnShapesByHref.get(href)!).y;
     return v < acc ? v : acc;
   }, snappedPosition.y + snappedDimensions.height - 
DECISION_SERVICE_DIVIDER_LINE_PADDING);
 
diff --git 
a/packages/dmn-editor/src/store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts.ts
 
b/packages/dmn-editor/src/store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts.ts
index 1c579853d9f..6365fa7fb88 100644
--- 
a/packages/dmn-editor/src/store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts.ts
+++ 
b/packages/dmn-editor/src/store/computed/computeContainingDecisionServiceHrefsByDecisionHrefs.ts.ts
@@ -31,7 +31,7 @@ export function 
computeContainingDecisionServiceHrefsByDecisionHrefs({
   drgElements: State["dmn"]["model"]["definitions"]["drgElement"];
 }) {
   drgElements ??= [];
-  const decisionServiecHrefsByDecisionHrefs = new Map<string, string[]>();
+  const decisionServiceHrefsByDecisionHrefs = new Map<string, string[]>();
 
   for (const drgElement of drgElements) {
     const drgElementHref = buildXmlHref({
@@ -41,9 +41,9 @@ export function 
computeContainingDecisionServiceHrefsByDecisionHrefs({
 
     // Decision
     if (drgElement.__$$element === "decision") {
-      decisionServiecHrefsByDecisionHrefs.set(
+      decisionServiceHrefsByDecisionHrefs.set(
         drgElementHref,
-        decisionServiecHrefsByDecisionHrefs.get(drgElementHref) ?? []
+        decisionServiceHrefsByDecisionHrefs.get(drgElementHref) ?? []
       );
     }
     // DS
@@ -55,8 +55,8 @@ export function 
computeContainingDecisionServiceHrefsByDecisionHrefs({
       });
 
       for (const containedDecisionHref of 
containedDecisionHrefsRelativeToThisDmn) {
-        decisionServiecHrefsByDecisionHrefs.set(containedDecisionHref, [
-          ...(decisionServiecHrefsByDecisionHrefs.get(containedDecisionHref) 
?? []),
+        decisionServiceHrefsByDecisionHrefs.set(containedDecisionHref, [
+          ...(decisionServiceHrefsByDecisionHrefs.get(containedDecisionHref) 
?? []),
           drgElementHref,
         ]);
       }
@@ -65,5 +65,5 @@ export function 
computeContainingDecisionServiceHrefsByDecisionHrefs({
     }
   }
 
-  return decisionServiecHrefsByDecisionHrefs;
+  return decisionServiceHrefsByDecisionHrefs;
 }
diff --git a/packages/dmn-editor/src/xml/xmlHrefs.ts 
b/packages/dmn-editor/src/xml/xmlHrefs.ts
index 2419b86a930..4fa05444828 100644
--- a/packages/dmn-editor/src/xml/xmlHrefs.ts
+++ b/packages/dmn-editor/src/xml/xmlHrefs.ts
@@ -39,3 +39,24 @@ export function parseXmlHref(href: string): XmlHref {
 
   return { namespace: split[0] ? split[0] : undefined, id: split[1] };
 }
+
+/**
+ * This function adds a `namespace` to an HREF. This operation will only 
succed if
+ * the provided HREF doesn't have a `namespace`.
+ *
+ * In case the provided `namespace` is `undefined`, this function will return 
the HREF.
+ *
+ * In case the provided HREF already have an `namespace`, this function will 
return the HREF.
+ */
+export function addNamespaceToHref({ href, namespace }: { href: string; 
namespace: string | undefined }) {
+  if (namespace === undefined) {
+    return href;
+  }
+
+  const { namespace: hrefNamespace, id } = parseXmlHref(href);
+  if (hrefNamespace !== undefined) {
+    return href;
+  }
+
+  return buildXmlHref({ namespace, id });
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to