public override string Export(QualityCondition qualityCondition)
        {
            LineNotNearPolyOverlapConfigurator.Matrix matrix =
                LineNotNearPolyOverlapConfigurator.Convert(qualityCondition);

            return(matrix.ToCsv());
        }
        public override QualityCondition CreateQualityCondition(
            StreamReader file, IList <Dataset> datasets,
            IEnumerable <TestParameterValue> parameterValues)
        {
            Assert.ArgumentNotNull(file, nameof(file));
            Assert.ArgumentNotNull(datasets, nameof(datasets));
            Assert.ArgumentNotNull(parameterValues, nameof(parameterValues));

            var datasetFilter = new Dictionary <Dataset, string>();

            foreach (TestParameterValue oldValue in parameterValues)
            {
                if (oldValue.TestParameterName !=
                    FeatureClassParamName)
                {
                    continue;
                }

                var dsValue = (DatasetTestParameterValue)oldValue;
                if (string.IsNullOrEmpty(dsValue.FilterExpression))
                {
                    continue;
                }

                Dataset dataset = dsValue.DatasetValue;
                Assert.NotNull(dataset, "Dataset parameter {0} does not refer to a dataset",
                               dsValue.TestParameterName);

                datasetFilter.Add(dataset, dsValue.FilterExpression);
            }

            LineNotNearPolyOverlapConfigurator.Matrix mat =
                LineNotNearPolyOverlapConfigurator.Matrix.Create(file);

            var config = new LineNotNearPolyOverlapConfigurator();

            QualityCondition qualityCondition = config.Convert(mat, datasets);

            foreach (TestParameterValue newValue in qualityCondition.ParameterValues)
            {
                if (newValue.TestParameterName !=
                    FeatureClassParamName)
                {
                    continue;
                }

                var     datasetTestParameterValue = (DatasetTestParameterValue)newValue;
                Dataset dataset = datasetTestParameterValue.DatasetValue;

                Assert.NotNull(dataset,
                               "Dataset parameter '{0}' in quality condition '{1}' does not refer to a dataset",
                               datasetTestParameterValue.TestParameterName,
                               qualityCondition.Name);

                if (datasetFilter.TryGetValue(dataset, out string filter))
                {
                    datasetTestParameterValue.FilterExpression = filter;
                }
            }

            return(qualityCondition);
        }
            public static ConstrParams Create(IFeatureClass featureClass,
                                              IList <int> referenceSubtypes,
                                              IList <string> featureClassRules)
            {
                string featureClassField   = ((ISubtypes)featureClass).SubtypeFieldName;
                string referenceClassField = ((ISubtypes)featureClass).SubtypeFieldName;

                double maxNear = 0;

                StringBuilder sbNear               = new StringBuilder();
                StringBuilder sbNearEnd            = new StringBuilder();
                StringBuilder sbRightSideNear      = new StringBuilder();
                StringBuilder sbRightSideNearEnd   = new StringBuilder();
                StringBuilder sbIgnore             = new StringBuilder();
                List <int>    featureClassSubtypes = new List <int>();
                bool          anyRightSide         = false;

                foreach (string featureClassRule in featureClassRules)
                {
                    string[] ruleParts = featureClassRule.Split(';');
                    if (!int.TryParse(ruleParts[0], out int subtype))
                    {
                        throw new InvalidOperationException(
                                  $"invalid subtype '{ruleParts[0]}' in featureClassRule '{featureClassRule}' ");
                    }

                    featureClassSubtypes.Add(subtype);

                    // handle default near
                    if (!double.TryParse(ruleParts[1], out double near))
                    {
                        throw new InvalidOperationException(
                                  $"invalid near distance '{ruleParts[1]}' in featureClassRule '{featureClassRule}' ");
                    }

                    maxNear = Math.Max(maxNear, near);
                    sbNear.Append($"IIF({featureClassField}={subtype},{near},");
                    sbNearEnd.Append(")");

                    // handle right side near
                    double rightSideNear;
                    if (!string.IsNullOrWhiteSpace(ruleParts[2]))
                    {
                        if (!double.TryParse(ruleParts[2], out rightSideNear))
                        {
                            throw new InvalidOperationException(
                                      $"invalid right side near distance '{ruleParts[2]}' in featureClassRule '{featureClassRule}' ");
                        }

                        anyRightSide = true;
                        maxNear      = Math.Max(maxNear, rightSideNear);
                    }
                    else
                    {
                        rightSideNear = near;
                    }

                    sbRightSideNear.Append($"IIF({featureClassField}={subtype},{rightSideNear},");
                    sbRightSideNearEnd.Append(")");

                    StringBuilder sbRefIgnore = new StringBuilder();
                    foreach (int overlapIndex in
                             LineNotNearPolyOverlapConfigurator.EnumOverlapIndices(
                                 ruleParts, featureClassRule, referenceSubtypes))
                    {
                        if (!int.TryParse(ruleParts[overlapIndex], out int overlapKey))
                        {
                            throw new InvalidOperationException(
                                      $"invalid rule '{ruleParts[overlapIndex]} in featureClassRule '{featureClassRule}'");
                        }

                        if (overlapKey == 0)
                        {
                            if (sbRefIgnore.Length > 0)
                            {
                                sbRefIgnore.Append(",");
                            }

                            sbRefIgnore.Append(
                                $"{referenceSubtypes[overlapIndex - ReferenceSubtypesStart]}");
                        }
                    }

                    if (sbRefIgnore.Length > 0)
                    {
                        if (sbIgnore.Length > 0)
                        {
                            sbIgnore.Append(" OR ");
                        }

                        sbIgnore.Append(
                            $"(G1.{featureClassField} = {subtype} AND G2.{referenceClassField} IN ({sbRefIgnore}))");
                    }
                }

                // prepare and create test parameters
                if (sbIgnore.Length > 0)
                {
                    sbIgnore.Append(" OR ");
                }

                string fcSubtypesList =
                    string.Concat(featureClassSubtypes.Select(x => $"{x},")).Trim(',');
                string refSubtypesList =
                    string.Concat(referenceSubtypes.Select(x => $"{x},")).Trim(',');

                sbIgnore.Append($"(G1.{featureClassField} NOT IN ({fcSubtypesList})");
                sbIgnore.Append($" OR G2.{referenceClassField} NOT IN ({refSubtypesList}))");

                ConstrParams pars = new ConstrParams
                {
                    MaxNear          = maxNear,
                    FeatureClassNear = $"{sbNear} 0 {sbNearEnd}",
                    RightSideNears   = anyRightSide
                                                                                     ? new List <string>
                    {
                        $"{sbRightSideNear} null {sbRightSideNearEnd}",
                        "0"
                    }
                                                                                     : null,
                    IgnoreNeighborCondition = $"{sbIgnore}"
                };

                return(pars);
            }