This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit bf22b758e100296e177b4a72b346a5b69cda0056 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Jan 26 18:36:00 2022 +0100 Fix a `MetadataVisitorException` when coyping the `Metadata.getLocaleAndCharsets()` property. It was caused by ClassCastException: Map.Entry. --- .../org/apache/sis/metadata/MetadataCopier.java | 19 ++++++++------- .../java/org/apache/sis/metadata/package-info.java | 2 +- .../apache/sis/metadata/MetadataCopierTest.java | 27 +++++++++++++++++++++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java index 7f3134d..cd54882 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java @@ -20,7 +20,6 @@ import java.util.Set; import java.util.EnumSet; import java.util.LinkedHashSet; import java.util.Map; -import java.util.LinkedHashMap; import java.util.List; import java.util.Arrays; import java.util.Collection; @@ -60,7 +59,7 @@ import org.apache.sis.internal.metadata.Resources; * In multi-threads environment, each thread should use its own {@code MetadataCopier} instance.</p> * * @author Martin Desruisseaux (Geomatys) - * @version 1.0 + * @version 1.2 * @since 0.8 * @module */ @@ -240,7 +239,7 @@ public class MetadataCopier extends MetadataVisitor<Object> { if (c instanceof EnumSet<?> || c instanceof CodeListSet<?>) { /* * Enum and CodeList elements can not be cloned. Do not clone their collection neither; - * we presume that the setter method will do that itself. + * we presume that the setter method (to be invoked by reflection) will do that itself. */ } else { final Object[] array = c.toArray(); @@ -254,12 +253,16 @@ public class MetadataCopier extends MetadataVisitor<Object> { } return c; } + /* + * Maps are rare in GeoAPI interfaces derived from ISO 19115. The main one + * is `Map<Locale,Charset>` returned by `Metadata.getLocalesAndCharsets()`. + * We can not copy those entries because the `type` argument is `Map.Entry`, + * which is not enough information. Recursive copy should not be necessary + * anyway because we do not use `Map` for storing other metadata objects. + * We do not clone the map because it should be done by the setter method. + */ if (metadata instanceof Map<?,?>) { - final Map<Object,Object> copy = new LinkedHashMap<>((Map<?,?>) metadata); - for (final Map.Entry<Object,Object> entry : copy.entrySet()) { - entry.setValue(copyRecursively(type, entry.getValue())); - } - return copy; + return metadata; } } return copyRecursively(type, metadata); diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java index ca31242..036790a 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java @@ -119,7 +119,7 @@ * * @author Martin Desruisseaux (IRD, Geomatys) * @author Adrian Custer (Geomatys) - * @version 1.0 + * @version 1.2 * @since 0.3 * @module */ diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java index 5c2634c..e2e25d7 100644 --- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java +++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java @@ -16,8 +16,14 @@ */ package org.apache.sis.metadata; +import java.util.Map; +import java.util.Locale; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import org.opengis.metadata.Metadata; import org.opengis.metadata.citation.Citation; import org.opengis.metadata.extent.GeographicExtent; +import org.apache.sis.metadata.iso.DefaultMetadata; import org.apache.sis.metadata.iso.citation.DefaultCitation; import org.apache.sis.metadata.iso.citation.HardCodedCitations; import org.apache.sis.metadata.iso.extent.DefaultGeographicDescription; @@ -34,7 +40,7 @@ import static org.apache.sis.test.TestUtilities.getSingleton; * Unless otherwise specified, all tests use the {@link MetadataStandard#ISO_19115} constant. * * @author Martin Desruisseaux (Geomatys) - * @version 1.0 + * @version 1.2 * * @see org.apache.sis.internal.metadata.MergerTest * @@ -99,4 +105,23 @@ public final strictfp class MetadataCopierTest extends TestCase { assertTrue(message, message.contains("DefaultCitation")); } } + + /** + * Tests with a metadata containing a {@link DefaultMetadata#getLocalesAndCharsets()} property. + * This property is defined by a {@link Map}. + */ + @Test + public void testLocaleAndCharsets() { + final MetadataCopier copier = new MetadataCopier(MetadataStandard.ISO_19115); + final DefaultMetadata original = new DefaultMetadata(); + original.getLocalesAndCharsets().put(Locale.FRENCH, StandardCharsets.UTF_8); + original.getLocalesAndCharsets().put(Locale.JAPANESE, StandardCharsets.UTF_16); + final Metadata copy = copier.copy(Metadata.class, original); + final Map<Locale,Charset> lc = copy.getLocalesAndCharsets(); + assertEquals(StandardCharsets.UTF_8, lc.get(Locale.FRENCH)); + assertEquals(StandardCharsets.UTF_16, lc.get(Locale.JAPANESE)); + assertEquals (original, copy); + assertNotSame(original, copy); + assertNotSame(original.getLocalesAndCharsets(), lc); + } }