Index: Core/Components/src/Core.Components.DotSpatial/Converter/FeatureBasedMapDataConverter.cs =================================================================== diff -u -r4dd90a5aa5bde0397de27124e0979d7a26a5b9b3 -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/src/Core.Components.DotSpatial/Converter/FeatureBasedMapDataConverter.cs (.../FeatureBasedMapDataConverter.cs) (revision 4dd90a5aa5bde0397de27124e0979d7a26a5b9b3) +++ Core/Components/src/Core.Components.DotSpatial/Converter/FeatureBasedMapDataConverter.cs (.../FeatureBasedMapDataConverter.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -131,7 +131,7 @@ protected abstract IFeatureSymbolizer CreateSymbolizer(TFeatureBasedMapData mapData); /// - /// Creates a new scheme to be applied on the data. + /// Creates a new to be applied on the data. /// /// The newly created . protected abstract IFeatureScheme CreateScheme(); @@ -289,7 +289,7 @@ return CreateRangeCriteriaFilterExpression(attributeIndex, rangeCriteria); } - throw new NotSupportedException($"Can't convert a {nameof(ICriteria)} of type {criteria.GetType()}"); // TODO WTI-1551: Test this exception + throw new NotSupportedException($"Can't convert a {nameof(ICriteria)} of type {criteria.GetType()}"); } /// @@ -331,9 +331,9 @@ { case RangeCriteriaOperator.AllBoundsInclusive: return $"[{attributeIndex}] >= {rangeCriteria.LowerBound} AND [{attributeIndex}] <= {rangeCriteria.UpperBound}"; - case RangeCriteriaOperator.LowerBoundInclusive: + case RangeCriteriaOperator.LowerBoundInclusiveUpperBoundExclusive: return $"[{attributeIndex}] >= {rangeCriteria.LowerBound} AND [{attributeIndex}] < {rangeCriteria.UpperBound}"; - case RangeCriteriaOperator.UpperBoundInclusive: + case RangeCriteriaOperator.LowerBoundExclusiveUpperBoundInclusive: return $"[{attributeIndex}] > {rangeCriteria.LowerBound} AND [{attributeIndex}] <= {rangeCriteria.UpperBound}"; case RangeCriteriaOperator.AllBoundsExclusive: return $"[{attributeIndex}] > {rangeCriteria.LowerBound} AND [{attributeIndex}] < {rangeCriteria.UpperBound}"; Index: Core/Components/src/Core.Components.Gis/Theme/Criteria/RangeCriteriaOperator.cs =================================================================== diff -u -r205d6bacdfb7da4a3f96e65cf4392135323ebd8d -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/src/Core.Components.Gis/Theme/Criteria/RangeCriteriaOperator.cs (.../RangeCriteriaOperator.cs) (revision 205d6bacdfb7da4a3f96e65cf4392135323ebd8d) +++ Core/Components/src/Core.Components.Gis/Theme/Criteria/RangeCriteriaOperator.cs (.../RangeCriteriaOperator.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -34,12 +34,12 @@ /// /// Represents an interval: Lower bound <= X < Upper bound /// - LowerBoundInclusive = 2, + LowerBoundInclusiveUpperBoundExclusive = 2, /// /// Represents an interval: Lower bound < X <= Upper bound /// - UpperBoundInclusive = 3, + LowerBoundExclusiveUpperBoundInclusive = 3, /// /// Represents an interval: Lower bound < X < Upper bound Index: Core/Components/test/Core.Components.DotSpatial.Test/Converter/FeatureBasedMapDataConverterTest.cs =================================================================== diff -u -r4dd90a5aa5bde0397de27124e0979d7a26a5b9b3 -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/test/Core.Components.DotSpatial.Test/Converter/FeatureBasedMapDataConverterTest.cs (.../FeatureBasedMapDataConverterTest.cs) (revision 4dd90a5aa5bde0397de27124e0979d7a26a5b9b3) +++ Core/Components/test/Core.Components.DotSpatial.Test/Converter/FeatureBasedMapDataConverterTest.cs (.../FeatureBasedMapDataConverterTest.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -30,6 +30,9 @@ using Core.Components.DotSpatial.TestUtil; using Core.Components.Gis.Features; using Core.Components.Gis.Geometries; +using Core.Components.Gis.TestUtil.Theme; +using Core.Components.Gis.Theme; +using Core.Components.Gis.Theme.Criteria; using DotSpatial.Controls; using DotSpatial.Data; using DotSpatial.Projections; @@ -419,6 +422,7 @@ Assert.AreEqual("[2]", labelCategory.Expression); } + [Test] [TestCase(true)] [TestCase(false)] public void ConvertLayerProperties_MapData_ShowLabelsSetToLayer(bool showLabels) @@ -438,6 +442,7 @@ Assert.AreEqual(showLabels, mapLayer.ShowLabels); } + [Test] [TestCase(true)] [TestCase(false)] public void ConvertLayerProperties_MapData_IsVisibleSetToLayer(bool isVisible) @@ -457,6 +462,7 @@ Assert.AreEqual(isVisible, mapLayer.IsVisible); } + [Test] [TestCase(null)] [TestCase("")] [TestCase("Unknown")] @@ -507,6 +513,247 @@ Assert.IsNull(mapLayer.LabelLayer.Symbology.Categories[0].Expression); } + [Test] + public void ConvertLayerProperties_MapDataWithMapThemeAndUnsupportedCriteria_ThrowsNotSupportedException() + { + // Setup + var random = new Random(21); + const string metadataAttributeName = "Meta"; + + var featureScheme = new PointScheme(); + var defaultCategory = new PointCategory(); + var category = new PointCategory(); + + var unsupportedCriteria = new TestCriteria(); + var theme = new MapTheme(metadataAttributeName, new[] + { + new CategoryTheme(Color.FromKnownColor(random.NextEnum()), + unsupportedCriteria) + }); + + var mapData = new TestFeatureBasedMapData("test data") + { + Features = new[] + { + new MapFeature(Enumerable.Empty()) + { + MetaData = + { + { + metadataAttributeName, new object() + } + } + } + }, + MapTheme = theme + }; + + var testConverter = new TestFeatureBasedMapDataConverter + { + CreatedFeatureScheme = featureScheme, + CreatedDefaultCategory = defaultCategory, + CreatedCategory = category + }; + + var mapLayer = new TestFeatureLayer(); + + // Call + TestDelegate call = () => testConverter.ConvertLayerProperties(mapData, mapLayer); + + // Assert + var exception = Assert.Throws(call); + string expectedMessage = $"Can't convert a {nameof(ICriteria)} of type {unsupportedCriteria.GetType()}"; + Assert.AreEqual(expectedMessage, exception.Message); + } + + [Test] + public void ConvertLayerProperties_MapDataWithMapThemeAndMetadataNameNotInFatures_ThrowsKeyNotFoundException() + { + // Setup + var random = new Random(21); + + var featureScheme = new PointScheme(); + var defaultCategory = new PointCategory(); + var category = new PointCategory(); + + var theme = new MapTheme("Meta", new[] + { + new CategoryTheme(Color.FromKnownColor(random.NextEnum()), + new ValueCriteria(random.NextEnum(), + random.NextDouble())) + }); + + var mapData = new TestFeatureBasedMapData("test data") + { + Features = new[] + { + new MapFeature(Enumerable.Empty()) + }, + MapTheme = theme + }; + + var testConverter = new TestFeatureBasedMapDataConverter + { + CreatedFeatureScheme = featureScheme, + CreatedDefaultCategory = defaultCategory, + CreatedCategory = category + }; + + var mapLayer = new TestFeatureLayer(); + + // Call + TestDelegate call = () => testConverter.ConvertLayerProperties(mapData, mapLayer); + + // Assert + Assert.Throws(call); + } + + [Test] + [TestCase(ValueCriteriaOperator.EqualValue, "[1] = {0}", TestName = "EqualValue")] + [TestCase(ValueCriteriaOperator.UnequalValue, "[1] != {0}", TestName = "UnequalValue")] + public void ConvertLayerProperties_MapDataWithMapThemeAndValidValueCriteria_SetsCorrectFilterExpression(ValueCriteriaOperator criteriaOperator, + string expressionFormat) + { + // Setup + var random = new Random(21); + const string metadataAttributeName = "Meta"; + double value = random.NextDouble(); + + var featureScheme = new PointScheme(); + var defaultCategory = new PointCategory(); + var category = new PointCategory(); + + var valueCriteria = new ValueCriteria(criteriaOperator, + value); + var theme = new MapTheme(metadataAttributeName, new[] + { + new CategoryTheme(Color.FromKnownColor(random.NextEnum()), + valueCriteria) + }); + + var mapData = new TestFeatureBasedMapData("test data") + { + Features = new[] + { + new MapFeature(Enumerable.Empty()) + { + MetaData = + { + { + metadataAttributeName, new object() + } + } + } + }, + MapTheme = theme + }; + + var testConverter = new TestFeatureBasedMapDataConverter + { + CreatedFeatureScheme = featureScheme, + CreatedDefaultCategory = defaultCategory, + CreatedCategory = category + }; + + var mapLayer = new TestFeatureLayer(); + + // Call + testConverter.ConvertLayerProperties(mapData, mapLayer); + + // Assert + Assert.AreSame(featureScheme, mapLayer.Symbology); + + Assert.IsNull(defaultCategory.FilterExpression); + string expectedFilterExpression = string.Format(expressionFormat, value); + Assert.AreEqual(expectedFilterExpression, category.FilterExpression); + + CollectionAssert.AreEqual(new[] + { + defaultCategory, + category + }, mapLayer.Symbology.Categories); + + CollectionAssert.AreEqual(new[] + { + Tuple.Create(mapData, Color.Transparent), + Tuple.Create(mapData, theme.CategoryThemes.Single().Color) + }, testConverter.CreatedCategories); + } + + [Test] + [TestCase(RangeCriteriaOperator.AllBoundsInclusive, "[1] >= {0} AND [1] <= {1}", TestName = "AllBoundsInclusive")] + [TestCase(RangeCriteriaOperator.LowerBoundInclusiveUpperBoundExclusive, "[1] >= {0} AND [1] < {1}", TestName = "LowerBoundInclusiveUpperBoundExclusive")] + [TestCase(RangeCriteriaOperator.LowerBoundExclusiveUpperBoundInclusive, "[1] > {0} AND [1] <= {1}", TestName = "LowerBoundExclusiveUpperBoundInclusive")] + [TestCase(RangeCriteriaOperator.AllBoundsExclusive, "[1] > {0} AND [1] < {1}", TestName = "AllBoundsExclusive")] + public void ConvertLayerProperties_MapDataWithMapThemeAndValidRangeCriteria_SetsCorrectFilterExpression(RangeCriteriaOperator criteriaOperator, + string expressionFormat) + { + // Setup + var random = new Random(21); + const string metadataAttributeName = "Meta"; + double lowerBound = random.NextDouble(); + double upperBound = 1 + lowerBound; + + var featureScheme = new PointScheme(); + var defaultCategory = new PointCategory(); + var category = new PointCategory(); + + var rangeCriteria = new RangeCriteria(criteriaOperator, lowerBound, upperBound); + var theme = new MapTheme(metadataAttributeName, new[] + { + new CategoryTheme(Color.FromKnownColor(random.NextEnum()), + rangeCriteria) + }); + + var mapData = new TestFeatureBasedMapData("test data") + { + Features = new[] + { + new MapFeature(Enumerable.Empty()) + { + MetaData = + { + { + metadataAttributeName, new object() + } + } + } + }, + MapTheme = theme + }; + + var testConverter = new TestFeatureBasedMapDataConverter + { + CreatedFeatureScheme = featureScheme, + CreatedDefaultCategory = defaultCategory, + CreatedCategory = category + }; + + var mapLayer = new TestFeatureLayer(); + + // Call + testConverter.ConvertLayerProperties(mapData, mapLayer); + + // Assert + Assert.AreSame(featureScheme, mapLayer.Symbology); + + Assert.IsNull(defaultCategory.FilterExpression); + string expectedFilterExpression = string.Format(expressionFormat, lowerBound, upperBound); + Assert.AreEqual(expectedFilterExpression, category.FilterExpression); + + CollectionAssert.AreEqual(new[] + { + defaultCategory, + category + }, mapLayer.Symbology.Categories); + + CollectionAssert.AreEqual(new[] + { + Tuple.Create(mapData, Color.Transparent), + Tuple.Create(mapData, theme.CategoryThemes.Single().Color) + }, testConverter.CreatedCategories); + } + private class TestFeatureLayer : MapPointLayer { public TestFeatureLayer() : base(new FeatureSet()) @@ -517,24 +764,47 @@ private class TestFeatureBasedMapDataConverter : FeatureBasedMapDataConverter { + private readonly List> createdCategories; + + public TestFeatureBasedMapDataConverter() + { + createdCategories = new List>(); + } + + public IFeatureCategory CreatedDefaultCategory { private get; set; } + + public IFeatureCategory CreatedCategory { private get; set; } + + public IFeatureScheme CreatedFeatureScheme { private get; set; } + + public IEnumerable> CreatedCategories + { + get + { + return createdCategories; + } + } + protected override IFeatureSymbolizer CreateSymbolizer(TestFeatureBasedMapData mapData) { return new PointSymbolizer(); } protected override IFeatureScheme CreateScheme() { - throw new NotImplementedException(); + return CreatedFeatureScheme; } protected override IFeatureCategory CreateDefaultCategory(TestFeatureBasedMapData mapData) { - throw new NotImplementedException(); + createdCategories.Add(Tuple.Create(mapData, Color.Transparent)); + return CreatedDefaultCategory; } protected override IFeatureCategory CreateCategory(TestFeatureBasedMapData mapData, Color color) { - throw new NotImplementedException(); + createdCategories.Add(Tuple.Create(mapData, color)); + return CreatedCategory; } protected override IEnumerable CreateFeatures(MapFeature mapFeature) Index: Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapLineDataConverterTest.cs =================================================================== diff -u -rc3e01df6dfac668c5e9bf1e9702cca333e1bbe19 -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapLineDataConverterTest.cs (.../MapLineDataConverterTest.cs) (revision c3e01df6dfac668c5e9bf1e9702cca333e1bbe19) +++ Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapLineDataConverterTest.cs (.../MapLineDataConverterTest.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -273,10 +273,10 @@ var allBoundsInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsInclusive, random.NextDouble(), 1 + random.NextDouble()); - var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusive, + var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusiveUpperBoundExclusive, random.NextDouble(), 1 + random.NextDouble()); - var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.UpperBoundInclusive, + var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundExclusiveUpperBoundInclusive, random.NextDouble(), 1 + random.NextDouble()); var allBoundsExclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsExclusive, Index: Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPointDataConverterTest.cs =================================================================== diff -u -rc3e01df6dfac668c5e9bf1e9702cca333e1bbe19 -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPointDataConverterTest.cs (.../MapPointDataConverterTest.cs) (revision c3e01df6dfac668c5e9bf1e9702cca333e1bbe19) +++ Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPointDataConverterTest.cs (.../MapPointDataConverterTest.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -269,10 +269,10 @@ var allBoundsInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsInclusive, random.NextDouble(), 1 + random.NextDouble()); - var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusive, + var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusiveUpperBoundExclusive, random.NextDouble(), 1 + random.NextDouble()); - var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.UpperBoundInclusive, + var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundExclusiveUpperBoundInclusive, random.NextDouble(), 1 + random.NextDouble()); var allBoundsExclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsExclusive, Index: Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPolygonDataConverterTest.cs =================================================================== diff -u -r4dd90a5aa5bde0397de27124e0979d7a26a5b9b3 -r44de3d2128c8d5393b40e767dde4822fdbfb8bbc --- Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPolygonDataConverterTest.cs (.../MapPolygonDataConverterTest.cs) (revision 4dd90a5aa5bde0397de27124e0979d7a26a5b9b3) +++ Core/Components/test/Core.Components.DotSpatial.Test/Converter/MapPolygonDataConverterTest.cs (.../MapPolygonDataConverterTest.cs) (revision 44de3d2128c8d5393b40e767dde4822fdbfb8bbc) @@ -347,10 +347,10 @@ var allBoundsInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsInclusive, random.NextDouble(), 1 + random.NextDouble()); - var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusive, + var lowerBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundInclusiveUpperBoundExclusive, random.NextDouble(), 1 + random.NextDouble()); - var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.UpperBoundInclusive, + var upperBoundInclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.LowerBoundExclusiveUpperBoundInclusive, random.NextDouble(), 1 + random.NextDouble()); var allBoundsExclusiveCriteria = new RangeCriteria(RangeCriteriaOperator.AllBoundsExclusive,