/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.metadata;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Date;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.citation.Series;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.citation.CitationDate;
import org.opengis.metadata.citation.OnlineResource;
import org.opengis.metadata.citation.PresentationForm;
import org.opengis.metadata.distribution.Format;
import org.opengis.metadata.constraint.Constraints;
import org.opengis.metadata.content.CoverageContentType;
import org.opengis.metadata.content.CoverageDescription;
import org.opengis.metadata.identification.*;                       // Really using almost everything.
import org.opengis.metadata.maintenance.MaintenanceInformation;
import org.opengis.metadata.spatial.SpatialRepresentationType;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.crs.GeodeticCRS;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.util.InternationalString;
import org.opengis.util.GenericName;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.SimpleInternationalString;
import org.apache.sis.metadata.iso.citation.DefaultCitation;
import org.apache.sis.metadata.iso.content.DefaultCoverageDescription;
import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
import static org.apache.sis.metadata.PropertyAccessor.APPEND;
import static org.apache.sis.metadata.PropertyAccessor.RETURN_NULL;
import static org.apache.sis.metadata.PropertyAccessor.RETURN_PREVIOUS;

// Test dependencies
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.sis.test.TestCase;
import org.apache.sis.test.mock.GeographicCRSMock;
import org.apache.sis.metadata.iso.citation.HardCodedCitations;
import static org.apache.sis.test.TestUtilities.getSingleton;
import static org.apache.sis.metadata.Assertions.assertTitleEquals;

// Specific to the main and geoapi-3.1 branches:
import org.opengis.metadata.citation.ResponsibleParty;
import org.opengis.referencing.ReferenceIdentifier;

// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.metadata.content.AttributeGroup;
import org.opengis.referencing.ObjectDomain;
import org.opengis.referencing.datum.DatumEnsemble;
import org.opengis.temporal.Duration;


/**
 * Tests the {@link PropertyAccessor} class. Every tests in this class instantiates directly a
 * {@link PropertyAccessor} object by invoking the {@link #createPropertyAccessor()} method.
 * This class shall not test accessors created indirectly (e.g. the accessors created
 * by {@link MetadataStandard}).
 *
 * <p>This test case uses the {@link Citation} and {@link GeographicCRS} types. If those types
 * are modified in a future GeoAPI version, then some hard-coded values in this test may need
 * to be updated.</p>
 *
 * @author  Martin Desruisseaux (Geomatys)
 */
@SuppressWarnings("OverlyStrongTypeCast")
public final class PropertyAccessorTest extends TestCase {
    /**
     * Creates a new test case.
     */
    public PropertyAccessorTest() {
    }

    /**
     * Creates a new property accessor for the {@link DefaultCitation} class.
     */
    private static PropertyAccessor createPropertyAccessor() {
        return new PropertyAccessor(Citation.class, DefaultCitation.class, DefaultCitation.class);
    }

