sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/01: Create a new branch compatible with GeoAPI 3.1. The content of this branch is an intermediate between GeoAPI 3.0 (master) and GeoAPI 4.0 (was named "JDK8" branch on Subversion repository). The content is actually more similar to the GeoAPI 4.0 branch, except where GeoAPI has an incompatible changes. In those cases, GeoAPI 3.1 is same as GeoAPI 3.0.
Date Wed, 20 Jun 2018 14:46:11 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-3.1
in repository https://gitbox.apache.org/repos/asf/sis.git

commit fcd6c5d6f140fe7f70086d9ffef734088dc80c01
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Jun 20 16:31:35 2018 +0200

    Create a new branch compatible with GeoAPI 3.1. The content of this branch is an intermediate between GeoAPI 3.0 (master) and GeoAPI 4.0 (was named "JDK8" branch on Subversion repository). The content is actually more similar to the GeoAPI 4.0 branch, except where GeoAPI has an incompatible changes. In those cases, GeoAPI 3.1 is same as GeoAPI 3.0.
---
 .../java/org/apache/sis/feature/Validator.java     |   2 +-
 .../sis/internal/jaxb/cat/CodeListAdapter.java     |  28 +-
 ...haracterSet.java => MD_CharacterSetLegacy.java} |  22 +-
 .../jaxb/code/MD_PixelOrientationCode.java         |  69 ++-
 .../internal/jaxb/code/MD_TopicCategoryCode.java   |  67 +-
 .../jaxb/metadata/CI_ResponsibleParty.java         | 128 ++++
 .../metadata/replace/ReferenceSystemMetadata.java  |  12 +-
 .../jaxb/metadata/replace/ServiceParameter.java    |   7 +-
 .../sis/internal/metadata/NameToIdentifier.java    |   3 +-
 .../sis/internal/metadata/ServicesForUtility.java  |  13 +-
 .../sis/internal/simple/CitationConstant.java      |   6 +-
 .../apache/sis/internal/simple/SimpleCitation.java |   6 +-
 .../internal/simple/SimpleIdentifiedObject.java    |   9 +-
 .../sis/internal/simple/SimpleIdentifier.java      |   8 +-
 .../apache/sis/internal/simple/SimpleMetadata.java |  21 +-
 .../apache/sis/metadata/PropertyInformation.java   |   6 +-
 .../iso/DefaultApplicationSchemaInformation.java   |  57 +-
 .../iso/DefaultExtendedElementInformation.java     |  42 +-
 .../apache/sis/metadata/iso/DefaultMetadata.java   |  50 +-
 .../sis/metadata/iso/ImmutableIdentifier.java      |   3 +-
 .../sis/metadata/iso/OnlineResourceAdapter.java    |  66 ++
 .../apache/sis/metadata/iso/URIStringAdapter.java  |  67 ++
 .../metadata/iso/acquisition/DefaultPlatform.java  |  24 +-
 .../iso/acquisition/DefaultRequirement.java        |  46 +-
 .../sis/metadata/iso/acquisition/package-info.java |   2 +-
 .../sis/metadata/iso/citation/DefaultAddress.java  |  22 +-
 .../sis/metadata/iso/citation/DefaultCitation.java |  51 +-
 .../sis/metadata/iso/citation/DefaultContact.java  |  25 +-
 .../iso/citation/DefaultOnlineResource.java        |  14 +-
 .../sis/metadata/iso/citation/DefaultSeries.java   |  34 +-
 .../sis/metadata/iso/citation/package-info.java    |   2 +-
 .../iso/distribution/DefaultDistributor.java       |  22 +-
 .../metadata/iso/distribution/package-info.java    |   1 +
 .../iso/identification/AbstractIdentification.java |  44 +-
 .../identification/DefaultDataIdentification.java  |  23 +-
 .../metadata/iso/identification/DefaultUsage.java  |  28 +-
 .../metadata/iso/identification/package-info.java  |   3 +-
 .../metadata/iso/lineage/DefaultProcessStep.java   |  24 +-
 .../sis/metadata/iso/lineage/package-info.java     |   2 +-
 .../iso/maintenance/AttributeTypeAdapter.java      |  52 ++
 .../maintenance/DefaultMaintenanceInformation.java |  24 +-
 .../iso/maintenance/DefaultScopeDescription.java   | 157 +++--
 .../iso/maintenance/FeatureTypeAdapter.java        |  52 ++
 .../sis/metadata/iso/maintenance/LegacyType.java   |  70 +++
 .../sis/metadata/iso/maintenance/package-info.java |   4 +-
 .../org/apache/sis/metadata/iso/package-info.java  |   4 +-
 .../metadata/iso/quality/DefaultDataQuality.java   |   3 +-
 .../sis/internal/jaxb/cat/EnumMarshallingTest.java |   2 -
 .../apache/sis/metadata/PropertyAccessorTest.java  |  18 +-
 .../sis/metadata/PropertyInformationTest.java      |   2 +-
 .../apache/sis/metadata/TreeNodeChildrenTest.java  |   3 +-
 .../java/org/apache/sis/metadata/TreeNodeTest.java |  52 +-
 .../apache/sis/metadata/TreeTableFormatTest.java   |  12 +-
 .../org/apache/sis/metadata/TreeTableViewTest.java |  14 +-
 .../java/org/apache/sis/metadata/TypeMapTest.java  |   4 +-
 .../java/org/apache/sis/metadata/ValueMapTest.java |  10 +-
 .../sis/metadata/iso/CustomMetadataTest.java       |   9 +-
 .../apache/sis/metadata/iso/MarshallingTest.java   | 677 ---------------------
 .../metadata/iso/citation/DefaultCitationTest.java |  26 +-
 .../iso/citation/DefaultResponsibilityTest.java    |   3 +-
 .../metadata/iso/citation/HardCodedCitations.java  |   7 +-
 .../DefaultDataIdentificationTest.java             |   6 +-
 .../maintenance/DefaultScopeDescriptionTest.java   |   7 +-
 .../sis/metadata/sql/MetadataWriterTest.java       |   2 +-
 .../apache/sis/test/mock/IdentifiedObjectMock.java |   8 +-
 .../apache/sis/test/suite/MetadataTestSuite.java   |   1 -
 .../sis/test/xml/AnnotationConsistencyCheck.java   |  14 +-
 .../referencing/CC_GeneralOperationParameter.java  |   3 +-
 .../apache/sis/internal/jaxb/referencing/Code.java |   3 +-
 .../internal/referencing/NilReferencingObject.java |   8 +-
 .../referencing/provider/AbstractProvider.java     |   6 +-
 .../referencing/provider/MapProjection.java        |   8 +-
 .../provider/ObliqueMercatorCenter.java            |   5 +-
 .../org/apache/sis/parameter/ParameterFormat.java  |   3 +-
 .../sis/referencing/AbstractIdentifiedObject.java  |  49 +-
 .../java/org/apache/sis/referencing/Builder.java   |  29 +-
 .../main/java/org/apache/sis/referencing/CRS.java  |   4 +-
 .../org/apache/sis/referencing/NameIterator.java   |  24 +-
 .../apache/sis/referencing/NamedIdentifier.java    |   3 +-
 .../org/apache/sis/referencing/Properties.java     |   6 +-
 .../sis/referencing/crs/AbstractDerivedCRS.java    |   2 +-
 .../sis/referencing/crs/DefaultDerivedCRS.java     |   2 +-
 .../sis/referencing/crs/DefaultProjectedCRS.java   |   4 +-
 .../operation/CoordinateOperationFinder.java       |   4 +-
 .../operation/CoordinateOperationRegistry.java     |   6 +-
 .../operation/DefaultConcatenatedOperation.java    |  13 +-
 .../operation/DefaultPassThroughOperation.java     |  41 +-
 .../referencing/operation/SubOperationInfo.java    |   2 +-
 .../apache/sis/referencing/operation/SubTypes.java |  13 +-
 .../org/apache/sis/parameter/ParametersTest.java   |   6 +-
 .../referencing/AbstractIdentifiedObjectTest.java  |  38 +-
 .../apache/sis/test/integration/MetadataTest.java  |  14 +-
 .../org/apache/sis/internal/util/CitationMock.java |   9 +-
 ide-project/NetBeans/nbproject/build-impl.xml      |  26 +-
 ide-project/NetBeans/nbproject/genfiles.properties |   4 +-
 ide-project/NetBeans/nbproject/project.properties  |  12 +-
 ide-project/NetBeans/nbproject/project.xml         |  12 +-
 pom.xml                                            |   2 +-
 .../profile/fra/DirectReferenceSystem.java         |   4 +-
 .../profile/fra/IndirectReferenceSystem.java       |   4 +-
 .../profile/fra/DirectReferenceSystemTest.java     |   4 +-
 .../main/java/org/apache/sis/storage/gdal/PJ.java  |   4 +-
 .../apache/sis/storage/netcdf/MetadataReader.java  |  17 +-
 .../sis/internal/storage/MetadataBuilder.java      |  37 +-
 .../apache/sis/internal/storage/gpx/Copyright.java |   7 +-
 .../org/apache/sis/internal/storage/gpx/Link.java  |   8 +-
 .../apache/sis/internal/storage/gpx/Metadata.java  |   5 +-
 .../apache/sis/internal/storage/gpx/Person.java    |  66 +-
 108 files changed, 1526 insertions(+), 1293 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java b/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
index 1a7fb44..6b759f3 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
@@ -28,7 +28,7 @@ import org.apache.sis.metadata.iso.quality.AbstractElement;
 import org.apache.sis.metadata.iso.quality.DefaultDataQuality;
 import org.apache.sis.metadata.iso.quality.DefaultDomainConsistency;
 import org.apache.sis.metadata.iso.quality.DefaultConformanceResult;
