/// <summary>
        /// Creates a new <see cref="Controller"/> instance.
        /// </summary>
        /// <param name="tagController">The tag controller used by the created controller.</param>
        /// <param name="controllerTag">The tag, the new controller is dependend on.</param>
        /// <param name="userDefinedInterfaces">User defined interfaces</param>
        /// <param name="tagListener">A tag listener instance</param>
        /// <returns>A new <see cref="Controller"/> instance.</returns>
        public Controller Create(
            ITagController tagController,
            IControllerTag controllerTag,
            IList <string> userDefinedInterfaces,
            ITagListener tagListener)
        {
            var controller = Create(tagController, controllerTag, tagListener);

            if (userDefinedInterfaces != null)
            {
                tagListener.AddUdtHandler <Command>(CmdList.PlcArrayDataType());

                foreach (var userDefinedInterface in userDefinedInterfaces.Where(value => !string.IsNullOrWhiteSpace(value)))
                {
                    var path = TagName.SpecificInterface(parent: null).AppendTagName(userDefinedInterface);

                    var userDefinedInterfaceTags = ChildTagsFromPath(controllerTag, path);
                    controller.AddUserDefinedInterface(path, userDefinedInterfaceTags);

                    // create the commands
                    foreach (var userDefinedInterfaceTag in userDefinedInterfaceTags)
                    {
                        var commands = CreateCommands(controllerTag, controller, userDefinedInterfaceTag, tagListener);
                        controller.UpdateUserDefinedCommands(userDefinedInterfaceTag.NestedName, commands.ToList());
                    }
                }
            }

            return(controller);
        }
        private IEnumerable <Impl.Command> CreateCommands(
            IControllerTag controllerTag,
            Controller controller,
            Tag userDefinedInterfaceTag,
            ITagListener tagListener)
        {
            var commandsTag = controller.FindTag(TagName.CmdList(parent: null), userDefinedInterfaceTag);

            if (commandsTag != null)
            {
                Tag modeTag    = null;
                Tag commandTag = null;

                // assuming that the job interface is defined in the parent tag of the commandsTag
                var jobTag = commandsTag.Parent;

                // get the mode tag
                modeTag    = controller.FindTag(TagName.Mode(parent: null), jobTag);
                commandTag = controller.FindTag(TagName.ManualCommand(parent: null), jobTag);

                if (jobTag.NestedName != TagName.Job(parent: null) ||
                    modeTag == null || commandTag == null)
                {
                    throw new InvalidOperationException(new StringBuilder()
                                                        .AppendFormat("The {0} is not defined inside a {1} structure for the controller {2} or ",
                                                                      TagName.CmdList(parent: null),
                                                                      TagName.Job(parent: null),
                                                                      controller.Name)
                                                        .AppendFormat("the {0} or {1} was not defined in the {2} structure. ",
                                                                      TagName.Mode(parent: null),
                                                                      TagName.ManualCommand(parent: null),
                                                                      TagName.Job(parent: null))
                                                        .AppendLine()
                                                        .AppendFormat("Set the {0} as a subelement of a valid {1} structure.",
                                                                      commandsTag.Name, TagName.Job(parent: null)).ToString());
                }

                tagListener.ReadTagSynchronously(commandsTag);
                var commands     = commandsTag.ArrayValues <Command>();
                int commandIndex = 0;

                if (commands.Any(c => c == null))
                {
                    throw new InvalidOperationException(new StringBuilder()
                                                        .AppendFormat("The commands {0} of the controller {1} could not be read. ",
                                                                      commandsTag.Name,
                                                                      controller.Name)
                                                        .AppendLine()
                                                        .AppendFormat("Expected array datatype {0}.", CmdList.PlcArrayDataType())
                                                        .AppendLine()
                                                        .AppendFormat("Current array datatype {0}.", commandsTag.DataType).ToString());
                }

                foreach (Command command in commands.Where(c => c != null && !c.Name.IsNullOrEmpty()))
                {
                    Tag tag = controller.FindTag(TagName.CmdList(null, commandIndex), commandsTag);
                    if (tag == null)
                    {
                        continue;
                    }
                    var commandImpl = new Impl.Command(controller, command, tag.Childs.ToReadOnly(), modeTag, commandTag);
                    yield return(commandImpl);

                    commandIndex++;
                }

                // remove CmdListArray-Tag in order to prevent that the same tags exists more
                // than once --> For example the tag "bolAvailable"
                jobTag.Childs.Remove(commandsTag);
            }
        }