#pragma warning disable CS1574 // XML comment has cref attribute 'dataException' that could not be resolved
#pragma warning disable CS1574 // XML comment has cref attribute 'aceObligationException' that could not be resolved
        /// <summary>
        /// Builds data sets --- calls <see cref="datasetBuildOnFinishDefault"/> and after that <see cref="datasetBuildOnFinish"/>
        /// </summary>
        /// <exception cref="aceCommonTypes.core.exceptions.dataException">DataSet is empty for record [" + instanceID + "] in test run [" + testRunStamp + "] - null - DataSet not populated</exception>
        /// <exception cref="aceCommonTypes.core.exceptions.aceObligationException"></exception>
        protected void _doOnRealFinish(bool callBuilds = false)
#pragma warning restore CS1574 // XML comment has cref attribute 'aceObligationException' that could not be resolved
#pragma warning restore CS1574 // XML comment has cref attribute 'dataException' that could not be resolved
        {
            lock (FinishLock)
            {
                if (state == modelRecordStateEnum.finished)
                {
                    return;
                }
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.callDataSetBuildOnFinish) || callBuilds)
                {
                    // datasetBuildOnFinishDefault();
                    //datasetBuildOnFinish();

                    //if (dataSet.Tables.Count == 0)
                    //{
                    //    if (VAR_RecordModeFlags.HasFlag(modelRecordMode.obligationDataSet))
                    //    {
                    //        throw new dataException("DataSet is empty for record [" + instanceID + "] in test run [" + testRunStamp + "]", null, this, "DataSet not populated");
                    //    }
                    //}

                    //if (VAR_RecordModeFlags.HasFlag(modelRecordMode.obligationBuildSummaryStatistics))
                    //{
                    //    if (!dataSet.Tables.Contains(DATANAME_Summary)) throw new aceObligationException(this, modelRecordMode.obligationBuildSummaryStatistics);
                    //}
                }
            }
        }
        /// <summary>
        /// Records the finish.
        /// </summary>
        public virtual void _recordFinish()
        {
            if (state == modelRecordStateEnum.notStarted)
            {
                throw new InvalidOperationException("This record was never started nor initiated!!!");
            }

            if (VAR_RecordModeFlags.HasFlag(modelRecordMode.nonStarter))
            {
                throw new InvalidOperationException("This record is nonStarter - should be started nor finished");
            }

            state      = modelRecordStateEnum.finished;
            timeFinish = DateTime.Now;

            duration.Add(timeFinish.Subtract(timeStart));

            logBuilder.log("Record finished: `**" + instanceID + "**`  _(UID:" + UID + ")_ after: [" + duration.TotalSeconds.getTimeSecString() + "]");

            // if (VAR_AllowAutoOutputToConsole) aceLog.consoleControl.removeFromOutput(this); //setAsOutput(this, VAR_LogPrefix);
            // TODO: Reimplement centralized loging

            _logContent = logBuilder.ContentToString(true, reportOutputFormatName.textMdFile);

            if (VAR_RecordModeFlags.HasFlag(modelRecordMode.singleStarter))
            {
                _doOnRealFinish();
            }
        }
        /// <summary>
        /// Appends the data fields.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="whatToAppend">The what to append.</param>
        /// <returns></returns>
        public virtual PropertyCollectionExtended AppendDataFields(PropertyCollectionExtended data, modelRecordFieldToAppendFlags whatToAppend)
        {
            if (data == null)
            {
                data = new PropertyCollectionExtended();
            }
            if (whatToAppend.HasFlag(modelRecordFieldToAppendFlags.identification))
            {
                data.Add(modelRecordColumnEnum.iid, instanceID, "Instance ID", "Human readable identification of instance covered by the record");
                if (instanceTypeInfo != null)
                {
                    data.Add(modelRecordColumnEnum.instance, instanceTypeInfo.displayName, "Instance type", "Type name of the instance followed by this record");
                    data.Add(modelRecordColumnEnum.instancedesc, instanceTypeInfo.description, "Instance info", "Notes on the instance type");
                }
                data.Add(modelRecordColumnEnum.uid, UID, "UID", "Universal code-ID of the record instance");
                data.Add(modelRecordColumnEnum.recordstate, state, "Record state", "State flag for this record instance");
                data.Add(modelRecordColumnEnum.runstamp, testRunStamp, "Run stamp", "Identification code of the experiment test run instance");
                data.Add(modelRecordColumnEnum.recordtype, iTI.displayName, "Record type", "Name of the record class");
                data.Add(modelRecordColumnEnum.recorddesc, iTI.description, "Record info", "Notes about applied record class");
            }
            if (whatToAppend.HasFlag(modelRecordFieldToAppendFlags.modelRecordCommonData))
            {
                string duration_str = timeFinish.Subtract(timeStart).TotalMilliseconds.getTimeSecString();
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.singleStarter))
                {
                    data.Add(modelRecordColumnEnum.start, timeStart.ToShortTimeString(), "Start", "Start of the record / the instance run");
                    data.Add(modelRecordColumnEnum.finish, timeFinish.ToShortTimeString(), "Finish", "Time of the instance execution finished");
                }
                else if (VAR_RecordModeFlags.HasFlag(modelRecordMode.multiStarter))
                {
                    data.Add(modelRecordColumnEnum.sessions, timeFinish.ToShortTimeString(), "Sessions", "Number of the record start-finish sessions");
                }
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.starter))
                {
                    data.Add(modelRecordColumnEnum.duration, duration_str, "Duration", "Time span of the instance run, in seconds.");
                }
                data.Add(modelRecordColumnEnum.remarks, remarkFlags.ToStringEnumSmart(), "Remarks", "Remark flags about the instance execution");
            }
            if (whatToAppend.HasFlag(modelRecordFieldToAppendFlags.modelRecordInstanceData))
            {
                data.AddRange(instanceOrKeyData, false, false, false);
            }
            //if (whatToAppend.HasFlag(modelRecordFieldToAppendFlags.modelRecordLogData))
            //{
            //    logBuilder.AppendDataFields(data);
            //}

            return(data);
        }
        /// <summary>
        /// Records the start.
        /// </summary>
        /// <param name="__testRunStamp">The test run stamp.</param>
        /// <param name="__instanceID">The instance identifier.</param>
        /// <param name="">The .</param>
        public virtual void _recordStart(string __testRunStamp, string __instanceID)
        {
            instanceID = __instanceID;

            if (instanceID.isNullOrEmpty())
            {
                instanceID = __testRunStamp + "_" + timeStart.ToString() + id_global + "_" + GetHashCode().ToString("D4");
            }

            UID = md5.GetMd5Hash(instanceID);

            if (VAR_RecordModeFlags.HasFlag(modelRecordMode.nonStarter))
            {
                throw new InvalidOperationException("This record is nonStarter - should be started nor finished");
            }

            testRunStamp = __testRunStamp;

            var laststate = state;

            state     = modelRecordStateEnum.started;
            timeStart = DateTime.Now;

            //if (VAR_AllowAutoOutputToConsole)  aceLog.consoleControl.setAsOutput(this, VAR_LogPrefix);

            //dataSet = new DataSet(instanceID + testRunStamp);

            logBuilder.log("Record (" + iTI.displayName + ") for `**" + __testRunStamp + "**` started as: `**" + instanceID + "**`  _(UID:" + UID + ")_ ");

            if (laststate == modelRecordStateEnum.initiated)
            {
                logBuilder.log("Record (" + iTI.displayName + ") for `**" + __testRunStamp + "**` started after [init call] as: `**" + instanceID + "**`  _(UID:" + UID + ")_ ");
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.obligationStartBeforeInit))
                {
                    throw new InvalidOperationException("Obligation " + nameof(modelRecordMode.obligationStartBeforeInit) + " not respected");
                }
            }
            else if (laststate == modelRecordStateEnum.notStarted)
            {
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.obligationInitBeforeStart))
                {
                    throw new InvalidOperationException("Obligation " + nameof(modelRecordMode.obligationInitBeforeStart) + " not respected");
                }
                logBuilder.log("Record (" + iTI.displayName + ") for `**" + __testRunStamp + "**` started before [init call] as: `**" + instanceID + "**`  _(UID:" + UID + ")_ ");
            }
            else if (laststate == modelRecordStateEnum.started)
            {
                if (VAR_RecordModeFlags.HasFlag(modelRecordMode.singleStarter))
                {
                    string threadName = Thread.CurrentThread.ManagedThreadId.ToString().add(Thread.CurrentThread.Name);
                    string msgSufix   = "";
                    if (threadName == startingThread)
                    {
                        msgSufix = " - by the same thread [" + threadName + "]";
                    }
                    else
                    {
                        msgSufix = " - by thread [" + startingThread + "]. This is [" + threadName + "]";
                    }

                    var axe = new InvalidOperationException("This record was already started [" + __instanceID + "] [" + testRunStamp + "] " + msgSufix);

                    throw axe;
                }
            }
            startCallCount++;

            startingThread = Thread.CurrentThread.ManagedThreadId.ToString().add(Thread.CurrentThread.Name);
            _recordStartHandle();
        }