-import org.apache.sis.metadata.iso.maintenance.DefaultScope;
+import org.apache.sis.metadata.iso.quality.DefaultScope;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.util.resources.Errors;
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/cat/CodeListAdapter.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/cat/CodeListAdapter.java
index 901c73b..ae81bbf 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/cat/CodeListAdapter.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/cat/CodeListAdapter.java
@@ -127,7 +127,33 @@ public abstract class CodeListAdapter<ValueType extends CodeListAdapter<ValueTyp
      */
     @Override
     public final ValueType marshal(final BoundType code) {
-        return (code != null) ? wrap(new CodeListUID(Context.current(), code)) : null;
+        if (code == null) {
+            return null;
+        }
+        final CodeListUID p;
+        if (isEnum()) {
+            // To be removed after GEO-199 resolution.
+            p = new CodeListUID();
+            p.value = Types.getCodeName(code);
+        } else {
+            p = new CodeListUID(Context.current(), code);
+        }
+        return wrap(p);
+    }
+
+    /**
+     * Returns {@code true} if this code list is actually an enum. The default implementation
+     * returns {@code false} in every cases, since there is very few enums in ISO 19115.
+     *
+     * @return {@code true} if this code list is actually an enum.
+     *
+     * @todo Remove this method after we refactored enum wrappers as {@code EnumAdapter} subclasses
+     *       instead of {@code CodeListAdapter}. This requires the resolution of GEO-199 first.
+     *
+     * @see <a href="http://jira.codehaus.org/browse/GEO-199">GEO-199</a>
+     */
+    protected boolean isEnum() {
+        return false;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/LegacyCharacterSet.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetLegacy.java
similarity index 73%
rename from core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/LegacyCharacterSet.java
rename to core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetLegacy.java
index 049a011..436c2d4 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/LegacyCharacterSet.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_CharacterSetLegacy.java
@@ -24,44 +24,38 @@ import org.apache.sis.internal.jaxb.LegacyNamespaces;
 
 
 /**
- * JAXB adapter for {@link CharacterSet}
- * in order to wrap the value in an XML element as specified by ISO 19115-3 standard.
- * See package documentation for more information about the handling of {@code CodeList} in ISO 19115-3.
+ * JAXB adapter for {@link CharacterSet}, in order to integrate the value in an element
+ * complying with ISO 19139:2007 standard.
  *
  * @author  Cédric Briançon (Geomatys)
  * @version 1.0
  * @since   0.3
  * @module
  */
-@SuppressWarnings("deprecation")
-public final class LegacyCharacterSet extends CodeListAdapter<LegacyCharacterSet, CharacterSet> {
+public final class MD_CharacterSetLegacy extends CodeListAdapter<MD_CharacterSetLegacy, CharacterSet> {
     /**
      * Empty constructor for JAXB only.
      */
-    public LegacyCharacterSet() {
+    public MD_CharacterSetLegacy() {
     }
 
     /**
-     * Creates a new adapter for the given value.
+     * Creates a new adapter for the given proxy.
      */
-    private LegacyCharacterSet(final CodeListUID value) {
+    private MD_CharacterSetLegacy(final CodeListUID value) {
         super(value);
     }
 
     /**
      * {@inheritDoc}
-     *
-     * @return the wrapper for the code list value.
      */
     @Override
-    protected LegacyCharacterSet wrap(final CodeListUID value) {
-        return new LegacyCharacterSet(value);
+    protected MD_CharacterSetLegacy wrap(final CodeListUID value) {
+        return new MD_CharacterSetLegacy(value);
     }
 
     /**
      * {@inheritDoc}
-     *
-     * @return the code list class.
      */
     @Override
     protected Class<CharacterSet> getCodeListClass() {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_PixelOrientationCode.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_PixelOrientationCode.java
index 4b88e53..31c876e 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_PixelOrientationCode.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_PixelOrientationCode.java
@@ -18,7 +18,8 @@ package org.apache.sis.internal.jaxb.code;
 
 import javax.xml.bind.annotation.XmlElement;
 import org.opengis.metadata.spatial.PixelOrientation;
-import org.apache.sis.internal.jaxb.cat.EnumAdapter;
+import org.apache.sis.internal.jaxb.cat.CodeListAdapter;
+import org.apache.sis.internal.jaxb.cat.CodeListUID;
 import org.apache.sis.xml.Namespaces;
 
 
@@ -33,43 +34,67 @@ import org.apache.sis.xml.Namespaces;
  * @since   0.3
  * @module
  */
-public final class MD_PixelOrientationCode extends EnumAdapter<MD_PixelOrientationCode, PixelOrientation> {
+public final class MD_PixelOrientationCode
+        extends CodeListAdapter<MD_PixelOrientationCode, PixelOrientation>
+{
     /**
-     * The enumeration value.
+     * Empty constructor for JAXB only.
      */
-    @XmlElement(name = "MD_PixelOrientationCode", namespace = Namespaces.MSR)
-    private String value;
+    public MD_PixelOrientationCode() {
+    }
 
     /**
-     * Empty constructor for JAXB only.
+     * Creates a new adapter for the given proxy.
      */
-    public MD_PixelOrientationCode() {
+    private MD_PixelOrientationCode(final CodeListUID value) {
+        super(value);
     }
 
     /**
-     * Returns the wrapped value.
+     * {@inheritDoc}
      *
-     * @param  wrapper  the wrapper.
-     * @return the wrapped value.
+     * @return the wrapper for the code list value.
      */
     @Override
-    public final PixelOrientation unmarshal(final MD_PixelOrientationCode wrapper) {
-        return PixelOrientation.valueOf(name(wrapper.value));
+    protected MD_PixelOrientationCode wrap(final CodeListUID value) {
+        return new MD_PixelOrientationCode(value);
     }
 
     /**
-     * Wraps the given value.
+     * {@inheritDoc}
      *
-     * @param  e  the value to wrap.
-     * @return the wrapped value.
+     * @return the code list class.
      */
     @Override
-    public final MD_PixelOrientationCode marshal(final PixelOrientation e) {
-        if (e == null) {
-            return null;
-        }
-        final MD_PixelOrientationCode wrapper = new MD_PixelOrientationCode();
-        wrapper.value = value(e);
-        return wrapper;
+    protected Class<PixelOrientation> getCodeListClass() {
+        return PixelOrientation.class;
+    }
+
+    /**
+     * Returns {@code true} since this code list is actually an enum.
+     */
+    @Override
+    protected boolean isEnum() {
+        return true;
+    }
+
+    /**
+     * Invoked by JAXB on marshalling.
+     *
+     * @return The value to be marshalled.
+     */
+    @Override
+    @XmlElement(name = "MD_PixelOrientationCode", namespace = Namespaces.MSR)
+    public CodeListUID getElement() {
+        return identifier;
+    }
+
+    /**
+     * Invoked by JAXB on unmarshalling.
+     *
+     * @param value The unmarshalled value.
+     */
+    public void setElement(final CodeListUID value) {
+        identifier = value;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_TopicCategoryCode.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_TopicCategoryCode.java
index dae9784..7d700ca 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_TopicCategoryCode.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/code/MD_TopicCategoryCode.java
@@ -18,7 +18,8 @@ package org.apache.sis.internal.jaxb.code;
 
 import javax.xml.bind.annotation.XmlElement;
 import org.opengis.metadata.identification.TopicCategory;
-import org.apache.sis.internal.jaxb.cat.EnumAdapter;
+import org.apache.sis.internal.jaxb.cat.CodeListAdapter;
+import org.apache.sis.internal.jaxb.cat.CodeListUID;
 import org.apache.sis.xml.Namespaces;
 
 
@@ -34,43 +35,65 @@ import org.apache.sis.xml.Namespaces;
  * @since   0.3
  * @module
  */
-public final class MD_TopicCategoryCode extends EnumAdapter<MD_TopicCategoryCode, TopicCategory> {
+public final class MD_TopicCategoryCode extends CodeListAdapter<MD_TopicCategoryCode, TopicCategory> {
     /**
-     * The enumeration value.
+     * Empty constructor for JAXB only.
      */
-    @XmlElement(name = "MD_TopicCategoryCode", namespace = Namespaces.MRI)
-    private String value;
+    public MD_TopicCategoryCode() {
+    }
 
     /**
-     * Empty constructor for JAXB only.
+     * Creates a new adapter for the given proxy.
      */
-    public MD_TopicCategoryCode() {
+    private MD_TopicCategoryCode(final CodeListUID value) {
+        super(value);
     }
 
     /**
-     * Returns the wrapped value.
+     * {@inheritDoc}
      *
-     * @param  wrapper  the wrapper.
-     * @return the wrapped value.
+     * @return the wrapper for the code list value.
      */
     @Override
-    public final TopicCategory unmarshal(final MD_TopicCategoryCode wrapper) {
-        return TopicCategory.valueOf(name(wrapper.value));
+    protected MD_TopicCategoryCode wrap(final CodeListUID value) {
+        return new MD_TopicCategoryCode(value);
     }
 
     /**
-     * Wraps the given value.
+     * {@inheritDoc}
      *
-     * @param  e  the value to wrap.
-     * @return the wrapped value.
+     * @return the code list class.
      */
     @Override
-    public final MD_TopicCategoryCode marshal(final TopicCategory e) {
-        if (e == null) {
-            return null;
-        }
-        final MD_TopicCategoryCode wrapper = new MD_TopicCategoryCode();
-        wrapper.value = value(e);
-        return wrapper;
+    protected Class<TopicCategory> getCodeListClass() {
+        return TopicCategory.class;
+    }
+
+    /**
+     * Returns {@code true} since this code list is actually an enum.
+     */
+    @Override
+    protected boolean isEnum() {
+        return true;
+    }
+
+    /**
+     * Invoked by JAXB on marshalling.
+     *
+     * @return The value to be marshalled.
+     */
+    @Override
+    @XmlElement(name = "MD_TopicCategoryCode", namespace = Namespaces.MRI)
+    public CodeListUID getElement() {
+        return identifier;
+    }
+
+    /**
+     * Invoked by JAXB on unmarshalling.
+     *
+     * @param value The unmarshalled value.
+     */
+    public void setElement(final CodeListUID value) {
+        identifier = value;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/CI_ResponsibleParty.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/CI_ResponsibleParty.java
new file mode 100644
index 0000000..7a57029
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/CI_ResponsibleParty.java
@@ -0,0 +1,128 @@
+/*
+ * 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.internal.jaxb.metadata;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import org.opengis.util.InternationalString;
+import org.opengis.metadata.citation.Contact;
+import org.opengis.metadata.citation.ResponsibleParty;
+import org.apache.sis.metadata.iso.citation.AbstractParty;
+import org.apache.sis.metadata.iso.citation.DefaultIndividual;
+import org.apache.sis.metadata.iso.citation.DefaultOrganisation;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
+import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.internal.jaxb.FilterByVersion;
+
+
+/**
+ * JAXB adapter mapping implementing class to the GeoAPI interface. See
+ * package documentation for more information about JAXB and interface.
+ *
+ * @author  Cédric Briançon (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   0.3
+ * @module
+ */
+@SuppressWarnings("deprecation")
+public final class CI_ResponsibleParty extends PropertyType<CI_ResponsibleParty, ResponsibleParty> {
+    /**
+     * Empty constructor for JAXB only.
+     */
+    public CI_ResponsibleParty() {
+    }
+
+    /**
+     * Returns the GeoAPI interface which is bound by this adapter.
+     * This method is indirectly invoked by the private constructor
+     * below, so it shall not depend on the state of this object.
+     *
+     * @return {@code ResponsibleParty.class}
+     */
+    @Override
+    protected Class<ResponsibleParty> getBoundType() {
+        return ResponsibleParty.class;
+    }
+
+    /**
+     * Constructor for the {@link #wrap} method only.
+     */
+    private CI_ResponsibleParty(final ResponsibleParty metadata) {
+        super(metadata);
+    }
+
+    /**
+     * Invoked by {@link PropertyType} at marshalling time for wrapping the given metadata value
+     * in a {@code <gmd:CI_ResponsibleParty>} XML element.
+     *
+     * @param  metadata  the metadata element to marshall.
+     * @return a {@code PropertyType} wrapping the given the metadata element.
+     */
+    @Override
+    protected CI_ResponsibleParty wrap(final ResponsibleParty metadata) {
+        return new CI_ResponsibleParty(metadata);
+    }
+
+    /**
+     * Invoked by JAXB at marshalling time for getting the actual metadata to write
+     * inside the {@code <gmd:CI_ResponsibleParty>} XML element.
+     * This is the value or a copy of the value given in argument to the {@code wrap} method.
+     *
+     * @return the metadata to be marshalled.
+     */
+    @XmlElementRef
+    public DefaultResponsibility getElement() {
+        if (FilterByVersion.LEGACY_METADATA.accept()) {
+            return DefaultResponsibleParty.castOrCopy(metadata);
+        } else if (metadata != null) {
+            final DefaultIndividual individual;
+            final String name = metadata.getIndividualName();
+            Contact contact = metadata.getContactInfo();
+            AbstractParty party;
+            if (name != null) {
+                individual = new DefaultIndividual(name, metadata.getPositionName(), contact);
+                party      = individual;
+                contact    = null;
+            } else {
+                individual = null;
+                party      = null;
+            }
+            final InternationalString organisation = metadata.getOrganisationName();
+            if (organisation != null) {
+                party = new DefaultOrganisation(organisation, null, individual, contact);
+            }
+            if (party != null) {
+                return new DefaultResponsibility(metadata.getRole(), null, party);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time for storing the result temporarily.
+     *
+     * @param  md  the unmarshalled metadata.
+     */
+    public void setElement(final DefaultResponsibility md) {
+        if (md instanceof DefaultResponsibleParty) {
+            metadata = (DefaultResponsibleParty) md;
+        } else if (md != null) {
+            metadata = new DefaultResponsibleParty(md);
+        }
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java
index 9c656a3..f2eb05a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ReferenceSystemMetadata.java
@@ -22,8 +22,8 @@ import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.opengis.metadata.Identifier;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.jaxb.metadata.MD_Identifier;
 import org.apache.sis.internal.jaxb.metadata.RS_Identifier;
 import org.apache.sis.internal.simple.SimpleIdentifiedObject;
@@ -87,7 +87,7 @@ public class ReferenceSystemMetadata extends SimpleIdentifiedObject implements R
      *
      * @param  name  the primary name by which this object is identified.
      */
-    public ReferenceSystemMetadata(final Identifier name) {
+    public ReferenceSystemMetadata(final ReferenceIdentifier name) {
         super(name);
     }
 
@@ -107,7 +107,7 @@ public class ReferenceSystemMetadata extends SimpleIdentifiedObject implements R
     @Override
     @XmlElement(name = "referenceSystemIdentifier")
     @XmlJavaTypeAdapter(MD_Identifier.class)
-    public final Identifier getName() {
+    public ReferenceIdentifier getName() {
         return isLegacyMetadata ? null : super.getName();
     }
 
@@ -116,7 +116,7 @@ public class ReferenceSystemMetadata extends SimpleIdentifiedObject implements R
      *
      * @param  name  the new primary name.
      */
-    public final void setName(final Identifier name) {
+    public final void setName(final ReferenceIdentifier name) {
         this.name = name;
     }
 
@@ -126,7 +126,7 @@ public class ReferenceSystemMetadata extends SimpleIdentifiedObject implements R
      */
     @XmlElement(name = "referenceSystemIdentifier", namespace = LegacyNamespaces.GMD)
     @XmlJavaTypeAdapter(RS_Identifier.class)
-    private Identifier getLegacyName() {
+    private ReferenceIdentifier getLegacyName() {
         return isLegacyMetadata ? super.getName() : null;
     }
 
@@ -134,7 +134,7 @@ public class ReferenceSystemMetadata extends SimpleIdentifiedObject implements R
      * Sets the name for this reference system metadata (used in ISO 19115:2003 model).
      */
     @SuppressWarnings("unused")
-    private void setLegacyName(final Identifier name) {
+    private void setLegacyName(final ReferenceIdentifier name) {
         this.name = name;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
index ece5628..0ca7508 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
@@ -31,6 +31,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterDirection;
 import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.simple.SimpleIdentifiedObject;
 import org.apache.sis.internal.jaxb.FilterByVersion;
 import org.apache.sis.internal.jaxb.LegacyNamespaces;
@@ -266,10 +267,10 @@ public final class ServiceParameter extends SimpleIdentifiedObject implements Pa
      * @return the parameter name as an identifier (the type specified by ISO 19111).
      */
     @Override
-    public synchronized Identifier getName() {
+    public synchronized ReferenceIdentifier getName() {
         if (name == null && memberName != null) {
-            if (memberName instanceof Identifier) {
-                name = (Identifier) memberName;
+            if (memberName instanceof ReferenceIdentifier) {
+                name = (ReferenceIdentifier) memberName;
             } else {
                 name = new NameToIdentifier(memberName);
             }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameToIdentifier.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameToIdentifier.java
index ce3c950..cfcb6cb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameToIdentifier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameToIdentifier.java
@@ -24,6 +24,7 @@ import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.CharSequences;
@@ -45,7 +46,7 @@ import static org.apache.sis.util.Characters.Filter.LETTERS_AND_DIGITS;
  * @since   0.4
  * @module
  */
-public final class NameToIdentifier implements Identifier {
+public final class NameToIdentifier implements ReferenceIdentifier {
     /**
      * The name from which to infer the identifier attributes.
      */
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java
index 5a6117a..766f7f7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ServicesForUtility.java
@@ -26,7 +26,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Role;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.PresentationForm;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.util.ControlledVocabulary;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.MetadataServices;
@@ -37,7 +37,7 @@ import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultOrganisation;
-import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Exceptions;
@@ -208,13 +208,14 @@ public final class ServicesForUtility extends MetadataServices {
         if (code                  != null) c.setIdentifiers(singleton(new ImmutableIdentifier(null, codeSpace, code, version, null)));
         if (presentationForm      != null) c.setPresentationForms(singleton(presentationForm));
         if (citedResponsibleParty != null) {
-            c.setCitedResponsibleParties(singleton(new DefaultResponsibility(Role.PRINCIPAL_INVESTIGATOR, null,
-                    new DefaultOrganisation(citedResponsibleParty, null, null, null))));
+            final DefaultResponsibleParty r = new DefaultResponsibleParty(Role.PRINCIPAL_INVESTIGATOR);
+            r.setParties(singleton(new DefaultOrganisation(citedResponsibleParty, null, null, null)));
+            c.setCitedResponsibleParties(singleton(r));
         }
         if (copyFrom != null) {
             for (final Citation other : copyFrom) {
-                final Collection<? extends Responsibility> parties = other.getCitedResponsibleParties();
-                final Collection<Responsibility> current = c.getCitedResponsibleParties();
+                final Collection<? extends ResponsibleParty> parties = other.getCitedResponsibleParties();
+                final Collection<ResponsibleParty> current = c.getCitedResponsibleParties();
                 if (current != null) {
                     current.addAll(parties);
                 } else {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/CitationConstant.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/CitationConstant.java
index f8a1dce..ea2f41b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/CitationConstant.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/CitationConstant.java
@@ -24,7 +24,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.identification.BrowseGraphic;
 import org.opengis.util.InternationalString;
@@ -163,10 +163,10 @@ public class CitationConstant extends SimpleCitation {
     @Override public InternationalString                        getEdition()                 {return delegate().getEdition();}
     @Override public Date                                       getEditionDate()             {return delegate().getEditionDate();}
     @Override public Collection<? extends Identifier>           getIdentifiers()             {return delegate().getIdentifiers();}
-    @Override public Collection<? extends Responsibility>       getCitedResponsibleParties() {return delegate().getCitedResponsibleParties();}
+    @Override public Collection<? extends ResponsibleParty>     getCitedResponsibleParties() {return delegate().getCitedResponsibleParties();}
     @Override public Collection<PresentationForm>               getPresentationForms()       {return delegate().getPresentationForms();}
     @Override public Series                                     getSeries()                  {return delegate().getSeries();}
-    @Override public Collection<? extends InternationalString>  getOtherCitationDetails()    {return delegate().getOtherCitationDetails();}
+    @Override public InternationalString                        getOtherCitationDetails()    {return delegate().getOtherCitationDetails();}
     @Override public Collection<? extends OnlineResource>       getOnlineResources()         {return delegate().getOnlineResources();}
     @Override public Collection<? extends BrowseGraphic>        getGraphics()                {return delegate().getGraphics();}
     @Override public String                                     getISBN()                    {return delegate().getISBN();}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java
index 7d49311..2e341fb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java
@@ -26,7 +26,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.identification.BrowseGraphic;
 import org.opengis.util.InternationalString;
@@ -89,10 +89,10 @@ public class SimpleCitation implements Citation, Serializable {
     @Override public InternationalString                        getEdition()                 {return null;}
     @Override public Date                                       getEditionDate()             {return null;}
     @Override public Collection<? extends Identifier>           getIdentifiers()             {return Collections.emptyList();}
-    @Override public Collection<? extends Responsibility>       getCitedResponsibleParties() {return Collections.emptyList();}
+    @Override public Collection<? extends ResponsibleParty>     getCitedResponsibleParties() {return Collections.emptyList();}
     @Override public Collection<PresentationForm>               getPresentationForms()       {return Collections.emptyList();}
     @Override public Series                                     getSeries()                  {return null;}
-    @Override public Collection<? extends InternationalString>  getOtherCitationDetails()    {return Collections.emptyList();}
+    @Override public InternationalString                        getOtherCitationDetails()    {return null;}
     @Override public Collection<? extends OnlineResource>       getOnlineResources()         {return Collections.emptyList();}
     @Override public Collection<? extends BrowseGraphic>        getGraphics()                {return Collections.emptyList();}
     @Override public String                                     getISBN()                    {return null;}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifiedObject.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifiedObject.java
index eadcf33..12eeadb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifiedObject.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifiedObject.java
@@ -27,6 +27,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.util.Citations;
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.LenientComparable;
@@ -56,7 +57,7 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab
     /**
      * The primary name by which this object is identified.
      */
-    protected Identifier name;
+    protected ReferenceIdentifier name;
 
     /**
      * Creates an identified object without identifier.
@@ -79,7 +80,7 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab
      *
      * @param  name  the primary name by which this object is identified.
      */
-    public SimpleIdentifiedObject(final Identifier name) {
+    public SimpleIdentifiedObject(final ReferenceIdentifier name) {
         this.name = name;
     }
 
@@ -89,7 +90,7 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab
      * @return the identifier given at construction time.
      */
     @Override
-    public Identifier getName() {
+    public ReferenceIdentifier getName() {
         return name;
     }
 
@@ -103,7 +104,7 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab
      * @return the identifiers, or an empty set if none.
      */
     @Override
-    public final Set<Identifier> getIdentifiers() {
+    public final Set<ReferenceIdentifier> getIdentifiers() {
         return Collections.emptySet();
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifier.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifier.java
index 881dd36..cd60fae 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleIdentifier.java
@@ -19,7 +19,7 @@ package org.apache.sis.internal.simple;
 import java.util.Objects;
 import java.io.Serializable;
 import org.opengis.util.InternationalString;
-import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.internal.util.Citations;
 import org.apache.sis.util.CharSequences;
@@ -31,14 +31,14 @@ import static org.apache.sis.util.iso.DefaultNameSpace.DEFAULT_SEPARATOR;
 
 
 /**
- * An implementation of {@link Identifier} as a wrapper around a {@link Citation}.
+ * An implementation of {@link ReferenceIdentifier} as a wrapper around a {@link Citation}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.0
  * @since   0.3
  * @module
  */
-public class SimpleIdentifier implements Identifier, Deprecable, Serializable {
+public class SimpleIdentifier implements ReferenceIdentifier, Deprecable, Serializable {
     /**
      * For cross-version compatibility.
      */
@@ -237,7 +237,7 @@ public class SimpleIdentifier implements Identifier, Deprecable, Serializable {
 
     /**
      * Returns a pseudo Well Known Text for this identifier.
-     * While this method is not defined in the {@link Identifier} interface, it is often
+     * While this method is not defined in the {@link ReferenceIdentifier} interface, it is often
      * defined in related interfaces like {@link org.opengis.referencing.IdentifiedObject}.
      *
      * @return pseudo Well Known Text for this identifier.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleMetadata.java
index 99f2e33..bada66b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/simple/SimpleMetadata.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.internal.simple;
 
-import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -32,7 +31,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.constraint.Constraints;
 import org.opengis.metadata.content.ContentInformation;
@@ -140,7 +139,7 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * Also the character coding standard(s) used for the dataset.
      */
     @Override
-    public Collection<Charset> getCharacterSets() {
+    public final Collection getCharacterSets() {
         return Collections.emptySet();                  // We use 'Set' because we handle 'Charset' like a CodeList.
     }
 
@@ -225,7 +224,7 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * Parties responsible for the metadata information.
      */
     @Override
-    public Collection<Responsibility> getContacts() {
+    public Collection<ResponsibleParty> getContacts() {
         return Collections.emptyList();
     }
 
@@ -365,8 +364,8 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * Information about the distributor of and options for obtaining the resource(s).
      */
     @Override
-    public Collection<Distribution> getDistributionInfo() {
-        return Collections.emptyList();
+    public Distribution getDistributionInfo() {
+        return null;
     }
 
     /**
@@ -463,7 +462,7 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * This is part of the information returned by {@link #getIdentificationInfo()}.
      */
     @Override
-    public Collection<InternationalString> getCredits() {
+    public Collection<String> getCredits() {
         return Collections.emptyList();
     }
 
@@ -481,7 +480,7 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * This is part of the information returned by {@link #getIdentificationInfo()}.
      */
     @Override
-    public Collection<Responsibility> getPointOfContacts() {
+    public Collection<ResponsibleParty> getPointOfContacts() {
         return Collections.emptyList();
     }
 
@@ -709,7 +708,7 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * This is part of the information returned by {@link #getCitation()}.
      */
     @Override
-    public Collection<Responsibility> getCitedResponsibleParties() {
+    public Collection<ResponsibleParty> getCitedResponsibleParties() {
         return Collections.emptyList();
     }
 
@@ -738,8 +737,8 @@ public class SimpleMetadata implements Metadata, MetadataScope, DataIdentificati
      * This is part of the information returned by {@link #getCitation()}.
      */
     @Override
-    public Collection<InternationalString> getOtherCitationDetails() {
-        return Collections.emptyList();
+    public InternationalString getOtherCitationDetails() {
+        return null;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
index c388d1c..7fe042e 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyInformation.java
@@ -21,11 +21,11 @@ import java.util.Collection;
 import java.util.Collections;
 import java.lang.reflect.Method;
 import org.opengis.annotation.UML;
-import org.opengis.annotation.Obligation;
 import org.opengis.metadata.Datatype;
+import org.opengis.metadata.Obligation;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.ExtendedElementInformation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.util.CodeList;
 import org.opengis.util.InternationalString;
 import org.apache.sis.internal.simple.SimpleIdentifier;
@@ -343,7 +343,7 @@ final class PropertyInformation<E> extends SimpleIdentifier
      * Returns the name of the person or organization creating the element.
      */
     @Override
-    public Collection<? extends Responsibility> getSources() {
+    public Collection<? extends ResponsibleParty> getSources() {
         return authority.getCitedResponsibleParties();
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultApplicationSchemaInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultApplicationSchemaInformation.java
index 868b31e..1beca0f 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultApplicationSchemaInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultApplicationSchemaInformation.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.metadata.iso;
 
+import java.net.URI;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -24,8 +25,6 @@ import org.opengis.metadata.ApplicationSchemaInformation;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.OnlineResource;
 import org.apache.sis.xml.Namespaces;
-import org.apache.sis.internal.jaxb.gco.CharSequenceAdapter;
-import org.apache.sis.internal.jaxb.metadata.CI_OnlineResource;
 
 
 /**
@@ -71,7 +70,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = 5667352094985433121L;
+    private static final long serialVersionUID = -884081423040392985L;
 
     /**
      * Name of the application schema used.
@@ -91,17 +90,17 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
     /**
      * Full application schema given as an ASCII file.
      */
-    private CharSequence schemaAscii;
+    private URI schemaAscii;
 
     /**
      * Full application schema given as a graphics file.
      */
-    private OnlineResource graphicsFile;
+    private URI graphicsFile;
 
     /**
      * Full application schema given as a software development file.
      */
-    private OnlineResource softwareDevelopmentFile;
+    private URI softwareDevelopmentFile;
 
     /**
      * Software dependent format used for the application schema software dependent file.
@@ -243,21 +242,29 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
     /**
      * Full application schema given as an ASCII file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * {@code URI} may be replaced by {@link CharSequence} in GeoAPI 4.0.
+     * </div>
+     *
      * @return application schema as an ASCII file, or {@code null}.
      */
     @Override
     @XmlElement(name = "schemaAscii")
-    @XmlJavaTypeAdapter(CharSequenceAdapter.Since2014.class)
-    public CharSequence getSchemaAscii()  {
+    @XmlJavaTypeAdapter(URIStringAdapter.class)
+    public URI getSchemaAscii()  {
         return schemaAscii;
     }
 
     /**
      * Sets the full application schema given as an ASCII file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * {@code URI} may be replaced by {@link CharSequence} in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new ASCII file.
      */
-    public void setSchemaAscii(final CharSequence newValue) {
+    public void setSchemaAscii(final URI newValue) {
         checkWritePermission();
         schemaAscii = newValue;
     }
@@ -265,21 +272,31 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
     /**
      * Full application schema given as a graphics file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * As of ISO 19115:2014, {@code URI} is replaced by {@link OnlineResource}.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return application schema as a graphics file, or {@code null}.
      */
     @Override
     @XmlElement(name = "graphicsFile")
-    @XmlJavaTypeAdapter(CI_OnlineResource.Since2014.class)
-    public OnlineResource getGraphicsFile()  {
+    @XmlJavaTypeAdapter(OnlineResourceAdapter.class)
+    public URI getGraphicsFile()  {
         return graphicsFile;
     }
 
     /**
      * Sets the full application schema given as a graphics file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * As of ISO 19115:2014, {@code URI} is replaced by {@link OnlineResource}.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new graphics file.
      */
-    public void setGraphicsFile(final OnlineResource newValue) {
+    public void setGraphicsFile(final URI newValue) {
         checkWritePermission();
         graphicsFile = newValue;
     }
@@ -287,21 +304,31 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
     /**
      * Full application schema given as a software development file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * As of ISO 19115:2014, {@code URI} is replaced by {@link OnlineResource}.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return application schema as a software development file, or {@code null}.
      */
     @Override
     @XmlElement(name = "softwareDevelopmentFile")
-    @XmlJavaTypeAdapter(CI_OnlineResource.Since2014.class)
-    public OnlineResource getSoftwareDevelopmentFile()  {
+    @XmlJavaTypeAdapter(OnlineResourceAdapter.class)
+    public URI getSoftwareDevelopmentFile()  {
         return softwareDevelopmentFile;
     }
 
     /**
      * Sets the full application schema given as a software development file.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * As of ISO 19115:2014, {@code URI} is replaced by {@link OnlineResource}.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new software development file.
      */
-    public void setSoftwareDevelopmentFile(final OnlineResource newValue) {
+    public void setSoftwareDevelopmentFile(final URI newValue) {
         checkWritePermission();
         softwareDevelopmentFile = newValue;
     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultExtendedElementInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultExtendedElementInformation.java
index a810d70..12d7e7b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultExtendedElementInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultExtendedElementInformation.java
@@ -22,9 +22,9 @@ import java.util.Iterator;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
-import org.opengis.annotation.Obligation;
 import org.opengis.metadata.Datatype;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.Obligation;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.ExtendedElementInformation;
 import org.opengis.util.InternationalString;
 import org.apache.sis.metadata.TitleProperty;
@@ -101,7 +101,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = 489138542195499530L;
+    private static final long serialVersionUID = 5892811836634834434L;
 
     /**
      * Name of the extended metadata element.
@@ -176,12 +176,12 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
     /**
      * Reason for creating the extended element.
      */
-    private InternationalString rationale;
+    private Collection<InternationalString> rationales;
 
     /**
      * Name of the person or organization creating the extended element.
      */
-    private Collection<Responsibility> sources;
+    private Collection<ResponsibleParty> sources;
 
     /**
      * Construct an initially empty extended element information.
@@ -206,7 +206,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
                                              final Datatype     dataType,
                                              final String       parentEntity,
                                              final CharSequence rule,
-                                             final Responsibility source)
+                                             final ResponsibleParty source)
     {
         this.name         = name;
         this.definition   = Types.toInternationalString(definition);
@@ -214,7 +214,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
         this.dataType     = dataType;
         this.parentEntity = singleton(parentEntity, String.class);
         this.rule         = Types.toInternationalString(rule);
-        this.sources      = singleton(source, Responsibility.class);
+        this.sources      = singleton(source, ResponsibleParty.class);
     }
 
     /**
@@ -248,8 +248,8 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
             domainValue       = object.getDomainValue();
             parentEntity      = copyCollection(object.getParentEntity(), String.class);
             rule              = object.getRule();
-            rationale         = object.getRationale();
-            sources           = copyCollection(object.getSources(), Responsibility.class);
+            rationales        = copyCollection(object.getRationales(), InternationalString.class);
+            sources           = copyCollection(object.getSources(), ResponsibleParty.class);
         }
     }
 
@@ -546,7 +546,8 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
     @Override
     @XmlElement(name = "rationale")
     public InternationalString getRationale() {
-        return rationale;
+        return LegacyPropertyAdapter.getSingleton(rationales, InternationalString.class, null,
+                DefaultExtendedElementInformation.class, "getRationale");
     }
 
     /**
@@ -557,8 +558,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @since 0.5
      */
     public void setRationale(final InternationalString newValue) {
-        checkWritePermission();
-        rationale = newValue;
+        rationales = writeCollection(LegacyPropertyAdapter.asCollection(newValue), rationales, InternationalString.class);
     }
 
     /**
@@ -609,21 +609,31 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
     /**
      * Name of the person or organization creating the extended element.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return name of the person or organization creating the extended element.
      */
     @Override
     @XmlElement(name = "source", required = true)
-    public Collection<Responsibility> getSources() {
-        return sources = nonNullCollection(sources, Responsibility.class);
+    public Collection<ResponsibleParty> getSources() {
+        return sources = nonNullCollection(sources, ResponsibleParty.class);
     }
 
     /**
      * Sets the name of the person or organization creating the extended element.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new sources.
      */
-    public void setSources(final Collection<? extends Responsibility> newValues) {
-        sources = writeCollection(newValues, sources, Responsibility.class);
+    public void setSources(final Collection<? extends ResponsibleParty> newValues) {
+        sources = writeCollection(newValues, sources, ResponsibleParty.class);
     }
 
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
index 4f0399b..f1c6f0b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
@@ -42,7 +42,7 @@ import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.CitationDate;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.citation.OnlineResource;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.constraint.Constraints;
 import org.opengis.metadata.content.ContentInformation;
 import org.opengis.metadata.distribution.Distribution;
@@ -188,7 +188,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -4935599812744534502L;
+    private static final long serialVersionUID = 7337533776231004504L;
 
     /**
      * Unique identifier for this metadata record, or {@code null} if none.
@@ -218,7 +218,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     /**
      * Parties responsible for the metadata information.
      */
-    private Collection<Responsibility> contacts;
+    private Collection<ResponsibleParty> contacts;
 
     /**
      * Date(s) associated with the metadata.
@@ -274,7 +274,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     /**
      * Provides information about the distributor of and options for obtaining the resource(s).
      */
-    private Collection<Distribution> distributionInfo;
+    private Distribution distributionInfo;
 
     /**
      * Provides overall assessment of quality of a resource(s).
@@ -324,11 +324,11 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      * @param dateStamp           date that the metadata was created.
      * @param identificationInfo  basic information about the resource to which the metadata applies.
      */
-    public DefaultMetadata(final Responsibility contact,
+    public DefaultMetadata(final ResponsibleParty contact,
                            final Date           dateStamp,
                            final Identification identificationInfo)
     {
-        this.contacts  = singleton(contact, Responsibility.class);
+        this.contacts  = singleton(contact, ResponsibleParty.class);
         this.identificationInfo = singleton(identificationInfo, Identification.class);
         if (dateStamp != null) {
             dateInfo = singleton(new DefaultCitationDate(dateStamp, DateType.CREATION), CitationDate.class);
@@ -352,7 +352,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
             languages                     = copyCollection(object.getLanguages(),                     Locale.class);
             characterSets                 = copyCollection(object.getCharacterSets(),                 Charset.class);
             metadataScopes                = copyCollection(object.getMetadataScopes(),                MetadataScope.class);
-            contacts                      = copyCollection(object.getContacts(),                      Responsibility.class);
+            contacts                      = copyCollection(object.getContacts(),                      ResponsibleParty.class);
             dateInfo                      = copyCollection(object.getDateInfo(),                      CitationDate.class);
             metadataStandards             = copyCollection(object.getMetadataStandards(),             Citation.class);
             metadataProfiles              = copyCollection(object.getMetadataProfiles(),              Citation.class);
@@ -363,7 +363,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
             metadataExtensionInfo         = copyCollection(object.getMetadataExtensionInfo(),         MetadataExtensionInformation.class);
             identificationInfo            = copyCollection(object.getIdentificationInfo(),            Identification.class);
             contentInfo                   = copyCollection(object.getContentInfo(),                   ContentInformation.class);
-            distributionInfo              = copyCollection(object.getDistributionInfo(),              Distribution.class);
+            distributionInfo              = object.getDistributionInfo();
             dataQualityInfo               = copyCollection(object.getDataQualityInfo(),               DataQuality.class);
             portrayalCatalogueInfo        = copyCollection(object.getPortrayalCatalogueInfo(),        PortrayalCatalogueReference.class);
             metadataConstraints           = copyCollection(object.getMetadataConstraints(),           Constraints.class);
@@ -865,12 +865,17 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     /**
      * Returns the parties responsible for the metadata information.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return parties responsible for the metadata information.
      */
     @Override
     @XmlElement(name = "contact", required = true)
-    public Collection<Responsibility> getContacts() {
-        return contacts = nonNullCollection(contacts, Responsibility.class);
+    public Collection<ResponsibleParty> getContacts() {
+        return contacts = nonNullCollection(contacts, ResponsibleParty.class);
     }
 
     /**
@@ -878,9 +883,9 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      *
      * @param  newValues  the new contacts.
      */
-    public void setContacts(final Collection<? extends Responsibility> newValues) {
+    public void setContacts(final Collection<? extends ResponsibleParty> newValues) {
         checkWritePermission();
-        contacts = writeCollection(newValues, contacts, Responsibility.class);
+        contacts = writeCollection(newValues, contacts, ResponsibleParty.class);
     }
 
     /**
@@ -1363,21 +1368,32 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     /**
      * Returns information about the distributor of and options for obtaining the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change will tentatively be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return the distributor of and options for obtaining the resource(s).
      */
     @Override
     @XmlElement(name = "distributionInfo")
-    public Collection<Distribution> getDistributionInfo() {
-        return distributionInfo = nonNullCollection(distributionInfo, Distribution.class);
+    public Distribution getDistributionInfo() {
+        return distributionInfo;
     }
 
     /**
      * Sets information about the distributor of and options for obtaining the resource(s).
      *
-     * @param  newValues  the new distribution info.
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change will tentatively be applied in GeoAPI 4.0.
+     * </div>
+     *
+     * @param  newValue  the new distribution info.
      */
-    public void setDistributionInfo(final Collection<? extends Distribution> newValues) {
-        distributionInfo = writeCollection(newValues, distributionInfo, Distribution.class);
+    public void setDistributionInfo(final Distribution newValue) {
+        checkWritePermission();
+        distributionInfo = newValue;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
index f372aaa..6f88327 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
@@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.parameter.ParameterValue;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.iso.Types;
@@ -137,7 +138,7 @@ import static org.apache.sis.util.collection.Containers.property;
     "version"
 })
 @XmlRootElement(name = "RS_Identifier", namespace = Namespaces.GMD)
-public class ImmutableIdentifier extends FormattableObject implements Identifier, Serializable {
+public class ImmutableIdentifier extends FormattableObject implements ReferenceIdentifier, Serializable {
     /**
      * For cross-version compatibility.
      */
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/OnlineResourceAdapter.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/OnlineResourceAdapter.java
new file mode 100644
index 0000000..9e7a202
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/OnlineResourceAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.iso;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.opengis.metadata.citation.OnlineResource;
+import org.apache.sis.internal.jaxb.metadata.CI_OnlineResource;
+import org.apache.sis.metadata.iso.citation.DefaultOnlineResource;
+
+
+/**
+ * Converts an URI to a {@code <cit:OnlineResource>} element for ISO 19115-3:2016 compliance.
+ * We need this additional adapter because some property type changed from {@code URI} to
+ * {@code OnlineResource} in the upgrade from ISO 19115:2003 to ISO 19115-1:2014.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ */
+final class OnlineResourceAdapter extends XmlAdapter<CI_OnlineResource, URI> {
+    /**
+     * The adapter performing the actual work.
+     */
+    private static final CI_OnlineResource ADAPTER = new CI_OnlineResource.Since2014();
+
+    /**
+     * Wraps the given URI in a {@code <cit:OnlineResource>} element.
+     */
+    @Override
+    public CI_OnlineResource marshal(final URI value) {
+        if (value != null) {
+            return ADAPTER.marshal(new DefaultOnlineResource(value));
+        }
+        return null;
+    }
+
+    /**
+     * Returns a URI from the given {@code <cit:OnlineResource>} element.
+     */
+    @Override
+    public URI unmarshal(final CI_OnlineResource value) throws URISyntaxException {
+        if (value != null) {
+            final OnlineResource res = ADAPTER.unmarshal(value);
+            if (res != null) {
+                return res.getLinkage();
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/URIStringAdapter.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/URIStringAdapter.java
new file mode 100644
index 0000000..07b42c5
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/URIStringAdapter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.iso;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.jaxb.gco.CharSequenceAdapter;
+import org.apache.sis.internal.jaxb.gco.GO_CharacterString;
+
+
+/**
+ * Converts an URI to a {@code <gco:CharacterSequence>} element for ISO 19115-3:2016 compliance.
+ * We need this additional adapter because some property type changed from {@code URI}
+ * to {@code CharacterSequence} in the upgrade from ISO 19115:2003 to ISO 19115-1:2014.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ */
+final class URIStringAdapter extends XmlAdapter<GO_CharacterString, URI> {
+    /**
+     * The adapter performing the actual work.
+     */
+    private static final CharSequenceAdapter ADAPTER = new CharSequenceAdapter.Since2014();
+
+    /**
+     * Wraps the given URI in a {@code <cit:OnlineResource>} element.
+     */
+    @Override
+    public GO_CharacterString marshal(final URI value) {
+        if (value != null) {
+            return ADAPTER.marshal(value.toString());
+        }
+        return null;
+    }
+
+    /**
+     * Returns a URI from the given {@code <cit:OnlineResource>} element.
+     */
+    @Override
+    public URI unmarshal(final GO_CharacterString value) throws URISyntaxException {
+        if (value != null) {
+            final CharSequence uri = ADAPTER.unmarshal(value);
+            if (uri != null) {
+                final Context context = Context.current();
+                return Context.converter(context).toURI(context, uri.toString());
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatform.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatform.java
index 79bbb55..5e5e70c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatform.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatform.java
@@ -24,7 +24,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.acquisition.Instrument;
 import org.opengis.metadata.acquisition.Platform;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.util.InternationalString;
 import org.apache.sis.metadata.iso.ISOMetadata;
 import org.apache.sis.internal.jaxb.NonMarshalledAuthority;
@@ -85,7 +85,7 @@ public class DefaultPlatform extends ISOMetadata implements Platform {
     /**
      * Organization responsible for building, launch, or operation of the platform.
      */
-    private Collection<Responsibility> sponsors;
+    private Collection<ResponsibleParty> sponsors;
 
     /**
      * Instrument(s) mounted on a platform.
@@ -113,7 +113,7 @@ public class DefaultPlatform extends ISOMetadata implements Platform {
             citation    = object.getCitation();
             identifiers = singleton(object.getIdentifier(), Identifier.class);
             description = object.getDescription();
-            sponsors    = copyCollection(object.getSponsors(), Responsibility.class);
+            sponsors    = copyCollection(object.getSponsors(), ResponsibleParty.class);
             instruments = copyCollection(object.getInstruments(), Instrument.class);
         }
     }
@@ -210,21 +210,31 @@ public class DefaultPlatform extends ISOMetadata implements Platform {
     /**
      * Returns the organization responsible for building, launch, or operation of the platform.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return organization responsible for building, launch, or operation of the platform.
      */
     @Override
     @XmlElement(name = "sponsor")
-    public Collection<Responsibility> getSponsors() {
-        return sponsors = nonNullCollection(sponsors, Responsibility.class);
+    public Collection<ResponsibleParty> getSponsors() {
+        return sponsors = nonNullCollection(sponsors, ResponsibleParty.class);
     }
 
     /**
      * Sets the organization responsible for building, launch, or operation of the platform.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new sponsors values;
      */
-    public void setSponsors(final Collection<? extends Responsibility> newValues) {
-        sponsors = writeCollection(newValues, sponsors, Responsibility.class);
+    public void setSponsors(final Collection<? extends ResponsibleParty> newValues) {
+        sponsors = writeCollection(newValues, sponsors, ResponsibleParty.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
index 34f6e5d..8374339 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
@@ -27,7 +27,7 @@ import org.opengis.metadata.acquisition.Priority;
 import org.opengis.metadata.acquisition.RequestedDate;
 import org.opengis.metadata.acquisition.Requirement;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.apache.sis.metadata.iso.ISOMetadata;
 import org.apache.sis.internal.jaxb.NonMarshalledAuthority;
 
@@ -95,12 +95,12 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
     /**
      * Origin of requirement.
      */
-    private Collection<Responsibility> requestors;
+    private Collection<ResponsibleParty> requestors;
 
     /**
      * Person(s), or body(ies), to receive results of requirement.
      */
-    private Collection<Responsibility> recipients;
+    private Collection<ResponsibleParty> recipients;
 
     /**
      * Relative ordered importance, or urgency, of the requirement.
@@ -143,8 +143,8 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
         if (object != null) {
             citation       = object.getCitation();
             identifiers    = singleton(object.getIdentifier(), Identifier.class);
-            requestors     = copyCollection(object.getRequestors(), Responsibility.class);
-            recipients     = copyCollection(object.getRecipients(), Responsibility.class);
+            requestors     = copyCollection(object.getRequestors(), ResponsibleParty.class);
+            recipients     = copyCollection(object.getRecipients(), ResponsibleParty.class);
             priority       = object.getPriority();
             requestedDate  = object.getRequestedDate();
             expiryDate     = toMilliseconds(object.getExpiryDate());
@@ -224,41 +224,61 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
     /**
      * Returns the origin of requirement.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return origin of requirement.
      */
     @Override
     @XmlElement(name = "requestor", required = true)
-    public Collection<Responsibility> getRequestors() {
-        return requestors = nonNullCollection(requestors, Responsibility.class);
+    public Collection<ResponsibleParty> getRequestors() {
+        return requestors = nonNullCollection(requestors, ResponsibleParty.class);
     }
 
     /**
      * Sets the origin of requirement.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new requestors values.
      */
-    public void setRequestors(final Collection<? extends Responsibility> newValues) {
-        requestors = writeCollection(newValues, requestors, Responsibility.class);
+    public void setRequestors(final Collection<? extends ResponsibleParty> newValues) {
+        requestors = writeCollection(newValues, requestors, ResponsibleParty.class);
     }
 
     /**
      * Returns the person(s), or body(ies), to receive results of requirement.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return person(s), or body(ies), to receive results.
      */
     @Override
     @XmlElement(name = "recipient", required = true)
-    public Collection<Responsibility> getRecipients() {
-        return recipients = nonNullCollection(recipients, Responsibility.class);
+    public Collection<ResponsibleParty> getRecipients() {
+        return recipients = nonNullCollection(recipients, ResponsibleParty.class);
     }
 
     /**
      * Sets the Person(s), or body(ies), to receive results of requirement.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new recipients values.
      */
-    public void setRecipients(final Collection<? extends Responsibility> newValues) {
-        recipients = writeCollection(newValues, recipients, Responsibility.class);
+    public void setRecipients(final Collection<? extends ResponsibleParty> newValues) {
+        recipients = writeCollection(newValues, recipients, ResponsibleParty.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/package-info.java
index 46b16ec..6bb47b9 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/package-info.java
@@ -100,7 +100,7 @@
 @XmlAccessorType(XmlAccessType.NONE)
 @XmlJavaTypeAdapters({
     @XmlJavaTypeAdapter(CI_Citation.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(EX_Extent.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
     @XmlJavaTypeAdapter(GO_Real.class),
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultAddress.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultAddress.java
index 14cf7dd..e4b5125 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultAddress.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultAddress.java
@@ -83,7 +83,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
     /**
      * Address line for the location (as described in ISO 11180, Annex A).
      */
-    private Collection<InternationalString> deliveryPoints;
+    private Collection<String> deliveryPoints;
 
     /**
      * Address of the electronic mailbox of the responsible organization or individual.
@@ -108,7 +108,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
     public DefaultAddress(final Address object) {
         super(object);
         if (object != null) {
-            deliveryPoints          = copyCollection(object.getDeliveryPoints(), InternationalString.class);
+            deliveryPoints          = copyCollection(object.getDeliveryPoints(), String.class);
             city                    = object.getCity();
             administrativeArea      = object.getAdministrativeArea();
             postalCode              = object.getPostalCode();
@@ -208,21 +208,31 @@ public class DefaultAddress extends ISOMetadata implements Address {
     /**
      * Returns the address line for the location (as described in ISO 11180, Annex A).
      *
+     * <div class="warning"><b>Upcoming API change — internationalization</b><br>
+     * The return type may be changed from {@code Collection<String>} to
+     * {@code Collection<? extends InternationalString>} in GeoAPI 4.0.
+     * </div>
+     *
      * @return address line for the location.
      */
     @Override
     @XmlElement(name = "deliveryPoint")
-    public Collection<InternationalString> getDeliveryPoints() {
-        return deliveryPoints = nonNullCollection(deliveryPoints, InternationalString.class);
+    public Collection<String> getDeliveryPoints() {
+        return deliveryPoints = nonNullCollection(deliveryPoints, String.class);
     }
 
     /**
      * Sets the address line for the location (as described in ISO 11180, Annex A).
      *
+     * <div class="warning"><b>Upcoming API change — internationalization</b><br>
+     * The argument type may be changed from {@code Collection<String>} to
+     * {@code Collection<? extends InternationalString>} in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new delivery points, or {@code null} if none.
      */
-    public void setDeliveryPoints(final Collection<? extends InternationalString> newValues) {
-        deliveryPoints = writeCollection(newValues, deliveryPoints, InternationalString.class);
+    public void setDeliveryPoints(final Collection<? extends String> newValues) {
+        deliveryPoints = writeCollection(newValues, deliveryPoints, String.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
index 96a13d3..8f4d457 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
@@ -26,7 +26,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.identification.BrowseGraphic;
 import org.opengis.util.InternationalString;
@@ -99,7 +99,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -7343644724857519090L;
+    private static final long serialVersionUID = 3490090845236158848L;
 
     /**
      * Name by which the cited resource is known.
@@ -132,7 +132,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * Roles, Name, contact, and position information for an individual or organization that is responsible
      * for the resource.
      */
-    private Collection<Responsibility> citedResponsibleParties;
+    private Collection<ResponsibleParty> citedResponsibleParties;
 
     /**
      * Mode in which the resource is represented, or an empty collection if none.
@@ -149,7 +149,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * Other information required to complete the citation that is not recorded elsewhere.
      * May be {@code null} if none.
      */
-    private Collection<InternationalString> otherCitationDetails;
+    private InternationalString otherCitationDetails;
 
     /**
      * Common title with holdings note. Note: title identifies elements of a series
@@ -206,10 +206,10 @@ public class DefaultCitation extends ISOMetadata implements Citation {
             edition                 = object.getEdition();
             editionDate             = toMilliseconds(object.getEditionDate());
             identifiers             = copyCollection(object.getIdentifiers(), Identifier.class);
-            citedResponsibleParties = copyCollection(object.getCitedResponsibleParties(), Responsibility.class);
+            citedResponsibleParties = copyCollection(object.getCitedResponsibleParties(), ResponsibleParty.class);
             presentationForms       = copyCollection(object.getPresentationForms(), PresentationForm.class);
             series                  = object.getSeries();
-            otherCitationDetails    = copyCollection(object.getOtherCitationDetails(), InternationalString.class);
+            otherCitationDetails    = object.getOtherCitationDetails();
             collectiveTitle         = object.getCollectiveTitle();
             onlineResources         = copyCollection(object.getOnlineResources(), OnlineResource.class);
             graphics                = copyCollection(object.getGraphics(), BrowseGraphic.class);
@@ -402,22 +402,32 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * Returns the role, name, contact and position information for an individual or organization
      * that is responsible for the resource.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return the individual or organization that is responsible, or an empty collection if none.
      */
     @Override
     @XmlElement(name = "citedResponsibleParty")
-    public Collection<Responsibility> getCitedResponsibleParties() {
-        return citedResponsibleParties = nonNullCollection(citedResponsibleParties, Responsibility.class);
+    public Collection<ResponsibleParty> getCitedResponsibleParties() {
+        return citedResponsibleParties = nonNullCollection(citedResponsibleParties, ResponsibleParty.class);
     }
 
     /**
      * Sets the role, name, contact and position information for an individual or organization
      * that is responsible for the resource.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new cited responsible parties, or {@code null} if none.
      */
-    public void setCitedResponsibleParties(final Collection<? extends Responsibility> newValues) {
-        citedResponsibleParties = writeCollection(newValues, citedResponsibleParties, Responsibility.class);
+    public void setCitedResponsibleParties(final Collection<? extends ResponsibleParty> newValues) {
+        citedResponsibleParties = writeCollection(newValues, citedResponsibleParties, ResponsibleParty.class);
     }
 
     /**
@@ -464,21 +474,32 @@ public class DefaultCitation extends ISOMetadata implements Citation {
     /**
      * Returns other information required to complete the citation that is not recorded elsewhere.
      *
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return other details, or {@code null} if none.
      */
     @Override
     @XmlElement(name = "otherCitationDetails")
-    public Collection<InternationalString> getOtherCitationDetails() {
-        return otherCitationDetails = nonNullCollection(otherCitationDetails, InternationalString.class);
+    public InternationalString getOtherCitationDetails() {
+        return otherCitationDetails;
     }
 
     /**
      * Sets other information required to complete the citation that is not recorded elsewhere.
      *
-     * @param newValues Other citations details.
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
+     * @param newValue Other citations details, or {@code null} if none.
      */
-    public void setOtherCitationDetails(final Collection<? extends InternationalString> newValues) {
-        otherCitationDetails = writeCollection(newValues, otherCitationDetails, InternationalString.class);
+    public void setOtherCitationDetails(final InternationalString newValue) {
+        checkWritePermission();
+        otherCitationDetails = newValue;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
index 64764c7..6017abf 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
@@ -97,7 +97,7 @@ public class DefaultContact extends ISOMetadata implements Contact {
     /**
      * Time period (including time zone) when individuals can contact the organization or individual.
      */
-    private Collection<InternationalString> hoursOfService;
+    private InternationalString hoursOfService;
 
     /**
      * Supplemental instructions on how or when to contact the individual or organization.
@@ -140,7 +140,7 @@ public class DefaultContact extends ISOMetadata implements Contact {
             phones              = copyCollection(object.getPhones(), Telephone.class);
             addresses           = copyCollection(object.getAddresses(), Address.class);
             onlineResources     = copyCollection(object.getOnlineResources(), OnlineResource.class);
-            hoursOfService      = copyCollection(object.getHoursOfService(), InternationalString.class);
+            hoursOfService      = object.getHoursOfService();
             contactInstructions = object.getContactInstructions();
             contactType         = object.getContactType();
         }
@@ -400,21 +400,32 @@ public class DefaultContact extends ISOMetadata implements Contact {
     /**
      * Returns the time period (including time zone) when individuals can contact the organization or individual.
      *
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change will tentatively be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return time period when individuals can contact the organization or individual.
      */
     @Override
     @XmlElement(name = "hoursOfService")
-    public Collection<InternationalString> getHoursOfService() {
-        return hoursOfService = nonNullCollection(hoursOfService, InternationalString.class);
+    public InternationalString getHoursOfService() {
+        return hoursOfService;
     }
 
     /**
      * Sets time period (including time zone) when individuals can contact the organization or individual.
      *
-     * @param  newValues  the new hours of service.
+     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
+     * As of ISO 19115:2014, this singleton has been replaced by a collection.
+     * This change will tentatively be applied in GeoAPI 4.0.
+     * </div>
+     *
+     * @param  newValue  the new hours of service.
      */
-    public void setHoursOfService(final Collection<? extends InternationalString> newValues) {
-        hoursOfService = writeCollection(newValues, hoursOfService, InternationalString.class);
+    public void setHoursOfService(final InternationalString newValue) {
+        checkWritePermission();
+        hoursOfService = newValue;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java
index 457cd6f..481906d 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java
@@ -90,7 +90,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
     /**
      * Name of the online resources.
      */
-    private InternationalString name;
+    private String name;
 
     /**
      * Detailed text description of what the online resource is/does.
@@ -196,20 +196,28 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
     /**
      * Name of the online resource. Returns {@code null} if none.
      *
+     * <div class="warning"><b>Upcoming API change — internationalization</b><br>
+     * The return type may be changed from {@code String} to {@code InternationalString} in GeoAPI 4.0.
+     * </div>
+     *
      * @return name of the online resource, or {@code null}.
      */
     @Override
     @XmlElement(name = "name")
-    public InternationalString getName() {
+    public String getName() {
         return name;
     }
 
     /**
      * Sets the name of the online resource.
      *
+     * <div class="warning"><b>Upcoming API change — internationalization</b><br>
+     * The argument type may be changed from {@code String} to {@code InternationalString} in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new name, or {@code null} if none.
      */
-    public void setName(final InternationalString newValue) {
+    public void setName(final String newValue) {
         checkWritePermission();
         name = newValue;
     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultSeries.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultSeries.java
index 564b97a..ceaa186 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultSeries.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultSeries.java
@@ -54,7 +54,7 @@ public class DefaultSeries extends ISOMetadata implements Series {
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -1584743260325409070L;
+    private static final long serialVersionUID = 7061644572814855051L;
 
     /**
      * Name of the series, or aggregate dataset, of which the dataset is a part.
@@ -64,12 +64,12 @@ public class DefaultSeries extends ISOMetadata implements Series {
     /**
      * Information identifying the issue of the series.
      */
-    private InternationalString issueIdentification;
+    private String issueIdentification;
 
     /**
      * Details on which pages of the publication the article was published.
      */
-    private InternationalString page;
+    private String page;
 
     /**
      * Constructs a default series.
@@ -153,20 +153,30 @@ public class DefaultSeries extends ISOMetadata implements Series {
     /**
      * Returns information identifying the issue of the series.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code String} is replaced by the {@link InternationalString} interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return information identifying the issue of the series, or {@code null}.
      */
     @Override
     @XmlElement(name = "issueIdentification")
-    public InternationalString getIssueIdentification() {
+    public String getIssueIdentification() {
         return issueIdentification;
     }
 
     /**
      * Sets information identifying the issue of the series.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code String} is replaced by the {@link InternationalString} interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new issue identification, or {@code null} if none.
      */
-    public void setIssueIdentification(final InternationalString newValue) {
+    public void setIssueIdentification(final String newValue) {
         checkWritePermission();
         issueIdentification = newValue;
     }
@@ -174,20 +184,30 @@ public class DefaultSeries extends ISOMetadata implements Series {
     /**
      * Returns details on which pages of the publication the article was published.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code String} is replaced by the {@link InternationalString} interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return details on which pages of the publication the article was published, or {@code null}.
      */
     @Override
     @XmlElement(name = "page")
-    public InternationalString getPage() {
+    public String getPage() {
         return page;
     }
 
     /**
      * Sets details on which pages of the publication the article was published.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code String} is replaced by the {@link InternationalString} interface.
+     * This change will be tentatively applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new page, or {@code null} if none.
      */
-    public void setPage(final InternationalString newValue) {
+    public void setPage(final String newValue) {
         checkWritePermission();
         page = newValue;
     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java
index 41bd627..8a98a5b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java
@@ -108,7 +108,7 @@
     @XmlJavaTypeAdapter(CI_OnlineResource.class),
     @XmlJavaTypeAdapter(CI_Party.class),
     @XmlJavaTypeAdapter(CI_PresentationFormCode.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(CI_RoleCode.class),
     @XmlJavaTypeAdapter(CI_Series.class),
     @XmlJavaTypeAdapter(CI_Telephone.class),
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistributor.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistributor.java
index 238e7d8..5ac6dca 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistributor.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistributor.java
@@ -20,7 +20,7 @@ import java.util.Collection;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.distribution.Format;
 import org.opengis.metadata.distribution.Distributor;
 import org.opengis.metadata.distribution.StandardOrderProcess;
@@ -71,12 +71,12 @@ public class DefaultDistributor extends ISOMetadata implements Distributor {
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -8819538342342106743L;
+    private static final long serialVersionUID = 5706757156163948001L;
 
     /**
      * Party from whom the resource may be obtained. This list need not be exhaustive.
      */
-    private Responsibility distributorContact;
+    private ResponsibleParty distributorContact;
 
     /**
      * Provides information about how the resource may be obtained, and related
@@ -105,7 +105,7 @@ public class DefaultDistributor extends ISOMetadata implements Distributor {
      *
      * @param distributorContact  party from whom the resource may be obtained, or {@code null}.
      */
-    public DefaultDistributor(final Responsibility distributorContact) {
+    public DefaultDistributor(final ResponsibleParty distributorContact) {
         this.distributorContact = distributorContact;
     }
 
@@ -156,20 +156,30 @@ public class DefaultDistributor extends ISOMetadata implements Distributor {
     /**
      * Party from whom the resource may be obtained.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return party from whom the resource may be obtained, or {@code null}.
      */
     @Override
     @XmlElement(name = "distributorContact", required = true)
-    public Responsibility getDistributorContact() {
+    public ResponsibleParty getDistributorContact() {
         return distributorContact;
     }
 
     /**
      * Sets the party from whom the resource may be obtained.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValue  the new distributor contact.
      */
-    public void setDistributorContact(final Responsibility newValue) {
+    public void setDistributorContact(final ResponsibleParty newValue) {
         checkWritePermission();
         distributorContact = newValue;
     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/package-info.java
index 3025f16..877e5af 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/package-info.java
@@ -97,6 +97,7 @@
     @XmlJavaTypeAdapter(MD_Medium.class),
     @XmlJavaTypeAdapter(MD_MediumFormatCode.class),
     @XmlJavaTypeAdapter(MD_MediumNameCode.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(MD_StandardOrderProcess.class),
 
     // Java types, primitive types and basic OGC types handling
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/AbstractIdentification.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/AbstractIdentification.java
index 4ff5e99..5ef5201 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/AbstractIdentification.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/AbstractIdentification.java
@@ -24,7 +24,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.constraint.Constraints;
 import org.opengis.metadata.distribution.Format;
 import org.opengis.metadata.extent.Extent;
@@ -145,7 +145,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
     /**
      * Recognition of those who contributed to the resource(s).
      */
-    private Collection<InternationalString> credits;
+    private Collection<String> credits;
 
     /**
      * Status of the resource(s).
@@ -156,7 +156,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * Identification of, and means of communication with, person(s) and organizations(s)
      * associated with the resource(s).
      */
-    private Collection<Responsibility> pointOfContacts;
+    private Collection<ResponsibleParty> pointOfContacts;
 
     /**
      * Methods used to spatially represent geographic information.
@@ -261,9 +261,9 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
             citation                   = object.getCitation();
             abstracts                  = object.getAbstract();
             purpose                    = object.getPurpose();
-            credits                    = copyCollection(object.getCredits(), InternationalString.class);
+            credits                    = copyCollection(object.getCredits(), String.class);
             status                     = copyCollection(object.getStatus(), Progress.class);
-            pointOfContacts            = copyCollection(object.getPointOfContacts(), Responsibility.class);
+            pointOfContacts            = copyCollection(object.getPointOfContacts(), ResponsibleParty.class);
             spatialRepresentationTypes = copyCollection(object.getSpatialRepresentationTypes(), SpatialRepresentationType.class);
             spatialResolutions         = copyCollection(object.getSpatialResolutions(), Resolution.class);
             temporalResolutions        = copyCollection(object.getTemporalResolutions(), Duration.class);
@@ -384,21 +384,29 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
     /**
      * Returns the recognition of those who contributed to the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * The element type may be changed to the {@code InternationalString} interface in GeoAPI 4.0.
+     * </div>
+     *
      * @return recognition of those who contributed to the resource(s).
      */
     @Override
     @XmlElement(name = "credit")
-    public Collection<InternationalString> getCredits() {
-        return credits = nonNullCollection(credits, InternationalString.class);
+    public Collection<String> getCredits() {
+        return credits = nonNullCollection(credits, String.class);
     }
 
     /**
      * Sets the recognition of those who contributed to the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * The element type may be changed to the {@code InternationalString} interface in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new credits.
      */
-    public void setCredits(final Collection<? extends InternationalString> newValues) {
-        credits = writeCollection(newValues, credits, InternationalString.class);
+    public void setCredits(final Collection<? extends String> newValues) {
+        credits = writeCollection(newValues, credits, String.class);
     }
 
     /**
@@ -425,23 +433,33 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * Returns the identification of, and means of communication with, person(s) and organizations(s)
      * associated with the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return means of communication with person(s) and organizations(s) associated with the resource(s).
      *
      * @see org.apache.sis.metadata.iso.DefaultMetadata#getContacts()
      */
     @Override
     @XmlElement(name = "pointOfContact")
-    public Collection<Responsibility> getPointOfContacts() {
-        return pointOfContacts = nonNullCollection(pointOfContacts, Responsibility.class);
+    public Collection<ResponsibleParty> getPointOfContacts() {
+        return pointOfContacts = nonNullCollection(pointOfContacts, ResponsibleParty.class);
     }
 
     /**
      * Sets the means of communication with persons(s) and organizations(s) associated with the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new points of contacts.
      */
-    public void setPointOfContacts(final Collection<? extends Responsibility> newValues) {
-        pointOfContacts = writeCollection(newValues, pointOfContacts, Responsibility.class);
+    public void setPointOfContacts(final Collection<? extends ResponsibleParty> newValues) {
+        pointOfContacts = writeCollection(newValues, pointOfContacts, ResponsibleParty.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
index 4a12fa6..987a81f 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java
@@ -25,6 +25,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.identification.CharacterSet;
 import org.opengis.metadata.identification.TopicCategory;
 import org.opengis.metadata.identification.DataIdentification;
 import org.apache.sis.internal.metadata.OtherLocales;
@@ -93,7 +94,7 @@ public class DefaultDataIdentification extends AbstractIdentification implements
     /**
      * Serial number for compatibility with different versions.
      */
-    private static final long serialVersionUID = 6104637930243499851L;
+    private static final long serialVersionUID = 6104637930243499850L;
 
     /**
      * Language(s) used within the dataset.
@@ -103,7 +104,7 @@ public class DefaultDataIdentification extends AbstractIdentification implements
     /**
      * Full name of the character coding standard used for the dataset.
      */
-    private Collection<Charset> characterSets;
+    private Collection<CharacterSet> characterSets;
 
     /**
      * Description of the dataset in the producer’s processing environment, including items
@@ -153,7 +154,7 @@ public class DefaultDataIdentification extends AbstractIdentification implements
         super(object);
         if (object != null) {
             languages                  = copyCollection(object.getLanguages(), Locale.class);
-            characterSets              = copyCollection(object.getCharacterSets(), Charset.class);
+            characterSets              = copyCollection(object.getCharacterSets(), CharacterSet.class);
             environmentDescription     = object.getEnvironmentDescription();
             supplementalInformation    = object.getSupplementalInformation();
         }
@@ -214,21 +215,29 @@ public class DefaultDataIdentification extends AbstractIdentification implements
     /**
      * Returns the character coding standard used for the dataset.
      *
+     * <div class="warning"><b>Upcoming API change — JDK integration</b><br>
+     * The element type may change to the {@link Charset} class in GeoAPI 4.0.
+     * </div>
+     *
      * @return character coding standard(s) used.
      */
     @Override
     @XmlElement(name = "characterSet", namespace = LegacyNamespaces.GMD)
-    public Collection<Charset> getCharacterSets() {
-        return characterSets = nonNullCollection(characterSets, Charset.class);
+    public Collection<CharacterSet> getCharacterSets() {
+        return characterSets = nonNullCollection(characterSets, CharacterSet.class);
     }
 
     /**
      * Sets the character coding standard used for the dataset.
      *
+     * <div class="warning"><b>Upcoming API change — JDK integration</b><br>
+     * The element type may change to the {@link Charset} class in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new character sets.
      */
-    public void setCharacterSets(final Collection<? extends Charset> newValues) {
-        characterSets = writeCollection(newValues, characterSets, Charset.class);
+    public void setCharacterSets(final Collection<? extends CharacterSet> newValues) {
+        characterSets = writeCollection(newValues, characterSets, CharacterSet.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultUsage.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultUsage.java
index 782ca7b..1b5f97c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultUsage.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultUsage.java
@@ -23,7 +23,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.identification.Usage;
 import org.apache.sis.internal.jaxb.FilterByVersion;
 import org.apache.sis.metadata.iso.ISOMetadata;
@@ -103,7 +103,7 @@ public class DefaultUsage extends ISOMetadata implements Usage {
     /**
      * Identification of and means of communicating with person(s) and organization(s) using the resource(s).
      */
-    private Collection<Responsibility> userContactInfo;
+    private Collection<ResponsibleParty> userContactInfo;
 
     /**
      * Responses to the user-determined limitations.
@@ -134,10 +134,10 @@ public class DefaultUsage extends ISOMetadata implements Usage {
      * @param userContactInfo  means of communicating with person(s) and organization(s), or {@code null} if none.
      */
     public DefaultUsage(final CharSequence specificUsage,
-                        final Responsibility userContactInfo)
+                        final ResponsibleParty userContactInfo)
     {
         this.specificUsage   = Types.toInternationalString(specificUsage);
-        this.userContactInfo = singleton(userContactInfo, Responsibility.class);
+        this.userContactInfo = singleton(userContactInfo, ResponsibleParty.class);
     }
 
     /**
@@ -155,7 +155,7 @@ public class DefaultUsage extends ISOMetadata implements Usage {
             specificUsage             = object.getSpecificUsage();
             usageDate                 = toMilliseconds(object.getUsageDate());
             userDeterminedLimitations = object.getUserDeterminedLimitations();
-            userContactInfo           = copyCollection(object.getUserContactInfo(), Responsibility.class);
+            userContactInfo           = copyCollection(object.getUserContactInfo(), ResponsibleParty.class);
             responses                 = copyCollection(object.getResponses(), InternationalString.class);
             additionalDocumentation   = copyCollection(object.getAdditionalDocumentation(), Citation.class);
             identifiedIssues          = copyCollection(object.getIdentifiedIssues(), Citation.class);
@@ -253,21 +253,31 @@ public class DefaultUsage extends ISOMetadata implements Usage {
     /**
      * Returns identification of and means of communicating with person(s) and organization(s) using the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return means of communicating with person(s) and organization(s) using the resource(s).
      */
     @Override
     @XmlElement(name = "userContactInfo")
-    public Collection<Responsibility> getUserContactInfo() {
-        return userContactInfo = nonNullCollection(userContactInfo, Responsibility.class);
+    public Collection<ResponsibleParty> getUserContactInfo() {
+        return userContactInfo = nonNullCollection(userContactInfo, ResponsibleParty.class);
     }
 
     /**
      * Sets identification of and means of communicating with person(s) and organization(s) using the resource(s).
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new user contact info.
      */
-    public void setUserContactInfo(final Collection<? extends Responsibility> newValues) {
-        userContactInfo = writeCollection(newValues, userContactInfo, Responsibility.class);
+    public void setUserContactInfo(final Collection<? extends ResponsibleParty> newValues) {
+        userContactInfo = writeCollection(newValues, userContactInfo, ResponsibleParty.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/package-info.java
index 4afb6e8..1182479 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/package-info.java
@@ -115,7 +115,7 @@
 @XmlJavaTypeAdapters({
     @XmlJavaTypeAdapter(CI_Citation.class),
     @XmlJavaTypeAdapter(CI_OnlineResource.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(DCPList.class),
     @XmlJavaTypeAdapter(EX_Extent.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
@@ -124,6 +124,7 @@
     @XmlJavaTypeAdapter(MD_AssociatedResource.class),
     @XmlJavaTypeAdapter(MD_BrowseGraphic.class),
     @XmlJavaTypeAdapter(MD_CharacterSetCode.class),
+    @XmlJavaTypeAdapter(MD_CharacterSetLegacy.class),
     @XmlJavaTypeAdapter(MD_Constraints.class),
     @XmlJavaTypeAdapter(MD_DataIdentification.class),
     @XmlJavaTypeAdapter(MD_Format.class),
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
index b73d362..4e7a925 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
@@ -26,7 +26,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.opengis.util.InternationalString;
 import org.opengis.temporal.TemporalPrimitive;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.maintenance.Scope;
 import org.opengis.metadata.lineage.Source;
 import org.opengis.metadata.lineage.Processing;
@@ -110,7 +110,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * Identification of, and means of communication with, person(s) and
      * organization(s) associated with the process step.
      */
-    private Collection<Responsibility> processors;
+    private Collection<ResponsibleParty> processors;
 
     /**
      * Process step documentation.
@@ -174,7 +174,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
             description           = object.getDescription();
             rationale             = object.getRationale();
             stepDateTime          = TemporalUtilities.createInstant(object.getDate());
-            processors            = copyCollection(object.getProcessors(), Responsibility.class);
+            processors            = copyCollection(object.getProcessors(), ResponsibleParty.class);
             references            = copyCollection(object.getReferences(), Citation.class);
             sources               = copyCollection(object.getSources(), Source.class);
             scope                 = object.getScope();
@@ -306,22 +306,32 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * Returns the identification of, and means of communication with, person(s) and
      * organization(s) associated with the process step.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return means of communication with person(s) and organization(s) associated with the process step.
      */
     @Override
     @XmlElement(name = "processor")
-    public Collection<Responsibility> getProcessors() {
-        return processors = nonNullCollection(processors, Responsibility.class);
+    public Collection<ResponsibleParty> getProcessors() {
+        return processors = nonNullCollection(processors, ResponsibleParty.class);
     }
 
     /**
      * Identification of, and means of communication with, person(s) and
      * organization(s) associated with the process step.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new processors.
      */
-    public void setProcessors(final Collection<? extends Responsibility> newValues) {
-        processors = writeCollection(newValues, processors, Responsibility.class);
+    public void setProcessors(final Collection<? extends ResponsibleParty> newValues) {
+        processors = writeCollection(newValues, processors, ResponsibleParty.class);
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/package-info.java
index 904b98c..960b846 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/package-info.java
@@ -80,7 +80,7 @@
 @XmlAccessorType(XmlAccessType.NONE)
 @XmlJavaTypeAdapters({
     @XmlJavaTypeAdapter(CI_Citation.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(EX_Extent.class),
     @XmlJavaTypeAdapter(GO_Real.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java
new file mode 100644
index 0000000..be02d95
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/AttributeTypeAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.iso.maintenance;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.opengis.feature.type.AttributeType;
+import org.apache.sis.internal.jaxb.gco.GO_CharacterString;
+
+
+/**
+ * For (un)marshalling deprecated {@link AttributeType} as a character string,
+ * as expected by ISO 19115-3:2016. This is a temporary bridge to be removed
+ * after the GeoAPI interfaces has been upgraded to ISO 19115-1:2014 model.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+final class AttributeTypeAdapter extends XmlAdapter<GO_CharacterString, AttributeType> {
+    /**
+     * Wrap the given value from {@link DefaultScopeDescription} to the elements
+     * defined by ISO 19115-3:2016 schema.
+     */
+    @Override
+    public AttributeType unmarshal(GO_CharacterString value) {
+        return new LegacyType(LegacyType.ADAPTER.unmarshal(value));
+    }
+
+    /**
+     * Unwrap the elements defined by ISO 19115-3:2016 schema to the value used by
+     * {@link DefaultScopeDescription}.
+     */
+    @Override
+    public GO_CharacterString marshal(AttributeType value) {
+        return LegacyType.ADAPTER.marshal(LegacyType.wrap(value));
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
index ff26354..ed33580 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultMaintenanceInformation.java
@@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.citation.CitationDate;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.maintenance.MaintenanceFrequency;
 import org.opengis.metadata.maintenance.MaintenanceInformation;
 import org.opengis.metadata.maintenance.ScopeCode;
@@ -116,7 +116,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      * Identification of, and means of communicating with, person(s) and organization(s)
      * with responsibility for maintaining the resource.
      */
-    private Collection<Responsibility> contacts;
+    private Collection<ResponsibleParty> contacts;
 
     /**
      * Creates a an initially empty maintenance information.
@@ -151,7 +151,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
             userDefinedMaintenanceFrequency = object.getUserDefinedMaintenanceFrequency();
             maintenanceScopes               = copyCollection(object.getMaintenanceScopes(), Scope.class);
             maintenanceNotes                = copyCollection(object.getMaintenanceNotes(), InternationalString.class);
-            contacts                        = copyCollection(object.getContacts(), Responsibility.class);
+            contacts                        = copyCollection(object.getContacts(), ResponsibleParty.class);
         }
     }
 
@@ -467,24 +467,34 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      * Returns identification of, and means of communicating with,
      * person(s) and organization(s) with responsibility for maintaining the resource.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @return means of communicating with person(s) and organization(s) with responsibility
      *         for maintaining the resource.
      */
     @Override
     @XmlElement(name = "contact")
-    public Collection<Responsibility> getContacts() {
-        return contacts = nonNullCollection(contacts, Responsibility.class);
+    public Collection<ResponsibleParty> getContacts() {
+        return contacts = nonNullCollection(contacts, ResponsibleParty.class);
     }
 
     /**
      * Sets identification of, and means of communicating with,
      * person(s) and organization(s) with responsibility for maintaining the resource.
      *
+     * <div class="warning"><b>Upcoming API change — generalization</b><br>
+     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@code Responsibility} parent interface.
+     * This change may be applied in GeoAPI 4.0.
+     * </div>
+     *
      * @param  newValues  the new identification of person(s) and organization(s)
      *                    with responsibility for maintaining the resource.
      */
-    public void setContacts(final Collection<? extends Responsibility> newValues) {
-        contacts = writeCollection(newValues, contacts, Responsibility.class);
+    public void setContacts(final Collection<? extends ResponsibleParty> newValues) {
+        contacts = writeCollection(newValues, contacts, ResponsibleParty.class);
     }
 
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
index 9cf6a72..f90927a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
@@ -34,6 +34,10 @@ import org.apache.sis.xml.Namespaces;
 
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
 
+// Branch-dependent imports
+import org.opengis.feature.type.AttributeType;
+import org.opengis.feature.type.FeatureType;
+
 
 /**
  * Description of the class of information covered by the information.
@@ -117,12 +121,12 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * The value, as one of the following types:
      *
      * <ul>
-     *   <li>{@code Set<CharSequence>}   for the {@code features} property</li>
-     *   <li>{@code Set<CharSequence>}   for the {@code attributes} property</li>
-     *   <li>{@code Set<CharSequence>}   for the {@code featureInstances} property</li>
-     *   <li>{@code Set<CharSequence>}   for the {@code attributeInstances} property</li>
-     *   <li>{@code String}              for the {@code dataset} property</li>
-     *   <li>{@code InternationalString} for the {@code other} property</li>
+     *   <li>{@code Set<FeatureType>}   for the {@code features} property</li>
+     *   <li>{@code Set<AttributeType>} for the {@code attributes} property</li>
+     *   <li>{@code Set<FeatureType>}   for the {@code featureInstances} property</li>
+     *   <li>{@code Set<AttributeType>} for the {@code attributeInstances} property</li>
+     *   <li>{@code String} for the {@code dataset} property</li>
+     *   <li>{@code String} for the {@code other} property</li>
      * </ul>
      */
     private Object value;
@@ -151,27 +155,36 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      *
      * @see #castOrCopy(ScopeDescription)
      */
+    @SuppressWarnings("unchecked")
     public DefaultScopeDescription(final ScopeDescription object) {
         super(object);
         if (object != null) {
             for (byte i=DATASET; i<=OTHER; i++) {
-                Collection<? extends CharSequence> props = null;
-                Object value = null;
+                Object candidate;
                 switch (i) {
-                    case DATASET:             value = object.getDataset();            break;
-                    case FEATURES:            props = object.getFeatures();           break;
-                    case ATTRIBUTES:          props = object.getAttributes();         break;
-                    case FEATURE_INSTANCES:   props = object.getFeatureInstances();   break;
-                    case ATTRIBUTE_INSTANCES: props = object.getAttributeInstances(); break;
-                    case OTHER:               value = object.getOther();              break;
+                    case DATASET:             candidate = object.getDataset();            break;
+                    case FEATURES:            candidate = object.getFeatures();           break;
+                    case ATTRIBUTES:          candidate = object.getAttributes();         break;
+                    case FEATURE_INSTANCES:   candidate = object.getFeatureInstances();   break;
+                    case ATTRIBUTE_INSTANCES: candidate = object.getAttributeInstances(); break;
+                    case OTHER:               candidate = object.getOther();              break;
                     default: throw new AssertionError(i);
                 }
-                if (props != null) {
-                    value = copySet(props, CharSequence.class);
-                }
-                if (value != null) {
-                    this.value = value;
-                    this.property = i;
+                if (candidate != null) {
+                    switch (i) {
+                        case ATTRIBUTES:
+                        case ATTRIBUTE_INSTANCES: {
+                            candidate = copySet((Collection<AttributeType>) candidate, AttributeType.class);
+                            break;
+                        }
+                        case FEATURES:
+                        case FEATURE_INSTANCES: {
+                            candidate = copySet((Collection<FeatureType>) candidate, FeatureType.class);
+                            break;
+                        }
+                    }
+                    value = candidate;
+                    property = i;
                     break;
                 }
             }
@@ -204,33 +217,35 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
     }
 
     /**
-     * Returns the given value casted to a {@code Set<CharSequence>}.
+     * Returns the given value casted to a {@code Set} of elements of the given type.
+     * It is caller responsibility to ensure that the cast is valid, as element type
+     * is verified only when assertions are enabled.
      */
     @SuppressWarnings("unchecked")
-    private static Set<CharSequence> cast(final Object value) {
-        assert ((CheckedContainer<?>) value).getElementType() == CharSequence.class;
-        return (Set<CharSequence>) value;
+    private static <E> Set<E> cast(final Object value, final Class<E> type) {
+        assert ((CheckedContainer<?>) value).getElementType() == type;
+        return (Set<E>) value;
     }
 
     /**
      * Returns the set of properties identified by the {@code code} argument,
      * or an unmodifiable empty set if another value is defined.
      */
-    private Set<CharSequence> getProperty(final byte code) {
+    private <E> Set<E> getProperty(final Class<E> type, final byte code) {
         final Object value = this.value;
         if (value != null) {
             if (property == code) {
-                return cast(value);
+                return cast(value, type);
             } else if (!(value instanceof Set) || !((Set<?>) value).isEmpty()) {
                 return Semaphores.query(Semaphores.NULL_COLLECTION)
-                       ? null : new ExcludedSet<>(NAMES[code-1], NAMES[property-1]);
+                       ? null : new ExcludedSet<E>(NAMES[code-1], NAMES[property-1]);
             }
         }
         /*
          * Unconditionally create a new set, because the
          * user may hold a reference to the previous one.
          */
-        final Set<CharSequence> c = nonNullSet(null, CharSequence.class);
+        final Set<E> c = nonNullSet(null, type);
         property = code;
         this.value = c;
         return c;
@@ -243,17 +258,17 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * @param newValue  the value to set.
      * @param code      the property which is going to be set.
      */
-    private void setProperty(final Set<? extends CharSequence> newValue, final byte code) {
-        Set<CharSequence> c = null;
+    private <E> void setProperty(final Set<? extends E> newValue, final Class<E> type, final byte code) {
+        Set<E> c = null;
         if (property == code) {
-            c = cast(value);
+            c = cast(value, type);
         } else if (isNullOrEmpty(newValue)) {
             return;
         } else {
             warningOnOverwrite(code);
             property = code;
         }
-        value = writeSet(newValue, c, CharSequence.class);
+        value = writeSet(newValue, c, type);
     }
 
     /**
@@ -317,12 +332,16 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * This method returns a modifiable collection only if no other property is set.
      * Otherwise, this method returns an unmodifiable empty collection.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @return feature types to which the information applies.
      */
     @Override
     @XmlElement(name = "features")
-    public Set<CharSequence> getFeatures() {
-        return getProperty(FEATURES);
+    public Set<FeatureType> getFeatures() {
+        return getProperty(FeatureType.class, FEATURES);
     }
 
     /**
@@ -332,10 +351,14 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * If and only if the {@code newValue} is non-empty, then this method automatically
      * discards all other properties.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @param  newValues  the new feature types.
      */
-    public void setFeatures(final Set<? extends CharSequence> newValues) {
-        setProperty(newValues, FEATURES);
+    public void setFeatures(final Set<? extends FeatureType> newValues) {
+        setProperty(newValues, FeatureType.class, FEATURES);
     }
 
     /**
@@ -351,12 +374,16 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * This method returns a modifiable collection only if no other property is set.
      * Otherwise, this method returns an unmodifiable empty collection.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @return attribute types to which the information applies.
      */
     @Override
     @XmlElement(name = "attributes")
-    public Set<CharSequence> getAttributes() {
-        return getProperty(ATTRIBUTES);
+    public Set<AttributeType> getAttributes() {
+        return getProperty(AttributeType.class, ATTRIBUTES);
     }
 
     /**
@@ -366,10 +393,14 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * If and only if the {@code newValue} is non-empty, then this method automatically
      * discards all other properties.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @param  newValues  the new attribute types.
      */
-    public void setAttributes(final Set<? extends CharSequence> newValues) {
-        setProperty(newValues, ATTRIBUTES);
+    public void setAttributes(final Set<? extends AttributeType> newValues) {
+        setProperty(newValues, AttributeType.class, ATTRIBUTES);
     }
 
     /**
@@ -385,12 +416,16 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * This method returns a modifiable collection only if no other property is set.
      * Otherwise, this method returns an unmodifiable empty collection.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @return feature instances to which the information applies.
      */
     @Override
     @XmlElement(name = "featureInstances")
-    public Set<CharSequence> getFeatureInstances() {
-        return getProperty(FEATURE_INSTANCES);
+    public Set<FeatureType> getFeatureInstances() {
+        return getProperty(FeatureType.class, FEATURE_INSTANCES);
     }
 
     /**
@@ -400,10 +435,14 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * If and only if the {@code newValue} is non-empty, then this method automatically
      * discards all other properties.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @param  newValues  the new feature instances.
      */
-    public void setFeatureInstances(final Set<? extends CharSequence> newValues) {
-        setProperty(newValues, FEATURE_INSTANCES);
+    public void setFeatureInstances(final Set<? extends FeatureType> newValues) {
+        setProperty(newValues, FeatureType.class, FEATURE_INSTANCES);
     }
 
     /**
@@ -419,12 +458,16 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * This method returns a modifiable collection only if no other property is set.
      * Otherwise, this method returns an unmodifiable empty collection.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @return attribute instances to which the information applies.
      */
     @Override
     @XmlElement(name = "attributeInstances")
-    public Set<CharSequence> getAttributeInstances() {
-        return getProperty(ATTRIBUTE_INSTANCES);
+    public Set<AttributeType> getAttributeInstances() {
+        return getProperty(AttributeType.class, ATTRIBUTE_INSTANCES);
     }
 
     /**
@@ -434,21 +477,29 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * If and only if the {@code newValue} is non-empty, then this method automatically
      * discards all other properties.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@code Set<CharSequence>} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-238">GEO-238</a> for more information.</div>
+     *
      * @param  newValues  the new attribute instances.
      */
-    public void setAttributeInstances(final Set<? extends CharSequence> newValues) {
-        setProperty(newValues, ATTRIBUTE_INSTANCES);
+    public void setAttributeInstances(final Set<? extends AttributeType> newValues) {
+        setProperty(newValues, AttributeType.class, ATTRIBUTE_INSTANCES);
     }
 
     /**
      * Returns the class of information that does not fall into the other categories to which the information applies.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@link InternationalString} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-221">GEO-221</a> for more information.</div>
+     *
      * @return class of information that does not fall into the other categories, or {@code null}.
      */
     @Override
     @XmlElement(name = "other")
-    public InternationalString getOther() {
-        return (property == OTHER) ? (InternationalString) value : null;
+    public String getOther() {
+        return (property == OTHER) ? (String) value : null;
     }
 
     /**
@@ -459,9 +510,13 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
+     * <div class="warning"><b>Upcoming API change:</b>
+     * The type of this property may be changed to {@link InternationalString} for ISO 19115:2014 conformance.
+     * See <a href="http://jira.codehaus.org/browse/GEO-221">GEO-221</a> for more information.</div>
+     *
      * @param newValue Other class of information.
      */
-    public void setOther(final InternationalString newValue) {
+    public void setOther(final String newValue) {
         checkWritePermission();
         if (newValue != null || property == OTHER) {
             warningOnOverwrite(OTHER);
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java
new file mode 100644
index 0000000..a9f1b47
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/FeatureTypeAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.iso.maintenance;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import org.opengis.feature.type.FeatureType;
+import org.apache.sis.internal.jaxb.gco.GO_CharacterString;
+
+
+/**
+ * For (un)marshalling deprecated {@link FeatureType} as a character string,
+ * as expected by ISO 19115-3:2016. This is a temporary bridge to be removed
+ * after the GeoAPI interfaces has been upgraded to ISO 19115-1:2014 model.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+final class FeatureTypeAdapter extends XmlAdapter<GO_CharacterString, FeatureType> {
+    /**
+     * Wrap the given value from {@link DefaultScopeDescription} to the elements
+     * defined by ISO 19115-3:2016 schema.
+     */
+    @Override
+    public FeatureType unmarshal(GO_CharacterString value) {
+        return new LegacyType(LegacyType.ADAPTER.unmarshal(value));
+    }
+
+    /**
+     * Unwrap the elements defined by ISO 19115-3:2016 schema to the value used by
+     * {@link DefaultScopeDescription}.
+     */
+    @Override
+    public GO_CharacterString marshal(FeatureType value) {
+        return LegacyType.ADAPTER.marshal(LegacyType.wrap(value));
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/LegacyType.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/LegacyType.java
new file mode 100644
index 0000000..d6f24c3
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/LegacyType.java
@@ -0,0 +1,70 @@
+/*
+ * 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.iso.maintenance;
+
+import org.opengis.feature.type.FeatureType;
+import org.opengis.feature.type.AttributeType;
+import org.apache.sis.internal.jaxb.gco.CharSequenceAdapter;
+
+
+/**
+ * Bridges between deprecated {@link FeatureType} / {@link AttributeType} and {@link CharSequence}.
+ * {@code FeatureType} and {@code AttributeType} were used in ISO 19115:2003, but have been replaced
+ * by {@link CharSequence} in ISO 19115:2014. The corresponding GeoAPI 3.0 interfaces are empty since
+ * they were placeholder for future work. We use this {@code LegacyType} as a temporary bridge, to be
+ * removed with GeoAPI 4.0.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+final class LegacyType implements FeatureType, AttributeType, CharSequence {
+    /**
+     * The adapter doing most of the actual work of converting {@code FeatureType} or {@code AttributeType}
+     * to {@code <gco:CharacterSequence>} elements.
+     */
+    static final CharSequenceAdapter ADAPTER = new CharSequenceAdapter();
+
+    /**
+     * The value to wrap as a {@code FeatureType} or {@code AttributeType}.
+     */
+    private final CharSequence value;
+
+    /**
+     * Creates a new type for the given value, which must be non-null.
+     */
+    LegacyType(final CharSequence value) {
+        this.value = value;
+    }
+
+    /**
+     * Wraps the given {@code FeatureType} or {@code AttributeType} as a {@code CharSequence}.
+     */
+    static CharSequence wrap(final Object value) {
+        return (value == null || value instanceof CharSequence)
+                ? (CharSequence) value : new LegacyType(value.toString());
+    }
+
+    /**
+     * Delegates to the value given at construction time.
+     */
+    @Override public int          length()                        {return value.length();}
+    @Override public char         charAt(int index)               {return value.charAt(index);}
+    @Override public CharSequence subSequence(int start, int end) {return value.subSequence(start, end);}
+    @Override public String       toString()                      {return value.toString();}
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/package-info.java
index 57e9225..4955e86 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/package-info.java
@@ -77,7 +77,7 @@
 @XmlAccessorType(XmlAccessType.NONE)
 @XmlJavaTypeAdapters({
     @XmlJavaTypeAdapter(CI_Date.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(EX_Extent.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
     @XmlJavaTypeAdapter(MD_MaintenanceFrequencyCode.class),
@@ -87,6 +87,8 @@
     @XmlJavaTypeAdapter(TM_PeriodDuration.class),
 
     // Java types, primitive types and basic OGC types handling
+    @XmlJavaTypeAdapter(FeatureTypeAdapter.class),
+    @XmlJavaTypeAdapter(AttributeTypeAdapter.class),
     @XmlJavaTypeAdapter(StringAdapter.class),
     @XmlJavaTypeAdapter(CharSequenceAdapter.class),
     @XmlJavaTypeAdapter(InternationalStringAdapter.class)
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/package-info.java
index f919127..47a1237 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/package-info.java
@@ -103,12 +103,13 @@
     @XmlJavaTypeAdapter(CI_Citation.class),
     @XmlJavaTypeAdapter(CI_Date.class),
     @XmlJavaTypeAdapter(CI_OnlineResource.class),
-    @XmlJavaTypeAdapter(CI_Responsibility.class),
+    @XmlJavaTypeAdapter(CI_ResponsibleParty.class),
     @XmlJavaTypeAdapter(DQ_DataQuality.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
     @XmlJavaTypeAdapter(GO_Integer.class),
     @XmlJavaTypeAdapter(LI_Lineage.class),
     @XmlJavaTypeAdapter(MD_ApplicationSchemaInformation.class),
+    @XmlJavaTypeAdapter(MD_CharacterSetLegacy.class),
     @XmlJavaTypeAdapter(MD_Constraints.class),
     @XmlJavaTypeAdapter(MD_ContentInformation.class),
     @XmlJavaTypeAdapter(MD_DatatypeCode.class),
@@ -125,7 +126,6 @@
     @XmlJavaTypeAdapter(MI_AcquisitionInformation.class),
     @XmlJavaTypeAdapter(PT_Locale.class),
     @XmlJavaTypeAdapter(RS_ReferenceSystem.class),
-    @XmlJavaTypeAdapter(LegacyCharacterSet.class),
 
     // Java types, primitive types and basic OGC types handling
     @XmlJavaTypeAdapter(StringAdapter.class),
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
index 4dd2d9b..237466c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
@@ -23,10 +23,9 @@ import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.metadata.lineage.Lineage;
 import org.opengis.metadata.quality.DataQuality;
 import org.opengis.metadata.quality.Element;
-import org.opengis.metadata.maintenance.Scope;
+import org.opengis.metadata.quality.Scope;
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.metadata.iso.maintenance.DefaultScope;
 import org.apache.sis.internal.jaxb.FilterByVersion;
 import org.apache.sis.internal.jaxb.LegacyNamespaces;
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/cat/EnumMarshallingTest.java b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/cat/EnumMarshallingTest.java
index bca1af2..03636a3 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/cat/EnumMarshallingTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/cat/EnumMarshallingTest.java
@@ -17,7 +17,6 @@
 package org.apache.sis.internal.jaxb.cat;
 
 import java.util.Arrays;
-import java.util.EnumSet;
 import java.util.Collection;
 import javax.xml.bind.JAXBException;
 import org.opengis.metadata.identification.TopicCategory;
@@ -72,7 +71,6 @@ public final strictfp class EnumMarshallingTest extends XMLTestCase {
          * Unmarshall the above XML and verify that we find all the topic categories.
          */
         final Collection<TopicCategory> unmarshalled = unmarshal(DefaultDataIdentification.class, expected).getTopicCategories();
-        assertInstanceOf("topicCategory", EnumSet.class, unmarshalled);
         assertSetEquals(topics, unmarshalled);
     }
 }
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
index 7198c2e..63a6ba3 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Locale;
 import java.util.Date;
-import java.nio.charset.Charset;
 
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.extent.Extent;
@@ -32,7 +31,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.distribution.Format;
 import org.opengis.metadata.constraint.Constraints;
 import org.opengis.metadata.content.AttributeGroup;
@@ -43,6 +42,7 @@ import org.opengis.metadata.maintenance.MaintenanceInformation;
 import org.opengis.metadata.spatial.SpatialRepresentationType;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.datum.GeodeticDatum;
@@ -177,10 +177,10 @@ public final strictfp class PropertyAccessorTest extends TestCase {
             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",  Responsibility[].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, "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,
@@ -205,9 +205,9 @@ public final strictfp class PropertyAccessorTest extends TestCase {
             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",                      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",            Responsibility[].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,
@@ -223,7 +223,7 @@ public final strictfp class PropertyAccessorTest extends TestCase {
             Identification.class, "getResourceConstraints",        "resourceConstraints",        "resourceConstraints",       "Resource constraints",         Constraints[].class,
             Identification.class, "getAssociatedResources",        "associatedResources",        "associatedResource",        "Associated resources",         AssociatedResource[].class,
         DataIdentification.class, "getLanguages",                  "languages",                  "language",                  "Languages",                    Locale[].class,
-        DataIdentification.class, "getCharacterSets",              "characterSets",              "characterSet",              "Character sets",               Charset[].class,
+        DataIdentification.class, "getCharacterSets",              "characterSets",              "characterSet",              "Character sets",               CharacterSet[].class,
         DataIdentification.class, "getEnvironmentDescription",     "environmentDescription",     "environmentDescription",    "Environment description",      InternationalString.class,
         DataIdentification.class, "getSupplementalInformation",    "supplementalInformation",    "supplementalInformation",   "Supplemental information",     InternationalString.class);
     }
@@ -242,10 +242,10 @@ public final strictfp class PropertyAccessorTest extends TestCase {
         //……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
-            IdentifiedObject.class, "getName",             "name",             "name",             "Name",               Identifier.class,
+            IdentifiedObject.class, "getName",             "name",             "name",             "Name",               ReferenceIdentifier.class,
             IdentifiedObject.class, "getAlias",            "alias",            "alias",            "Alias",              GenericName[].class,
             ReferenceSystem.class,  "getDomainOfValidity", "domainOfValidity", "domainOfValidity", "Domain of validity", Extent.class,
-            IdentifiedObject.class, "getIdentifiers",      "identifiers",      "identifier",       "Identifiers",        Identifier[].class,
+            IdentifiedObject.class, "getIdentifiers",      "identifiers",      "identifier",       "Identifiers",        ReferenceIdentifier[].class,
             IdentifiedObject.class, "getRemarks",          "remarks",          "remarks",          "Remarks",            InternationalString.class,
             ReferenceSystem.class,  "getScope",            "scope",            "SC_CRS.scope",     "Scope",              InternationalString.class);
     }
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
index 4eaae22..5c96d80 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyInformationTest.java
@@ -18,8 +18,8 @@ package org.apache.sis.metadata;
 
 import java.util.Locale;
 import org.opengis.util.InternationalString;
-import org.opengis.annotation.Obligation;
 import org.opengis.metadata.Datatype;
+import org.opengis.metadata.Obligation;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.PresentationForm;
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeChildrenTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeChildrenTest.java
index a4703d4..a903c83 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeChildrenTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeChildrenTest.java
@@ -21,7 +21,6 @@ import java.util.Random;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Collections;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.citation.PresentationForm;
@@ -70,7 +69,7 @@ public final strictfp class TreeNodeChildrenTest extends TestCase {
     static DefaultCitation metadataWithoutCollections() {
         final DefaultCitation citation = new DefaultCitation("Some title");
         citation.setEdition(new SimpleInternationalString("Some edition"));
-        citation.setOtherCitationDetails(Collections.singleton(new SimpleInternationalString("Some other details")));
+        citation.setOtherCitationDetails(new SimpleInternationalString("Some other details"));
         return citation;
     }
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeTest.java
index 7163237..79db6a9 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeNodeTest.java
@@ -22,14 +22,14 @@ import org.opengis.metadata.citation.Address;
 import org.opengis.metadata.citation.Contact;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.Party;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.PresentationForm;
 import org.opengis.metadata.citation.Role;
 import org.opengis.util.InternationalString;
 import org.apache.sis.metadata.iso.citation.DefaultAddress;
 import org.apache.sis.metadata.iso.citation.DefaultContact;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
-import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
 import org.apache.sis.metadata.iso.citation.DefaultOrganisation;
 import org.apache.sis.metadata.iso.citation.DefaultIndividual;
 import org.apache.sis.metadata.iso.citation.AbstractParty;
@@ -84,7 +84,8 @@ public final strictfp class TreeNodeTest extends TestCase {
     static DefaultCitation metadataWithHierarchy() {
         final DefaultCitation citation = TreeNodeChildrenTest.metadataWithMultiOccurrences();
         AbstractParty party = new DefaultOrganisation("Some organisation", null, null, null);
-        DefaultResponsibility responsibility = new DefaultResponsibility(Role.DISTRIBUTOR, null, party);
+        DefaultResponsibleParty responsibility = new DefaultResponsibleParty(Role.DISTRIBUTOR);
+        responsibility.setParties(singleton(party));
         assertTrue(citation.getCitedResponsibleParties().add(responsibility));
 
         // Add a second responsible party with deeper hierarchy.
@@ -93,7 +94,8 @@ public final strictfp class TreeNodeTest extends TestCase {
         address.setElectronicMailAddresses(singleton("Some email"));
         contact.setAddresses(singleton(address));
         party = new DefaultIndividual("Some person of contact", null, contact);
-        responsibility = new DefaultResponsibility(Role.POINT_OF_CONTACT, null, party);
+        responsibility = new DefaultResponsibleParty(Role.POINT_OF_CONTACT);
+        responsibility.setParties(singleton(party));
         assertTrue(citation.getCitedResponsibleParties().add(responsibility));
         return citation;
     }
@@ -177,7 +179,7 @@ public final strictfp class TreeNodeTest extends TestCase {
      *
      * <p>If {@link #valuePolicy} is {@link ValueExistencePolicy#COMPACT}, then this method removes the elements at
      * indices 0, 6 and 10 (if {@code offset} = 0) or 1, 7 and 11 (if {@code offset} = 1) from the {@code expected}
-     * array before to perform the comparison.</p>
+     * array before to perform the comparison (note: actual indices vary according branches).</p>
      *
      * @param  offset    0 if compact mode excludes the parent, or 1 if compact mode exclude the first child.
      * @param  column    the column from which to get a value.
@@ -188,8 +190,8 @@ public final strictfp class TreeNodeTest extends TestCase {
     private void assertCitationContentEquals(final int offset, final TableColumn<?> column, final Object... expected) {
         if (valuePolicy == ValueExistencePolicy.COMPACT) {
             assertEquals(19, expected.length);
-            System.arraycopy(expected, 12+offset, expected, 11+offset,  7-offset);    // Compact the "Individual" element.
-            System.arraycopy(expected,  8+offset, expected,  7+offset, 10-offset);    // Compact the "Organisation" element.
+            System.arraycopy(expected, 11+offset, expected, 10+offset,  8-offset);    // Compact the "Individual" element.
+            System.arraycopy(expected,  7+offset, expected,  6+offset, 11-offset);    // Compact the "Organisation" element.
             System.arraycopy(expected,  1+offset, expected,    offset, 16-offset);    // Compact the "Title" element.
             Arrays.fill(expected, 16, 19, null);
         }
@@ -209,16 +211,16 @@ public final strictfp class TreeNodeTest extends TestCase {
               "Alternate title (2 of 2)",
               "Edition",
               "Cited responsible party (1 of 2)",
-                "Role",
-                "Organisation",                         // A Party subtype
+                "Organisation",
                   "Name",                               // In COMPACT mode, this value is associated to "Organisation" node.
-              "Cited responsible party (2 of 2)",
                 "Role",
-                "Individual",                           // A Party subtype
+              "Cited responsible party (2 of 2)",
+                "Individual",
                   "Name",                               // In COMPACT mode, this value is associated to "Individual" node.
                   "Contact info",
                     "Address",
                       "Electronic mail address",
+                "Role",
               "Presentation form (1 of 2)",
               "Presentation form (2 of 2)",
               "Other citation details");
@@ -240,16 +242,16 @@ public final strictfp class TreeNodeTest extends TestCase {
               "alternateTitle",
               "edition",
               "citedResponsibleParty",
-                "role",
                 "party",
                   "name",                               // In COMPACT mode, this value is associated to "party" node.
-              "citedResponsibleParty",
                 "role",
+              "citedResponsibleParty",
                 "party",
                   "name",                               // In COMPACT mode, this value is associated to "party" node.
                   "contactInfo",
                     "address",
                       "electronicMailAddress",
+                "role",
               "presentationForm",
               "presentationForm",
               "otherCitationDetails");
@@ -263,6 +265,7 @@ public final strictfp class TreeNodeTest extends TestCase {
     public void testGetIndex() {
         final Integer ZERO = 0;
         final Integer ONE  = 1;
+        skipCountCheck = true;                              // Because of the null value at the end of following array.
         assertCitationContentEquals(1, TableColumn.INDEX,
             null,           // CI_Citation
               null,         // title
@@ -270,19 +273,19 @@ public final strictfp class TreeNodeTest extends TestCase {
               ONE,          // alternateTitle
               null,         // edition
               ZERO,         // citedResponsibleParty
-                null,       // role
                 ZERO,       // party (organisation)
                   null,     // name                         — in COMPACT mode, this value is associated to "party" node.
-              ONE,          // citedResponsibleParty
                 null,       // role
+              ONE,          // citedResponsibleParty
                 ZERO,       // party (individual)
                   null,     // name                         — in COMPACT mode, this value is associated to "party" node.
                   ZERO,     // contactInfo
                     ZERO,   // address
                       ZERO, // electronicMailAddress
+                null,       // role
               ZERO,         // presentationForm
               ONE,          // presentationForm
-              ZERO);        // otherCitationDetails
+              null);        // otherCitationDetails
     }
 
     /**
@@ -297,17 +300,17 @@ public final strictfp class TreeNodeTest extends TestCase {
               InternationalString.class,
               InternationalString.class,
               InternationalString.class,
-              Responsibility.class,
-                Role.class,
+              ResponsibleParty.class,
                 Party.class,                            // In COMPACT mode, value with be the one of "name" node instead.
                   InternationalString.class,            // Name
-              Responsibility.class,
                 Role.class,
+              ResponsibleParty.class,
                 Party.class,                            // In COMPACT mode, value with be the one of "name" node instead.
                   InternationalString.class,            // Name
                   Contact.class,
                     Address.class,
                       String.class,
+                Role.class,
               PresentationForm.class,
               PresentationForm.class,
               InternationalString.class);
@@ -326,16 +329,16 @@ public final strictfp class TreeNodeTest extends TestCase {
               "Second alternate title",
               "Some edition",
               null,                             // ResponsibleParty
-                Role.DISTRIBUTOR,
                 null,                           // Party (organisation)
                   "Some organisation",
+                Role.DISTRIBUTOR,
               null,                             // ResponsibleParty
-                Role.POINT_OF_CONTACT,
                 null,                           // Party (individual)
                   "Some person of contact",
                   null,                         // Contact
                     null,                       // Address
                       "Some email",
+                Role.POINT_OF_CONTACT,
               PresentationForm.MAP_DIGITAL,
               PresentationForm.MAP_HARDCOPY,
               "Some other details");
@@ -381,6 +384,12 @@ public final strictfp class TreeNodeTest extends TestCase {
     }
 
     /**
+     * For disabling the check of child nodes count.
+     * This hack is specific to the branch using GeoAPI 3.0 (not needed on the branch using GeoAPI 4.0).
+     */
+    private boolean skipCountCheck;
+
+    /**
      * Compares the result of the given getter method invoked on the given node, then invoked
      * on all children of that given. In the particular case of the {@link TableColumn#NAME},
      * international strings are replaced by unlocalized strings before comparisons.
@@ -398,6 +407,7 @@ public final strictfp class TreeNodeTest extends TestCase {
         if (valuePolicy == ValueExistencePolicy.COMPACT) {
             while (expected[count-1] == null) count--;
         }
+        if (skipCountCheck) return;
         assertEquals("Missing values in the tested metadata.", count,
                 assertColumnContentEquals(node, column, expected, 0));
     }
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java
index 2c77b1c..5c33496 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java
@@ -26,7 +26,7 @@ import org.apache.sis.metadata.iso.content.DefaultBand;
 import org.apache.sis.metadata.iso.content.DefaultImageDescription;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultCitationTest;
-import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
 import org.apache.sis.metadata.iso.content.DefaultAttributeGroup;
 import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
 import org.apache.sis.metadata.iso.lineage.DefaultProcessing;
@@ -91,10 +91,9 @@ public final strictfp class TreeTableFormatTest extends TestCase {
             "  │   │   └─Alternate title…………………………… ISBN\n" +
             "  │   └─Code space…………………………………………………… ISBN\n"+
             "  ├─Cited responsible party (1 of 2)\n" +
-            "  │   ├─Role…………………………………………………………………… Author\n" +
-            "  │   └─Individual…………………………………………………… Testsuya Toyoda\n" +
+            "  │   ├─Individual…………………………………………………… Testsuya Toyoda\n" +
+            "  │   └─Role…………………………………………………………………… Author\n" +
             "  ├─Cited responsible party (2 of 2)\n" +
-            "  │   ├─Role…………………………………………………………………… Editor\n" +
             "  │   ├─Extent……………………………………………………………… World\n" +
             "  │   │   └─Geographic element\n" +
             "  │   │       ├─West bound longitude…… 180°W\n" +
@@ -102,7 +101,8 @@ public final strictfp class TreeTableFormatTest extends TestCase {
             "  │   │       ├─South bound latitude…… 90°S\n" +
             "  │   │       ├─North bound latitude…… 90°N\n" +
             "  │   │       └─Extent type code……………… true\n" +
-            "  │   └─Organisation……………………………………………… Kōdansha\n" +
+            "  │   ├─Organisation……………………………………………… Kōdansha\n" +
+            "  │   └─Role…………………………………………………………………… Editor\n" +
             "  ├─Presentation form (1 of 2)…………………… Document digital\n" +
             "  ├─Presentation form (2 of 2)…………………… Document hardcopy\n" +
             "  └─ISBN……………………………………………………………………………… 9782505004509\n", text);
@@ -118,7 +118,7 @@ public final strictfp class TreeTableFormatTest extends TestCase {
         final DefaultCitation untitled = new DefaultCitation();
         titled  .setPresentationForms(singleton(PresentationForm.DOCUMENT_HARDCOPY));
         coded   .setPresentationForms(singleton(PresentationForm.IMAGE_HARDCOPY));
-        untitled.setCitedResponsibleParties(singleton(new DefaultResponsibility(Role.AUTHOR, null, null)));
+        untitled.setCitedResponsibleParties(singleton(new DefaultResponsibleParty(Role.AUTHOR)));
         final DefaultProcessing processing = new DefaultProcessing();
         processing.setDocumentations(asList(titled, coded, untitled));
         final String text = format.format(processing.asTreeTable());
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java
index 9d0c6e9..d177a81 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableViewTest.java
@@ -59,14 +59,14 @@ public final strictfp class TreeTableViewTest extends TestCase {
             "  ├─Alternate title (2 of 2)…………………………………………… Second alternate title\n" +
             "  ├─Edition………………………………………………………………………………………… Some edition\n" +
             "  ├─Cited responsible party (1 of 2)\n" +
-            "  │   ├─Role……………………………………………………………………………………… Distributor\n" +
-            "  │   └─Organisation………………………………………………………………… Some organisation\n" +
+            "  │   ├─Organisation………………………………………………………………… Some organisation\n" +
+            "  │   └─Role……………………………………………………………………………………… Distributor\n" +
             "  ├─Cited responsible party (2 of 2)\n" +
-            "  │   ├─Role……………………………………………………………………………………… Point of contact\n" +
-            "  │   └─Individual……………………………………………………………………… Some person of contact\n" +
-            "  │       └─Contact info\n" +
-            "  │           └─Address\n" +
-            "  │               └─Electronic mail address…… Some email\n" +
+            "  │   ├─Individual……………………………………………………………………… Some person of contact\n" +
+            "  │   │   └─Contact info\n" +
+            "  │   │       └─Address\n" +
+            "  │   │           └─Electronic mail address…… Some email\n" +
+            "  │   └─Role……………………………………………………………………………………… Point of contact\n" +
             "  ├─Presentation form (1 of 2)……………………………………… Map digital\n" +
             "  ├─Presentation form (2 of 2)……………………………………… Map hardcopy\n" +
             "  └─Other citation details………………………………………………… Some other details\n";
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TypeMapTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TypeMapTest.java
index 3614969..ac76716 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/TypeMapTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/TypeMapTest.java
@@ -24,7 +24,7 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.extent.GeographicExtent;
 import org.opengis.metadata.extent.GeographicDescription;
@@ -70,7 +70,7 @@ public final strictfp class TypeMapTest extends TestCase {
             new SimpleEntry<>("edition",               InternationalString.class),
             new SimpleEntry<>("editionDate",           Date.class),
             new SimpleEntry<>("identifier",            Identifier.class),
-            new SimpleEntry<>("citedResponsibleParty", Responsibility.class),
+            new SimpleEntry<>("citedResponsibleParty", ResponsibleParty.class),
             new SimpleEntry<>("presentationForm",      PresentationForm.class),
             new SimpleEntry<>("series",                Series.class),
             new SimpleEntry<>("otherCitationDetails",  InternationalString.class),
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/ValueMapTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/ValueMapTest.java
index 129c75c..a7c6eb6 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/ValueMapTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/ValueMapTest.java
@@ -24,7 +24,7 @@ import org.apache.sis.xml.NilReason;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultIndividual;
-import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -68,7 +68,7 @@ public final strictfp class ValueMapTest extends TestCase {
     /**
      * The author of the metadata instance created by {@link #createCitation()}.
      */
-    private DefaultResponsibility author;
+    private DefaultResponsibleParty author;
 
     /**
      * Creates the metadata instance to be used for testing purpose.
@@ -91,7 +91,7 @@ public final strictfp class ValueMapTest extends TestCase {
      */
     private Map<String,Object> createCitation() {
         title    = new SimpleInternationalString("Undercurrent");
-        author   = new DefaultResponsibility();
+        author   = new DefaultResponsibleParty();
         citation = new DefaultCitation(title);
         author.setParties(singleton(new DefaultIndividual("Testsuya Toyoda", null, null)));
         citation.setCitedResponsibleParties(singleton(author));
@@ -172,7 +172,6 @@ public final strictfp class ValueMapTest extends TestCase {
             new SimpleEntry<>("identifiers",             citation.getIdentifiers()),
             new SimpleEntry<>("citedResponsibleParties", singletonList(author)),
             new SimpleEntry<>("presentationForms",       emptySet()),
-            new SimpleEntry<>("otherCitationDetails",    emptyList()),
             new SimpleEntry<>("ISBN",                    "9782505004509"),
             new SimpleEntry<>("onlineResources",         emptyList()),
             new SimpleEntry<>("graphics",                emptyList())
@@ -203,7 +202,6 @@ public final strictfp class ValueMapTest extends TestCase {
             new SimpleEntry<>("identifiers",             citation.getIdentifiers()),
             new SimpleEntry<>("citedResponsibleParties", singletonList(author)),
             new SimpleEntry<>("presentationForms",       emptySet()),
-            new SimpleEntry<>("otherCitationDetails",    emptyList()),
             new SimpleEntry<>("ISBN",                    "9782505004509"),
             new SimpleEntry<>("onlineResources",         emptyList()),
             new SimpleEntry<>("graphics",                emptyList())
@@ -234,7 +232,7 @@ public final strictfp class ValueMapTest extends TestCase {
             new SimpleEntry<>("citedResponsibleParties", singletonList(author)),
             new SimpleEntry<>("presentationForms",       emptySet()),
             new SimpleEntry<>("series",                  null),
-            new SimpleEntry<>("otherCitationDetails",    emptyList()),
+            new SimpleEntry<>("otherCitationDetails",    null),
 //          new SimpleEntry<>("collectiveTitle",         null),  -- deprecated as of ISO 19115:2014.
             new SimpleEntry<>("ISBN",                    "9782505004509"),
             new SimpleEntry<>("ISSN",                    null),
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/CustomMetadataTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/CustomMetadataTest.java
index 0ffade4..59eb7d1 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/CustomMetadataTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/CustomMetadataTest.java
@@ -23,13 +23,12 @@ import java.util.Locale;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Method;
 import java.lang.reflect.InvocationHandler;
-import java.nio.charset.Charset;
 import javax.xml.bind.JAXBException;
 import org.opengis.util.NameFactory;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.identification.*;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.constraint.Constraints;
 import org.opengis.metadata.distribution.Format;
 import org.opengis.metadata.extent.Extent;
@@ -123,12 +122,12 @@ public final strictfp class CustomMetadataTest extends XMLTestCase {
             @Override public Collection<Resolution>                getSpatialResolutions()         {return null;}
             @Override public Collection<Duration>                  getTemporalResolutions()        {return null;}
             @Override public Collection<Locale>                    getLanguages()                  {return null;}
-            @Override public Collection<Charset>                   getCharacterSets()              {return null;}
+            @Override public Collection<CharacterSet>              getCharacterSets()              {return null;}
             @Override public Collection<TopicCategory>             getTopicCategories()            {return null;}
             @Override public Collection<Extent>                    getExtents()                    {return null;}
-            @Override public Collection<InternationalString>       getCredits()                    {return null;}
+            @Override public Collection<String>                    getCredits()                    {return null;}
             @Override public Collection<Progress>                  getStatus()                     {return null;}
-            @Override public Collection<Responsibility>            getPointOfContacts()            {return null;}
+            @Override public Collection<ResponsibleParty>          getPointOfContacts()            {return null;}
             @Override public Collection<MaintenanceInformation>    getResourceMaintenances()       {return null;}
             @Override public Collection<BrowseGraphic>             getGraphicOverviews()           {return null;}
             @Override public Collection<Format>                    getResourceFormats()            {return null;}
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/MarshallingTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/MarshallingTest.java
deleted file mode 100644
index b30c809..0000000
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/MarshallingTest.java
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * 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.iso;
-
-import java.util.Date;
-import java.util.Locale;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.logging.LogRecord;
-import java.util.MissingResourceException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.io.StringWriter;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.JAXBException;
-import org.opengis.annotation.Obligation;
-import org.opengis.util.RecordType;
-import org.opengis.metadata.Datatype;
-import org.opengis.metadata.citation.*;
-import org.opengis.metadata.constraint.*;
-import org.opengis.metadata.content.*;
-import org.opengis.metadata.extent.*;
-import org.opengis.metadata.identification.*;
-import org.opengis.metadata.maintenance.*;
-import org.opengis.metadata.spatial.*;
-import org.opengis.geometry.primitive.Point;
-import org.apache.sis.metadata.iso.citation.*;
-import org.apache.sis.metadata.iso.constraint.*;
-import org.apache.sis.metadata.iso.content.*;
-import org.apache.sis.metadata.iso.distribution.*;
-import org.apache.sis.metadata.iso.extent.*;
-import org.apache.sis.metadata.iso.identification.*;
-import org.apache.sis.metadata.iso.maintenance.*;
-import org.apache.sis.metadata.iso.spatial.*;
-import org.apache.sis.util.iso.DefaultRecordSchema;
-import org.apache.sis.util.iso.SimpleInternationalString;
-import org.apache.sis.util.iso.DefaultInternationalString;
-import org.apache.sis.util.logging.WarningListener;
-import org.apache.sis.measure.Units;
-import org.apache.sis.xml.XML;
-import org.apache.sis.xml.NilReason;
-import org.apache.sis.xml.MarshallerPool;
-import org.apache.sis.xml.IdentifierSpace;
-import org.apache.sis.internal.jaxb.gcx.Anchor;
-import org.apache.sis.internal.jaxb.metadata.replace.ReferenceSystemMetadata;
-import org.apache.sis.metadata.xml.TestUsingFile;
-import org.apache.sis.util.iso.Names;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-/**
- * Simple test cases for marshalling a {@link DefaultMetadata} object to an XML file.
- * This class is used to test the ISO 19115-3 metadata standard implementation.
- *
- * @author  Cullen Rombach (Image Matters)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- *
- * @see <a href="https://issues.apache.org/jira/browse/SIS-400">SIS-400</a>
- *
- * @since 1.0
- * @module
- */
-public final class MarshallingTest extends TestUsingFile implements WarningListener<Object> {
-    /**
-     * The marshaller used to handle marshalling the created DefaultMetadata object.
-     */
-    private final Marshaller marshaller;
-
-    /**
-     * The pool from which the marshaller is pulled.
-     */
-    private final MarshallerPool pool;
-
-    /**
-     * The output to which the metadata object will be marshaled.
-     */
-    private final StringWriter output;
-
-    /**
-     * {@code true} if marshalling legacy XML instead than latest schema.
-     */
-    private boolean legacyXML;
-
-    /**
-     * Initializes a new test case.
-     *
-     * @throws JAXBException if an error occurred while preparing the marshaller.
-     */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
-    public MarshallingTest() throws JAXBException {
-        output     = new StringWriter();
-        pool       = getMarshallerPool();
-        marshaller = pool.acquireMarshaller();
-        marshaller.setProperty(XML.WARNING_LISTENER, this);
-    }
-
-    /**
-     * Creates a metadata object to marshal.
-     */
-    @SuppressWarnings("deprecation")
-    private static DefaultMetadata metadata() throws URISyntaxException {
-        /*
-         * Metadata
-         *   ├─Metadata identifier…… a-metadata-identifier
-         *   │   └─Code space………………… md.id.ns
-         *   ├─Parent metadata……………… A parent metadata
-         *   │   └─Identifier………………… a-parent-identifier
-         *   │       └─Code space……… pmd.id.ns
-         *   ├─Language (1 de 2)………… English
-         *   ├─Language (2 de 2)………… French (Canada)
-         *   ├─Character set…………………… ISO-8859-1
-         *   └─Metadata scope
-         *       ├─Resource scope……… Dataset
-         *       └─Name………………………………… Metadata for an imaginary data set
-         *
-         * Some code are indented for readability and more local variable scopes.
-         */
-        final DefaultMetadata md = new DefaultMetadata();
-        {
-            // Metadata identifier
-            final DefaultIdentifier id = new DefaultIdentifier("a-metadata-identifier");
-            id.setCodeSpace("md.id.ns");
-            md.setMetadataIdentifier(id);
-        }
-        // Languages — one language only, and one (country, language) tupple.
-        final Collection<Locale> languages = Arrays.asList(Locale.ENGLISH, Locale.CANADA_FRENCH);
-        md.setLanguages(languages);
-
-        // Character Sets (character encoding)
-        final Collection<Charset> charSets = Collections.singleton(StandardCharsets.ISO_8859_1);
-        md.setCharacterSets(charSets);
-        {
-            // Parent metadata
-            final DefaultCitation parent = new DefaultCitation("A parent metadata");
-            final DefaultIdentifier parentId = new DefaultIdentifier("a-parent-identifier");
-            parentId.setCodeSpace("pmd.id.ns");
-            parent.getIdentifiers().add(parentId);
-            md.setParentMetadata(parent);
-        }
-        // mdb:metadataScope (hierarchyLevel and hierarchyLevelName in legacy ISO 19115:2003 model)
-        md.getMetadataScopes().add(new DefaultMetadataScope(ScopeCode.DATASET, "Metadata for an imaginary data set"));
-        final DefaultOnlineResource onlineResource;
-        {
-            /*
-             * Contact information for the parties.
-             *
-             * Organisation………………………………………………………………… Plato Republic
-             *   ├─Contact info
-             *   │   ├─Phone (1 de 2)
-             *   │   │   ├─Number………………………………………………… 555-444-3333
-             *   │   │   └─Number type…………………………………… Voice
-             *   │   ├─Phone (2 de 2)
-             *   │   │   ├─Number………………………………………………… 555-555-5555
-             *   │   │   └─Number type…………………………………… Facsimile
-             *   │   ├─Address
-             *   │   │   ├─Delivery point…………………………… 123 Main Street
-             *   │   │   ├─City……………………………………………………… Metropolis city
-             *   │   │   ├─Administrative area……………… Utopia province
-             *   │   │   ├─Postal code…………………………………… A1A 2C2
-             *   │   │   ├─Country……………………………………………… Atlantis island
-             *   │   │   └─Electronic mail address…… test@example.com
-             *   │   ├─Online resource
-             *   │   │   ├─Linkage……………………………………………… http://example.com
-             *   │   │   ├─Protocol…………………………………………… Submarine HTTP
-             *   │   │   ├─Application profile……………… Imaginary work
-             *   │   │   ├─Name……………………………………………………… Timaeus & Critias
-             *   │   │   ├─Description…………………………………… A dialog between philosophers.
-             *   │   │   └─Function…………………………………………… Search
-             *   │   ├─Hours of service………………………………… Weekdays 9:00 AM - 5:00 PM
-             *   │   ├─Contact instructions……………………… Through thought
-             *   │   └─Contact type…………………………………………… Virtual
-             *   └─Individual…………………………………………………………… Socrates
-             *       └─Position name………………………………………… Philosopher
-             */
-            final DefaultContact contact = new DefaultContact();
-            contact.setPhones(Arrays.asList(new DefaultTelephone("555-444-3333", TelephoneType.VOICE),
-                                            new DefaultTelephone("555-555-5555", TelephoneType.FACSIMILE)));
-            {
-                {
-                    // Address information
-                    final DefaultAddress address = new DefaultAddress();
-                    address.setDeliveryPoints(Collections.singleton(new SimpleInternationalString("123 Main Street")));
-                    address.getElectronicMailAddresses().add("test@example.com");
-                    address.setCity(new SimpleInternationalString("Metropolis city"));
-                    address.setAdministrativeArea(new SimpleInternationalString("Utopia province"));
-                    address.setPostalCode("A1A 2C2");
-                    address.setCountry(new SimpleInternationalString("Atlantis island"));
-                    contact.getAddresses().add(address);
-                }
-                // Online resources
-                final DefaultInternationalString description = new DefaultInternationalString();
-                description.add(Locale.ENGLISH, "A dialog between philosophers.");
-                description.add(Locale.FRENCH,  "Un dialogue entre philosophes.");
-                onlineResource = new DefaultOnlineResource(new URI("http://example.com"));
-                onlineResource.setName(new SimpleInternationalString("Timaeus & Critias"));
-                onlineResource.setDescription(description);
-                onlineResource.setProtocol("Submarine HTTP");
-                onlineResource.setApplicationProfile("Imaginary work");
-                onlineResource.setFunction(OnLineFunction.SEARCH);
-                onlineResource.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "timaeus");    // For enabling references
-                contact.getOnlineResources().add(onlineResource);
-                contact.setHoursOfService(Collections.singleton(new SimpleInternationalString("Weekdays 9:00 AM - 5:00 PM")));
-                contact.setContactInstructions(new SimpleInternationalString("Through thought"));
-                contact.setContactType(new SimpleInternationalString("Virtual"));
-                contact.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "thought");           // For enabling references
-            }
-            // Create some individuals
-            final DefaultIndividual individual  = new DefaultIndividual("Socrates", "Philosopher", null);
-            final DefaultIndividual individual2 = new DefaultIndividual("Hermocrates", "Politician", contact);
-            final DefaultOrganisation org = new DefaultOrganisation("Plato Republic", null, individual, contact);
-            md.setContacts(Arrays.asList(new DefaultResponsibility(Role.POINT_OF_CONTACT, null, org),
-                                         new DefaultResponsibility(Role.POINT_OF_CONTACT, null, individual2)));
-        }
-        // Date info (date stamp in legacy ISO 19115:2003 model)
-        final Collection<CitationDate> dateInfo = Collections.singleton(new DefaultCitationDate(new Date(1260961229580L), DateType.CREATION));
-        md.setDateInfo(dateInfo);
-        {
-            // Metadata standard
-            final DefaultCitation standard = new DefaultCitation("ISO 19115-1");
-            standard.setEdition(new SimpleInternationalString("2014"));
-            md.getMetadataStandards().add(standard);
-        }
-        {
-            /*
-             * Spatial representation info : Georectified
-             *   ├─Number of dimensions………………………………………………… 2
-             *   ├─Axis dimension properties (1 de 2)…………… Row
-             *   │   ├─Dimension size……………………………………………………… 7 777
-             *   │   └─Resolution………………………………………………………………… 10
-             *   ├─Axis dimension properties (2 de 2)…………… Column
-             *   │   ├─Dimension size……………………………………………………… 2 233
-             *   │   └─Resolution………………………………………………………………… 5
-             *   ├─Cell geometry…………………………………………………………………… Area
-             *   ├─Transformation parameter availability…… false
-             *   ├─Check point availability……………………………………… false
-             *   └─Point in pixel………………………………………………………………… Upper right
-             */
-            final DefaultGeorectified georectified = new DefaultGeorectified();
-            georectified.setNumberOfDimensions(2);
-            final DefaultDimension rows = new DefaultDimension(DimensionNameType.ROW,    7777);
-            final DefaultDimension cols = new DefaultDimension(DimensionNameType.COLUMN, 2233);
-            rows.setResolution(10.0);
-            cols.setResolution( 5.0);
-            georectified.setAxisDimensionProperties(Arrays.asList(rows, cols));
-            georectified.setCellGeometry(CellGeometry.AREA);
-            georectified.setPointInPixel(PixelOrientation.UPPER_RIGHT);
-            georectified.getCornerPoints().add(NilReason.MISSING.createNilObject(Point.class));
-            md.getSpatialRepresentationInfo().add(georectified);
-        }
-        {
-            // Reference System Information
-            final ReferenceSystemMetadata refSystem = new ReferenceSystemMetadata();
-            final DefaultCitation cit = new DefaultCitation("Atlantis grid");
-            cit.setDates(dateInfo);
-            {
-                //  Responsibilities
-                final DefaultOrganisation org = new DefaultOrganisation();
-                org.setName(new SimpleInternationalString("Atlantis national mapping agency"));
-                cit.getCitedResponsibleParties().add(new DefaultResponsibility(Role.PUBLISHER, null, org));
-            }
-            // Identifier
-            final DefaultIdentifier id = new DefaultIdentifier("AG9000");
-            id.setAuthority(cit);
-            id.setCodeSpace("rs.id.ns");
-            id.setVersion("1.0");
-            id.setDescription(new SimpleInternationalString("An imaginary reference system."));
-            refSystem.setName(id);
-            md.getReferenceSystemInfo().add(refSystem);
-        }
-        {
-            /*
-             * Extended element information…… ExtendedElementName
-             *   ├─Parent entity………………………………… VirtualObject
-             *   ├─Definition………………………………………… An extended element not included in the standard.
-             *   ├─Obligation………………………………………… Conditional
-             *   ├─Condition…………………………………………… Presents in “Imaginary work” profile.
-             *   ├─Data type…………………………………………… Meta class
-             *   ├─Maximum occurrence…………………… 3
-             *   ├─Domain value…………………………………… Alpha, beta or gamma.
-             *   ├─Rule………………………………………………………… Element exists in cited resource.
-             *   └─Rationale…………………………………………… For testing extended elements.
-             */
-            final DefaultMetadataExtensionInformation extension = new DefaultMetadataExtensionInformation();
-            extension.setExtensionOnLineResource(onlineResource);
-            final DefaultExtendedElementInformation elementInfo = new DefaultExtendedElementInformation();
-            elementInfo.setName("ExtendedElementName");
-            elementInfo.setDefinition(new SimpleInternationalString("An extended element not included in the standard."));
-            elementInfo.setObligation(Obligation.CONDITIONAL);
-            elementInfo.setCondition(new SimpleInternationalString("Presents in “Imaginary work” profile."));
-            elementInfo.setDataType(Datatype.META_CLASS);
-            elementInfo.setMaximumOccurrence(3);
-            elementInfo.setDomainValue(new SimpleInternationalString("Alpha, beta or gamma."));
-            elementInfo.setShortName("ExtEltName");
-            elementInfo.setDomainCode(1234);
-            elementInfo.setParentEntity(Collections.singleton("VirtualObject"));
-            elementInfo.setRule(new SimpleInternationalString("Element exists in cited resource."));
-            elementInfo.setRationale(new SimpleInternationalString("For testing extended elements."));
-            elementInfo.getSources().add(NilReason.valueOf("other:test").createNilObject(Responsibility.class));
-            extension.getExtendedElementInformation().add(elementInfo);
-            md.getMetadataExtensionInfo().add(extension);
-        }
-        /*
-         * Data identification info
-         *   ├─Abstract………………… Méta-données pour une carte imaginaire.
-         *   └─Purpose…………………… For XML (un)marshalling tests.
-         */
-        final DefaultDataIdentification dataId = new DefaultDataIdentification();
-        {
-            final DefaultInternationalString description = new DefaultInternationalString();
-            description.add(Locale.ENGLISH, "Metadata for an imaginary map.");
-            description.add(Locale.FRENCH,  "Méta-données pour une carte imaginaire.");
-            dataId.setAbstract(description);
-            dataId.setPurpose(new SimpleInternationalString("For XML (un)marshalling tests."));
-        }
-        final Collection<Extent> extents;
-        {
-            /*
-             * Extent……………………………………………………………… Azores
-             *   ├─Geographic element
-             *   │   ├─West bound longitude…… 24°30′W
-             *   │   ├─East bound longitude…… 32°W
-             *   │   ├─South bound latitude…… 36°45′N
-             *   │   ├─North bound latitude…… 40°N
-             *   │   └─Extent type code……………… true
-             *   └─Temporal element
-             */
-            final DefaultExtent extent = new DefaultExtent();
-            extent.setDescription(new SimpleInternationalString("Azores"));
-            {
-                final DefaultGeographicBoundingBox bbox = new DefaultGeographicBoundingBox();
-                bbox.setInclusion(true);
-                bbox.setNorthBoundLatitude( 40.00);
-                bbox.setEastBoundLongitude(-32.00);
-                bbox.setSouthBoundLatitude( 36.75);
-                bbox.setWestBoundLongitude(-24.50);
-                extent.getGeographicElements().add(bbox);
-            }
-            final DefaultTemporalExtent temporal = new DefaultTemporalExtent();
-            extent.getTemporalElements().add(temporal);
-            extent.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "azores");     // For enabling references
-            extents = Collections.singleton(extent);
-            dataId.setExtents(extents);
-        }
-        final Collection<Constraints> resourceConstraints;
-        {
-            /*
-             * Constraints
-             *   ├─Use limitation…………………………………… Not for navigation.
-             *   ├─Constraint application scope
-             *   │   └─Level………………………………………………… Document
-             *   ├─Graphic
-             *   │   ├─File name……………………………………… ocean.png
-             *   │   ├─File description…………………… Somewhere in the Atlantic ocean
-             *   │   ├─File type……………………………………… PNG image
-             *   │   ├─Linkage
-             *   │   └─Image constraints
-             *   └─Releasability
-             *       └─Statement……………………………………… Public domain
-             */
-            final DefaultConstraints constraint = new DefaultConstraints();
-            final DefaultBrowseGraphic graphic = new DefaultBrowseGraphic(new URI("ocean.png"));
-            graphic.setFileDescription(new SimpleInternationalString("Somewhere in the Atlantic ocean"));
-            graphic.setFileType("PNG image");
-            graphic.getImageConstraints().add(new DefaultConstraints());
-            graphic.getLinkages().add(new DefaultOnlineResource());
-            constraint.getGraphics().add(graphic);
-            constraint.setUseLimitations(Collections.singleton(new SimpleInternationalString("Not for navigation.")));
-
-            // Releasability
-            final DefaultReleasability releasability = new DefaultReleasability();
-            releasability.setStatement(new SimpleInternationalString("Public domain"));
-            constraint.setReleasability(releasability);
-            constraint.setConstraintApplicationScope(new DefaultScope(ScopeCode.DOCUMENT));
-            constraint.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "public");         // For enabling references
-            resourceConstraints = Collections.singleton(constraint);
-            dataId.setResourceConstraints(resourceConstraints);
-        }
-        dataId.getSpatialRepresentationTypes().add(SpatialRepresentationType.GRID);
-        {
-            // Spatial resolution
-            final DefaultResolution resolution = new DefaultResolution();
-            resolution.setDistance(56777.0);
-            dataId.getSpatialResolutions().add(resolution);
-        }
-        dataId.setTopicCategories(Arrays.asList(TopicCategory.OCEANS, TopicCategory.SOCIETY));
-        dataId.getStatus().add(Progress.HISTORICAL_ARCHIVE);
-        /*
-         * Citation………………………………………………………… A lost island
-         *   ├─Alternate title (1 de 2)…… Island lost again
-         *   ├─Alternate title (2 de 2)…… Map example
-         *   ├─Date………………………………………………………… 2018-04-09 00:00:00
-         *   │   └─Date type………………………………… Création
-         *   ├─Edition………………………………………………… First edition
-         *   └─Edition date…………………………………… 2018-04-10 00:00:00
-         */
-        final DefaultCitation cit = new DefaultCitation();
-        cit.setTitle(new SimpleInternationalString("A lost island"));
-        cit.setEdition(new SimpleInternationalString("First edition"));
-        cit.setEditionDate(new Date(1523311200000L));
-        cit.setCollectiveTitle(new SimpleInternationalString("Popular legends"));
-        cit.setAlternateTitles(Arrays.asList(new SimpleInternationalString("Island lost again"),
-                                             new Anchor(new URI("http://map-example.com"), "Map example")));
-        cit.getDates().add(new DefaultCitationDate(new Date(1523224800000L), DateType.CREATION));
-        cit.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "lost-island");
-        dataId.setCitation(cit);
-        dataId.setTemporalResolutions(Collections.emptySet());              // TODO: depends on sis-temporal
-        final Collection<MaintenanceInformation> resourceMaintenances;
-        {
-            /*
-             * Maintenance information
-             *   ├─Maintenance and update frequency…… Not planned
-             *   ├─Maintenance date……………………………………………… 3000-01-01 00:00:00
-             *   │   └─Date type……………………………………………………… Révision
-             *   └─Maintenance scope
-             *       ├─Level………………………………………………………………… Model
-             *       └─Level description
-             *           └─Dataset………………………………………………… Imaginary map
-             */
-            DefaultMaintenanceInformation maintenanceInfo = new DefaultMaintenanceInformation();
-            maintenanceInfo.setMaintenanceAndUpdateFrequency(MaintenanceFrequency.NOT_PLANNED);
-            maintenanceInfo.getMaintenanceDates().add(new DefaultCitationDate(new Date(32503676400000L), DateType.REVISION));
-            final DefaultScope maintenanceScope = new DefaultScope();
-            maintenanceScope.setLevel(ScopeCode.MODEL);
-            {
-                // Scope level descriptions
-                final DefaultScopeDescription scopeDescription = new DefaultScopeDescription();
-                scopeDescription.setDataset("Imaginary map");
-                maintenanceScope.getLevelDescription().add(scopeDescription);
-            }
-            maintenanceInfo.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "not-planned");
-            maintenanceInfo.getMaintenanceScopes().add(maintenanceScope);
-            resourceMaintenances = Collections.singleton(maintenanceInfo);
-            dataId.setResourceMaintenances(resourceMaintenances);
-        }
-        {
-            /*
-             * Format
-             *   ├─Format specification citation…… Portable Network Graphics
-             *   │   ├─Alternate title……………………………… PNG
-             *   │   └─Edition…………………………………………………… November 2003
-             *   ├─Amendment number……………………………………… Second edition
-             *   └─File decompression technique……… L77 / Huffman coding
-             */
-            final DefaultFormat resourceFormat = new DefaultFormat();
-            resourceFormat.setName(new SimpleInternationalString("PNG"));
-            resourceFormat.setSpecification(new SimpleInternationalString("Portable Network Graphics"));
-            resourceFormat.setAmendmentNumber(new SimpleInternationalString("Second edition"));
-            resourceFormat.setVersion(new SimpleInternationalString("November 2003"));
-            resourceFormat.setFileDecompressionTechnique(new SimpleInternationalString("L77 / Huffman coding"));
-            dataId.getResourceFormats().add(resourceFormat);
-        }
-        final Collection<Keywords> descriptiveKeywords;
-        {
-            /*
-             * Keywords
-             *   ├─Thesaurus name………… Plato's dialogues
-             *   ├─Keyword class…………… Greek elements
-             *   ├─Keyword (1 de 2)…… Water
-             *   ├─Keyword (2 de 2)…… Aether
-             *   └─Type…………………………………… Theme
-             */
-            final DefaultKeywords keywords = new DefaultKeywords();
-            keywords.setType(KeywordType.THEME);
-            keywords.setThesaurusName(new DefaultCitation("Plato's dialogues"));
-            final DefaultKeywordClass keywordClass = new DefaultKeywordClass();
-            keywordClass.setClassName(new SimpleInternationalString("Greek elements"));
-            keywords.setKeywordClass(keywordClass);
-            keywords.setKeywords(Arrays.asList(new SimpleInternationalString("Water"),
-                                               new SimpleInternationalString("Aether")));
-            keywords.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "greek-elements");
-            descriptiveKeywords = Collections.singleton(keywords);
-            dataId.setDescriptiveKeywords(descriptiveKeywords);
-        }
-        {
-            /*
-             * Usage………………………………………………………………………… For testing purpose only.
-             *   ├─Usage date time…………………………………… 2018-04-10 14:00:00
-             *   ├─User determined limitations…… Not to be used outside MarshallingTest.java test file.
-             *   └─Response……………………………………………………… Random elements
-             */
-            final DefaultUsage usage = new DefaultUsage();
-            usage.setSpecificUsage(new SimpleInternationalString("For testing purpose only."));
-            usage.setUsageDate(new Date(1523361600000L));
-            usage.setResponses(Collections.singleton(new SimpleInternationalString("Random elements")));
-            usage.setUserDeterminedLimitations(new SimpleInternationalString("Not to be used outside MarshallingTest.java test file."));
-            dataId.getResourceSpecificUsages().add(usage);
-        }
-        final Collection<AssociatedResource> associatedResources;
-        {
-            // Associated resources (AggregationInfo in 19139)
-            final DefaultAssociatedResource associatedResource = new DefaultAssociatedResource();
-            associatedResource.setAssociationType(AssociationType.DEPENDENCY);
-            associatedResource.setInitiativeType(InitiativeType.EXPERIMENT);
-            associatedResource.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "dependency");
-            associatedResources = Collections.singleton(associatedResource);
-            dataId.setAssociatedResources(associatedResources);
-        }
-        dataId.setLanguages(languages);     // Locales (ISO 19115:2014) a.k.a Languages and CharacterSets (ISO 19115:2003)
-        dataId.setCharacterSets(charSets);
-        dataId.setEnvironmentDescription (new SimpleInternationalString("High humidity."));
-        dataId.setSupplementalInformation(new SimpleInternationalString("High water pressure."));
-        {
-            // Service identification info
-            final DefaultServiceIdentification serviceId = new DefaultServiceIdentification();
-            serviceId.setCitation(cit);
-            serviceId.setAbstract(new SimpleInternationalString("An inspiration for story tellers."));
-            serviceId.setExtents(extents);
-            serviceId.setResourceMaintenances(resourceMaintenances);
-            serviceId.setDescriptiveKeywords(descriptiveKeywords);
-            serviceId.setResourceConstraints(resourceConstraints);
-            serviceId.setAssociatedResources(associatedResources);
-            serviceId.setServiceTypeVersions(Collections.singleton("Version 1000+"));
-            // TODO: Coupled resources
-            final DefaultCoupledResource coupledResource = new DefaultCoupledResource();
-            serviceId.getCoupledResources().add(coupledResource);
-            serviceId.setCouplingType(CouplingType.LOOSE);
-            final DefaultOperationMetadata operationMetadata = new DefaultOperationMetadata();
-            {
-                operationMetadata.setOperationName("Authoring");
-                operationMetadata.setOperationDescription(new SimpleInternationalString("Write a book."));
-                operationMetadata.setInvocationName(new SimpleInternationalString("someMethodName"));
-                operationMetadata.getDistributedComputingPlatforms().add(DistributedComputingPlatform.JAVA);
-            }
-            serviceId.getContainsOperations().add(operationMetadata);
-            serviceId.getOperatesOn().add(dataId);
-            md.setIdentificationInfo(Arrays.asList(dataId, serviceId));
-        }
-        {
-            // Content info
-            final DefaultCoverageDescription coverageDescription;
-            {
-                coverageDescription = new DefaultCoverageDescription();
-                // Attribute description
-                final DefaultRecordSchema schema = new DefaultRecordSchema(null, null, "IslandFeatures");
-                final Map<CharSequence,Class<?>> members = new LinkedHashMap<>();
-                members.put("city",      String.class);
-                members.put("latitude",  Double.class);
-                members.put("longitude", Double.class);
-                final RecordType recordType = schema.createRecordType("SettledArea", members);
-                coverageDescription.setAttributeDescription(recordType);
-                {
-                    /*
-                     * Attribute group
-                     *   ├─Content type…………………… Auxilliary information
-                     *   ├─Attribute (1 de 2)…… 42
-                     *   │   ├─Description…………… Population density
-                     *   │   └─Name
-                     *   └─Attribute (2 de 2)
-                     *       ├─Description…………… Temperature
-                     *       ├─Max value………………… 22,22
-                     *       ├─Min value………………… 11,11
-                     *       ├─Units…………………………… °C
-                     *       └─Scale factor………… 1,5
-                     */
-                    final DefaultAttributeGroup attributeGroup = new DefaultAttributeGroup();
-                    attributeGroup.getContentTypes().add(CoverageContentType.AUXILLARY_INFORMATION);
-                    // Attributes
-                    final DefaultRangeDimension rangeDimension = new DefaultRangeDimension();
-                    rangeDimension.setDescription(new SimpleInternationalString("Population density"));
-                    rangeDimension.setSequenceIdentifier(Names.createMemberName(null, null, "42", Integer.class));
-                    rangeDimension.getNames().add(new DefaultIdentifier());
-                    final DefaultSampleDimension sampleDimension = new DefaultSampleDimension();
-                    sampleDimension.setDescription(new SimpleInternationalString("Temperature"));
-                    sampleDimension.setMinValue(11.11);
-                    sampleDimension.setMaxValue(22.22);
-                    sampleDimension.setUnits(Units.CELSIUS);
-                    sampleDimension.setScaleFactor(1.5);
-                    attributeGroup.setAttributes(Arrays.asList(rangeDimension, sampleDimension));
-                    coverageDescription.getAttributeGroups().add(attributeGroup);
-                }
-            }
-            // Feature Catalogue Description
-            final DefaultFeatureCatalogueDescription featureCatalogueDescription = new DefaultFeatureCatalogueDescription();
-            featureCatalogueDescription.setIncludedWithDataset(true);
-            featureCatalogueDescription.setCompliant(true);
-            md.setContentInfo(Arrays.asList(coverageDescription, featureCatalogueDescription));
-        }
-        return md;
-    }
-
-    /**
-     * Tests marshalling of an ISO 19139:2007 document (based on ISO 19115:2003 model).
-     * Current implementation merely tests that marshalling does not produce exception.
-     *
-     * @throws URISyntaxException if an error occurred while creating the metadata object.
-     * @throws JAXBException if an error occurred while marshalling the document.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-400">SIS-400</a>
-     */
-    @Test
-    public void testLegacySchema() throws URISyntaxException, JAXBException {
-        legacyXML = true;
-        final DefaultMetadata md = metadata();
-        marshaller.setProperty(XML.METADATA_VERSION, VERSION_2007);
-        marshaller.marshal(md, output);
-        recycle();
-    }
-
-    /**
-     * Tests marshalling of an ISO 19115-3 document (based on ISO 19115:2014 model).
-     * Current implementation merely tests that marshalling does not produce exception.
-     *
-     * @throws URISyntaxException if an error occurred while creating the metadata object.
-     * @throws JAXBException if an error occurred while marshalling the document.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-400">SIS-400</a>
-     */
-    @Test
-    public void testCurrentSchema() throws JAXBException, URISyntaxException {
-        final DefaultMetadata md = metadata();
-        marshaller.setProperty(XML.METADATA_VERSION, VERSION_2014);
-        marshaller.marshal(md, output);
-        recycle();
-    }
-
-    /**
-     * Invoked only on success, for recycling the marshaller.
-     */
-    private void recycle() {
-        pool.recycle(marshaller);
-    }
-
-    /**
-     * For internal {@code DefaultMetadata} usage.
-     *
-     * @return {@code Object.class}.
-     */
-    @Override
-    public Class<Object> getSourceClass() {
-        return Object.class;
-    }
-
-    /**
-     * Invoked when a warning occurred while marshalling a test XML fragment. Expected warnings are
-     * "Can't find resource for bundle {@code java.util.PropertyResourceBundle}, key <cite>Foo</cite>".
-     * When marshalling legacy XML only, additional warnings may occur.
-     *
-     * @param source  ignored.
-     * @param warning the warning.
-     */
-    @Override
-    public void warningOccured(final Object source, final LogRecord warning) {
-        if (warning.getThrown() instanceof MissingResourceException) {
-            assertNull("Expected a warning message without parameters.", warning.getParameters());
-            return;
-        }
-        final String message = warning.getMessage();
-        if (legacyXML) {
-            assertEquals("IgnoredPropertiesAfterFirst_1", message);
-            assertArrayEquals(new String[] {"RangeDimension"}, warning.getParameters());
-        } else {
-            fail("Unexpected logging message: " + message);
-        }
-    }
-}
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
index 82149a8..35d88d8 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
@@ -30,6 +30,7 @@ import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.citation.Party;
 import org.opengis.metadata.citation.Role;
 import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.OnLineFunction;
 import org.opengis.metadata.citation.OnlineResource;
 import org.opengis.metadata.citation.PresentationForm;
@@ -84,9 +85,15 @@ public final strictfp class DefaultCitationTest extends TestUsingFile {
                 PresentationForm.DOCUMENT_DIGITAL));
         citation.setAlternateTitles(Collections.singleton(
                 new SimpleInternationalString("Andākarento")));   // Actually a different script of the Japanese title.
-        citation.setCitedResponsibleParties(Arrays.asList(
-                new DefaultResponsibility(Role.AUTHOR, null, new DefaultIndividual("Testsuya Toyoda", null, null)),
-                new DefaultResponsibility(Role.EDITOR, Extents.WORLD, new DefaultOrganisation("Kōdansha", null, null, null))));
+
+        final DefaultResponsibleParty author = new DefaultResponsibleParty(Role.AUTHOR);
+        author.setParties(Collections.singleton(new DefaultIndividual("Testsuya Toyoda", null, null)));
+
+        final DefaultResponsibleParty editor = new DefaultResponsibleParty(Role.EDITOR);
+        editor.setParties(Collections.singleton(new DefaultOrganisation("Kōdansha", null, null, null)));
+        editor.setExtents(Collections.singleton(Extents.WORLD));
+
+        citation.setCitedResponsibleParties(Arrays.asList(author, editor));
         return citation;
     }
 
@@ -214,7 +221,7 @@ public final strictfp class DefaultCitationTest extends TestUsingFile {
      */
     private void testMarshalling(final String file, final Version version) throws JAXBException {
         final DefaultOnlineResource rs = new DefaultOnlineResource(URI.create("https://tools.ietf.org/html/rfc1149"));
-        rs.setName(new SimpleInternationalString("IP over Avian Carriers"));
+        rs.setName("IP over Avian Carriers");
         rs.setDescription(new SimpleInternationalString("High delay, low throughput, and low altitude service."));
         rs.setFunction(OnLineFunction.OFFLINE_ACCESS);
 
@@ -222,10 +229,11 @@ public final strictfp class DefaultCitationTest extends TestUsingFile {
         contact.setContactInstructions(new SimpleInternationalString("Send carrier pigeon."));
         contact.getIdentifierMap().putSpecialized(IdentifierSpace.ID, "ip-protocol");
         final DefaultCitation c = new DefaultCitation("Fight against poverty");
-        c.setCitedResponsibleParties(Arrays.asList(
-                new DefaultResponsibility(Role.ORIGINATOR, null, new DefaultIndividual("Maid Marian", null, contact)),
-                new DefaultResponsibility(Role.FUNDER,     null, new DefaultIndividual("Robin Hood",  null, contact))
-        ));
+        final DefaultResponsibleParty r1 = new DefaultResponsibleParty(Role.ORIGINATOR);
+        final DefaultResponsibleParty r2 = new DefaultResponsibleParty(Role.FUNDER);
+        r1.setParties(Collections.singleton(new DefaultIndividual("Maid Marian", null, contact)));
+        r2.setParties(Collections.singleton(new DefaultIndividual("Robin Hood",  null, contact)));
+        c.setCitedResponsibleParties(Arrays.asList(r1, r2));
         c.getDates().add(new DefaultCitationDate(TestUtilities.date("2015-10-17 00:00:00"), DateType.ADOPTED));
         c.getPresentationForms().add(PresentationForm.PHYSICAL_OBJECT);
         /*
@@ -276,7 +284,7 @@ public final strictfp class DefaultCitationTest extends TestUsingFile {
         assertEquals("dateType", DateType.ADOPTED, date.getDateType());
         assertEquals("presentationForm", PresentationForm.PHYSICAL_OBJECT, getSingleton(c.getPresentationForms()));
 
-        final Iterator<Responsibility> it = c.getCitedResponsibleParties().iterator();
+        final Iterator<ResponsibleParty> it = c.getCitedResponsibleParties().iterator();
         final Contact contact = assertResponsibilityEquals(Role.ORIGINATOR, "Maid Marian", it.next());
         assertEquals("Contact instruction", "Send carrier pigeon.", String.valueOf(contact.getContactInstructions()));
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultResponsibilityTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultResponsibilityTest.java
index 24362b9..6badf16 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultResponsibilityTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultResponsibilityTest.java
@@ -44,8 +44,9 @@ public final strictfp class DefaultResponsibilityTest extends XMLTestCase {
     @Test
     public void testLegacyMarshalling() throws JAXBException {
         final DefaultIndividual  party = new DefaultIndividual("An author", null, null);
-        final DefaultResponsibility  r = new DefaultResponsibility(Role.AUTHOR, null, party);
+        final DefaultResponsibleParty r = new DefaultResponsibleParty(Role.AUTHOR);
         final DefaultCitation citation = new DefaultCitation();
+        r.setParties(singleton(party));
         citation.setCitedResponsibleParties(singleton(r));
         final String xml = marshal(citation, VERSION_2007);
         assertXmlEquals("<gmd:CI_Citation xmlns:gco=\"" + LegacyNamespaces.GCO + '"' +
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java
index 78feb24..9e64a36 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java
@@ -27,6 +27,8 @@ import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.Static;
 
+import static java.util.Collections.singleton;
+
 
 /**
  * Hard-coded citation constants used for testing purpose only.
@@ -92,8 +94,9 @@ public final strictfp class HardCodedCitations extends Static {
         final DefaultOnlineResource r = new DefaultOnlineResource(URI.create("http://www.epsg.org"));
         r.setFunction(OnLineFunction.INFORMATION);
 
-        final DefaultResponsibility p = new DefaultResponsibility(Role.PRINCIPAL_INVESTIGATOR, null,
-                new DefaultOrganisation("International Association of Oil & Gas Producers", null, null, new DefaultContact(r)));
+        final DefaultResponsibleParty p = new DefaultResponsibleParty(Role.PRINCIPAL_INVESTIGATOR);
+        p.setParties(singleton(new DefaultOrganisation("International Association of Oil & Gas Producers",
+                null, null, new DefaultContact(r))));
 
         final DefaultCitation c = new DefaultCitation("EPSG Geodetic Parameter Dataset");
         c.getPresentationForms().add(PresentationForm.TABLE_DIGITAL);
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java
index 52f6d46..97d9a16 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultDataIdentificationTest.java
@@ -19,7 +19,6 @@ package org.apache.sis.metadata.iso.identification;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Locale;
-import java.nio.charset.StandardCharsets;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.citation.DateType;
 import org.opengis.metadata.identification.KeywordType;
@@ -38,6 +37,9 @@ import static java.util.Arrays.asList;
 import static java.util.Collections.singleton;
 import static org.apache.sis.test.MetadataAssert.*;
 
+// Branch-specific imports
+import org.opengis.metadata.identification.CharacterSet;
+
 
 /**
  * Tests {@link DefaultDataIdentification}.
@@ -117,7 +119,7 @@ public final strictfp class DefaultDataIdentificationTest extends TestCase {
         info.setResourceConstraints(singleton(new DefaultConstraints("Freely available")));
         info.setExtents(singleton(Extents.WORLD));
         info.setLanguages(asList(LOCALES));
-        info.setCharacterSets(singleton(StandardCharsets.US_ASCII));
+        info.setCharacterSets(singleton(CharacterSet.US_ASCII));
         return info;
     }
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescriptionTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescriptionTest.java
index f1d2108..5082ab5 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescriptionTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescriptionTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.metadata.iso.maintenance;
 
-import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.TestCase;
@@ -62,14 +61,14 @@ public final strictfp class DefaultScopeDescriptionTest extends TestCase {
         assertEquals("dataset", "A dataset", metadata.getDataset());
         loggings.assertNoUnexpectedLog();
 
-        metadata.setOther(new SimpleInternationalString("Other value"));
-        assertEquals("other", "Other value", String.valueOf(metadata.getOther()));
+        metadata.setOther("Other value");
+        assertEquals("other", "Other value", metadata.getOther());
         assertNull("dataset", metadata.getDataset());
         loggings.assertNextLogContains("dataset", "other");
         loggings.assertNoUnexpectedLog();
 
         metadata.setDataset(null);                  // Expected to be a no-op.
-        assertEquals("other", "Other value", String.valueOf(metadata.getOther()));
+        assertEquals("other", "Other value", metadata.getOther());
         assertNull("dataset", metadata.getDataset());
 
         metadata.setOther(null);
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
index 04ba6c1..5849532 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
@@ -126,7 +126,7 @@ public final strictfp class MetadataWriterTest extends TestCase {
         assertEquals("EPSG",      source.search(HardCodedCitations.EPSG));
         assertEquals("SIS",       source.search(HardCodedCitations.SIS));
         assertNull  ("ISO 19111", source.search(HardCodedCitations.ISO_19111));
-        assertEquals("EPSG",      source.search(TestUtilities.getSingleton(
+        assertEquals("{CI_ResponsibleParty}EPS", source.search(TestUtilities.getSingleton(
                 HardCodedCitations.EPSG.getCitedResponsibleParties())));
     }
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/test/mock/IdentifiedObjectMock.java b/core/sis-metadata/src/test/java/org/apache/sis/test/mock/IdentifiedObjectMock.java
index 5663d47..4d85c36 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/test/mock/IdentifiedObjectMock.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/test/mock/IdentifiedObjectMock.java
@@ -25,9 +25,9 @@ import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
-import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.jaxb.gco.GO_GenericName;
 
@@ -44,7 +44,7 @@ import org.apache.sis.internal.jaxb.gco.GO_GenericName;
  */
 @SuppressWarnings("serial")
 @XmlRootElement(name = "IO_IdentifiedObject")
-public strictfp class IdentifiedObjectMock implements IdentifiedObject, Identifier, Serializable {
+public strictfp class IdentifiedObjectMock implements IdentifiedObject, ReferenceIdentifier, Serializable {
     /**
      * The object name to be returned by {@link #getCode()}.
      */
@@ -102,7 +102,7 @@ public strictfp class IdentifiedObjectMock implements IdentifiedObject, Identifi
      * @return the name of this object, or {@code null} if none.
      */
     @Override
-    public final Identifier getName() {
+    public final ReferenceIdentifier getName() {
         return (code != null) ? this : null;
     }
 
@@ -162,7 +162,7 @@ public strictfp class IdentifiedObjectMock implements IdentifiedObject, Identifi
      * @return the identifiers of this object.
      */
     @Override
-    public final Set<Identifier> getIdentifiers() {
+    public final Set<ReferenceIdentifier> getIdentifiers() {
         return null;
     }
 
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
index 3d66fb1..f9dd7c2 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
@@ -125,7 +125,6 @@ import org.junit.BeforeClass;
     org.apache.sis.metadata.iso.DefaultMetadataTest.class,
     org.apache.sis.metadata.iso.CustomMetadataTest.class,
     org.apache.sis.metadata.iso.AllMetadataTest.class,
-    org.apache.sis.metadata.iso.MarshallingTest.class,
     org.apache.sis.metadata.iso.APIVerifier.class,
 
     org.apache.sis.io.wkt.ConventionTest.class,
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/test/xml/AnnotationConsistencyCheck.java b/core/sis-metadata/src/test/java/org/apache/sis/test/xml/AnnotationConsistencyCheck.java
index f8e069e..68d3a09 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/test/xml/AnnotationConsistencyCheck.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/test/xml/AnnotationConsistencyCheck.java
@@ -502,7 +502,7 @@ public abstract strictfp class AnnotationConsistencyCheck extends TestCase {
          * We check only the namespace start, since some specifications define many namespaces
          * under a common root (e.g. "http://standards.iso.org/iso/19115/-3/").
          */
-        if (uml != null) {
+        if (uml != null && false) {     // This verification is available only on development branches.
             final String expected = getExpectedNamespaceStart(impl, uml);
             if (!namespace.startsWith(expected)) {
                 fail("Expected " + expected + "… namespace for that ISO specification but got " + namespace);
@@ -565,6 +565,18 @@ public abstract strictfp class AnnotationConsistencyCheck extends TestCase {
     protected boolean isIgnored(final Method method) {
         switch (method.getName()) {
             /*
+             * Spelling changed.
+             */
+            case "getCenterPoint": {
+                return true;
+            }
+            /*
+             * Method that override an annotated method in parent class.
+             */
+            case "getUnits": {
+                return org.opengis.metadata.content.Band.class.isAssignableFrom(method.getDeclaringClass());
+            }
+            /*
              * Types for which JAXB binding has not yet implemented.
              */
             case "getGeographicCoordinates": {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
index 5c97eef..af5ed04 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
@@ -27,6 +27,7 @@ import java.lang.reflect.Array;
 import javax.xml.bind.annotation.XmlElementRef;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.GeneralParameterDescriptor;
@@ -261,7 +262,7 @@ public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralO
         final Map<String,Object> merged = new HashMap<>(expected);
         merged.putAll(actual);  // May overwrite pre-defined properties.
         mergeArrays(GeneralParameterDescriptor.ALIAS_KEY,       GenericName.class, provided.getAlias(),       merged, complete.getName());
-        mergeArrays(GeneralParameterDescriptor.IDENTIFIERS_KEY, Identifier.class,  provided.getIdentifiers(), merged, null);
+        mergeArrays(GeneralParameterDescriptor.IDENTIFIERS_KEY, ReferenceIdentifier.class, provided.getIdentifiers(), merged, null);
         if (isGroup) {
             final List<GeneralParameterDescriptor> descriptors = ((ParameterDescriptorGroup) provided).descriptors();
             return merge(DefaultParameterValueGroup.class, merged, merged, minimumOccurs, maximumOccurs,
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
index 96b0cd0..536dd23 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
@@ -21,6 +21,7 @@ import javax.xml.bind.annotation.XmlValue;
 import javax.xml.bind.annotation.XmlAttribute;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.internal.metadata.NameMeaning;
@@ -95,7 +96,7 @@ public final class Code {
      *
      * @return the identifier, or {@code null} if none.
      */
-    public Identifier getIdentifier() {
+    public ReferenceIdentifier getIdentifier() {
         String c = code;
         if (c == null) {
             return null;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/NilReferencingObject.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/NilReferencingObject.java
index 455b421..46b6c40 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/NilReferencingObject.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/NilReferencingObject.java
@@ -21,7 +21,7 @@ import java.util.Collection;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.referencing.ReferenceSystem;
-import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.metadata.extent.Extent;
 import org.apache.sis.xml.NilReason;
 import org.apache.sis.xml.NilObject;
@@ -54,7 +54,7 @@ public final class NilReferencingObject implements NilObject, ReferenceSystem {
      *
      * @since 0.6
      */
-    public static final Identifier UNNAMED = new NamedIdentifier(null, Vocabulary.format(Vocabulary.Keys.Unnamed));
+    public static final ReferenceIdentifier UNNAMED = new NamedIdentifier(null, Vocabulary.format(Vocabulary.Keys.Unnamed));
 
     /**
      * The unique instance.
@@ -80,9 +80,9 @@ public final class NilReferencingObject implements NilObject, ReferenceSystem {
      * Returning null for collection are okay in the particular case of SIS implementation,
      * because the constructor will replace empty collections by null references anyway.
      */
-    @Override public Identifier               getName()        {return UNNAMED;}
+    @Override public ReferenceIdentifier      getName()        {return UNNAMED;}
     @Override public Collection<GenericName>  getAlias()       {return null;}
-    @Override public Set<Identifier>          getIdentifiers() {return null;}
+    @Override public Set<ReferenceIdentifier> getIdentifiers() {return null;}
     @Override public InternationalString      getRemarks()     {return null;}
     @Override public InternationalString      getScope()       {return null;}
     @Override public Extent getDomainOfValidity()              {return null;}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
index 3bb38f7..d3b067f 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
@@ -21,10 +21,10 @@ import java.util.HashMap;
 import java.util.Collection;
 import javax.xml.bind.annotation.XmlTransient;
 import org.opengis.util.GenericName;
-import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.measure.Units;
 import org.apache.sis.measure.Latitude;
@@ -95,10 +95,10 @@ public abstract class AbstractProvider extends DefaultOperationMethod implements
         ArgumentChecks.ensureNonNull("parameters", parameters);
         final Map<String,Object> properties = new HashMap<>(4);
         properties.put(NAME_KEY, parameters.getName());
-        final Collection<Identifier> identifiers = parameters.getIdentifiers();
+        final Collection<ReferenceIdentifier> identifiers = parameters.getIdentifiers();
         int size = identifiers.size();
         if (size != 0) {
-            properties.put(IDENTIFIERS_KEY, identifiers.toArray(new Identifier[size]));
+            properties.put(IDENTIFIERS_KEY, identifiers.toArray(new ReferenceIdentifier[size]));
         }
         final Collection<GenericName> aliases = parameters.getAlias();
         size = aliases.size();
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
index 378cb6a..6331263 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
@@ -31,6 +31,7 @@ import org.opengis.util.GenericName;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
@@ -293,7 +294,8 @@ public abstract class MapProjection extends AbstractProvider {
             final ParameterDescriptor<Double> replacement, final ParameterBuilder builder)
     {
         return copyAliases(template, toRename, sameNameAs(toRename, replacement),
-                IdentifiedObjects.getIdentifier(replacement, toRename), builder.addName(template.getName()));
+                (ReferenceIdentifier) IdentifiedObjects.getIdentifier(replacement, toRename),
+                builder.addName(template.getName()));
     }
 
     /**
@@ -310,7 +312,7 @@ public abstract class MapProjection extends AbstractProvider {
      * @return the given {@code builder}, for method call chaining.
      */
     private static ParameterBuilder copyAliases(final ParameterDescriptor<Double> template, final Citation exclude,
-            GenericName replacement, Identifier newCode, final ParameterBuilder builder)
+            GenericName replacement, ReferenceIdentifier newCode, final ParameterBuilder builder)
     {
         for (GenericName alias : template.getAlias()) {
             if (((Identifier) alias).getAuthority() == exclude) {
@@ -320,7 +322,7 @@ public abstract class MapProjection extends AbstractProvider {
             }
             builder.addName(alias);
         }
-        for (Identifier id : template.getIdentifiers()) {
+        for (ReferenceIdentifier id : template.getIdentifiers()) {
             if (id.getAuthority() == exclude) {
                 if (newCode == null) continue;
                 id = newCode;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java
index cea037b..ed517e7 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java
@@ -24,6 +24,9 @@ import org.apache.sis.metadata.iso.citation.Citations;
 
 import static org.apache.sis.referencing.IdentifiedObjects.getIdentifier;
 
+// Branch-dependent imports
+import org.opengis.referencing.ReferenceIdentifier;
+
 
 /**
  * The provider for <cite>"Hotine Oblique Mercator (variant B)"</cite> projection (EPSG:9815).
@@ -97,7 +100,7 @@ public final class ObliqueMercatorCenter extends ObliqueMercator {
                 .addName      (Citations.S57,     "OME")
                 .addIdentifier(Citations.S57,     "9")
                 .addName      (Citations.GEOTIFF, "CT_ObliqueMercator")
-                .addIdentifier(getIdentifier(PARAMETERS_A, Citations.GEOTIFF))      // Same GeoTIFF identifier.
+                .addIdentifier((ReferenceIdentifier) getIdentifier(PARAMETERS_A, Citations.GEOTIFF))      // Same GeoTIFF identifier.
                 .addName      (Citations.PROJ4,   "omerc")
                 .createGroupForMapProjection(
                         LATITUDE_OF_CENTRE,
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java b/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
index 2ec921d..8f2d171 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
@@ -40,6 +40,7 @@ import org.opengis.util.ScopedName;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.Identifier;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.referencing.operation.OperationMethod;
 
 import org.apache.sis.measure.Range;
@@ -836,7 +837,7 @@ public class ParameterFormat extends TabularFormat<Object> {
              * Put the first identifier in the first column. If no identifier has a codespace in the list
              * supplied by the user, then we will use the first identifier (any codespace) as a fallback.
              */
-            final Set<Identifier> identifiers = object.getIdentifiers();
+            final Set<ReferenceIdentifier> identifiers = object.getIdentifiers();
             if (identifiers != null) {                                              // Paranoiac check.
                 Identifier identifier = null;
                 for (final Identifier candidate : identifiers) {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
index 877bc4b..ebb8cf4 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@ -68,6 +68,9 @@ import static org.apache.sis.internal.util.CollectionsExt.nonNull;
 import static org.apache.sis.internal.util.CollectionsExt.nonEmpty;
 import static org.apache.sis.internal.util.CollectionsExt.immutableSet;
 
+// Branch-dependent imports
+import org.opengis.referencing.ReferenceIdentifier;
+
 
 /**
  * Base class for objects identified by a name or a code. Those objects are typically
@@ -110,7 +113,7 @@ import static org.apache.sis.internal.util.CollectionsExt.immutableSet;
  * </ul>
  *
  * <div class="section">Immutability and thread safety</div>
- * This base class is immutable if the {@link Citation}, {@link Identifier}, {@link GenericName} and
+ * This base class is immutable if the {@link Citation}, {@link ReferenceIdentifier}, {@link GenericName} and
  * {@link InternationalString} instances given to the constructor are also immutable. Most SIS subclasses and
  * related classes are immutable under similar conditions. This means that unless otherwise noted in the javadoc,
  * {@code IdentifiedObject} instances created using only SIS factories and static constants can be shared by many
@@ -171,12 +174,12 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * The name for this object or code. Shall never be {@code null}.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link Names#add(Identifier)}.</p>
+     * This field is modified only at unmarshalling time by {@code Names.add(Identifier)}.</p>
      *
      * @see #getName()
      * @see #getNames()
      */
-    private Identifier name;
+    private ReferenceIdentifier name;
 
     /**
      * An alternative name by which this object is identified, or {@code null} if none.
@@ -184,7 +187,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * we may get both on unmarshalling.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link Names#add(Identifier)}.</p>
+     * This field is modified only at unmarshalling time by {@code Names.add(Identifier)}.</p>
      */
     private Collection<GenericName> alias;
 
@@ -198,7 +201,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * @see #getIdentifiers()
      * @see #getIdentifier()
      */
-    private Set<Identifier> identifiers;
+    private Set<ReferenceIdentifier> identifiers;
 
     /**
      * Comments on or information about this object, or {@code null} if none.
@@ -233,7 +236,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * Other properties listed in the table below are optional.
      * In particular, {@code "authority"}, {@code "code"}, {@code "codespace"} and {@code "version"}
      * are convenience properties for building a name, and are ignored if the {@code "name"} property
-     * is already a {@link Identifier} object instead than a {@link String}.
+     * is already a {@link ReferenceIdentifier} object instead than a {@link String}.
      *
      * <table class="sis">
      *   <caption>Recognized properties (non exhaustive list)</caption>
@@ -244,7 +247,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      *   </tr>
      *   <tr>
      *     <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td>
-     *     <td>{@link Identifier} or {@link String}</td>
+     *     <td>{@link ReferenceIdentifier} or {@link String}</td>
      *     <td>{@link #getName()}</td>
      *   </tr>
      *   <tr>
@@ -258,12 +261,12 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      *     <td>{@link NamedIdentifier#getCode()} on the {@linkplain #getName() name}</td>
      *   </tr>
      *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#CODESPACE_KEY}</td>
+     *     <td>{@value org.opengis.referencing.ReferenceIdentifier#CODESPACE_KEY}</td>
      *     <td>{@link String}</td>
      *     <td>{@link NamedIdentifier#getCodeSpace()} on the {@linkplain #getName() name}</td>
      *   </tr>
      *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#VERSION_KEY}</td>
+     *     <td>{@value org.opengis.referencing.ReferenceIdentifier#VERSION_KEY}</td>
      *     <td>{@link String}</td>
      *     <td>{@link NamedIdentifier#getVersion()} on the {@linkplain #getName() name}</td>
      *   </tr>
@@ -279,7 +282,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      *   </tr>
      *   <tr>
      *     <td>{@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}</td>
-     *     <td>{@link Identifier} (optionally as array)</td>
+     *     <td>{@link ReferenceIdentifier} (optionally as array)</td>
      *     <td>{@link #getIdentifiers()}</td>
      *   </tr>
      *   <tr>
@@ -330,8 +333,8 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
                         .getString(Errors.Keys.MissingValueForProperty_1, NAME_KEY));
             }
             name = new NamedIdentifier(PropertiesConverter.convert(properties));
-        } else if (value instanceof Identifier) {
-            name = (Identifier) value;
+        } else if (value instanceof ReferenceIdentifier) {
+            name = (ReferenceIdentifier) value;
         } else {
             throw illegalPropertyType(properties, NAME_KEY, value);
         }
@@ -360,10 +363,10 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
         value = properties.get(IDENTIFIERS_KEY);
         if (value == null) {
             identifiers = null;
-        } else if (value instanceof Identifier) {
-            identifiers = Collections.singleton((Identifier) value);
-        } else if (value instanceof Identifier[]) {
-            identifiers = immutableSet(true, (Identifier[]) value);
+        } else if (value instanceof ReferenceIdentifier) {
+            identifiers = Collections.singleton((ReferenceIdentifier) value);
+        } else if (value instanceof ReferenceIdentifier[]) {
+            identifiers = immutableSet(true, (ReferenceIdentifier[]) value);
         } else {
             throw illegalPropertyType(properties, IDENTIFIERS_KEY, value);
         }
@@ -481,7 +484,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * @see IdentifiedObjects#getName(IdentifiedObject, Citation)
      */
     @Override
-    public Identifier getName() {
+    public ReferenceIdentifier getName() {
         return name;
     }
 
@@ -506,7 +509,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * @see IdentifiedObjects#getIdentifier(IdentifiedObject, Citation)
      */
     @Override
-    public Set<Identifier> getIdentifiers() {
+    public Set<ReferenceIdentifier> getIdentifiers() {
         return nonNull(identifiers);    // Needs to be null-safe because we may have a null value on unmarshalling.
     }
 
@@ -967,7 +970,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
     private void setIdentifier(final Code identifier) {
         if (identifiers == null) {
             if (identifier != null) {
-                final Identifier id = identifier.getIdentifier();
+                final ReferenceIdentifier id = identifier.getIdentifier();
                 if (id != null) {
                     identifiers = Collections.singleton(id);
                 }
@@ -995,7 +998,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * @see <a href="https://java.net/jira/browse/JAXB-488">JAXB-488</a>
      */
     @XmlElement(name = "name", required = true)
-    final Collection<Identifier> getNames() {
+    final Collection<ReferenceIdentifier> getNames() {
         return new Names();
     }
 
@@ -1012,7 +1015,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
      * subclasses, this is too late. For example {@code DefaultOperationMethod} may need to know the operation name
      * before to parse the parameters.
      */
-    private final class Names extends AbstractCollection<Identifier> {
+    private final class Names extends AbstractCollection<ReferenceIdentifier> {
         /**
          * Invoked by JAXB before to write in the collection at unmarshalling time.
          * Do nothing since our object is already empty.
@@ -1033,7 +1036,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
          * Returns an iterator over the name and aliases that are instance of {@link Identifier}.
          */
         @Override
-        public Iterator<Identifier> iterator() {
+        public Iterator<ReferenceIdentifier> iterator() {
             return new NameIterator(AbstractIdentifiedObject.this);
         }
 
@@ -1047,7 +1050,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident
          * See <a href="https://java.net/jira/browse/JAXB-488">JAXB-488</a> for more information.</p>
          */
         @Override
-        public boolean add(final Identifier id) {
+        public boolean add(final ReferenceIdentifier id) {
             if (NameIterator.isUnnamed(name)) {
                 name = id;
             } else {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
index 3509fda..ae84d2c 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
@@ -41,6 +41,9 @@ import org.apache.sis.util.resources.Errors;
 
 import static org.apache.sis.util.ArgumentChecks.*;
 
+// Branch-dependent imports
+import org.opengis.referencing.ReferenceIdentifier;
+
 
 /**
  * Base class of builders for various kind of {@link IdentifiedObject}. This class provides convenience methods
@@ -93,7 +96,7 @@ import static org.apache.sis.util.ArgumentChecks.*;
  *       The result is a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} or identifier,
  *       in which the code space information is shown by the {@code toString()} method.</li>
  *
- *   <li>The {@link #addIdentifier(Identifier)}, {@link #addName(Identifier)} and {@link #addName(GenericName)}
+ *   <li>The {@code addIdentifier(Identifier)}, {@code addName(Identifier)} and {@link #addName(GenericName)}
  *       methods take the given object <cite>as-is</cite>. Any authority, code space, version or description
  *       information given to the {@code Builder} are ignored.</li>
  * </ul>
@@ -202,7 +205,7 @@ public abstract class Builder<B extends Builder<B>> {
     /**
      * A temporary list for identifiers, before to assign them to the {@link #properties}.
      */
-    private final List<Identifier> identifiers;
+    private final List<ReferenceIdentifier> identifiers;
 
     /**
      * The codespace as a {@code NameSpace} object, or {@code null} if not yet created.
@@ -271,7 +274,7 @@ public abstract class Builder<B extends Builder<B>> {
         if (object != null) {
             properties.putAll(IdentifiedObjects.getProperties(object));
             final GenericName[] valueAlias = (GenericName[]) properties.remove(IdentifiedObject.ALIAS_KEY);
-            final Identifier[]  valueIds   = (Identifier[])  properties.remove(IdentifiedObject.IDENTIFIERS_KEY);
+            final ReferenceIdentifier[] valueIds = (ReferenceIdentifier[])  properties.remove(IdentifiedObject.IDENTIFIERS_KEY);
             if (valueAlias != null) aliases.addAll(Arrays.asList(valueAlias));
             if (valueIds != null) identifiers.addAll(Arrays.asList(valueIds));
         }
@@ -320,7 +323,7 @@ public abstract class Builder<B extends Builder<B>> {
      * then the new identifier will also contain the user-supplied code space and version (if any).
      * The new identifier will be marked as deprecated if {@link #isDeprecated()} returns {@code true}.
      */
-    private Identifier createIdentifier(final Citation authority, final String identifier) {
+    private ReferenceIdentifier createIdentifier(final Citation authority, final String identifier) {
         final String codeSpace;
         final String version;
         if (authority == getAuthority()) {
@@ -338,7 +341,9 @@ public abstract class Builder<B extends Builder<B>> {
      * Creates an identifier for the given authority, code space and version.
      * The new identifier will be marked as deprecated if {@link #isDeprecated()} returns {@code true}.
      */
-    private Identifier createIdentifier(final Citation authority, final String codeSpace, final String identifier, final String version) {
+    private ReferenceIdentifier createIdentifier(final Citation authority,
+            final String codeSpace, final String identifier, final String version)
+    {
         if (isDeprecated()) {
             return new DeprecatedCode(authority, codeSpace, identifier, version, null, getRemarks());
         } else {
@@ -350,8 +355,8 @@ public abstract class Builder<B extends Builder<B>> {
      * Converts the given name into an identifier. Note that {@link NamedIdentifier}
      * implements both {@link GenericName} and {@link Identifier} interfaces.
      */
-    private static Identifier toIdentifier(final GenericName name) {
-        return (name instanceof Identifier) ? (Identifier) name : new NamedIdentifier(name);
+    private static ReferenceIdentifier toIdentifier(final GenericName name) {
+        return (name instanceof ReferenceIdentifier) ? (ReferenceIdentifier) name : new NamedIdentifier(name);
     }
 
     /**
@@ -582,7 +587,7 @@ public abstract class Builder<B extends Builder<B>> {
      * @param  name  the {@code IdentifiedObject} name as an identifier.
      * @return {@code this}, for method call chaining.
      */
-    public B addName(final Identifier name) {
+    public B addName(final ReferenceIdentifier name) {
         ensureNonNull("name", name);
         if (properties.putIfAbsent(IdentifiedObject.NAME_KEY, name) != null) {
             // A primary name is already present. Add the given name as an alias instead.
@@ -674,7 +679,7 @@ public abstract class Builder<B extends Builder<B>> {
      * @param  identifier  the {@code IdentifiedObject} identifier.
      * @return {@code this}, for method call chaining.
      */
-    public B addIdentifier(final Identifier identifier) {
+    public B addIdentifier(final ReferenceIdentifier identifier) {
         ensureNonNull("identifier", identifier);
         identifiers.add(identifier);
         return self();
@@ -704,12 +709,12 @@ public abstract class Builder<B extends Builder<B>> {
      */
     public B addNamesAndIdentifiers(final IdentifiedObject object) {
         ensureNonNull("object", object);
-        for (final Identifier id : object.getIdentifiers()) {
+        for (final ReferenceIdentifier id : object.getIdentifiers()) {
             if (!isDeprecated(id)) {
                 addIdentifier(id);
             }
         }
-        Identifier id = object.getName();
+        ReferenceIdentifier id = object.getName();
         if (!isDeprecated(id)) {
             addName(id);
         }
@@ -1020,7 +1025,7 @@ public abstract class Builder<B extends Builder<B>> {
             valueIds   = null;
         } else {
             valueAlias = aliases    .toArray(new GenericName[aliases    .size()]);
-            valueIds   = identifiers.toArray(new Identifier [identifiers.size()]);
+            valueIds   = identifiers.toArray(new ReferenceIdentifier[identifiers.size()]);
         }
         properties.put(IdentifiedObject.ALIAS_KEY,       valueAlias);
         properties.put(IdentifiedObject.IDENTIFIERS_KEY, valueIds);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index cc3ef56..63883a2 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -556,12 +556,12 @@ public final class CRS extends Static {
              */
             if (maxInsideArea < roiArea) {
                 if (tryDerivedCRS) break;                                               // Do not try twice.
-                final SingleCRS[] derivedCRS = new SingleCRS[sourceCRS.length];
+                final CoordinateReferenceSystem[] derivedCRS = new CoordinateReferenceSystem[sourceCRS.length];
                 for (int i=0; i < derivedCRS.length; i++) {
                     GeographicBoundingBox bbox = null;
                     final CoordinateReferenceSystem crs = sourceCRS[i];
                     if (crs instanceof GeneralDerivedCRS) {
-                        final SingleCRS baseCRS = ((GeneralDerivedCRS) crs).getBaseCRS();
+                        final CoordinateReferenceSystem baseCRS = ((GeneralDerivedCRS) crs).getBaseCRS();
                         bbox = getGeographicBoundingBox(baseCRS);
                         if (bbox == null && bestCRS == null && baseCRS instanceof GeodeticCRS) {
                             bestCRS = baseCRS;      // Fallback to be used if we don't find anything better.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
index 0a57422..497d975 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
@@ -19,8 +19,8 @@ package org.apache.sis.referencing;
 import java.util.Iterator;
 import java.util.Collection;
 import org.opengis.util.GenericName;
-import org.opengis.metadata.Identifier;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.internal.referencing.NilReferencingObject;
@@ -30,7 +30,7 @@ import static org.apache.sis.internal.util.Utilities.appendUnicodeIdentifier;
 
 /**
  * An iterator over the {@linkplain IdentifiedObject#getName() name} of an identified object followed by
- * {@linkplain IdentifiedObject#getAlias() aliases} which are instance of {@link Identifier}.
+ * {@linkplain IdentifiedObject#getAlias() aliases} which are instance of {@link ReferenceIdentifier}.
  * This iterator is used for {@link AbstractIdentifiedObject} XML marshalling because GML merges the name
  * and aliases in a single {@code <gml:name>} property. However this iterator is useful only if the aliases
  * are instances of {@link NamedIdentifier}, or any other implementation which is both a name and an identifier.
@@ -42,11 +42,11 @@ import static org.apache.sis.internal.util.Utilities.appendUnicodeIdentifier;
  * @since   0.4
  * @module
  */
-final class NameIterator implements Iterator<Identifier> {
+final class NameIterator implements Iterator<ReferenceIdentifier> {
     /**
      * The next element to return, or {@code null} if we reached the end of iteration.
      */
-    private Identifier next;
+    private ReferenceIdentifier next;
 
     /**
      * An iterator over the aliases.
@@ -68,7 +68,7 @@ final class NameIterator implements Iterator<Identifier> {
     /**
      * Returns {@code true} if the given identifier is null or the {@link NilReferencingObject#UNNAMED} instance.
      */
-    static boolean isUnnamed(final Identifier name) {
+    static boolean isUnnamed(final ReferenceIdentifier name) {
         return (name == null) || (name == NilReferencingObject.UNNAMED);
     }
 
@@ -87,12 +87,12 @@ final class NameIterator implements Iterator<Identifier> {
      * will be used only by JAXB, which is presumed checking for {@link #hasNext()} correctly.
      */
     @Override
-    public Identifier next() {
-        final Identifier n = next;
+    public ReferenceIdentifier next() {
+        final ReferenceIdentifier n = next;
         while (alias.hasNext()) {
             final GenericName c = alias.next();
-            if (c instanceof Identifier) {
-                next = (Identifier) c;
+            if (c instanceof ReferenceIdentifier) {
+                next = (ReferenceIdentifier) c;
                 return n;
             }
         }
@@ -144,8 +144,8 @@ final class NameIterator implements Iterator<Identifier> {
      * @param  identifiers  the identifiers, or {@code null} if none.
      * @return proposed value for {@code gml:id} attribute, or {@code null} if none.
      */
-    static String getID(final Context context, final IdentifiedObject object, final Identifier name,
-            final Collection<? extends GenericName> alias, final Collection<? extends Identifier> identifiers)
+    static String getID(final Context context, final IdentifiedObject object, final ReferenceIdentifier name,
+            final Collection<? extends GenericName> alias, final Collection<? extends ReferenceIdentifier> identifiers)
     {
         String candidate = Context.getObjectID(context, object);
         if (candidate == null) {
@@ -155,7 +155,7 @@ final class NameIterator implements Iterator<Identifier> {
              * if we found no suitable ID, then we will use the primary name as a last resort.
              */
             if (identifiers != null) {
-                for (final Identifier identifier : identifiers) {
+                for (final ReferenceIdentifier identifier : identifiers) {
                     if (appendUnicodeIdentifier(id, '-', identifier.getCodeSpace(), "", true) |    // Really |, not ||
                         appendUnicodeIdentifier(id, '-', NameMeaning.toObjectType(object.getClass()), "", false) |
                         appendUnicodeIdentifier(id, '-', identifier.getCode(), "", true))
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
index d2d2e16..a1cf4b3 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
@@ -32,6 +32,7 @@ import org.opengis.util.InternationalString;
 import org.apache.sis.util.resources.Errors;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.parameter.InvalidParameterValueException;
 import org.apache.sis.internal.metadata.NameToIdentifier;
 import org.apache.sis.internal.system.DefaultFactories;
@@ -94,7 +95,7 @@ import org.apache.sis.util.ArgumentChecks;
  * @since 0.4
  * @module
  */
-public class NamedIdentifier extends ImmutableIdentifier implements GenericName {
+public class NamedIdentifier extends ImmutableIdentifier implements GenericName, ReferenceIdentifier {
     /**
      * Serial number for inter-operability with different versions.
      */
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
index 8a4b0af..10c7911 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/Properties.java
@@ -21,10 +21,10 @@ import java.util.HashMap;
 import java.util.Collection;
 import java.io.Serializable;
 import org.opengis.util.GenericName;
-import org.opengis.metadata.Identifier;
 import org.opengis.referencing.datum.Datum;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.metadata.quality.PositionalAccuracy;
@@ -125,11 +125,11 @@ final class Properties extends AbstractMap<String,Object> implements Serializabl
                     return object.getName();
                 }
                 case 1: {   // IDENTIFIERS_KEY
-                    final Collection<Identifier> c = object.getIdentifiers();
+                    final Collection<ReferenceIdentifier> c = object.getIdentifiers();
                     if (c != null) {
                         final int size = c.size();
                         if (size != 0) {
-                            return c.toArray(new Identifier[size]);
+                            return c.toArray(new ReferenceIdentifier[size]);
                         }
                     }
                     break;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
index 55fe5d4..1c66728 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
@@ -145,7 +145,7 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
      */
     AbstractDerivedCRS(final GeneralDerivedCRS crs) {
         super(crs);
-        conversionFromBase = createConversionFromBase(null, crs.getBaseCRS(), crs.getConversionFromBase());
+        conversionFromBase = createConversionFromBase(null, (SingleCRS) crs.getBaseCRS(), crs.getConversionFromBase());
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
index a00f7ec..613e309 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
@@ -381,7 +381,7 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
         if (object == null || object instanceof DefaultDerivedCRS) {
             return (DefaultDerivedCRS) object;
         } else {
-            final String type = getType(object.getBaseCRS(), object.getCoordinateSystem());
+            final String type = getType((SingleCRS) object.getBaseCRS(), object.getCoordinateSystem());
             if (type != null) switch (type) {
                 case WKTKeywords.GeodeticCRS:    return new Geodetic   (object);
                 case WKTKeywords.VerticalCRS:    return new Vertical   (object);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
index 27e14f0..5ae000c 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
@@ -235,7 +235,7 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen
     @XmlElement(name = "baseGeodeticCRS", required = true)        // Note: older GML version used "baseGeographicCRS".
     public GeographicCRS getBaseCRS() {
         final Projection projection = super.getConversionFromBase();
-        return (projection != null) ? projection.getSourceCRS() : null;
+        return (projection != null) ? (GeographicCRS) projection.getSourceCRS() : null;
     }
 
     /**
@@ -288,7 +288,7 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen
     @Override
     final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
         final Projection conversion = super.getConversionFromBase();
-        return new DefaultProjectedCRS(properties, conversion.getSourceCRS(), conversion, (CartesianCS) cs);
+        return new DefaultProjectedCRS(properties, (GeographicCRS) conversion.getSourceCRS(), conversion, (CartesianCS) cs);
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index d7853bc..5dff676 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -972,7 +972,7 @@ public class CoordinateOperationFinder extends CoordinateOperationRegistry {
                  * it is not, try to copy it in such object.
                  */
                 final SingleOperation op;
-                if (subOperation instanceof SingleOperation) {
+                if (SubTypes.isSingleOperation(subOperation)) {
                     op = (SingleOperation) subOperation;
                 } else {
                     op = factorySIS.createSingleOperation(properties,
@@ -1073,7 +1073,7 @@ public class CoordinateOperationFinder extends CoordinateOperationRegistry {
             if (isAxisChange1 && mt1.getSourceDimensions() == mt1.getTargetDimensions()) main = step2;
             if (isAxisChange2 && mt2.getSourceDimensions() == mt2.getTargetDimensions()) main = step1;
         }
-        if (main instanceof SingleOperation) {
+        if (SubTypes.isSingleOperation(main)) {
             final SingleOperation op = (SingleOperation) main;
             final MathTransform mt = factorySIS.getMathTransformFactory().createConcatenatedTransform(mt1, mt2);
             main = createFromMathTransform(new HashMap<>(IdentifiedObjects.getProperties(main)),
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
index 67278e5..6a733d3 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
@@ -601,7 +601,7 @@ class CoordinateOperationRegistry {
     private CoordinateOperation inverse(final CoordinateOperation operation)
             throws NoninvertibleTransformException, FactoryException
     {
-        if (operation instanceof SingleOperation) {
+        if (SubTypes.isSingleOperation(operation)) {
             return inverse((SingleOperation) operation);
         }
         if (operation instanceof ConcatenatedOperation) {
@@ -788,7 +788,7 @@ class CoordinateOperationRegistry {
          * be prepared to see the 'redimension' call fails. In such case, we will try to get
          * the SIS implementation of the operation method and try again.
          */
-        if (operation instanceof SingleOperation) {
+        if (SubTypes.isSingleOperation(operation)) {
             final SingleOperation single = (SingleOperation) operation;
             properties.put(ReferencingServices.PARAMETERS_KEY, single.getParameterValues());
             if (method == null) {
@@ -947,7 +947,7 @@ class CoordinateOperationRegistry {
              */
             Matrix matrix = MathTransforms.getMatrix(op.getMathTransform());
             if (matrix == null) {
-                if (op instanceof SingleOperation) {
+                if (SubTypes.isSingleOperation(op)) {
                     final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory();
                     if (mtFactory instanceof DefaultMathTransformFactory) {
                         if (forward) sourceCRS = toGeodetic3D(sourceCRS, source3D);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
index 99a6f50..44d6c7c 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
@@ -43,6 +43,7 @@ import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.Utilities.deepEquals;
 
+import org.opengis.referencing.operation.SingleOperation;
 
 /**
  * An ordered sequence of two or more single coordinate operations. The sequence of operations is constrained
@@ -70,7 +71,7 @@ final class DefaultConcatenatedOperation extends AbstractCoordinateOperation imp
      * <p><b>Consider this field as final!</b>
      * This field is modified only at unmarshalling time by {@link #setSteps(CoordinateOperation[])}</p>
      */
-    private List<? extends CoordinateOperation> operations;
+    private List<SingleOperation> operations;
 
     /**
      * Constructs a concatenated operation from a set of properties and a
@@ -142,7 +143,7 @@ final class DefaultConcatenatedOperation extends AbstractCoordinateOperation imp
          * At this point we should have flattened.size() >= 2, except if some operations
          * were omitted because their associated math transform were identity operation.
          */
-        this.operations = UnmodifiableArrayList.wrap(flattened.toArray(new CoordinateOperation[flattened.size()]));
+        this.operations = UnmodifiableArrayList.wrap(flattened.toArray(new SingleOperation[flattened.size()]));
     }
 
     /**
@@ -326,11 +327,17 @@ final class DefaultConcatenatedOperation extends AbstractCoordinateOperation imp
     /**
      * Returns the sequence of operations.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * This method is conformant to ISO 19111:2003. But the ISO 19111:2007 revision changed the element type
+     * from {@code SingleOperation} to {@link CoordinateOperation}. This change may be applied in GeoAPI 4.0.
+     * This is necessary for supporting usage of {@code PassThroughOperation} with {@link ConcatenatedOperation}.
+     * </div>
+     *
      * @return the sequence of operations.
      */
     @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    public List<? extends CoordinateOperation> getOperations() {
+    public List<SingleOperation> getOperations() {
         return operations;
     }
 
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
index cca675d..8196889 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
@@ -22,6 +22,7 @@ import java.util.Objects;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.PassThroughOperation;
@@ -39,6 +40,8 @@ import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.Utilities.deepEquals;
 
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.SingleOperation;
 
 /**
  * Specifies that a subset of a coordinate tuple is subject to a specific coordinate operation.
@@ -63,11 +66,11 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
      * The operation to apply on the subset of a coordinate tuple.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setOperation(CoordinateOperation)}</p>
+     * This field is modified only at unmarshalling time by {@code setOperation(CoordinateOperation)}</p>
      *
      * @see #getOperation()
      */
-    private CoordinateOperation operation;
+    private SingleOperation operation;
 
     /**
      * Constructs a single operation from a set of properties.
@@ -105,7 +108,7 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
     public DefaultPassThroughOperation(final Map<String,?>            properties,
                                        final CoordinateReferenceSystem sourceCRS,
                                        final CoordinateReferenceSystem targetCRS,
-                                       final CoordinateOperation       operation,
+                                       final SingleOperation           operation,
                                        final int firstAffectedOrdinate,
                                        final int numTrailingOrdinates)
     {
@@ -165,15 +168,43 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
     }
 
     /**
+     * @deprecated May be removed in GeoAPI 4.0 since it does not apply to pass-through operations.
+     *
+     * @return {@code null}.
+     */
+    @Override
+    @Deprecated
+    public OperationMethod getMethod() {
+        return null;
+    }
+
+    /**
+     * @deprecated May be removed in GeoAPI 4.0 since it does not apply to pass-through operations.
+     *
+     * @return {@code null}.
+     */
+    @Override
+    @Deprecated
+    public ParameterValueGroup getParameterValues() {
+        return null;
+    }
+
+    /**
      * Returns the operation to apply on the subset of a coordinate tuple.
      *
+     * <div class="warning"><b>Upcoming API change</b><br>
+     * This method is conformant to ISO 19111:2003. But the ISO 19111:2007 revision changed the type from
+     * {@code SingleOperation} to {@link CoordinateOperation}. This change may be applied in GeoAPI 4.0.
+     * This is necessary for supporting usage of {@code PassThroughOperation} with {@code ConcatenatedOperation}.
+     * </div>
+     *
      * @return the operation to apply on the subset of a coordinate tuple.
      *
      * @see PassThroughTransform#getSubTransform()
      */
     @Override
     @XmlElement(name = "coordOperation", required = true)
-    public CoordinateOperation getOperation() {
+    public SingleOperation getOperation() {
         return operation;
     }
 
@@ -309,7 +340,7 @@ public class DefaultPassThroughOperation extends AbstractCoordinateOperation imp
      *
      * @see #getOperation()
      */
-    private void setOperation(final CoordinateOperation op) {
+    private void setOperation(final SingleOperation op) {
         if (operation == null) {
             operation = op;
         } else {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
index f797bae..2576836 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubOperationInfo.java
@@ -65,7 +65,7 @@ final class SubOperationInfo {
      */
     private static Class<?> type(SingleCRS crs) {
         while (crs instanceof GeneralDerivedCRS) {
-            crs = ((GeneralDerivedCRS) crs).getBaseCRS();
+            crs = (SingleCRS) ((GeneralDerivedCRS) crs).getBaseCRS();
         }
         return crs.getClass();
     }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
index 51e1e64..f525f8d 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SubTypes.java
@@ -47,6 +47,17 @@ final class SubTypes {
     }
 
     /**
+     * Returns {@code true} if the given operation is a single operation but not a pass-through operation.
+     * In an older ISO 19111 model, {@link PassThroughOperation} extended {@link SingleOperation}, which
+     * was a problem for providing a value to the inherited {@link SingleOperation#getMethod()} method.
+     * This has been fixed in newer ISO 19111 model, but for safety with objects following the older model
+     * (e.g. GeoAPI 3.0) we are better to perform an explicit exclusion of {@link PassThroughOperation}.
+     */
+    static boolean isSingleOperation(final CoordinateOperation operation) {
+        return (operation instanceof SingleOperation) && !(operation instanceof PassThroughOperation);
+    }
+
+    /**
      * Returns a SIS implementation for the given coordinate operation.
      *
      * @see AbstractCoordinateOperation#castOrCopy(CoordinateOperation)
@@ -64,7 +75,7 @@ final class SubTypes {
         if (object instanceof ConcatenatedOperation) {
             return DefaultConcatenatedOperation.castOrCopy((ConcatenatedOperation) object);
         }
-        if (object instanceof SingleOperation) {
+        if (isSingleOperation(object)) {
             return (object instanceof AbstractSingleOperation) ? (AbstractSingleOperation) object
                    : new AbstractSingleOperation((SingleOperation) object);
         }
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParametersTest.java b/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParametersTest.java
index ed1c8e9..31aacc3 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParametersTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParametersTest.java
@@ -23,8 +23,8 @@ import javax.measure.Unit;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDirection;
 import org.opengis.parameter.ParameterValue;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.metadata.Identifier;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.apache.sis.measure.Range;
@@ -115,9 +115,9 @@ public final strictfp class ParametersTest extends TestCase {
     {
         assertEquals(valueDomain, Parameters.getValueDomain(descriptor));
         assertEquals(valueDomain, Parameters.getValueDomain(new ParameterDescriptor<T>() {
-            @Override public Identifier               getName()          {return descriptor.getName();}
+            @Override public ReferenceIdentifier      getName()          {return descriptor.getName();}
             @Override public Collection<GenericName>  getAlias()         {return descriptor.getAlias();}
-            @Override public Set<Identifier>          getIdentifiers()   {return descriptor.getIdentifiers();}
+            @Override public Set<ReferenceIdentifier> getIdentifiers()   {return descriptor.getIdentifiers();}
             @Override public InternationalString      getRemarks()       {return descriptor.getRemarks();}
             @Override public InternationalString      getDescription()   {return descriptor.getDescription();}
             @Override public ParameterDirection       getDirection()     {return descriptor.getDirection();}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractIdentifiedObjectTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractIdentifiedObjectTest.java
index 04b92b8..094df04 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractIdentifiedObjectTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractIdentifiedObjectTest.java
@@ -23,7 +23,7 @@ import java.util.LinkedHashSet;
 import java.util.Locale;
 import java.util.Collections;
 import org.opengis.test.Validators;
-import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.referencing.datum.AbstractDatum;
 import org.apache.sis.internal.jaxb.referencing.Code;
@@ -57,10 +57,10 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
      *
      * @param  identifiers  the value for the {@code "identifiers"} property.
      */
-    private static Map<String,Object> properties(final Set<Identifier> identifiers) {
+    private static Map<String,Object> properties(final Set<ReferenceIdentifier> identifiers) {
         final Map<String,Object> properties = new HashMap<>(8);
         assertNull(properties.put("name",       "GRS 1980"));
-        assertNull(properties.put("identifiers", identifiers.toArray(new Identifier[identifiers.size()])));
+        assertNull(properties.put("identifiers", identifiers.toArray(new ReferenceIdentifier[identifiers.size()])));
         assertNull(properties.put("codespace",  "EPSG"));
         assertNull(properties.put("version",    "8.3"));
         assertNull(properties.put("alias",      "International 1979"));
@@ -77,11 +77,11 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
      * @param  gmlID        the expected value of {@link AbstractIdentifiedObject#getID()}.
      * @return the value of {@link AbstractIdentifiedObject#getIdentifier()}.
      */
-    private static Identifier validate(final AbstractIdentifiedObject object,
-            final Set<Identifier> identifiers, final String gmlID)
+    private static ReferenceIdentifier validate(final AbstractIdentifiedObject object,
+            final Set<ReferenceIdentifier> identifiers, final String gmlID)
     {
         Validators.validate(object);
-        final Identifier name = object.getName();
+        final ReferenceIdentifier name = object.getName();
         assertEquals("name",        "GRS 1980",                      name.getCode());
         assertEquals("codespace",   "EPSG",                          name.getCodeSpace());
         assertEquals("version",     "8.3",                           name.getVersion());
@@ -134,9 +134,9 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
      */
     @Test
     public void testWithoutIdentifier() {
-        final Set<Identifier>          identifiers = Collections.emptySet();
+        final Set<ReferenceIdentifier> identifiers = Collections.emptySet();
         final AbstractIdentifiedObject object      = new AbstractIdentifiedObject(properties(identifiers));
-        final Identifier               gmlId       = validate(object, identifiers, "GRS1980");
+        final ReferenceIdentifier      gmlId       = validate(object, identifiers, "GRS1980");
         assertNull("gmlId", gmlId);
     }
 
@@ -153,10 +153,10 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
     @Test
     @DependsOnMethod("testWithoutIdentifier")
     public void testWithSingleIdentifier() {
-        final Identifier               identifier  = new ImmutableIdentifier(null, "EPSG", "7019");
-        final Set<Identifier>          identifiers = Collections.singleton(identifier);
+        final ReferenceIdentifier      identifier  = new ImmutableIdentifier(null, "EPSG", "7019");
+        final Set<ReferenceIdentifier> identifiers = Collections.singleton(identifier);
         final AbstractIdentifiedObject object      = new AbstractIdentifiedObject(properties(identifiers));
-        final Identifier               gmlId       = validate(object, identifiers, "epsg-7019");
+        final ReferenceIdentifier      gmlId       = validate(object, identifiers, "epsg-7019");
         assertNotNull("gmlId",                   gmlId);
         assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
         assertEquals ("gmlId.code",      "7019", gmlId.getCode());
@@ -170,11 +170,11 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
     @Test
     @DependsOnMethod("testWithSingleIdentifier")
     public void testWithManyIdentifiers() {
-        final Set<Identifier> identifiers = new LinkedHashSet<>(4);
+        final Set<ReferenceIdentifier> identifiers = new LinkedHashSet<>(4);
         assertTrue(identifiers.add(new NamedIdentifier(EPSG, "7019")));
         assertTrue(identifiers.add(new NamedIdentifier(EPSG, "IgnoreMe")));
         final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
-        final Identifier gmlId  = validate(object, identifiers, "epsg-7019");
+        final ReferenceIdentifier      gmlId  = validate(object, identifiers, "epsg-7019");
         assertNotNull("gmlId",                   gmlId);
         assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
         assertEquals ("gmlId.code",      "7019", gmlId.getCode());
@@ -188,10 +188,10 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
     @Test
     @DependsOnMethod("testWithManyIdentifiers")
     public void testAsSubtype() {
-        final Identifier               identifier  = new NamedIdentifier(EPSG, "7019");
-        final Set<Identifier>          identifiers = Collections.singleton(identifier);
+        final ReferenceIdentifier      identifier  = new NamedIdentifier(EPSG, "7019");
+        final Set<ReferenceIdentifier> identifiers = Collections.singleton(identifier);
         final AbstractIdentifiedObject object      = new AbstractDatum(properties(identifiers));
-        final Identifier               gmlId       = validate(object, identifiers, "epsg-datum-7019");
+        final ReferenceIdentifier      gmlId       = validate(object, identifiers, "epsg-datum-7019");
         assertNotNull("gmlId",                   gmlId);
         assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
         assertEquals ("gmlId.code",      "7019", gmlId.getCode());
@@ -235,9 +235,9 @@ public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
     @Test
     @DependsOnMethod("testWithoutIdentifier")
     public void testSerialization() {
-        final Set<Identifier>     identifiers = Collections.emptySet();
-        final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
-        final AbstractIdentifiedObject actual = assertSerializedEquals(object);
+        final Set<ReferenceIdentifier> identifiers = Collections.emptySet();
+        final AbstractIdentifiedObject object      = new AbstractIdentifiedObject(properties(identifiers));
+        final AbstractIdentifiedObject actual      = assertSerializedEquals(object);
         assertNotSame(object, actual);
         assertNull("gmlId", validate(actual, identifiers, "GRS1980"));
     }
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java b/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java
index 4680a8e..64ca99f 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/integration/MetadataTest.java
@@ -162,7 +162,7 @@ public strictfp class MetadataTest extends XMLTestCase {
          * because this is what will be unmarshalled from the XML document.
          */
         @SuppressWarnings("deprecation")
-        final DefaultResponsibility author = new DefaultResponsibleParty(Role.AUTHOR);
+        final DefaultResponsibleParty author = new DefaultResponsibleParty(Role.AUTHOR);
         final Anchor country = new Anchor(URI.create("SDN:C320:2:FR"), "France"); // Non-public SIS class.
         {
             final DefaultOnlineResource online = new DefaultOnlineResource(URI.create("http://www.ifremer.fr/sismer/"));
@@ -174,7 +174,7 @@ public strictfp class MetadataTest extends XMLTestCase {
                     new DefaultTelephone("+33 (0)2 xx.xx.xx.x4", TelephoneType.FACSIMILE)
             ));
             final DefaultAddress address = new DefaultAddress();
-            address.setDeliveryPoints(singleton(new SimpleInternationalString("Brest institute")));
+            address.setDeliveryPoints(singleton("Brest institute"));
             address.setCity(new SimpleInternationalString("Plouzane"));
             address.setPostalCode("29280");
             address.setCountry(country);
@@ -194,7 +194,7 @@ public strictfp class MetadataTest extends XMLTestCase {
                     new DefaultCitationDate(TestUtilities.date("1979-08-02 22:00:00"), DateType.CREATION)));
             {
                 @SuppressWarnings("deprecation")
-                final DefaultResponsibility originator = new DefaultResponsibleParty(Role.ORIGINATOR);
+                final DefaultResponsibleParty originator = new DefaultResponsibleParty(Role.ORIGINATOR);
                 final DefaultOnlineResource online = new DefaultOnlineResource(URI.create("http://www.com.univ-mrs.fr/LOB/"));
                 online.setProtocol("http");
                 final DefaultContact contact = new DefaultContact(online);
@@ -203,7 +203,7 @@ public strictfp class MetadataTest extends XMLTestCase {
                         new DefaultTelephone("+33 (0)4 xx.xx.xx.x8", TelephoneType.FACSIMILE)
                 ));
                 final DefaultAddress address = new DefaultAddress();
-                address.setDeliveryPoints(singleton(new SimpleInternationalString("Oceanology institute")));
+                address.setDeliveryPoints(singleton("Oceanology institute"));
                 address.setCity(new SimpleInternationalString("Marseille"));
                 address.setPostalCode("13288");
                 address.setCountry(country);
@@ -218,7 +218,7 @@ public strictfp class MetadataTest extends XMLTestCase {
                     TopicCategory.OCEANS);      // Topic category
             {
                 @SuppressWarnings("deprecation")
-                final DefaultResponsibility custodian = new DefaultResponsibleParty(author);
+                final DefaultResponsibleParty custodian = new DefaultResponsibleParty((DefaultResponsibility) author);
                 custodian.setRole(Role.CUSTODIAN);
                 identification.setPointOfContacts(singleton(custodian));
             }
@@ -352,7 +352,7 @@ public strictfp class MetadataTest extends XMLTestCase {
          */
         {
             @SuppressWarnings("deprecation")
-            final DefaultResponsibility distributor = new DefaultResponsibleParty(author);
+            final DefaultResponsibleParty distributor = new DefaultResponsibleParty((DefaultResponsibility) author);
             final DefaultDistribution distributionInfo = new DefaultDistribution();
             distributor.setRole(Role.DISTRIBUTOR);
             distributionInfo.setDistributors(singleton(new DefaultDistributor(distributor)));
@@ -372,7 +372,7 @@ public strictfp class MetadataTest extends XMLTestCase {
             onlines.setProtocol("http");
             transfer.setOnLines(singleton(onlines));
             distributionInfo.setTransferOptions(singleton(transfer));
-            metadata.setDistributionInfo(singleton(distributionInfo));
+            metadata.setDistributionInfo(distributionInfo);
         }
         return metadata;
     }
diff --git a/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationMock.java b/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationMock.java
index e91116a..c8513b9 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationMock.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/internal/util/CitationMock.java
@@ -25,9 +25,10 @@ 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.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Series;
 import org.opengis.metadata.identification.BrowseGraphic;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.Debug;
@@ -43,7 +44,7 @@ import org.apache.sis.util.Debug;
  * @module
  */
 @SuppressWarnings("ReturnOfCollectionOrArrayField")
-final strictfp class CitationMock implements Citation, Identifier {
+final strictfp class CitationMock implements Citation, ReferenceIdentifier {
     /**
      * The title to be returned by {@link #getTitle()}.
      */
@@ -85,10 +86,10 @@ final strictfp class CitationMock implements Citation, Identifier {
     @Override public String                           getCodeSpace()               {return codeSpace;}
     @Override public String                           getVersion()                 {return null;}
     @Override public InternationalString              getDescription()             {return null;}
-    @Override public Collection<Responsibility>       getCitedResponsibleParties() {return Collections.emptyList();}
+    @Override public Collection<ResponsibleParty>     getCitedResponsibleParties() {return Collections.emptyList();}
     @Override public Collection<PresentationForm>     getPresentationForms()       {return Collections.emptyList();}
     @Override public Series                           getSeries()                  {return null;}
-    @Override public Collection<InternationalString>  getOtherCitationDetails()    {return Collections.emptyList();}
+    @Override public InternationalString              getOtherCitationDetails()    {return null;}
     @Override public Collection<OnlineResource>       getOnlineResources()         {return Collections.emptyList();}
     @Override public Collection<BrowseGraphic>        getGraphics()                {return Collections.emptyList();}
     @Override public String                           getISBN()                    {return null;}
diff --git a/ide-project/NetBeans/nbproject/build-impl.xml b/ide-project/NetBeans/nbproject/build-impl.xml
index 1f0a2f8..d8cd687 100644
--- a/ide-project/NetBeans/nbproject/build-impl.xml
+++ b/ide-project/NetBeans/nbproject/build-impl.xml
@@ -19,7 +19,7 @@ is divided into following sections:
   - cleanup
 
         -->
-<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Apache_SIS_on_GeoAPI_4.0-impl">
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Apache_SIS_on_GeoAPI_3.1-impl">
     <fail message="Please build using Ant 1.8.0 or higher.">
         <condition>
             <not>
@@ -634,7 +634,7 @@ is divided into following sections:
                     </fileset>
                 </union>
                 <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
-                <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Apache_SIS_on_GeoAPI_4.0" testname="TestNG tests" workingDir="${work.dir}">
+                <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Apache_SIS_on_GeoAPI_3.1" testname="TestNG tests" workingDir="${work.dir}">
                     <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
                     <propertyset>
                         <propertyref prefix="test-sys-prop."/>
@@ -839,7 +839,7 @@ is divided into following sections:
                 <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
                     <isset property="test.method"/>
                 </condition>
-                <condition else="-suitename Apache_SIS_on_GeoAPI_4.0 -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+                <condition else="-suitename Apache_SIS_on_GeoAPI_3.1 -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
                     <matches pattern=".*\.xml" string="@{testClass}"/>
                 </condition>
                 <delete dir="${build.test.results.dir}" quiet="true"/>
@@ -1131,7 +1131,7 @@ is divided into following sections:
         <delete file="${built-jar.properties}" quiet="true"/>
     </target>
     <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
-        <echo level="warn" message="Cycle detected: Apache SIS on GeoAPI 4.0 was already built"/>
+        <echo level="warn" message="Cycle detected: Apache SIS on GeoAPI 3.1 was already built"/>
     </target>
     <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
         <mkdir dir="${build.dir}"/>
@@ -1141,14 +1141,6 @@ is divided into following sections:
         <propertyfile file="${built-jar.properties}">
             <entry key="${basedir}" value=""/>
         </propertyfile>
-        <antcall target="-maybe-call-dep">
-            <param name="call.built.properties" value="${built-jar.properties}"/>
-            <param location="${project.GeoAPI}" name="call.subproject"/>
-            <param location="${project.GeoAPI}/build.xml" name="call.script"/>
-            <param name="call.target" value="jar"/>
-            <param name="transfer.built-jar.properties" value="${built-jar.properties}"/>
-            <param name="transfer.not.archive.disabled" value="true"/>
-        </antcall>
     </target>
     <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
     <target depends="init" name="-check-automatic-build">
@@ -1800,7 +1792,7 @@ is divided into following sections:
         <delete file="${built-clean.properties}" quiet="true"/>
     </target>
     <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
-        <echo level="warn" message="Cycle detected: Apache SIS on GeoAPI 4.0 was already built"/>
+        <echo level="warn" message="Cycle detected: Apache SIS on GeoAPI 3.1 was already built"/>
     </target>
     <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
         <mkdir dir="${build.dir}"/>
@@ -1810,14 +1802,6 @@ is divided into following sections:
         <propertyfile file="${built-clean.properties}">
             <entry key="${basedir}" value=""/>
         </propertyfile>
-        <antcall target="-maybe-call-dep">
-            <param name="call.built.properties" value="${built-clean.properties}"/>
-            <param location="${project.GeoAPI}" name="call.subproject"/>
-            <param location="${project.GeoAPI}/build.xml" name="call.script"/>
-            <param name="call.target" value="clean"/>
-            <param name="transfer.built-clean.properties" value="${built-clean.properties}"/>
-            <param name="transfer.not.archive.disabled" value="true"/>
-        </antcall>
     </target>
     <target depends="init" name="-do-clean">
         <delete dir="${build.dir}"/>
diff --git a/ide-project/NetBeans/nbproject/genfiles.properties b/ide-project/NetBeans/nbproject/genfiles.properties
index ec32b8a..c89c1fe 100644
--- a/ide-project/NetBeans/nbproject/genfiles.properties
+++ b/ide-project/NetBeans/nbproject/genfiles.properties
@@ -3,6 +3,6 @@
 build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
-nbproject/build-impl.xml.data.CRC32=40d83d59
-nbproject/build-impl.xml.script.CRC32=b7ab89c5
+nbproject/build-impl.xml.data.CRC32=5a0e9d09
+nbproject/build-impl.xml.script.CRC32=fb8d24ed
 nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
diff --git a/ide-project/NetBeans/nbproject/project.properties b/ide-project/NetBeans/nbproject/project.properties
index e3f775c..c816707 100644
--- a/ide-project/NetBeans/nbproject/project.properties
+++ b/ide-project/NetBeans/nbproject/project.properties
@@ -88,17 +88,11 @@ src.fra-profile.dir  = ${project.root}/profiles/sis-french-profile/src/main/java
 test.fra-profile.dir = ${project.root}/profiles/sis-french-profile/src/test/java
 
 #
-# Dependencies on other NetBeans projects. The path is relative to the "NetBeans" parent directory.
-# If a different path is desired, copy that line in the "private/private.properties" file and edit
-# its value there.
-#
-project.GeoAPI       = ../../../../GeoAPI/master/ide-project/NetBeans
-
-#
 # Version numbers for all dependencies.
 # Those dependencies must exist in the local Maven repository.
 # Those numbers should match the ones declared in the pom.xml files.
 #
+geoapi.version       = 3.1-SNAPSHOT
 jsr363.version       = 1.0
 jama.version         = 1.0.3
 esri.api.version     = 2.1.0
@@ -130,7 +124,7 @@ icons.version        = 3.0.1
 maven.repository   = ${user.home}/.m2/repository
 endorsed.classpath=
 javac.classpath=\
-    ${project.GeoAPI}/dist/geoapi.jar:\
+    ${maven.repository}/org/opengis/geoapi-pending/${geoapi.version}/geoapi-pending-${geoapi.version}.jar:\
     ${maven.repository}/javax/measure/unit-api/${jsr363.version}/unit-api-${jsr363.version}.jar:\
     ${maven.repository}/com/esri/geometry/esri-geometry-api/${esri.api.version}/esri-geometry-api-${esri.api.version}.jar:\
     ${maven.repository}/org/locationtech/jts/jts-core/${jts.version}/jts-core-${jts.version}.jar:\
@@ -148,11 +142,11 @@ javac.test.classpath=\
     ${javac.classpath}:\
     ${maven.repository}/junit/junit/${junit.version}/junit-${junit.version}.jar:\
     ${maven.repository}/org/hamcrest/hamcrest-core/${hamcrest.version}/hamcrest-core-${hamcrest.version}.jar:\
+    ${maven.repository}/org/opengis/geoapi-conformance/${geoapi.version}/geoapi-conformance-${geoapi.version}.jar:\
     ${maven.repository}/org/apache/derby/derby/${derby.version}/derby-${derby.version}.jar:\
     ${maven.repository}/org/postgresql/postgresql/${postgresql.version}/postgresql-${postgresql.version}.jar:\
     ${maven.repository}/org/hsqldb/hsqldb/${hsqldb.version}/hsqldb-${hsqldb.version}.jar:\
     ${maven.repository}/gov/nist/math/jama/${jama.version}/jama-${jama.version}.jar:\
-    ${project.GeoAPI}/dist/geoapi-tests.jar:\
     ${build.classes.dir}
 javac.test.processorpath=\
     ${javac.test.classpath}
diff --git a/ide-project/NetBeans/nbproject/project.xml b/ide-project/NetBeans/nbproject/project.xml
index 507a692..5d3865c 100644
--- a/ide-project/NetBeans/nbproject/project.xml
+++ b/ide-project/NetBeans/nbproject/project.xml
@@ -21,7 +21,7 @@
     <type>org.netbeans.modules.java.j2seproject</type>
     <configuration>
         <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
-            <name>Apache SIS on GeoAPI 4.0</name>
+            <name>Apache SIS on GeoAPI 3.1</name>
             <source-roots>
                 <root id="src.local-src.dir" name="Local sources (unversioned)"/>
                 <root id="src.webapp.dir" name="Web application"/>
@@ -67,16 +67,6 @@
                 <root id="test.gdal.dir" name="Test GDAL/Proj4"/>
             </test-roots>
         </data>
-        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
-            <reference>
-                <foreign-project>GeoAPI</foreign-project>
-                <artifact-type>jar</artifact-type>
-                <script>build.xml</script>
-                <target>jar</target>
-                <clean-target>clean</clean-target>
-                <id>jar</id>
-            </reference>
-        </references>
         <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1">
             <word>accessor</word>
             <word>bilevel</word>
diff --git a/pom.xml b/pom.xml
index e8558c9..42751f5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -514,7 +514,7 @@
     <maven.compile.target>1.8</maven.compile.target>
     <sis.plugin.version>${project.version}</sis.plugin.version>
     <sis.non-free.version>0.8</sis.non-free.version>
-    <geoapi.version>4.0-SNAPSHOT</geoapi.version>
+    <geoapi.version>3.1-SNAPSHOT</geoapi.version>
   </properties>
 
   <profiles>
diff --git a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DirectReferenceSystem.java b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DirectReferenceSystem.java
index b65a2f4..56f6759 100644
--- a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DirectReferenceSystem.java
+++ b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DirectReferenceSystem.java
@@ -18,8 +18,8 @@ package org.apache.sis.internal.profile.fra;
 
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlRootElement;
-import org.opengis.metadata.Identifier;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.jaxb.metadata.replace.ReferenceSystemMetadata;
 import org.apache.sis.util.ComparisonMode;
 
@@ -71,7 +71,7 @@ public class DirectReferenceSystem extends ReferenceSystemMetadata {
      *
      * @param  identifier  the reference system identifier.
      */
-    public DirectReferenceSystem(final Identifier identifier) {
+    public DirectReferenceSystem(final ReferenceIdentifier identifier) {
         super(identifier);
     }
 
diff --git a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/IndirectReferenceSystem.java b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/IndirectReferenceSystem.java
index a649347..17f6ba5 100644
--- a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/IndirectReferenceSystem.java
+++ b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/IndirectReferenceSystem.java
@@ -18,8 +18,8 @@ package org.apache.sis.internal.profile.fra;
 
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlRootElement;
-import org.opengis.metadata.Identifier;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.internal.jaxb.metadata.replace.ReferenceSystemMetadata;
 import org.apache.sis.util.ComparisonMode;
 
@@ -71,7 +71,7 @@ public class IndirectReferenceSystem extends ReferenceSystemMetadata {
      *
      * @param  identifier  the reference system identifier.
      */
-    public IndirectReferenceSystem(final Identifier identifier) {
+    public IndirectReferenceSystem(final ReferenceIdentifier identifier) {
         super(identifier);
     }
 
diff --git a/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java b/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java
index 3031f69..beab79f 100644
--- a/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java
+++ b/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java
@@ -18,7 +18,7 @@ package org.apache.sis.internal.profile.fra;
 
 import java.util.Collection;
 import javax.xml.bind.JAXBException;
-import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
@@ -58,7 +58,7 @@ public final strictfp class DirectReferenceSystemTest extends XMLTestCase {
     private static DefaultMetadata createMetadata(final boolean legacy) {
         final DefaultMetadata metadata = new DefaultMetadata();
         final DefaultCitation citation = new DefaultCitation("EPSG Geodetic Parameter Dataset");
-        Collection<Responsibility> r = HardCodedCitations.EPSG.getCitedResponsibleParties();
+        Collection<ResponsibleParty> r = HardCodedCitations.EPSG.getCitedResponsibleParties();
         if (legacy) {
             r = singleton(new DefaultResponsibleParty(TestUtilities.getSingleton(r)));
         }
diff --git a/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java b/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java
index 97babef..a3d4964 100644
--- a/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java
+++ b/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/PJ.java
@@ -20,9 +20,9 @@ import java.util.Objects;
 import java.io.Serializable;
 import java.io.ObjectStreamException;
 import java.io.InvalidObjectException;
-import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
+import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.GeodeticDatum;
@@ -51,7 +51,7 @@ import org.apache.sis.internal.system.OS;
  * @module
  */
 @SuppressWarnings("serial")     // serialVersionUID not needed since writeReplace() gives another kind of object.
-final class PJ implements Identifier, Serializable {
+final class PJ implements ReferenceIdentifier, Serializable {
     /**
      * Loads the {@literal Proj.4} library.
      * This static initializer may throw a {@link UnsatisfiedLinkError} if the static library can not be loaded.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
index 48d59f5..b3b6c0d 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -187,7 +187,7 @@ final class MetadataReader extends MetadataBuilder {
      * An object very similar is used as the creator. The point of contact and the creator
      * are often identical except for their role attribute.
      */
-    private transient Responsibility pointOfContact;
+    private transient ResponsibleParty pointOfContact;
 
     /**
      * Creates a new <cite>netCDF to ISO</cite> mapper for the given source.
@@ -457,7 +457,7 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
      * @see AttributeNames#CONTRIBUTOR
      * @see AttributeNames#PUBLISHER
      */
-    private Responsibility createResponsibleParty(final Responsible keys, final boolean isPointOfContact) {
+    private ResponsibleParty createResponsibleParty(final Responsible keys, final boolean isPointOfContact) {
         String individualName   = stringValue(keys.NAME);
         String organisationName = stringValue(keys.INSTITUTION);
         final String email      = stringValue(keys.EMAIL);
@@ -489,7 +489,7 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
          * Verify if we can share the existing 'pointOfContact' instance. This is often the case in practice.
          * If we can not share the whole existing instance, we usually can share parts of it like the address.
          */
-        Responsibility responsibility = pointOfContact;
+        ResponsibleParty responsibility = pointOfContact;
         Contact        contact        = null;
         Address        address        = null;
         OnlineResource resource       = null;
@@ -542,7 +542,8 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
                 if (organisationName != null) party = new DefaultOrganisation(organisationName, null, (Individual) party, null);
                 if (party            == null) party = isOrganisation(keys) ? new DefaultOrganisation() : new DefaultIndividual();
                 if (contact          != null) party.setContactInfo(singleton(contact));
-                responsibility = new DefaultResponsibility(role, null, party);
+                responsibility = new DefaultResponsibleParty(role);
+                ((DefaultResponsibleParty) responsibility).setParties(singleton(party));
             }
         }
         return responsibility;
@@ -593,7 +594,7 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
          */
         for (final String path : searchPath) {
             decoder.setSearchPath(path);
-            final Responsibility party = createResponsibleParty(CREATOR, true);
+            final ResponsibleParty party = createResponsibleParty(CREATOR, true);
             if (party != pointOfContact) {
                 addPointOfContact(party, Scope.RESOURCE);
                 if (pointOfContact == null) {
@@ -614,11 +615,11 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
         Set<InternationalString> publisher = null;
         for (final String path : searchPath) {
             decoder.setSearchPath(path);
-            final Responsibility contributor = createResponsibleParty(CONTRIBUTOR, false);
+            final ResponsibleParty contributor = createResponsibleParty(CONTRIBUTOR, false);
             if (contributor != pointOfContact) {
                 addCitedResponsibleParty(contributor, null);
             }
-            final Responsibility r = createResponsibleParty(PUBLISHER, false);
+            final ResponsibleParty r = createResponsibleParty(PUBLISHER, false);
             if (r != null) {
                 addDistributor(r);
                 /*
@@ -652,7 +653,7 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
             for (final String keyword : split(stringValue(ACCESS_CONSTRAINT))) {
                 addAccessConstraint(forCodeName(Restriction.class, keyword));
             }
-            addTopicCategory(forEnumName(TopicCategory.class, stringValue(TOPIC_CATEGORY)));
+            addTopicCategory(forCodeName(TopicCategory.class, stringValue(TOPIC_CATEGORY)));
             addSpatialRepresentation(forCodeName(SpatialRepresentationType.class, stringValue(DATA_TYPE)));
             if (!hasExtent) {
                 /*
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
index 12f9f1e..ab02e70 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
@@ -117,8 +117,10 @@ import static java.util.Collections.singleton;
 import static org.apache.sis.internal.util.StandardDateFormat.MILLISECONDS_PER_DAY;
 
 // Branch-dependent imports
+import org.opengis.metadata.citation.ResponsibleParty;
+import org.opengis.metadata.identification.CharacterSet;
 import org.opengis.feature.FeatureType;
-import org.opengis.metadata.citation.Responsibility;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
 
 
 /**
@@ -244,16 +246,16 @@ public class MetadataBuilder {
     /**
      * Part of the responsible party of the {@linkplain #citation}, or {@code null} if none.
      */
-    private DefaultResponsibility responsibility;
+    private DefaultResponsibleParty responsibility;
 
     /**
      * Creates the responsibility object if it does not already exists, then returns it.
      *
      * @return the responsibility party (never {@code null}).
      */
-    private DefaultResponsibility responsibility() {
+    private DefaultResponsibleParty responsibility() {
         if (responsibility == null) {
-            responsibility = new DefaultResponsibility();
+            responsibility = new DefaultResponsibleParty();
         }
         return responsibility;
     }
@@ -688,7 +690,7 @@ public class MetadataBuilder {
      */
     public final void newDistribution() {
         if (distribution != null) {
-            addIfNotPresent(metadata().getDistributionInfo(), distribution);
+            metadata().setDistributionInfo(distribution);
             distribution = null;
         }
     }
@@ -977,7 +979,8 @@ public class MetadataBuilder {
         if (encoding != null) {
             // No need to use 'addIfNotPresent(…)' because Charset collection is a Set by default.
             if (scope != Scope.RESOURCE) metadata().getCharacterSets().add(encoding);
-            if (scope != Scope.METADATA) identification().getCharacterSets().add(encoding);
+            if (scope != Scope.METADATA) identification().getCharacterSets().add(
+                    Types.forCodeName(CharacterSet.class, encoding.toString(), true));
         }
     }
 
@@ -1220,7 +1223,8 @@ public class MetadataBuilder {
     public final void addOtherCitationDetails(final CharSequence details) {
         final InternationalString i18n = trim(details);
         if (i18n != null) {
-            addIfNotPresent(citation().getOtherCitationDetails(), i18n);
+            final DefaultCitation citation = citation();
+            citation.setOtherCitationDetails(append(citation.getOtherCitationDetails(), i18n));
         }
     }
 
@@ -1345,10 +1349,10 @@ public class MetadataBuilder {
      * @param  party  the individual or organization that is responsible, or {@code null} for no-operation.
      * @param  role   the role to set, or {@code null} for leaving it unchanged.
      */
-    public final void addCitedResponsibleParty(Responsibility party, final Role role) {
+    public final void addCitedResponsibleParty(ResponsibleParty party, final Role role) {
         if (party != null) {
             if (role != null && !role.equals(party.getRole())) {
-                party = new DefaultResponsibility(party);
+                party = new DefaultResponsibleParty(party);
                 ((DefaultResponsibility) party).setRole(role);
             }
             addIfNotPresent(citation().getCitedResponsibleParties(), party);
@@ -1368,7 +1372,7 @@ public class MetadataBuilder {
      * @param  contact  means of communication with party associated with the resource, or {@code null} for no-operation.
      * @param  scope    whether the contact applies to data, to metadata or to both.
      */
-    public final void addPointOfContact(final Responsibility contact, final Scope scope) {
+    public final void addPointOfContact(final ResponsibleParty contact, final Scope scope) {
         ArgumentChecks.ensureNonNull("scope", scope);
         if (contact != null) {
             if (scope != Scope.RESOURCE)     addIfNotPresent(metadata().getContacts(), contact);
@@ -1386,7 +1390,7 @@ public class MetadataBuilder {
      *
      * @param  distributor  the distributor, or {@code null} for no-operation.
      */
-    public final void addDistributor(final Responsibility distributor) {
+    public final void addDistributor(final ResponsibleParty distributor) {
         if (distributor != null) {
             addIfNotPresent(distribution().getDistributors(), new DefaultDistributor(distributor));
         }
@@ -1403,9 +1407,11 @@ public class MetadataBuilder {
      * @param  credit  recognition of those who contributed to the resource, or {@code null} for no-operation.
      */
     public final void addCredits(final CharSequence credit) {
-        final InternationalString i18n = trim(credit);
-        if (i18n != null) {
-            addIfNotPresent(identification().getCredits(), i18n);
+        if (credit != null) {
+            final String c = CharSequences.trimWhitespaces(credit).toString();
+            if (!c.isEmpty()) {
+                addIfNotPresent(identification().getCredits(), c);
+            }
         }
     }
 
@@ -1588,7 +1594,8 @@ parse:      for (int i = 0; i < length;) {
                 buffer.setLength(i);
                 // Same limitation than MetadataBuilder.party().
                 final AbstractParty party = new AbstractParty(buffer, null);
-                final DefaultResponsibility r = new DefaultResponsibility(Role.OWNER, null, party);
+                final DefaultResponsibleParty r = new DefaultResponsibleParty(Role.OWNER);
+                r.setParties(Collections.singleton(party));
                 c.setCitedResponsibleParties(Collections.singleton(r));
             }
             constraints.getReferences().add(c);
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Copyright.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Copyright.java
index 3b40632..b7b275f 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Copyright.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Copyright.java
@@ -45,6 +45,7 @@ import org.apache.sis.util.iso.Types;
 // Branch-dependent imports
 import org.opengis.metadata.citation.Party;
 import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.constraint.Releasability;
 import org.opengis.metadata.maintenance.Scope;
 
@@ -432,7 +433,7 @@ resp:   for (final Responsibility r : c.getResponsibleParties()) {
      * @see #getResponsibleParties()
      */
     @Override
-    public Collection<Responsibility> getCitedResponsibleParties() {
+    public Collection<ResponsibleParty> getCitedResponsibleParties() {
         return Collections.emptySet();
     }
 
@@ -465,8 +466,8 @@ resp:   for (final Responsibility r : c.getResponsibleParties()) {
      * @return other details.
      */
     @Override
-    public Collection<InternationalString> getOtherCitationDetails() {
-        return Collections.emptySet();
+    public InternationalString getOtherCitationDetails() {
+        return null;
     }
 
     /**
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java
index bdbe53a..a885717 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java
@@ -26,9 +26,7 @@ import javax.xml.bind.annotation.XmlElement;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.OnLineFunction;
 import org.opengis.metadata.citation.OnlineResource;
-import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.internal.jaxb.Context;
-import org.apache.sis.util.iso.Types;
 
 
 /**
@@ -134,7 +132,7 @@ public final class Link implements OnlineResource {
      */
     private Link(final OnlineResource r, final Locale locale) {
         uri  = r.getLinkage();
-        text = Types.toString(r.getName(), locale);
+        text = r.getName();
     }
 
     /**
@@ -185,8 +183,8 @@ public final class Link implements OnlineResource {
      * @return name of the online resource.
      */
     @Override
-    public InternationalString getName() {
-        return (text != null) ? new SimpleInternationalString(text) : null;
+    public String getName() {
+        return text;
     }
 
     /**
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
index 01d4c9d..218778d 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
@@ -52,6 +52,7 @@ import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.iso.Types;
 
 // Branch-dependent imports
+import org.opengis.metadata.citation.ResponsibleParty;
 import org.opengis.metadata.citation.Responsibility;
 
 
@@ -319,10 +320,10 @@ public final class Metadata extends SimpleMetadata {
      * @return means of communication with person(s) and organisations(s) associated with the resource.
      */
     @Override
-    public Collection<Responsibility> getPointOfContacts() {
+    public Collection<ResponsibleParty> getPointOfContacts() {
         if (creator != null) {
             final Person p = new Person(creator);
-            return (author != null) ? UnmodifiableArrayList.wrap(new Responsibility[] {p, author})
+            return (author != null) ? UnmodifiableArrayList.wrap(new ResponsibleParty[] {p, author})
                                     : Collections.singletonList(author);
         }
         return (author != null) ? Collections.singletonList(author) : super.getPointOfContacts();
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Person.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Person.java
index 7cbad4f..3d28e83 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Person.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Person.java
@@ -16,8 +16,10 @@
  */
 package org.apache.sis.internal.storage.gpx;
 
+import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.Locale;
 import java.util.Objects;
 import javax.xml.bind.annotation.XmlElement;
@@ -35,6 +37,7 @@ import org.apache.sis.util.iso.Types;
 // Branch-dependent imports
 import org.opengis.metadata.citation.Party;
 import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.ResponsibleParty;
 
 
 /**
@@ -61,7 +64,7 @@ import org.opengis.metadata.citation.Responsibility;
  * @since   0.8
  * @module
  */
-public final class Person implements Responsibility, Party, Contact, Address {
+public final class Person implements ResponsibleParty, Party, Contact, Address {
     /**
      * Name of person or organization.
      *
@@ -186,6 +189,37 @@ public final class Person implements Responsibility, Party, Contact, Address {
     }
 
     /**
+     * ISO 19115 metadata property not specified by GPX. Actually could be the {@link #name},
+     * but we have no way to know if the author is an individual or an organization.
+     *
+     * @return name of the organization, or {@code null} if none.
+     */
+    @Override
+    public InternationalString getOrganisationName() {
+        return null;
+    }
+
+    /**
+     * ISO 19115 metadata property not specified by GPX.
+     *
+     * @return position of the individual in the organization, or {@code null} if none.
+     */
+    @Override
+    public InternationalString getPositionName() {
+        return null;
+    }
+
+    /**
+     * ISO 19115 metadata property determined by the {@link #name} field.
+     *
+     * @return name of the party, or {@code null} if none.
+     */
+    @Override
+    public String getIndividualName() {
+        return name;
+    }
+
+    /**
      * ISO 19115 metadata property determined by the {@link #email} and {@link #link} fields.
      * Invoking this method is one of the steps in the path from the {@code Responsibility} root
      * to the {@link #getElectronicMailAddresses()} and {@link #getOnlineResources()} methods.
@@ -196,8 +230,28 @@ public final class Person implements Responsibility, Party, Contact, Address {
      * @see #getOnlineResources()
      */
     @Override
-    public Collection<? extends Contact> getContactInfo() {
-        return thisOrEmpty(email != null || link != null);
+    public Proxy getContactInfo() {        // Both Contact singleton and Collection<Contact>.
+        return new Proxy();
+    }
+
+    private final class Proxy extends AbstractSet<Contact> implements Contact {
+        @Override public int size() {
+            return (email != null || link != null) ? 1 : 0;
+        }
+
+        @Override public Iterator<Contact> iterator() {
+            return Collections.<Contact>singleton(Person.this).iterator();
+        }
+
+        @Override public Collection<Telephone>         getPhones()              {return Person.this.getPhones();}
+        @Override public Telephone                     getPhone()               {return Person.this.getPhone();}
+        @Override public Collection<? extends Address> getAddresses()           {return Person.this.getAddresses();}
+        @Override public Address                       getAddress()             {return Person.this.getAddress();}
+        @Override public Collection<OnlineResource>    getOnlineResources()     {return Person.this.getOnlineResources();}
+        @Override public OnlineResource                getOnlineResource()      {return Person.this.getOnlineResource();}
+        @Override public InternationalString           getHoursOfService()      {return Person.this.getHoursOfService();}
+        @Override public InternationalString           getContactInstructions() {return Person.this.getContactInstructions();}
+        @Override public InternationalString           getContactType()         {return Person.this.getContactType();}
     }
 
 
@@ -273,8 +327,8 @@ public final class Person implements Responsibility, Party, Contact, Address {
      * @return time period when individuals can contact the organization or individual.
      */
     @Override
-    public Collection<InternationalString> getHoursOfService() {
-        return Collections.emptyList();
+    public InternationalString getHoursOfService() {
+        return null;
     }
 
     /**
@@ -309,7 +363,7 @@ public final class Person implements Responsibility, Party, Contact, Address {
      * @return address line for the location.
      */
     @Override
-    public Collection<InternationalString> getDeliveryPoints() {
+    public Collection<String> getDeliveryPoints() {
         return Collections.emptyList();
     }
 


Mime
View raw message