private IQualityCheckingResult DoesValueMeetRuleItem(Core.Action action, ChemistryValueCheckingRuleItem ruleItem)
        {
            if (action == null || action.FeatureActions == null || !action.FeatureActions.Any())
            {
                return new QualityCheckingResult("No result found for the action.", false, QualityCheckingResultLevel.Info);
            }

            // Assume chemistry action contains only one result
            var result = action.FeatureActions.FirstOrDefault().Results.FirstOrDefault();

            if (result == null)
            {
                return new QualityCheckingResult("No result found for the action.", false, QualityCheckingResultLevel.Info);
            }

            var resultStringBuilder = new StringBuilder();
            var needCorrection = false;

            // Assume only one measurement result value
            var measurementResultValue = result.MeasurementResult.MeasurementResultValues.FirstOrDefault();

            if (measurementResultValue == null)
            {
                resultStringBuilder.AppendLine("Sample Result: " + ResultToString(result) + " does not contain data.");
            }
            else
            {
                if (measurementResultValue.DataValue == ruleItem.CorrectionValue)
                {
                    resultStringBuilder.AppendLine(
                        string.Format(validManualQualityResultFormat, ResultToString(result))
                    );
                }
                else
                {
                    resultStringBuilder.AppendLine(
                        string.Format(invalidManualQualityResultFormat,
                                      ResultToString(result),
                                      measurementResultValue.DataValue,
                                      ruleItem.CorrectionValue)
                    );

                    needCorrection = true;
                }
            }


            var qcResult = new QualityCheckingResult(resultStringBuilder.ToString(), needCorrection, QualityCheckingResultLevel.Info);

            return qcResult;
        }
        private IQualityCheckingResult IsSampleMatrixTypeDataMeetQualityCheckingRule(Hatfield.EnviroData.Core.Action sampleActionData, 
                                                                                     StringCompareCheckingRule rule)
        {
            if (sampleActionData == null || sampleActionData.FeatureActions == null || !sampleActionData.FeatureActions.Any())
            {
                return new QualityCheckingResult("No results found for the sample action.", false, QualityCheckingResultLevel.Info);
            }

            var sampleResults = from featureAction in sampleActionData.FeatureActions
                                from result in featureAction.Results
                                where featureAction.SamplingFeature.SamplingFeatureTypeCV == QualityAssuranceConstants.SiteSampleFeatureTypeCV
                                select result;

            if (sampleResults == null || !sampleResults.Any())
            {
                return new QualityCheckingResult("No results found for the sample action.", false, QualityCheckingResultLevel.Info);
            }

            var resultStringBuilder = new StringBuilder();
            var needCorrection = false;

            foreach(var result in sampleResults)
            {
                var sampleMatrixExtension = result.ResultExtensionPropertyValues
                                                    .Where(x => x.ExtensionProperty.PropertyName == 
                                                           ESDATSampleCollectionConstants.ResultExtensionPropertyValueKeyMatrixType)
                                                    .FirstOrDefault();

                if (sampleMatrixExtension == null)
                {
                    resultStringBuilder.AppendLine("Sample Result: " + ResultToString(result) + " does not contain sample matrix data.");
                }
                else
                {
                    var stringCompareOption = rule.IsCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

                    if (string.Equals(sampleMatrixExtension.PropertyValue, rule.ExpectedValue, stringCompareOption))
                    {
                        resultStringBuilder.AppendLine(
                            string.Format(validSampleMatrixResultFormat, ResultToString(result))
                        );
                    }
                    else
                    {
                        resultStringBuilder.AppendLine(
                            string.Format(invalidSampleMatrixResultFormat, 
                                          ResultToString(result), 
                                          sampleMatrixExtension.PropertyValue, 
                                          rule.ExpectedValue)
                        );
                        needCorrection = true;
                    }
                }
            }

            var qcResult = new QualityCheckingResult(resultStringBuilder.ToString(), needCorrection, QualityCheckingResultLevel.Info);
            return qcResult;
        }