    /**
     * Asserts that the properties found by the given {@code accessor} have the given names and types.
     * The {@code expected} array shall be a sequence of tuples having the following components:
     *
     * <ul>
     *   <li>The interface that declare the method.</li>
     *   <li>Name of the getter method as specified by {@link KeyNamePolicy#METHOD_NAME}.</li>
     *   <li>Name of the JavaBeans property as specified by {@link KeyNamePolicy#JAVABEANS_PROPERTY}.</li>
     *   <li>ISO 19115 UML identifier as specified by {@link KeyNamePolicy#UML_IDENTIFIER}.</li>
     *   <li>A sentence as specified by {@link KeyNamePolicy#SENTENCE}.</li>
     *   <li>The type of elements. By convention, an array type stands for {@link Collection}
     *       (we have to do this replacement because of parameterized types erasure).</li>
     * </ul>
     *
     * The tuples shall be ordered according the {@link PropertyComparator}.
     *
     * @param  accessor  the accessor to test.
     * @param  expected  the expected names and types as described above.
     *
     * @see PropertyAccessor#mapping
     */
    private static void assertMappingEquals(final PropertyAccessor accessor, final Object... expected) {
        int i = 0;
        while (i < expected.length) {
            final int      index         = i / 6;
            final Class<?> declaringType = (Class<?>) expected[i++];
            final String   methodName    = (String)   expected[i++];
            final String   propertyName  = (String)   expected[i++];
            final String   umlIdentifier = (String)   expected[i++];
            final String   sentence      = (String)   expected[i++];
            assertEquals(methodName,    accessor.name(index, KeyNamePolicy.METHOD_NAME));
            assertEquals(propertyName,  accessor.name(index, KeyNamePolicy.JAVABEANS_PROPERTY));
            assertEquals(umlIdentifier, accessor.name(index, KeyNamePolicy.UML_IDENTIFIER));
            assertEquals(sentence,      accessor.name(index, KeyNamePolicy.SENTENCE));
            assertEquals(declaringType, accessor.type(index, TypeValuePolicy.DECLARING_INTERFACE));
            assertEquals(index,         accessor.indexOf(methodName,    false), methodName);
            assertEquals(index,         accessor.indexOf(propertyName,  false), propertyName);
            assertEquals(index,         accessor.indexOf(umlIdentifier, false), umlIdentifier);
            assertEquals(index,         accessor.indexOf(propertyName .toLowerCase(Locale.ROOT), false), propertyName);
            assertEquals(index,         accessor.indexOf(umlIdentifier.toLowerCase(Locale.ROOT), false), umlIdentifier);
            /*
             * Verifies the type of values. This need special handling for collections.
             */
            Class<?> propertyType = (Class<?>) expected[i++];
            Class<?> elementType  = propertyType;
            if (propertyType.isArray()) {
                elementType  = propertyType.getComponentType();
                propertyType = Collection.class;
                if (IdentifiedObject.class.isAssignableFrom(accessor.type)) {
                    // Special cases
                    if (propertyName.equals("identifiers")) {
                        propertyType = Set.class;
                    }
                }
            } else if (propertyType == Map.class) {
                elementType = Map.Entry.class;
            }
            assertEquals(propertyType, accessor.type(index, TypeValuePolicy.PROPERTY_TYPE), propertyName);
            assertEquals(elementType,  accessor.type(index, TypeValuePolicy.ELEMENT_TYPE), umlIdentifier);
        }
        assertEquals(i/6, accessor.count(), "Count of getter methods.");
    }

    /**
     * Tests the constructor with the {@link DefaultCitation} implementation.
     * The order of properties shall be the order declared in the {@code XmlType.propOrder} annotation.
     * This test may need to be updated if a future GeoAPI release modifies the {@link Citation} interface.
     * Other tests that depends on {@link Citation} property order are {@link NameMapTest#testEntrySet()},
     * {@link TypeMapTest#testEntrySet()} and most tests in {@link ValueMapTest}.
     *
     * @see NameMapTest#testEntrySet()
     * @see TypeMapTest#testEntrySet()
     * @see ValueMapTest
     */
    @Test
    public void testConstructor() {
        assertMappingEquals(createPropertyAccessor(),
        //……Declaring type………Method………………………………………………………………JavaBeans………………………………………………UML identifier……………………………Sentence………………………………………………………Type………………………………………………………………
            Citation.class, "getTitle",                   "title",                   "title",                 "Title",                      InternationalString.class,
            Citation.class, "getAlternateTitles",         "alternateTitles",         "alternateTitle",        "Alternate titles",           InternationalString[].class,
            Citation.class, "getDates",                   "dates",                   "date",                  "Dates",                      CitationDate[].class,
            Citation.class, "getEdition",                 "edition",                 "edition",               "Edition",                    InternationalString.class,
            Citation.class, "getEditionDate",             "editionDate",             "editionDate",           "Edition date",               Date.class,
            Citation.class, "getIdentifiers",             "identifiers",             "identifier",            "Identifiers",                Identifier[].class,
            Citation.class, "getCitedResponsibleParties", "citedResponsibleParties", "citedResponsibleParty", "Cited responsible parties",  ResponsibleParty[].class,
            Citation.class, "getPresentationForms",       "presentationForms",       "presentationForm",      "Presentation forms",         PresentationForm[].class,
            Citation.class, "getSeries",                  "series",                  "series",                "Series",                     Series.class,
            Citation.class, "getOtherCitationDetails",    "otherCitationDetails",    "otherCitationDetails",  "Other citation details",     InternationalString.class,
//          Citation.class, "getCollectiveTitle",         "collectiveTitle",         "collectiveTitle",       "Collective title",           InternationalString.class,   -- deprecated as of ISO 19115:2014
            Citation.class, "getISBN",                    "ISBN",                    "ISBN",                  "ISBN",                       String.class,
            Citation.class, "getISSN",                    "ISSN",                    "ISSN",                  "ISSN",                       String.class,
            Citation.class, "getOnlineResources",         "onlineResources",         "onlineResource",        "Online resources",           OnlineResource[].class,
            Citation.class, "getGraphics",                "graphics",                "graphic",               "Graphics",                   BrowseGraphic[].class);
    }

