/// <summary>
        /// The add include to collection.
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <param name="itemName">
        /// The item name.
        /// </param>
        /// <param name="expression">
        /// The expression.
        /// </param>
        /// <param name="parent">
        /// The parent.
        /// </param>
        private void AddIncludeToCollection(string fileName, string itemName, string expression, DefinitionDescription parent)
        {
            // check if I already have the definition in the collection
            lock (this.processCollection)
            {
                DefinitionDescription basicProgramDescription = null;
                if (this.processCollection.ContainsKey(fileName, itemName, typeof(BasicProgramDescription)))
                {
                    basicProgramDescription = this.processCollection[fileName, itemName, typeof(BasicProgramDescription)];
                }

                if (basicProgramDescription == null)
                {
                    basicProgramDescription = new BasicProgramDescription(fileName, itemName);
                    BasicProgramDescription.IsInclude = true;
                    this.processCollection.Add(basicProgramDescription);
                }

                this.AddBasicProgramToCollection(
                    basicProgramDescription,
                    new ProcessLoadState { Expression = expression, HookPoint = "INCLUDE", ParentDefinitionDescription = parent });
            }
        }
        /// <summary>
        /// The load basic program.
        /// </summary>
        /// <param name="programName">
        /// The program name.
        /// </param>
        /// <param name="parent">
        /// The parent.
        /// </param>
        /// <param name="expression">
        /// The expression.
        /// </param>
        /// <param name="hookPoint">
        /// The hook point.
        /// </param>
        private void LoadBasicProgram(
            string programName,
            DefinitionDescription parent = null,
            string expression = "",
            string hookPoint = "")
        {
            JobManager.RunInUIThread(
                DispatcherPriority.Input,
                delegate
                    {
                        // check if I already have the definition in the collection
                        lock (this.processCollection)
                        {
                            if (this.processCollection.ContainsKey(string.Empty, programName, typeof(BasicProgramDescription)))
                            {
                                // Debug.WriteLine("[ProcessAnalysisViewModel.LoadBasicProgram(320)] Loaded " + programName + " from cache");
                                this.AddBasicProgramToCollection(
                                    this.processCollection[programName] as BasicProgramDescription,
                                    new ProcessLoadState
                                        {
                                            Expression = expression,
                                            HookPoint = hookPoint,
                                            ParentDefinitionDescription = parent
                                        });
                                return;
                            }

                            // not in cache so add it.
                            // Debug.WriteLine("[ProcessAnalysisViewModel.LoadBasicProgram(328)] Added " + programName + " to cache.");
                            var basicProgramDescription = new BasicProgramDescription(string.Empty, programName);
                            this.processCollection.Add(basicProgramDescription);
                        }

                        this.SetIsLoading(1);
                        SBFile.Read(
                            "VOC",
                            programName,
                            this.ReadBasicProgramVocPointerCompleted,
                            new ProcessLoadState { HookPoint = hookPoint, ParentDefinitionDescription = parent, Expression = expression });
                    });
        }
        /// <summary>
        /// The read basic program voc pointer completed.
        /// </summary>
        /// <param name="subroutineName">
        /// The subroutine name.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="userState">
        /// The user state.
        /// </param>
        private void ReadBasicProgramVocPointerCompleted(string subroutineName, SBString[] parameters, object userState)
        {
            try
            {
                this.SetIsLoading(-1);
                var processState = userState as ProcessLoadState;
                if (processState == null)
                {
                    return;
                }

                BasicProgramDescription basicProgramDescription = null;
                lock (this.processCollection)
                {
                    // it should be in the cache so retrieve it.
                    if (this.processCollection.ContainsKey(string.Empty, parameters[1].Value, typeof(BasicProgramDescription)))
                    {
                        basicProgramDescription = this.processCollection[parameters[1].Value] as BasicProgramDescription;
            /*
                        Debug.WriteLine(
                            "[ProcessAnalysisViewModel.ReadBasicProgramVocPointerCompleted(355)] Read " + parameters[1].Value
                            + " from cache.");
            */
                    }

                    if (basicProgramDescription == null)
                    {
                        basicProgramDescription = new BasicProgramDescription(string.Empty, parameters[1].Value);
                        this.processCollection.Add(basicProgramDescription);
            /*
                        Debug.WriteLine(
                            "[ProcessAnalysisViewModel.ReadBasicProgramVocPointerCompleted(363)] Added " + basicProgramDescription.Name
                            + " to cache.");
            */
                    }
                }

                if (parameters[5].Count != 1 || !parameters[5].Value.Equals("0"))
                {
                    // Error
                    this.LastProcessReadError = string.Format("Failed to read {0} from {1}.", parameters[1].Value, parameters[0].Value);
                    basicProgramDescription.IsError = true;
                    return;
                }

                this.AddBasicProgramToCollection(
                    basicProgramDescription,
                    new ProcessLoadState
                        {
                            Expression = processState.Expression,
                            HookPoint = processState.HookPoint,
                            ParentDefinitionDescription = processState.ParentDefinitionDescription
                        });

                /*
                 * UniVerse VOC pointer
                 *  V
                    C:\U2\SBXA3427\APPLICATIONSERVER\UNIVERSE\SBDEMO\CHPROGS.O/B.BRANCH
                    B
                    BNP

                    PICK.FORMAT
                    SýNýPýIýAýEýH
                    NO.WARNýNOPAGEýLPTRýKEEP.COMMONýýTRAPýHDR-SUPP
                    C:\U2\SBXA3427\APPLICATIONSERVER\UNIVERSE\SBDEMO\CHPROGS.O

                 * UniData VOC Pointer
                 * C
                 * E:\U2\SBXA\APPLICATIONSERVER\UNIDATA\SB.DEFN\DM\_SB.LOGIN
                 */
                if (!basicProgramDescription.Parsed && !basicProgramDescription.IsError)
                {
                    if (parameters[3].Extract(1).Value.Equals("V"))
                    {
                        // UniVerse
                        basicProgramDescription.ObjectFileLocation = parameters[3].Extract(9).Value;
                        basicProgramDescription.ObjectLocation = parameters[3].Extract(2).Value;
                        if (!string.IsNullOrEmpty(basicProgramDescription.ObjectFileLocation))
                        {
                            // figure out the name of the file
                            var fileName = Path.GetFileName(basicProgramDescription.ObjectFileLocation);
                            if (!string.IsNullOrEmpty(fileName))
                            {
                                if (fileName.EndsWith(".O"))
                                {
                                    basicProgramDescription.FileName = fileName.Substring(0, fileName.Length - 2);
                                }
                            }
                        }
                    }
                    else
                    {
                        // UniData, on windows.
                        var parts = parameters[3].Extract(2).Value.Split(@"\".ToCharArray());
                        basicProgramDescription.FileName = parts[parts.Length - 2];
                    }

                    if (!string.IsNullOrEmpty(basicProgramDescription.FileName))
                    {
                        // no need to go any further if I am excluding this file.
                        if (!IsExcludeFile(basicProgramDescription.FileName))
                        {
                            // if I have a file name try open it and see if I can read the code.
                            JobManager.RunInUIThread(
                                DispatcherPriority.Input,
                                delegate
                                    {
                                        this.SetIsLoading(1);
                                        SBFile.Read(
                                            basicProgramDescription.FileName,
                                            basicProgramDescription.Name,
                                            this.ReadBasicProgramCompleted,
                                            new object[] { basicProgramDescription });
                                    });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.LastProcessReadError = "Exception caught after reading definition definition. " + ex.Message;
            }
        }
        /// <summary>
        /// The find calls in basic program.
        /// </summary>
        /// <param name="basicProgram">
        /// The basic program.
        /// </param>
        /// <param name="basicProgramDescription">
        /// The basic program description.
        /// </param>
        private void FindCallsInBasicProgram(IEnumerable<SBString> basicProgram, BasicProgramDescription basicProgramDescription)
        {
            foreach (var line in basicProgram)
            {
                if (line.Dcount() == 1 && !string.IsNullOrEmpty(line.Value))
                {
                    if (line.Value.IndexOf("CALL") >= 0)
                    {
                        // have CALL statement
                        //CALL PROGRAM(
                        var code = line.Value.Trim();
                        var parts = code.Split("(".ToCharArray());
                        int start = parts[0].IndexOf("CALL") + 5;
                        var progName = parts[0].Substring(start);
                        this.LoadBasicProgram(progName, basicProgramDescription, line.Value, "CALL");
                        continue;
                    }

                    if (line.Value.IndexOf("INCLUDE") >= 0)
                    {
                        var code = line.Value.Trim();
                        var parts = code.Split(GenericConstants.CHAR_ARRAY_SPACE);
                        var noElements = parts.Length;
                        for (int elemNo = 0; elemNo < noElements; elemNo++)
                        {
                            if (parts[elemNo].EndsWith("INCLUDE"))
                            {
                                var itemName = parts[elemNo + 1];
                                if (parts.Length >= elemNo + 2 && !string.IsNullOrEmpty(parts[elemNo + 2]))
                                {
                                    var fileName = parts[elemNo + 1];
                                    itemName = parts[elemNo + 2];
                                    if (!IsExcludeFile(fileName))
                                    {
                                        JobManager.RunInUIThread(
                                            DispatcherPriority.Normal,
                                            () => this.AddIncludeToCollection(fileName, itemName, code, basicProgramDescription));
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }
            }

            basicProgramDescription.Parsed = true;
        }