private string generateStepFlow(StepTiming timing, string nidReturn)
        {
            var firstNode = new NRFunctionNode();
            var prev      = firstNode;

            foreach (var parTiming in timing.ParallelTimings)
            {
                var next = new NRJoinFunctionNode();
                // prev will be written in this invocation.
                generateParallelFlow(parTiming, prev, next);
                prev = next;
            }
            // For understandability.
            var last = prev;

            last.Wire(nidReturn);
            last.WriteTo(_writer);
            return(firstNode.Id);
        }
        private void generateParallelFlow(ParallelTiming timing, NRFunctionNode prev, NRJoinFunctionNode next)
        {
            var svcmap = _activity.ServiceMap;

            foreach (var anim in timing.Animations)
            {
                var service = svcmap.Lookup(anim.ShapeId);
                if (null == service)
                {
                    // No available service for the shape.
                    continue;
                }

                JObject flowObj;
                using (var flow =
                           anim.Type == AnimationType.Entrance ?
                           service.ActivationFlow :
                           service.DeactivationFlow)
                    using (var flowReader = flow.Reader)
                    {
                        flowObj = (JObject)JToken.ReadFrom(flowReader);
                    }
                var meta   = (JObject)flowObj["meta"];
                var nidIn  = (string)meta["in"];
                var nidOut = (string)meta["out"];

                var topic =
                    $@"{service.nodeName}-{(anim.Type == AnimationType.Entrance ? "activation" : "deactivation")}";
                var nodeTopic = new NRFunctionNode(func: $"msg.topic = '{topic}';return msg;");
                nodeTopic.Wire(next.Id);
                nodeTopic.WriteTo(_writer);

                nidIn = generateCopyOfFlow((JArray)flowObj["flow"], nidIn, nidOut, nodeTopic.Id);

                // If this animation effect has a delay, put a delay node.
                var nidFirst = nidIn;
                if (anim.HasDefiniteDelay && anim.Delay > 0)
                {
                    var nodeDelay = new NRDelayNode(anim.Delay);
                    nodeDelay.Wire(nidIn);
                    nodeDelay.WriteTo(_writer);
                    nidFirst = nodeDelay.Id;
                }

                prev.Wire(nidFirst);

                next.AddTopic(topic);
            }
            prev.WriteTo(_writer);
        }