    /**
     * Tests the constructor with the {@link DefaultDataIdentification} implementation.
     * The purpose of this test is to ensure that the properties defined in the parent
     * class are sorted first.
     *
     * Note that if there is any element not declared as JAXB elements,
     * those ones will be last in alphabetical order.
     * Such situation is usually temporary until the JAXB annotations are completed.
     */
    @Test
    public void testConstructorWithInheritance() {
        assertMappingEquals(new PropertyAccessor(DataIdentification.class, DefaultDataIdentification.class, DefaultDataIdentification.class),
        //……Declaring type………………………Method………………………………………………………………………JavaBeans………………………………………………………UML identifier………………………………………Sentence……………………………………………………………Type………………………………………………………………
            Identification.class, "getCitation",                   "citation",                   "citation",                  "Citation",                     Citation.class,
            Identification.class, "getAbstract",                   "abstract",                   "abstract",                  "Abstract",                     InternationalString.class,
            Identification.class, "getPurpose",                    "purpose",                    "purpose",                   "Purpose",                      InternationalString.class,
            Identification.class, "getCredits",                    "credits",                    "credit",                    "Credits",                      String[].class,
            Identification.class, "getStatus",                     "status",                     "status",                    "Status",                       Progress[].class,
            Identification.class, "getPointOfContacts",            "pointOfContacts",            "pointOfContact",            "Point of contacts",            ResponsibleParty[].class,
            Identification.class, "getSpatialRepresentationTypes", "spatialRepresentationTypes", "spatialRepresentationType", "Spatial representation types", SpatialRepresentationType[].class,
            Identification.class, "getSpatialResolutions",         "spatialResolutions",         "spatialResolution",         "Spatial resolutions",          Resolution[].class,
            Identification.class, "getTemporalResolutions",        "temporalResolutions",        "temporalResolution",        "Temporal resolutions",         Duration[].class,
            Identification.class, "getTopicCategories",            "topicCategories",            "topicCategory",             "Topic categories",             TopicCategory[].class,
            Identification.class, "getExtents",                    "extents",                    "extent",                    "Extents",                      Extent[].class,
            Identification.class, "getAdditionalDocumentations",   "additionalDocumentations",   "additionalDocumentation",   "Additional documentations",    Citation[].class,
            Identification.class, "getProcessingLevel",            "processingLevel",            "processingLevel",           "Processing level",             Identifier.class,
            Identification.class, "getResourceMaintenances",       "resourceMaintenances",       "resourceMaintenance",       "Resource maintenances",        MaintenanceInformation[].class,
            Identification.class, "getGraphicOverviews",           "graphicOverviews",           "graphicOverview",           "Graphic overviews",            BrowseGraphic[].class,
            Identification.class, "getResourceFormats",            "resourceFormats",            "resourceFormat",            "Resource formats",             Format[].class,
            Identification.class, "getDescriptiveKeywords",        "descriptiveKeywords",        "descriptiveKeywords",       "Descriptive keywords",         Keywords[].class,
            Identification.class, "getResourceSpecificUsages",     "resourceSpecificUsages",     "resourceSpecificUsage",     "Resource specific usages",     Usage[].class,
            Identification.class, "getResourceConstraints",        "resourceConstraints",        "resourceConstraints",       "Resource constraints",         Constraints[].class,
            Identification.class, "getAssociatedResources",        "associatedResources",        "associatedResource",        "Associated resources",         AssociatedResource[].class,
        DataIdentification.class, "getEnvironmentDescription",     "environmentDescription",     "environmentDescription",    "Environment description",      InternationalString.class,
        DataIdentification.class, "getSupplementalInformation",    "supplementalInformation",    "supplementalInformation",   "Supplemental information",     InternationalString.class,
        DataIdentification.class, "getLocalesAndCharsets",         "localesAndCharsets",         "defaultLocale+otherLocale", "Locales and charsets",         Map.class);
    }

