private void EnsureBorderingLineMatchCondition()
        {
            if (_borderingPointMatchCondition != null)
            {
                return;
            }

            _borderingPointMatchCondition =
                new PointMatchCondition(_borderingPointMatchConditionSql,
                                        GetSqlCaseSensitivity(_allPointClassIndexes));
        }
        private int CheckBorderConnection(
            [NotNull] BorderConnection borderConnection,
            [NotNull] IEnumerable <int> neighborPointClassIndexes,
            int neighborBorderClassIndex,
            [NotNull] PointMatchCondition borderingPointMatchCondition)
        {
            double coincidenceTolerance = GetCoincidenceTolerance(borderConnection.ClassIndex);

            var anyNeighborFound = false;

            var errorCount = 0;

            foreach (int neighborPointClassIndex in neighborPointClassIndexes)
            {
                foreach (IRow neighborRow in SearchNeighborRows(borderConnection.Point,
                                                                neighborPointClassIndex))
                {
                    if (WasReportedInOppositeDirection(borderConnection.Feature,
                                                       borderConnection.ClassIndex,
                                                       neighborRow,
                                                       neighborPointClassIndex))
                    {
                        return(NoError);
                    }

                    if (!borderingPointMatchCondition.IsFulfilled(borderConnection.Feature,
                                                                  borderConnection.ClassIndex,
                                                                  neighborRow,
                                                                  neighborPointClassIndex))
                    {
                        continue;
                    }

                    var neighborFeature = (IFeature)neighborRow;
                    var neighborPoint   = (IPoint)neighborFeature.Shape;

                    double pointDistance = GeometryUtils.GetPointDistance(borderConnection.Point,
                                                                          neighborPoint);

                    if (pointDistance > _searchDistance)
                    {
                        // the point is outside the search distance
                        continue;
                    }

                    // determine if the neighbor point is connected to it's border
                    BorderConnection neighborBorderConnection = GetBorderConnection(neighborPoint,
                                                                                    neighborFeature,
                                                                                    neighborPointClassIndex,
                                                                                    neighborBorderClassIndex);

                    if (neighborBorderConnection == null)
                    {
                        // there is no neighboring point within the search distance on its border
                        continue;
                    }

                    anyNeighborFound = true;

                    ICollection <AttributeConstraintViolation> constraintViolations =
                        GetAttributeConstraintViolations(borderConnection,
                                                         neighborFeature,
                                                         neighborPointClassIndex);

                    if (EdgeMatchUtils.IsWithinTolerance(pointDistance, coincidenceTolerance))
                    {
                        // the points are coincident
                        if (constraintViolations.Count == 0)
                        {
                            return(NoError);
                        }

                        AddReportedRowPair(borderConnection.Feature,
                                           borderConnection.ClassIndex,
                                           neighborFeature,
                                           neighborPointClassIndex);

                        foreach (AttributeConstraintViolation constraintViolation in
                                 constraintViolations)
                        {
                            errorCount += ReportError(
                                constraintViolation.Description,
                                GeometryFactory.Clone(borderConnection.Point),
                                Codes[Code.Match_ConstraintsNotFulfilled],
                                constraintViolation.AffectedComponents,
                                new[] { constraintViolation.TextValue },
                                borderConnection.Feature, neighborFeature);
                        }

                        return(errorCount);
                    }

                    // the point is not coincident with the neighbor point
                    bool areBordersCoincident = AreBordersCoincident(
                        borderConnection, neighborBorderConnection);

                    AddReportedRowPair(borderConnection.Feature,
                                       borderConnection.ClassIndex,
                                       neighborBorderConnection.Feature,
                                       neighborBorderConnection.ClassIndex);

                    if (!areBordersCoincident &&
                        AllowDisjointCandidateFeatureIfBordersAreNotCoincident)
                    {
                        continue;
                    }

                    if (constraintViolations.Count == 0 &&
                        AllowDisjointCandidateFeatureIfAttributeConstraintsAreFulfilled)
                    {
                        continue;
                    }

                    errorCount += ReportDisjointNeighborPointErrors(
                        constraintViolations,
                        borderConnection,
                        neighborBorderConnection,
                        areBordersCoincident,
                        pointDistance);
                }
            }

            if (!anyNeighborFound)
            {
                if (!AllowNoFeatureWithinSearchDistance)
                {
                    errorCount += ReportError(
                        LocalizableStrings.QaEdgeMatchBorderingPoints_NoMatch_NoCandidate,
                        GeometryFactory.Clone(borderConnection.Point),
                        Codes[Code.NoMatch_NoCandidate], null,
                        borderConnection.Feature);
                }
            }

            return(errorCount);
        }