    /**
     * Tests the constructor with a method which override another method with covariant return type.
     * This test may need to be updated if a future GeoAPI release modifies the {@link GeographicCRS}
     * interface or one of its parent interfaces.
     */
    @Test
    public void testConstructorWithCovariantReturnType() {
        assertMappingEquals(new PropertyAccessor(GeographicCRS.class, GeographicCRSMock.class, GeographicCRSMock.class),
        //……Declaring type……………………………Method……………………………………………JavaBeans……………………………UML identifier……………………Sentence………………………………Type…………………………………………………………
            GeographicCRS.class,    "getCoordinateSystem", "coordinateSystem", "coordinateSystem",   "Coordinate system", EllipsoidalCS.class,       // Covariant return type
            GeodeticCRS.class,      "getDatum",            "datum",            "datum",              "Datum",             GeodeticDatum.class,       // Covariant return type
            GeodeticCRS.class,      "getDatumEnsemble",    "datumEnsemble",    "datumEnsemble",      "Datum ensemble",    DatumEnsemble.class,       // Covariant return type
            IdentifiedObject.class, "getName",             "name",             "name",               "Name",              ReferenceIdentifier.class,
            IdentifiedObject.class, "getAlias",            "alias",            "alias",              "Alias",             GenericName[].class,
            IdentifiedObject.class, "getIdentifiers",      "identifiers",      "identifier",         "Identifiers",       ReferenceIdentifier[].class,
            IdentifiedObject.class, "getDomains",          "domains",          "ObjectUsage.domain", "Domains",           ObjectDomain[].class,
            IdentifiedObject.class, "getRemarks",          "remarks",          "remarks",            "Remarks",           InternationalString.class);
    }

    /**
     * Tests the {@link PropertyAccessor#information(Citation, int)} method.
     * This method delegates to some {@link PropertyInformationTest} methods.
     */
    @Test
    public void testInformation() {
        final PropertyAccessor accessor = createPropertyAccessor();
        PropertyInformationTest.validateTitle           (accessor.information(HardCodedCitations.ISO_19115, accessor.indexOf("title",            true)));
        PropertyInformationTest.validatePresentationForm(accessor.information(HardCodedCitations.ISO_19115, accessor.indexOf("presentationForm", true)));
    }

    /**
     * Tests the {@link PropertyAccessor#get(int, Object)} method on the {@link HardCodedCitations#ISO_19111} constant.
     * The metadata object read by this test is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title…………………………………… International Organization for Standardization
     *     ├─Alternate title………… ISO 19111
     *     ├─Identifier
     *     │   ├─Code…………………………… 19111
     *     │   └─Code space…………… ISO
     *     └─Presentation form…… Document digital</pre>
     */
    @Test
    public void testGet() {
        final DefaultCitation  instance = HardCodedCitations.ISO_19111;
        final PropertyAccessor accessor = createPropertyAccessor();

        // Singleton value (not a collection)
        final Object title = accessor.get(accessor.indexOf("title", true), instance);
        assertInstanceOf(InternationalString.class, title);
        assertEquals("Spatial referencing by coordinates", title.toString());

        // Collection of InternationalStrings
        final Object alternateTitles = accessor.get(accessor.indexOf("alternateTitles", true), instance);
        assertInstanceOf(Collection.class, alternateTitles);
        assertEquals("ISO 19111", getSingleton((Collection<?>) alternateTitles).toString());

        // Collection of Identifiers
        final Object identifiers = accessor.get(accessor.indexOf("identifiers", true), instance);
        assertEquals("19111", getSingletonCode(identifiers));
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method
     * with a value to be stored <em>as-is</em> (without conversion).
     * The metadata object created by this test is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title………………………… Some title
     *     ├─Identifier
     *     │   ├─Code………………… Some ISBN code
     *     │   └─Authority
     *     │       └─Title…… ISBN
     *     └─ISBN…………………………… Some ISBN code</pre>
     */
    @Test
    public void testSet() {
        final DefaultCitation  instance = new DefaultCitation();
        final PropertyAccessor accessor = createPropertyAccessor();
        Object newValue;
        int index;

        newValue = new SimpleInternationalString("Some title");
        index = accessor.indexOf("title", true);
        assertNull(accessor.set(index, instance, newValue, RETURN_PREVIOUS));
        assertSame(newValue, accessor.get(index, instance));
        assertSame(newValue, instance.getTitle());

        newValue = "Some ISBN code";
        index = accessor.indexOf("ISBN", true);
        assertNull(accessor.set(index, instance, newValue, RETURN_PREVIOUS));
        assertSame(newValue, accessor.get(index, instance));
        assertSame(newValue, instance.getISBN());
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method with a {@code null} value.
     * Setting a property to {@code null} is equivalent to removing that property value.
     * The metadata object used by this test (before removal) is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     └─Title………………………… Some title</pre>
     */
    @Test
    public void testSetNull() {
        final DefaultCitation  instance = new DefaultCitation("Some title");
        final PropertyAccessor accessor = createPropertyAccessor();
        final InternationalString title = instance.getTitle();
        final int index = accessor.indexOf("title", true);

        assertEquals("Some title", title.toString()); // Sanity check before to continue.
        assertNull(accessor.set(index, instance, null, RETURN_NULL));
        assertNull(instance.getTitle());

        instance.setTitle(title);
        assertSame(title, accessor.set(index, instance, null, RETURN_PREVIOUS));
        assertNull(instance.getTitle());
    }

    /**
     * Tests setting a deprecated properties. This properties should not be visible in the map,
     * but still be accepted by the map views.
     */
    @Test
    public void testSetDeprecated() {
        final PropertyAccessor accessor = new PropertyAccessor(CoverageDescription.class,
                    DefaultCoverageDescription.class, DefaultCoverageDescription.class);
        final int indexOfDeprecated  = accessor.indexOf("contentType", true);
        final int indexOfReplacement = accessor.indexOf("attributeGroup", true);
        assertTrue(indexOfDeprecated > indexOfReplacement,
                "Deprecated elements shall be sorted after non-deprecated ones.");
        /*
         * Writes a value using the deprecated property.
         */
        final DefaultCoverageDescription instance = new DefaultCoverageDescription();
        assertNull(accessor.set(indexOfDeprecated, instance, CoverageContentType.IMAGE, PropertyAccessor.RETURN_PREVIOUS),
                   "Shall be initially empty.");
        assertEquals(CoverageContentType.IMAGE, accessor.get(indexOfDeprecated, instance));
        /*
         * Compares with the non-deprecated property.
         */
        final Collection<AttributeGroup> groups = instance.getAttributeGroups();
        assertSame(groups, accessor.get(indexOfReplacement, instance));
        assertEquals(CoverageContentType.IMAGE, getSingleton(getSingleton(groups).getContentTypes()));
        /*
         * While we can read/write the value through two properties,
         * only one should be visible.
         */
        assertEquals(1, accessor.count(instance, ValueExistencePolicy.NON_EMPTY, PropertyAccessor.COUNT_SHALLOW),
                     "Deprecated property shall not be visible.");
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method
     * with a value that will need to be converted. The conversion will be from
     * {@link String} to {@link InternationalString}. The created metadata object is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     └─Title……………… Some title</pre>
     */
    @Test
    public void testSetWithConversion() {
        final String           expected = "Some title";
        final DefaultCitation  instance = new DefaultCitation();
        final PropertyAccessor accessor = createPropertyAccessor();
        final int              index    = accessor.indexOf("title", true);
        final Object           oldValue = accessor.set(index, instance, expected, RETURN_PREVIOUS);
        final Object           value    = accessor.get(index, instance);

        assertNull      (oldValue);
        assertInstanceOf(InternationalString.class, value);
        assertSame      (expected, value.toString());
        assertSame      (value, instance.getTitle());
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method when the value
     * is a collection. The new collection shall replace the previous one (no merge expected).
     * The metadata object created by this test after the replacement is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title……………………………………………………… Ignored title
     *     ├─Alternate title (1 of 2)…… New title 1
     *     └─Alternate title (2 of 2)…… New title 2</pre>
     *
     * @see #testSetInAppendMode()
     */
    @Test
    public void testSetCollection() {
        final DefaultCitation instance = new DefaultCitation("Ignored title");
        final List<InternationalString> oldTitles = List.of(
                new SimpleInternationalString("Old title 1"),
                new SimpleInternationalString("Old title 2"));
        final List<InternationalString> newTitles = List.of(
                new SimpleInternationalString("New title 1"),
                new SimpleInternationalString("New title 2"));

        // Set the alternate titles.
        instance.setAlternateTitles(oldTitles);
        final PropertyAccessor accessor = createPropertyAccessor();
        final int              index    = accessor.indexOf("alternateTitles", true);
        final Object           oldValue = accessor.set(index, instance, newTitles, RETURN_PREVIOUS);
        final Object           newValue = accessor.get(index, instance);

        // Verify the values.
        assertEquals(oldTitles, oldValue, "set(…, RETURN_PREVIOUS)");
        assertEquals(newTitles, newValue, "get(…)");
        assertSame  (newValue, instance.getAlternateTitles());
        assertTitleEquals("Ignored title", instance, "citation");
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method
     * when adding elements in a collection, without conversion of type.
     * The metadata object created by this test is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title……………………………………………………… Ignored title
     *     ├─Alternate title (1 of 2)…… Another title
     *     └─Alternate title (2 of 2)…… Yet another title</pre>
     */
    @Test
    public void testSetIntoCollection() {
        testSetIntoCollection(false);
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method
     * when adding elements in a collection, with conversion of type.
     * The metadata object created by this test is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title……………………………………………………… Ignored title
     *     ├─Alternate title (1 of 2)…… Another title
     *     └─Alternate title (2 of 2)…… Yet another title</pre>
     */
    @Test
    public void testSetIntoCollectionWithConversion() {
        testSetIntoCollection(true);
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method
     * when adding elements in a collection, with or without conversion of type.
     */
    private static void testSetIntoCollection(final boolean conversion) {
        final String              text1    = "Another title";
        final String              text2    = "Yet another title";
        final InternationalString title1   = new SimpleInternationalString(text1);
        final InternationalString title2   = new SimpleInternationalString(text2);
        final DefaultCitation     instance = new DefaultCitation("Ignored title");
        final PropertyAccessor    accessor = createPropertyAccessor();
        final int                 index    = accessor.indexOf("alternateTitles", true);

        // Insert the first value. Old collection shall be empty.
        Object oldValue = accessor.set(index, instance, conversion ? text1 : title1, RETURN_PREVIOUS);
        assertTrue(assertInstanceOf(Collection.class, oldValue).isEmpty());

        // Insert the second value. Old collection shall contain the first value.
        oldValue = accessor.set(index, instance, conversion ? text2 : title2, RETURN_PREVIOUS);
        assertInstanceOf(Collection.class, oldValue);
        oldValue = getSingleton((Collection<?>) oldValue);
        assertSame(text1, oldValue.toString());
        if (!conversion) {
            assertSame(title1, oldValue, "InternationalString should have been stored as-is.");
        }

        // Check final collection content.
        final List<InternationalString> expected = List.of(title1, title2);
        assertEquals(expected, accessor.get(index, instance));
        assertTitleEquals("Ignored title", instance, "citation");
    }

    /**
     * Tests the {@link PropertyAccessor#set(int, Object, Object, int)} method in
     * {@link PropertyAccessor#APPEND} mode. In this mode, new collections
     * are added into existing collections instead of replacing them.
     * The metadata object created by this test after the merge is:
     *
     * <pre class="text">
     *   DefaultCitation
     *     ├─Title……………………………………………………… Added title
     *     ├─Alternate title (1 of 4)…… Old title 1
     *     ├─Alternate title (2 of 4)…… Old title 2
     *     ├─Alternate title (3 of 4)…… New title 1
     *     └─Alternate title (4 of 4)…… New title 2</pre>
     *
     * @see #testSetCollection()
     */
    public void testSetInAppendMode() {
        final DefaultCitation instance = new DefaultCitation();
        final List<InternationalString> oldTitles = List.of(
                new SimpleInternationalString("Old title 1"),
                new SimpleInternationalString("Old title 2"));
        final List<InternationalString> newTitles = List.of(
                new SimpleInternationalString("New title 1"),
                new SimpleInternationalString("New title 2"));
        final List<InternationalString> merged = new ArrayList<>(oldTitles);
        assertTrue(merged.addAll(newTitles));

        // Set the title.
        instance.setAlternateTitles(oldTitles);
        final PropertyAccessor accessor = createPropertyAccessor();
        final int titleIndex = accessor.indexOf("title", true);
        Object titleChanged = accessor.set(titleIndex, instance, "Added title", APPEND);

        // Set the alternate titles.
        final int    index    = accessor.indexOf("alternateTitles", true);
        final Object changed  = accessor.set(index, instance, newTitles, APPEND);
        final Object newValue = accessor.get(index, instance);

        // Verify the values.
        assertEquals(Boolean.TRUE, titleChanged, "set(…, APPEND)");
        assertEquals(Boolean.TRUE, changed, "set(…, APPEND)");
        assertEquals(merged, newValue, "get(…)");
        assertSame  (newValue, instance.getAlternateTitles());
        assertTitleEquals("Added title", instance, "citation");

        // Test setting again the title to the same value.
        titleChanged = accessor.set(titleIndex, instance, "Added title", APPEND);
        assertEquals(Boolean.FALSE, titleChanged, "set(…, APPEND)");
        assertTitleEquals("Added title", instance, "citation");

        // Test setting the title to a different value.
        titleChanged = accessor.set(titleIndex, instance, "Different title", APPEND);
        assertNull(titleChanged, "set(…, APPEND)");     // Operation shall be refused.
        assertTitleEquals("Added title", instance, "citation");
    }

    /**
     * Tests the equals methods.
     */
    @Test
    public void testEquals() {
        DefaultCitation citation = HardCodedCitations.EPSG;
        final PropertyAccessor accessor = createPropertyAccessor();
        assertFalse(accessor.equals(citation, HardCodedCitations.SIS,  ComparisonMode.STRICT));
        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG, ComparisonMode.STRICT));

        // Same test as above, but on a copy of the EPSG constant.
        citation = new DefaultCitation(HardCodedCitations.EPSG);
        assertFalse(accessor.equals(citation, HardCodedCitations.SIS,  ComparisonMode.STRICT));
        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG, ComparisonMode.STRICT));

        // Identifiers shall be stored in different collection instances with equal content.
        final int    index  = accessor.indexOf("identifiers", true);
        final Object source = accessor.get(index, HardCodedCitations.EPSG);
        final Object target = accessor.get(index, citation);
        assertInstanceOf(Collection.class, source);
        assertInstanceOf(Collection.class, target);
        assertNotSame(source, target, "Distinct objects shall have distinct collections.");
        assertEquals (source, target, "The two collections shall have the same content.");
        assertEquals ("EPSG", getSingletonCode(target));

        // Set the identifiers to null, which should clear the collection.
        assertEquals(source, accessor.set(index, citation, null, RETURN_PREVIOUS), "Expected the previous value.");
        final Object value = accessor.get(index, citation);
        assertNotNull(value, "Should have replaced null by an empty collection.");
        assertTrue(((Collection<?>) value).isEmpty(), "Should have replaced null by an empty collection.");
    }

    /**
     * Tests {@link PropertyAccessor#toString()}. The {@code toString()}
     * method is only for debugging purpose, but we test it anyway.
     */
    @Test
    public void testToString() {
        final PropertyAccessor accessor = createPropertyAccessor();
        assertEquals("PropertyAccessor[14 getters (+1 ext.) & 15 setters in DefaultCitation:Citation]", accessor.toString());
    }

    /**
     * Returns the code of the singleton identifier found in the given collection.
     * This method verifies that the object is of the expected type.
     *
     * @param  identifiers  a singleton {@code Collection<Identifier>}.
     * @return {@link Identifier#getCode()}.
     */
    static String getSingletonCode(final Object identifiers) {
        assertInstanceOf(Collection.class, identifiers);
        Object identifier = getSingleton((Collection<?>) identifiers);
        return assertInstanceOf(Identifier.class, identifier).getCode();
    }
}
