sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/02: Introduce a new State mode: COMPLETABLE.
Date Wed, 25 Jul 2018 17:40:06 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit 5d6255e17e80f91723734d7e92f6fc739f4e7f77
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Jul 25 19:39:32 2018 +0200

    Introduce a new State mode: COMPLETABLE.
---
 .../sis/internal/metadata/MetadataUtilities.java   | 24 ++++++-
 .../apache/sis/metadata/ModifiableMetadata.java    | 81 +++++++++++++++-------
 .../iso/DefaultApplicationSchemaInformation.java   | 14 ++--
 .../iso/DefaultExtendedElementInformation.java     | 22 +++---
 .../apache/sis/metadata/iso/DefaultIdentifier.java | 10 +--
 .../apache/sis/metadata/iso/DefaultMetadata.java   | 21 +++---
 .../iso/DefaultMetadataExtensionInformation.java   |  4 +-
 .../sis/metadata/iso/DefaultMetadataScope.java     |  4 +-
 .../org/apache/sis/metadata/iso/ISOMetadata.java   |  2 +-
 .../acquisition/DefaultAcquisitionInformation.java |  2 +-
 .../acquisition/DefaultEnvironmentalRecord.java    |  8 +--
 .../sis/metadata/iso/acquisition/DefaultEvent.java |  8 +--
 .../iso/acquisition/DefaultInstrument.java         |  6 +-
 .../metadata/iso/acquisition/DefaultObjective.java |  2 +-
 .../metadata/iso/acquisition/DefaultOperation.java | 12 ++--
 .../sis/metadata/iso/acquisition/DefaultPlan.java  |  6 +-
 .../metadata/iso/acquisition/DefaultPlatform.java  |  4 +-
 .../iso/acquisition/DefaultPlatformPass.java       |  2 +-
 .../iso/acquisition/DefaultRequestedDate.java      |  5 +-
 .../iso/acquisition/DefaultRequirement.java        |  9 +--
 .../sis/metadata/iso/citation/AbstractParty.java   |  2 +-
 .../sis/metadata/iso/citation/DefaultAddress.java  |  8 +--
 .../sis/metadata/iso/citation/DefaultCitation.java | 26 ++++---
 .../metadata/iso/citation/DefaultCitationDate.java |  5 +-
 .../sis/metadata/iso/citation/DefaultContact.java  |  4 +-
 .../metadata/iso/citation/DefaultIndividual.java   |  2 +-
 .../iso/citation/DefaultOnlineResource.java        | 14 ++--
 .../iso/citation/DefaultResponsibility.java        |  2 +-
 .../iso/citation/DefaultResponsibleParty.java      |  4 +-
 .../sis/metadata/iso/citation/DefaultSeries.java   |  6 +-
 .../metadata/iso/citation/DefaultTelephone.java    |  4 +-
 .../iso/constraint/DefaultConstraints.java         |  4 +-
 .../iso/constraint/DefaultReleasability.java       |  2 +-
 .../iso/constraint/DefaultSecurityConstraints.java |  8 +--
 .../sis/metadata/iso/content/DefaultBand.java      | 16 ++---
 .../iso/content/DefaultCoverageDescription.java    |  8 +--
 .../DefaultFeatureCatalogueDescription.java        |  6 +-
 .../iso/content/DefaultFeatureTypeInfo.java        |  4 +-
 .../iso/content/DefaultImageDescription.java       | 22 +++---
 .../iso/content/DefaultRangeDimension.java         |  4 +-
 .../content/DefaultRangeElementDescription.java    |  4 +-
 .../iso/content/DefaultSampleDimension.java        | 26 +++----
 .../metadata/iso/distribution/DefaultDataFile.java |  8 +--
 .../DefaultDigitalTransferOptions.java             |  6 +-
 .../iso/distribution/DefaultDistribution.java      |  2 +-
 .../iso/distribution/DefaultDistributor.java       |  2 +-
 .../metadata/iso/distribution/DefaultFormat.java   | 12 ++--
 .../metadata/iso/distribution/DefaultMedium.java   | 10 +--
 .../distribution/DefaultStandardOrderProcess.java  | 14 ++--
 .../iso/extent/AbstractGeographicExtent.java       |  2 +-
 .../sis/metadata/iso/extent/DefaultExtent.java     | 15 +++-
 .../iso/extent/DefaultGeographicBoundingBox.java   | 34 +++++----
 .../iso/extent/DefaultGeographicDescription.java   |  2 +-
 .../iso/extent/DefaultSpatialTemporalExtent.java   |  4 +-
 .../metadata/iso/extent/DefaultTemporalExtent.java |  6 +-
 .../metadata/iso/extent/DefaultVerticalExtent.java | 18 +++--
 .../iso/identification/AbstractIdentification.java |  8 +--
 .../DefaultAggregateInformation.java               |  2 +-
 .../identification/DefaultAssociatedResource.java  |  8 +--
 .../iso/identification/DefaultBrowseGraphic.java   |  6 +-
 .../iso/identification/DefaultCoupledResource.java |  8 +--
 .../identification/DefaultDataIdentification.java  |  4 +-
 .../iso/identification/DefaultKeywordClass.java    |  6 +-
 .../iso/identification/DefaultKeywords.java        |  6 +-
 .../DefaultOperationChainMetadata.java             |  4 +-
 .../identification/DefaultOperationMetadata.java   |  6 +-
 .../iso/identification/DefaultResolution.java      |  2 +-
 .../DefaultServiceIdentification.java              |  6 +-
 .../metadata/iso/identification/DefaultUsage.java  |  9 +--
 .../sis/metadata/iso/lineage/DefaultAlgorithm.java |  4 +-
 .../sis/metadata/iso/lineage/DefaultLineage.java   |  4 +-
 .../iso/lineage/DefaultNominalResolution.java      |  4 +-
 .../metadata/iso/lineage/DefaultProcessStep.java   | 10 +--
 .../iso/lineage/DefaultProcessStepReport.java      |  6 +-
 .../metadata/iso/lineage/DefaultProcessing.java    |  4 +-
 .../sis/metadata/iso/lineage/DefaultSource.java    | 18 ++---
 .../maintenance/DefaultMaintenanceInformation.java | 10 +--
 .../sis/metadata/iso/maintenance/DefaultScope.java |  2 +-
 .../iso/maintenance/DefaultScopeDescription.java   |  4 +-
 .../sis/metadata/iso/quality/AbstractElement.java  | 12 ++--
 .../iso/quality/DefaultConformanceResult.java      |  6 +-
 .../iso/quality/DefaultCoverageResult.java         | 10 +--
 .../metadata/iso/quality/DefaultDataQuality.java   |  4 +-
 .../iso/quality/DefaultQuantitativeResult.java     |  6 +-
 .../sis/metadata/iso/spatial/DefaultDimension.java | 12 ++--
 .../sis/metadata/iso/spatial/DefaultGCP.java       |  2 +-
 .../metadata/iso/spatial/DefaultGCPCollection.java |  6 +-
 .../iso/spatial/DefaultGeometricObjects.java       |  4 +-
 .../metadata/iso/spatial/DefaultGeorectified.java  | 10 +--
 .../iso/spatial/DefaultGeoreferenceable.java       |  8 +--
 .../spatial/DefaultGridSpatialRepresentation.java  | 17 +++--
 .../DefaultVectorSpatialRepresentation.java        |  2 +-
 .../apache/sis/metadata/sql/MetadataFallback.java  |  8 ++-
 93 files changed, 455 insertions(+), 355 deletions(-)

diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataUtilities.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataUtilities.java
index 972ce6c..3843385 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataUtilities.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataUtilities.java
@@ -31,7 +31,7 @@ import org.apache.sis.internal.util.Utilities;
  * Miscellaneous utility methods for metadata.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.3
  * @module
  *
@@ -68,6 +68,28 @@ public final class MetadataUtilities extends Static {
     }
 
     /**
+     * Returns {@link Boolean#TRUE} if the given value is a valid date, or {@code null} otherwise.
+     * This method is used for calls to {@code checkWritePermission(Object)}. The use of a boolean
+     * as return type is for avoiding to create new {@link Date} instances.
+     *
+     * @param  value  the time in milliseconds.
+     * @return {@code Boolean.TRUE} if the given value is a valid date.
+     */
+    public static Boolean isDateDefined(final long value) {
+        return (value != Long.MIN_VALUE) ? Boolean.TRUE : null;
+    }
+
+    /**
+     * Returns {@link Boolean#TRUE} if the given value is a valid double, or {@code null} if NaN.
+     *
+     * @param  value  the numeric value.
+     * @return {@code Boolean.TRUE} if the given value is non-NaN.
+     */
+    public static Boolean isDefined(final double value) {
+        return Double.isNaN(value) ? null : Boolean.TRUE;
+    }
+
+    /**
      * Ensures that the given property value is positive. If the user gave a negative value or (in some case) zero,
      * then this method logs a warning if we are in process of (un)marshalling a XML document or throw an exception
      * otherwise.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
index ceecee1..538ba9b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
@@ -98,9 +98,10 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
     private static final byte EDITABLE = 0;
 
     /**
-     * A bitmask for {@link #state} meaning that {@code apply(State.FINAL)} has been invoked.
+     * The {@link #state} value meaning that missing properties can be set,
+     * but no existing properties can be modified (including collections).
      */
-    private static final byte FINAL = 1;
+    private static final byte COMPLETABLE = 1;
 
     /**
      * See https://issues.apache.org/jira/browse/SIS-81 - not yet committed.
@@ -109,8 +110,15 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
 
     /**
      * A value for {@link #state} meaning that execution of {@code apply(State.FINAL)} is in progress.
+     * Must be greater than all other values except {@link #FINAL}.
      */
-    private static final byte FREEZING = FINAL | STAGED;
+    private static final byte FREEZING = 3;
+
+    /**
+     * A value for {@link #state} meaning that {@code apply(State.FINAL)} has been invoked.
+     * Must be greater than all other values.
+     */
+    private static final byte FINAL = 4;
 
     /**
      * Whether this metadata has been made unmodifiable, as one of {@link #EDITABLE}, {@link #FREEZING}
@@ -163,6 +171,12 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
         EDITABLE,
 
         /**
+         * The metadata allows missing values to be set, but does not allow existing values to be modified.
+         * This state is not appendable, i.e. it does not allow adding elements in a collection.
+         */
+        COMPLETABLE,
+
+        /**
          * The metadata is unmodifiable.
          * When a metadata is final, it can not be moved back to an editable state
          * (but it is still possible to create a modifiable copy with {@link MetadataCopier}).
@@ -176,12 +190,13 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
          * A mapping exists because {@code ModifiableMetadata} does not use the same set of enumeration values
          * (e.g. it has an internal {@link #FREEZING} value), and because future versions may use a bitmask.
          */
-        private static final State[] VALUES = new State[ModifiableMetadata.FREEZING + 1];
+        private static final State[] VALUES = new State[ModifiableMetadata.FINAL + 1];
         static {
-            VALUES[ModifiableMetadata.EDITABLE] = EDITABLE;
-            VALUES[ModifiableMetadata.STAGED]   = EDITABLE;
-            VALUES[ModifiableMetadata.FREEZING] = FINAL;
-            VALUES[ModifiableMetadata.FINAL]    = FINAL;
+            VALUES[ModifiableMetadata.EDITABLE]    = EDITABLE;
+            VALUES[ModifiableMetadata.COMPLETABLE] = COMPLETABLE;
+            VALUES[ModifiableMetadata.STAGED]      = EDITABLE;
+            VALUES[ModifiableMetadata.FREEZING]    = FINAL;
+            VALUES[ModifiableMetadata.FINAL]       = FINAL;
         }
     }
 
@@ -246,11 +261,11 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
     public boolean transition(final State target) {
         switch (target) {
             case EDITABLE: {
-                if ((state & FINAL) == 0) break;
+                if (state == EDITABLE) break;
                 throw new UnmodifiableMetadataException(Errors.format(Errors.Keys.UnmodifiableMetadata));
             }
             case FINAL: {
-                if ((state & FINAL) != 0) break;
+                if (state >= FREEZING) break;
                 byte result = state;
                 try {
                     state = FREEZING;
@@ -279,7 +294,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
      */
     @Deprecated
     public final boolean isModifiable() {
-        return (state & FINAL) == 0;
+        return state < FREEZING;
     }
 
     /**
@@ -317,7 +332,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
      */
     @Deprecated
     public AbstractMetadata unmodifiable() {
-        if ((state & FINAL) != 0) {
+        if (!isModifiable()) {
             unmodifiable = this;
         }
         /*
@@ -358,13 +373,11 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
     }
 
     /**
-     * Checks if changes in the metadata are allowed. All {@code setFoo(…)} methods in subclasses
-     * shall invoke this method (directly or indirectly) before to apply any change.
+     * @deprecated Replaced by {@link #checkWritePermission(Object)}.
      *
      * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
-     *
-     * @see #state()
      */
+    @Deprecated
     protected void checkWritePermission() throws UnmodifiableMetadataException {
         if (state == FINAL) {
             throw new UnmodifiableMetadataException(Errors.format(Errors.Keys.UnmodifiableMetadata));
@@ -374,11 +387,29 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
     }
 
     /**
+     * Checks if changes in the metadata are allowed. All {@code setFoo(…)} methods in subclasses
+     * shall invoke this method (directly or indirectly) before to apply any change.
+     * The current property value should be specified in argument.
+     *
+     * @param  current  the current value, or {@code null} if none.
+     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
+     *
+     * @see #state()
+     */
+    protected void checkWritePermission(final Object current) throws UnmodifiableMetadataException {
+        if (state != COMPLETABLE) {
+            checkWritePermission();
+        } else if (current != null) {
+            throw new UnmodifiableMetadataException(Errors.format(Errors.Keys.UnmodifiableMetadata));
+        }
+    }
+
+    /**
      * Writes the content of the {@code source} collection into the {@code target} list,
      * creating it if needed. This method performs the following steps:
      *
      * <ul>
-     *   <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is modifiable.</li>
+     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
      *   <li>If {@code source} is null or empty, returns {@code null}
      *       (meaning that the metadata property is not provided).</li>
      *   <li>If {@code target} is null, creates a new {@link List}.</li>
@@ -405,7 +436,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
             if (state == FREEZING) {
                 return (List<E>) source;
             }
-            checkWritePermission();
+            checkWritePermission(target);
             if (isNullOrEmpty(source)) {
                 target = null;
             } else {
@@ -425,7 +456,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
      * creating it if needed. This method performs the following steps:
      *
      * <ul>
-     *   <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is modifiable.</li>
+     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
      *   <li>If {@code source} is null or empty, returns {@code null}
      *       (meaning that the metadata property is not provided).</li>
      *   <li>If {@code target} is null, creates a new {@link Set}.</li>
@@ -452,7 +483,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
             if (state == FREEZING) {
                 return (Set<E>) source;
             }
-            checkWritePermission();
+            checkWritePermission(target);
             if (isNullOrEmpty(source)) {
                 target = null;
             } else {
@@ -472,7 +503,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
      * creating it if needed. This method performs the following steps:
      *
      * <ul>
-     *   <li>Invokes {@link #checkWritePermission()} in order to ensure that this metadata is modifiable.</li>
+     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
      *   <li>If {@code source} is null or empty, returns {@code null}
      *       (meaning that the metadata property is not provided).</li>
      *   <li>If {@code target} is null, creates a new {@link Set} or a new {@link List}
@@ -515,7 +546,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
                 assert collectionType(elementType).isInstance(source);
                 return (Collection<E>) source;
             }
-            checkWritePermission();
+            checkWritePermission(target);
             if (isNullOrEmpty(source)) {
                 target = null;
             } else {
@@ -658,7 +689,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
         if (emptyCollectionAsNull()) {
             return null;
         }
-        if ((state & FINAL) == 0) {
+        if (state < FREEZING) {
             /*
              * Do not specify an initial capacity, because the list will stay empty in a majority of cases
              * (i.e. the users will want to iterate over the list elements more often than they will want
@@ -687,7 +718,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
         if (emptyCollectionAsNull()) {
             return null;
         }
-        if ((state & FINAL) == 0) {
+        if (state < FREEZING) {
             return createSet(elementType, INITIAL_CAPACITY);
         }
         return Collections.emptySet();
@@ -717,7 +748,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
         if (emptyCollectionAsNull()) {
             return null;
         }
-        final boolean isModifiable = (state & FINAL) == 0;
+        final boolean isModifiable = (state < FREEZING);
         if (useSet(elementType)) {
             if (isModifiable) {
                 return createSet(elementType, INITIAL_CAPACITY);
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 56d30d9..14bcb47 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
@@ -193,7 +193,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new name.
      */
     public void setName(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -214,7 +214,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new schema language.
      */
     public void setSchemaLanguage(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(schemaLanguage);
         schemaLanguage = newValue;
     }
 
@@ -235,7 +235,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new constraint language.
      */
     public void setConstraintLanguage(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(constraintLanguage);
         constraintLanguage = newValue;
     }
 
@@ -257,7 +257,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new ASCII file.
      */
     public void setSchemaAscii(final CharSequence newValue) {
-        checkWritePermission();
+        checkWritePermission(schemaAscii);
         schemaAscii = newValue;
     }
 
@@ -279,7 +279,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new graphics file.
      */
     public void setGraphicsFile(final OnlineResource newValue) {
-        checkWritePermission();
+        checkWritePermission(graphicsFile);
         graphicsFile = newValue;
     }
 
@@ -301,7 +301,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new software development file.
      */
     public void setSoftwareDevelopmentFile(final OnlineResource newValue) {
-        checkWritePermission();
+        checkWritePermission(softwareDevelopmentFile);
         softwareDevelopmentFile = newValue;
     }
 
@@ -322,7 +322,7 @@ public class DefaultApplicationSchemaInformation extends ISOMetadata implements
      * @param  newValue  the new software development file format.
      */
     public void setSoftwareDevelopmentFileFormat(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(softwareDevelopmentFileFormat);
         softwareDevelopmentFileFormat = 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 56cbf06..450c8d8 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
@@ -294,7 +294,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new name.
      */
     public void setName(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -321,7 +321,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      */
     @Deprecated
     public void setShortName(final String newValue)  {
-        checkWritePermission();
+        checkWritePermission(shortName);
         shortName = newValue;
     }
 
@@ -350,7 +350,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      */
     @Deprecated
     public void setDomainCode(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(domainCode);
         domainCode = newValue;
     }
 
@@ -371,7 +371,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new definition.
      */
     public void setDefinition(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(definition);
         definition = newValue;
     }
 
@@ -392,7 +392,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new obligation.
      */
     public void setObligation(final Obligation newValue)  {
-        checkWritePermission();
+        checkWritePermission(obligation);
         obligation = newValue;
     }
 
@@ -415,7 +415,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new condition.
      */
     public void setCondition(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(condition);
         condition = newValue;
     }
 
@@ -436,7 +436,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new data type.
      */
     public void setDataType(final Datatype newValue) {
-        checkWritePermission();
+        checkWritePermission(dataType);
         dataType = newValue;
     }
 
@@ -462,7 +462,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setMaximumOccurrence(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(maximumOccurrence);
         if (ensurePositive(DefaultExtendedElementInformation.class, "maximumOccurrence", false, newValue)) {
             maximumOccurrence = newValue;
         }
@@ -489,7 +489,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new domain value.
      */
     public void setDomainValue(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(domainValue);
         domainValue = newValue;
     }
 
@@ -531,7 +531,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @param  newValue  the new rule.
      */
     public void setRule(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(rule);
         rule = newValue;
     }
 
@@ -556,7 +556,7 @@ public class DefaultExtendedElementInformation extends ISOMetadata implements Ex
      * @since 0.5
      */
     public void setRationale(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(rationale);
         rationale = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
index 6ba134a..c1ca67d 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
@@ -251,7 +251,7 @@ public class DefaultIdentifier extends ISOMetadata implements Identifier {
      * @param  newValue  the new authority.
      */
     public void setAuthority(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(authority);
         authority = newValue;
     }
 
@@ -279,7 +279,7 @@ public class DefaultIdentifier extends ISOMetadata implements Identifier {
      * @param  newValue  the new code, or {@code null}.
      */
     public void setCode(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(code);
         code = newValue;
     }
 
@@ -307,7 +307,7 @@ public class DefaultIdentifier extends ISOMetadata implements Identifier {
      * @since 0.5
      */
     public void setCodeSpace(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(codeSpace);
         codeSpace = newValue;
     }
 
@@ -332,7 +332,7 @@ public class DefaultIdentifier extends ISOMetadata implements Identifier {
      * @param  newValue  the new version, or {@code null} if none.
      */
     public void setVersion(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(version);
         version = newValue;
     }
 
@@ -359,7 +359,7 @@ public class DefaultIdentifier extends ISOMetadata implements Identifier {
      * @since 0.5
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 }
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 6635325..bc0e1f8 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
@@ -545,7 +545,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setLanguage(final Locale newValue) {
-        checkWritePermission();
+        checkWritePermission(languages);
         setDefaultLocale(newValue);
     }
 
@@ -573,7 +573,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setLocales(final Collection<? extends Locale> newValues) {
-        checkWritePermission();
+        checkWritePermission(languages);
         setOtherLocales(newValues);
     }
 
@@ -684,7 +684,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      * @since 0.5
      */
     public void setParentMetadata(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(parentMetadata);
         parentMetadata = newValue;
     }
 
@@ -721,7 +721,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setParentIdentifier(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(parentMetadata);
         // See "Note about deprecated methods implementation"
         DefaultCitation parent = DefaultCitation.castOrCopy(parentMetadata);
         if (parent == null) {
@@ -801,7 +801,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setHierarchyLevels(final Collection<? extends ScopeCode> newValues) {
-        checkWritePermission();
+        checkWritePermission(metadataScopes);
         ((LegacyPropertyAdapter<ScopeCode,?>) getHierarchyLevels()).setValues(newValues);
     }
 
@@ -852,7 +852,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setHierarchyLevelNames(final Collection<? extends String> newValues) {
-        checkWritePermission();
+        checkWritePermission(metadataScopes);
         ((LegacyPropertyAdapter<String,?>) getHierarchyLevelNames()).setValues(newValues);
     }
 
@@ -873,7 +873,6 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      * @param  newValues  the new contacts.
      */
     public void setContacts(final Collection<? extends Responsibility> newValues) {
-        checkWritePermission();
         contacts = writeCollection(newValues, contacts, Responsibility.class);
     }
 
@@ -938,7 +937,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      */
     @Deprecated
     public void setDateStamp(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(dateInfo);
         Collection<CitationDate> newValues = dateInfo;      // See "Note about deprecated methods implementation"
         if (newValues == null) {
             if (newValue == null) {
@@ -1071,7 +1070,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      * {@link #setMetadataStandardVersion(String)} methods.
      */
     private void setMetadataStandard(final boolean version, final String newValue) {
-        checkWritePermission();
+        checkWritePermission(metadataStandards);
         final InternationalString i18n = (newValue != null) ? new SimpleInternationalString(newValue) : null;
         final List<Citation> newValues = (metadataStandards != null)
                 ? new ArrayList<>(metadataStandards)
@@ -1229,7 +1228,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
     @Deprecated
     public void setDataSetUri(final String newValue) throws URISyntaxException {
         final URI uri = new URI(newValue);
-        checkWritePermission();
+        checkWritePermission(identificationInfo);
         Collection<Identification> info = identificationInfo; // See "Note about deprecated methods implementation"
         AbstractIdentification firstId = AbstractIdentification.castOrCopy(CollectionsExt.first(info));
         if (firstId == null) {
@@ -1499,7 +1498,7 @@ public class DefaultMetadata extends ISOMetadata implements Metadata {
      * @see org.apache.sis.metadata.iso.identification.AbstractIdentification#setResourceMaintenances(Collection)
      */
     public void setMetadataMaintenance(final MaintenanceInformation newValue) {
-        checkWritePermission();
+        checkWritePermission(metadataMaintenance);
         metadataMaintenance = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataExtensionInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataExtensionInformation.java
index 14f74b4..b5b7366 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataExtensionInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataExtensionInformation.java
@@ -135,8 +135,8 @@ public class DefaultMetadataExtensionInformation extends ISOMetadata implements
      * @param  newValue  the new extension online resource.
      */
     public void setExtensionOnLineResource(final OnlineResource newValue) {
-        checkWritePermission();
-        this.extensionOnLineResource = newValue;
+        checkWritePermission(extensionOnLineResource);
+        extensionOnLineResource = newValue;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataScope.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataScope.java
index 7236046..1e0a4dd 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataScope.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadataScope.java
@@ -144,7 +144,7 @@ public class DefaultMetadataScope extends ISOMetadata implements MetadataScope {
      * @param  newValue  the new code for the scope.
      */
     public void setResourceScope(final ScopeCode newValue) {
-        checkWritePermission();
+        checkWritePermission(resourceScope);
         resourceScope = newValue;
     }
 
@@ -165,7 +165,7 @@ public class DefaultMetadataScope extends ISOMetadata implements MetadataScope {
      * @param  newValue  the new description of the scope.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java
index 45ccb67..77408e3 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ISOMetadata.java
@@ -206,7 +206,7 @@ public class ISOMetadata extends ModifiableMetadata implements IdentifiedObject,
      * @since 1.0
      */
     protected void setIdentifier(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(identifiers);
         identifiers = nonNullCollection(identifiers, Identifier.class);
         identifiers = writeCollection(NonMarshalledAuthority.setMarshallable(identifiers, newValue), identifiers, Identifier.class);
     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultAcquisitionInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultAcquisitionInformation.java
index e5e646c..c260bd7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultAcquisitionInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultAcquisitionInformation.java
@@ -212,7 +212,7 @@ public class DefaultAcquisitionInformation extends ISOMetadata implements Acquis
      * @param  newValue  the new environmental record value.
      */
     public void setEnvironmentalConditions(final EnvironmentalRecord newValue) {
-        checkWritePermission();
+        checkWritePermission(environmentalConditions);
         environmentalConditions = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEnvironmentalRecord.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEnvironmentalRecord.java
index abe4cef..97b1cec 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEnvironmentalRecord.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEnvironmentalRecord.java
@@ -159,7 +159,7 @@ public class DefaultEnvironmentalRecord extends ISOMetadata implements Environme
      * @param  newValue  the new average air temperature value.
      */
     public void setAverageAirTemperature(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(averageAirTemperature);
         averageAirTemperature = newValue;
     }
 
@@ -182,7 +182,7 @@ public class DefaultEnvironmentalRecord extends ISOMetadata implements Environme
      * @throws IllegalArgumentException if the given value is out of range.
      */
     public void setMaxRelativeHumidity(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(maxRelativeHumidity);
         if (ensureInRange(DefaultEnvironmentalRecord.class, "maxRelativeHumidity", 0, 100, newValue)) {
             maxRelativeHumidity = newValue;
         }
@@ -205,7 +205,7 @@ public class DefaultEnvironmentalRecord extends ISOMetadata implements Environme
      * @param  newValue  the new maximum altitude value.
      */
     public void setMaxAltitude(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(maxAltitude);
         maxAltitude = newValue;
     }
 
@@ -226,7 +226,7 @@ public class DefaultEnvironmentalRecord extends ISOMetadata implements Environme
      * @param  newValue  the meteorological conditions value.
      */
     public void setMeteorologicalConditions(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(meteorologicalConditions);
         meteorologicalConditions = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
index b1ffe20..d75389d 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
@@ -206,7 +206,7 @@ public class DefaultEvent extends ISOMetadata implements Event {
      * @param  newValue  the new trigger value.
      */
     public void setTrigger(final Trigger newValue) {
-        checkWritePermission();
+        checkWritePermission(trigger);
         trigger = newValue;
     }
 
@@ -227,7 +227,7 @@ public class DefaultEvent extends ISOMetadata implements Event {
      * @param  newValue  the new context value.
      */
     public void setContext(final Context newValue) {
-        checkWritePermission();
+        checkWritePermission(context);
         context = newValue;
     }
 
@@ -248,7 +248,7 @@ public class DefaultEvent extends ISOMetadata implements Event {
      * @param  newValue  the new sequence value.
      */
     public void setSequence(final Sequence newValue) {
-        checkWritePermission();
+        checkWritePermission(sequence);
         sequence = newValue;
     }
 
@@ -269,7 +269,7 @@ public class DefaultEvent extends ISOMetadata implements Event {
      * @param  newValue  the new time value.
      */
     public void setTime(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(time);
         time = toMilliseconds(newValue);
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultInstrument.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultInstrument.java
index 9ef0545..b9a49b6 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultInstrument.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultInstrument.java
@@ -195,7 +195,7 @@ public class DefaultInstrument extends ISOMetadata implements Instrument {
      * @param  newValue  the new type value.
      */
     public void setType(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(type);
         type = newValue;
     }
 
@@ -216,7 +216,7 @@ public class DefaultInstrument extends ISOMetadata implements Instrument {
      * @param  newValue  the new description value.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -237,7 +237,7 @@ public class DefaultInstrument extends ISOMetadata implements Instrument {
      * @param  newValue  the new platform value.
      */
     public void setMountedOn(final Platform newValue) {
-        checkWritePermission();
+        checkWritePermission(mountedOn);
         mountedOn = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultObjective.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultObjective.java
index e51360e..d4a4bf6 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultObjective.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultObjective.java
@@ -220,7 +220,7 @@ public class DefaultObjective extends ISOMetadata implements Objective {
      * @param  newValue  the new priority value.
      */
     public void setPriority(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(priority);
         priority = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultOperation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultOperation.java
index 425d859..2800bc6 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultOperation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultOperation.java
@@ -204,7 +204,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new description value.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -225,7 +225,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new citation value.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
@@ -267,7 +267,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new status value.
      */
     public void setStatus(final Progress newValue) {
-        checkWritePermission();
+        checkWritePermission(status);
         status = newValue;
     }
 
@@ -288,7 +288,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new type value.
      */
     public void setType(final OperationType newValue) {
-        checkWritePermission();
+        checkWritePermission(type);
         type = newValue;
     }
 
@@ -349,7 +349,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new parent operation value.
      */
     public void setParentOperation(final Operation newValue) {
-        checkWritePermission();
+        checkWritePermission(parentOperation);
         parentOperation = newValue;
     }
 
@@ -370,7 +370,7 @@ public class DefaultOperation extends ISOMetadata implements Operation {
      * @param  newValue  the new plan value.
      */
     public void setPlan(final Plan newValue) {
-        checkWritePermission();
+        checkWritePermission(plan);
         plan = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlan.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlan.java
index 30311bf..23a4dd1 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlan.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlan.java
@@ -163,7 +163,7 @@ public class DefaultPlan extends ISOMetadata implements Plan {
      * @param  newValue  the new type value.
      */
     public void setType(final GeometryType newValue) {
-        checkWritePermission();
+        checkWritePermission(type);
         type = newValue;
     }
 
@@ -184,7 +184,7 @@ public class DefaultPlan extends ISOMetadata implements Plan {
      * @param  newValue  the new status value.
      */
     public void setStatus(final Progress newValue) {
-        checkWritePermission();
+        checkWritePermission(status);
         status = newValue;
     }
 
@@ -205,7 +205,7 @@ public class DefaultPlan extends ISOMetadata implements Plan {
      * @param  newValue  the new citation value.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
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 34bed9c..6fae5c8 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
@@ -158,7 +158,7 @@ public class DefaultPlatform extends ISOMetadata implements Platform {
      * @param  newValue  the new citation value.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
@@ -200,7 +200,7 @@ public class DefaultPlatform extends ISOMetadata implements Platform {
      * @param  newValue  the new description value.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatformPass.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatformPass.java
index 78a128a..8a05d43 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatformPass.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultPlatformPass.java
@@ -159,7 +159,7 @@ public class DefaultPlatformPass extends ISOMetadata implements PlatformPass {
      * @param  newValue  the new extent value.
      */
     public void setExtent(final Geometry newValue) {
-        checkWritePermission();
+        checkWritePermission(extent);
         extent = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
index 13bb801..661d337 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
@@ -25,6 +25,7 @@ import org.apache.sis.metadata.iso.ISOMetadata;
 
 import static org.apache.sis.internal.metadata.MetadataUtilities.toDate;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toMilliseconds;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDateDefined;
 
 
 /**
@@ -138,7 +139,7 @@ public class DefaultRequestedDate extends ISOMetadata implements RequestedDate {
      * @param  newValue  the new requested date of collection value.
      */
     public void setRequestedDateOfCollection(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(requestedDateOfCollection));
         requestedDateOfCollection = toMilliseconds(newValue);
     }
 
@@ -159,7 +160,7 @@ public class DefaultRequestedDate extends ISOMetadata implements RequestedDate {
      * @param  newValue  the new latest acceptable data value.
      */
     public void setLatestAcceptableDate(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(latestAcceptableDate));
         latestAcceptableDate = toMilliseconds(newValue);
     }
 }
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 f7bbc0b..e83040b 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
@@ -32,6 +32,7 @@ import org.apache.sis.metadata.iso.ISOMetadata;
 
 import static org.apache.sis.internal.metadata.MetadataUtilities.toDate;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toMilliseconds;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDateDefined;
 
 
 /**
@@ -193,7 +194,7 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
      * @param  newValue  the new citation value.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
@@ -275,7 +276,7 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
      * @param  newValue  the new priority value.
      */
     public void setPriority(final Priority newValue) {
-        checkWritePermission();
+        checkWritePermission(priority);
         priority = newValue;
     }
 
@@ -296,7 +297,7 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
      * @param  newValue  the new requested date value.
      */
     public void setRequestedDate(final RequestedDate newValue) {
-        checkWritePermission();
+        checkWritePermission(requestedDate);
         requestedDate = newValue;
     }
 
@@ -317,7 +318,7 @@ public class DefaultRequirement extends ISOMetadata implements Requirement {
      * @param  newValue  the new expiry date.
      */
     public void setExpiryDate(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(expiryDate));
         expiryDate = toMilliseconds(newValue);
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/AbstractParty.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/AbstractParty.java
index 2d1fef8..2bb73c7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/AbstractParty.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/AbstractParty.java
@@ -166,7 +166,7 @@ public class AbstractParty extends ISOMetadata implements Party {
      * @param  newValue  the new name of the party.
      */
     public void setName(final InternationalString newValue) {
-       checkWritePermission();
+       checkWritePermission(name);
        name = newValue;
     }
 
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 72ba588..98e3be8 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
@@ -158,7 +158,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
      * @param  newValue  the new administrative area.
      */
     public void setAdministrativeArea(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(administrativeArea);
         administrativeArea = newValue;
     }
 
@@ -179,7 +179,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
      * @param  newValue  the new city, or {@code null} if none.
      */
     public void setCity(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(city);
         city = newValue;
     }
 
@@ -200,7 +200,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
      * @param  newValue  the new country, or {@code null} if none.
      */
     public void setCountry(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(country);
         country = newValue;
     }
 
@@ -261,7 +261,7 @@ public class DefaultAddress extends ISOMetadata implements Address {
      * @param  newValue  the new postal code, or {@code null} if none.
      */
     public void setPostalCode(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(postalCode);
         postalCode = newValue;
     }
 }
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 f9fd71e..4608e1a 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
@@ -42,6 +42,7 @@ import org.apache.sis.xml.IdentifierMap;
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toDate;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toMilliseconds;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDateDefined;
 
 
 /**
@@ -264,7 +265,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @param  newValue  the new title, or {@code null} if none.
      */
     public void setTitle(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(title);
         title = newValue;
     }
 
@@ -327,7 +328,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @param  newValue  the new edition, or {@code null} if none.
      */
     public void setEdition(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(edition);
         edition = newValue;
     }
 
@@ -348,7 +349,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @param  newValue  the new edition date, or {@code null} if none.
      */
     public void setEditionDate(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(editionDate));
         editionDate = toMilliseconds(newValue);
     }
 
@@ -456,7 +457,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @param  newValue  the new series.
      */
     public void setSeries(final Series newValue) {
-        checkWritePermission();
+        checkWritePermission(series);
         series = newValue;
     }
 
@@ -504,11 +505,18 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      */
     @Deprecated
     public void setCollectiveTitle(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(collectiveTitle);
         collectiveTitle = newValue;
     }
 
     /**
+     * Returns the ISBN or ISSN identifier for the given authority, or {@code null} if none.
+     */
+    private String getIdentifier(final Citation authority) {
+        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(authority);
+    }
+
+    /**
      * Returns the International Standard Book Number.
      * In this SIS implementation, invoking this method is equivalent to:
      *
@@ -524,7 +532,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
     @Override
     @XmlElement(name = "ISBN")
     public String getISBN() {
-        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(Citations.ISBN);
+        return getIdentifier(Citations.ISBN);
     }
 
     /**
@@ -541,7 +549,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @see Citations#ISBN
      */
     public void setISBN(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(getIdentifier(Citations.ISBN));
         if (newValue != null || !isNullOrEmpty(identifiers)) {
             getIdentifierMap().putSpecialized(Citations.ISBN, newValue);
         }
@@ -563,7 +571,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
     @Override
     @XmlElement(name = "ISSN")
     public String getISSN() {
-        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(Citations.ISSN);
+        return getIdentifier(Citations.ISSN);
     }
 
     /**
@@ -580,7 +588,7 @@ public class DefaultCitation extends ISOMetadata implements Citation {
      * @see Citations#ISSN
      */
     public void setISSN(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(getIdentifier(Citations.ISSN));
         if (newValue != null || !isNullOrEmpty(identifiers)) {
             getIdentifierMap().putSpecialized(Citations.ISSN, newValue);
         }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
index f863b29..a88c98a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
@@ -27,6 +27,7 @@ import org.apache.sis.metadata.TitleProperty;
 
 import static org.apache.sis.internal.metadata.MetadataUtilities.toDate;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toMilliseconds;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDateDefined;
 
 
 /**
@@ -151,7 +152,7 @@ public class DefaultCitationDate extends ISOMetadata implements CitationDate {
      * @param  newValue  the new date.
      */
     public void setDate(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(date));
         date = toMilliseconds(newValue);
     }
 
@@ -172,7 +173,7 @@ public class DefaultCitationDate extends ISOMetadata implements CitationDate {
      * @param  newValue  the new event.
      */
     public void setDateType(final DateType newValue) {
-        checkWritePermission();
+        checkWritePermission(dateType);
         dateType = 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 2feb168..117d1bc 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
@@ -433,7 +433,7 @@ public class DefaultContact extends ISOMetadata implements Contact {
      * @param  newValue  the new contact instructions, or {@code null} if none.
      */
     public void setContactInstructions(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(contactInstructions);
         contactInstructions = newValue;
     }
 
@@ -460,7 +460,7 @@ public class DefaultContact extends ISOMetadata implements Contact {
      * @since 0.5
      */
     public void setContactType(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(contactType);
         contactType = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultIndividual.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultIndividual.java
index ec1d72a..14449fe 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultIndividual.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultIndividual.java
@@ -137,7 +137,7 @@ public class DefaultIndividual extends AbstractParty implements Individual {
      * @param  newValue  the new position of the individual in an organization.
      */
     public void setPositionName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(positionName);
         positionName = 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 90726bf..6d8f04d 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
@@ -188,7 +188,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new application profile.
      */
     public void setApplicationProfile(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(applicationProfile);
         applicationProfile = newValue;
     }
 
@@ -209,7 +209,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new name, or {@code null} if none.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -230,7 +230,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new description, or {@code null} if none.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -251,7 +251,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new function, or {@code null} if none.
      */
     public void setFunction(final OnLineFunction newValue) {
-        checkWritePermission();
+        checkWritePermission(function);
         function = newValue;
     }
 
@@ -275,7 +275,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new linkage, or {@code null} if none.
      */
     public void setLinkage(final URI newValue) {
-        checkWritePermission();
+        checkWritePermission(linkage);
         linkage = newValue;
     }
 
@@ -300,7 +300,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @param  newValue  the new protocol, or {@code null} if none.
      */
     public void setProtocol(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(protocol);
         protocol = newValue;
     }
 
@@ -337,7 +337,7 @@ public class DefaultOnlineResource extends ISOMetadata implements OnlineResource
      * @since 0.5
      */
     public void setProtocolRequest(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(protocolRequest);
         protocolRequest = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibility.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibility.java
index b52c0e3..bb1fbf7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibility.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibility.java
@@ -170,7 +170,7 @@ public class DefaultResponsibility extends ISOMetadata implements Responsibility
      * @param  newValue  the new role, or {@code null} if none.
      */
     public void setRole(final Role newValue) {
-        checkWritePermission();
+        checkWritePermission(role);
         role = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java
index a0bf497..cdcf6c6 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java
@@ -188,7 +188,7 @@ public class DefaultResponsibleParty extends DefaultResponsibility implements Re
      * @return {@code true} if the name has been set, or {@code false} otherwise.
      */
     private boolean setName(final Class<? extends Party> type, final boolean position, final InternationalString name) {
-        checkWritePermission();
+        checkWritePermission(null);
         final Iterator<Party> it = getParties().iterator();
         while (it.hasNext()) {
             final Party party = it.next();
@@ -370,7 +370,7 @@ public class DefaultResponsibleParty extends DefaultResponsibility implements Re
      */
     @Deprecated
     public void setContactInfo(final Contact newValue) {
-        checkWritePermission();
+        checkWritePermission(null);
         final Iterator<Party> it = getParties().iterator();
         while (it.hasNext()) {
             final Party party = it.next();
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 ec007be..26bcde0 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
@@ -145,7 +145,7 @@ public class DefaultSeries extends ISOMetadata implements Series {
      * @param  newValue  the new name, or {@code null} if none.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -166,7 +166,7 @@ public class DefaultSeries extends ISOMetadata implements Series {
      * @param  newValue  the new issue identification, or {@code null} if none.
      */
     public void setIssueIdentification(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(issueIdentification);
         issueIdentification = newValue;
     }
 
@@ -187,7 +187,7 @@ public class DefaultSeries extends ISOMetadata implements Series {
      * @param  newValue  the new page, or {@code null} if none.
      */
     public void setPage(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(page);
         page = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
index 462350d..f1aef1f 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
@@ -180,7 +180,7 @@ public class DefaultTelephone extends ISOMetadata implements Telephone {
      * @since 0.5
      */
     public void setNumber(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(number);
         number = newValue;
     }
 
@@ -206,7 +206,7 @@ public class DefaultTelephone extends ISOMetadata implements Telephone {
      * @since 0.5
      */
     public void setNumberType(final TelephoneType newValue) {
-        checkWritePermission();
+        checkWritePermission(numberType);
         numberType = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultConstraints.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultConstraints.java
index c87caa8..10fe07a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultConstraints.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultConstraints.java
@@ -227,7 +227,7 @@ public class DefaultConstraints extends ISOMetadata implements Constraints {
      * @since 0.5
      */
     public void setConstraintApplicationScope(final Scope newValue) {
-        checkWritePermission();
+        checkWritePermission(constraintApplicationScope);
         constraintApplicationScope = newValue;
     }
 
@@ -302,7 +302,7 @@ public class DefaultConstraints extends ISOMetadata implements Constraints {
      * @since 0.5
      */
     public void setReleasability(final Releasability newValue) {
-        checkWritePermission();
+        checkWritePermission(releasability);
         releasability = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java
index 44e4ba4..ed7bbdd 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java
@@ -157,7 +157,7 @@ public class DefaultReleasability extends ISOMetadata implements Releasability {
      * @param  newValue  the new release statement.
      */
     public void setStatement(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(statement);
         statement = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultSecurityConstraints.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultSecurityConstraints.java
index 0dc0d27..dbf91c9 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultSecurityConstraints.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/constraint/DefaultSecurityConstraints.java
@@ -166,7 +166,7 @@ public class DefaultSecurityConstraints extends DefaultConstraints implements Se
      * @param  newValue  the new classification.
      */
     public void setClassification(final Classification newValue) {
-        checkWritePermission();
+        checkWritePermission(classification);
         classification = newValue;
     }
 
@@ -189,7 +189,7 @@ public class DefaultSecurityConstraints extends DefaultConstraints implements Se
      * @param  newValue  the new user note.
      */
     public void setUserNote(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(userNote);
         userNote = newValue;
     }
 
@@ -210,7 +210,7 @@ public class DefaultSecurityConstraints extends DefaultConstraints implements Se
      * @param  newValue  the new classification system.
      */
     public void setClassificationSystem(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(classificationSystem);
         classificationSystem = newValue;
     }
 
@@ -231,7 +231,7 @@ public class DefaultSecurityConstraints extends DefaultConstraints implements Se
      * @param  newValue  the new handling description.
      */
     public void setHandlingDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(handlingDescription);
         handlingDescription = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultBand.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultBand.java
index 133180f..cf1d470 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultBand.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultBand.java
@@ -207,7 +207,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @since 0.5
      */
     public void setBoundMin(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(boundMin);
         if (ensurePositive(DefaultBand.class, "boundMin", false, newValue)) {
             boundMin = newValue;
         }
@@ -239,7 +239,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @since 0.5
      */
     public void setBoundMax(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(boundMax);
         if (ensurePositive(DefaultBand.class, "boundMax", false, newValue)) {
             boundMax = newValue;
         }
@@ -269,7 +269,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @since 0.5
      */
     public void setBoundUnits(final Unit<Length> newValue) {
-        checkWritePermission();
+        checkWritePermission(boundUnits);
         boundUnits = newValue;
     }
 
@@ -290,7 +290,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @param  newValue  the new band definition.
      */
     public void setBandBoundaryDefinition(final BandDefinition newValue) {
-        checkWritePermission();
+        checkWritePermission(bandBoundaryDefinition);
         bandBoundaryDefinition = newValue;
     }
 
@@ -314,7 +314,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setPeakResponse(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(peakResponse);
         if (ensurePositive(DefaultBand.class, "peakResponse", false, newValue)) {
             peakResponse = newValue;
         }
@@ -338,7 +338,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @param  newValue  the new tone gradation.
      */
     public void setToneGradation(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(toneGradation);
         if (ensurePositive(DefaultBand.class, "toneGradation", false, newValue)) {
             toneGradation = newValue;
         }
@@ -401,7 +401,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @param  newValue  the new transmitted polarization.
      */
     public void setTransmittedPolarization(final PolarizationOrientation newValue) {
-        checkWritePermission();
+        checkWritePermission(transmittedPolarization);
         transmittedPolarization = newValue;
     }
 
@@ -422,7 +422,7 @@ public class DefaultBand extends DefaultSampleDimension implements Band {
      * @param  newValue  the new detected polarization.
      */
     public void setDetectedPolarization(final PolarizationOrientation newValue) {
-        checkWritePermission();
+        checkWritePermission(detectedPolarization);
         detectedPolarization = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultCoverageDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultCoverageDescription.java
index 13e22f9..13a2fcc 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultCoverageDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultCoverageDescription.java
@@ -174,7 +174,7 @@ public class DefaultCoverageDescription extends AbstractContentInformation imple
      * @param  newValue  the new attribute description.
      */
     public void setAttributeDescription(final RecordType newValue) {
-        checkWritePermission();
+        checkWritePermission(attributeDescription);
         attributeDescription = newValue;
     }
 
@@ -202,7 +202,7 @@ public class DefaultCoverageDescription extends AbstractContentInformation imple
      * @since 0.5
      */
     public void setProcessingLevelCode(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(processingLevelCode);
         processingLevelCode = newValue;
     }
 
@@ -276,7 +276,7 @@ public class DefaultCoverageDescription extends AbstractContentInformation imple
      */
     @Deprecated
     public void setContentType(final CoverageContentType newValue) {
-        checkWritePermission();
+        checkWritePermission(attributeGroups);
         final Collection<CoverageContentType> newValues = LegacyPropertyAdapter.asCollection(newValue);
         Collection<AttributeGroup> groups = attributeGroups;
         if (groups != null) {
@@ -346,7 +346,7 @@ public class DefaultCoverageDescription extends AbstractContentInformation imple
      */
     @Deprecated
     public void setDimensions(final Collection<? extends RangeDimension> newValues) {
-        checkWritePermission();
+        checkWritePermission(attributeGroups);
         ((LegacyPropertyAdapter<RangeDimension,?>) getDimensions()).setValues(newValues);
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java
index 8398143..b4c2023 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java
@@ -175,7 +175,7 @@ public class DefaultFeatureCatalogueDescription extends AbstractContentInformati
      * @param  newValue  the new compliance value.
      */
     public void setCompliant(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(compliant);
         compliant = newValue;
     }
 
@@ -216,7 +216,7 @@ public class DefaultFeatureCatalogueDescription extends AbstractContentInformati
      * @param  newValue  {@code true} if the feature catalogue is included.
      */
     public void setIncludedWithDataset(final boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(includedWithDataset ? Boolean.TRUE : null);
         includedWithDataset = newValue;
     }
 
@@ -288,7 +288,7 @@ public class DefaultFeatureCatalogueDescription extends AbstractContentInformati
      */
     @Deprecated
     public void setFeatureTypes(final Collection<? extends GenericName> newValues) {
-        checkWritePermission();
+        checkWritePermission(featureTypes);
         ((LegacyPropertyAdapter<GenericName,?>) getFeatureTypes()).setValues(newValues);
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureTypeInfo.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureTypeInfo.java
index ca06318..288f1bb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureTypeInfo.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultFeatureTypeInfo.java
@@ -155,7 +155,7 @@ public class DefaultFeatureTypeInfo extends ISOMetadata implements FeatureTypeIn
      * @param  newValue  the new name.
      */
     public void setFeatureTypeName(final GenericName newValue) {
-        checkWritePermission();
+        checkWritePermission(featureTypeName);
         featureTypeName = newValue;
     }
 
@@ -178,7 +178,7 @@ public class DefaultFeatureTypeInfo extends ISOMetadata implements FeatureTypeIn
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setFeatureInstanceCount(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(featureInstanceCount);
         if (ensurePositive(DefaultFeatureTypeInfo.class, "featureInstanceCount", true, newValue)) {
             featureInstanceCount = newValue;
         }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultImageDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultImageDescription.java
index 19e02cf..708679b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultImageDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultImageDescription.java
@@ -228,7 +228,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @throws IllegalArgumentException if the given value is out of range.
      */
     public void setIlluminationElevationAngle(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(illuminationElevationAngle);
         if (ensureInRange(DefaultImageDescription.class, "illuminationElevationAngle", -90, +90, newValue)) {
             illuminationElevationAngle = newValue;
         }
@@ -255,7 +255,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @throws IllegalArgumentException if the given value is out of range.
      */
     public void setIlluminationAzimuthAngle(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(illuminationAzimuthAngle);
         if (ensureInRange(DefaultImageDescription.class, "illuminationAzimuthAngle", 0, 360, newValue)) {
             illuminationAzimuthAngle = newValue;
         }
@@ -278,7 +278,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  the new imaging condition.
      */
     public void setImagingCondition(final ImagingCondition newValue) {
-        checkWritePermission();
+        checkWritePermission(imagingCondition);
         imagingCondition = newValue;
     }
 
@@ -299,7 +299,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  the new image quality code.
      */
     public void setImageQualityCode(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(imageQualityCode);
         imageQualityCode = newValue;
     }
 
@@ -322,7 +322,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @throws IllegalArgumentException if the given value is out of range.
      */
     public void setCloudCoverPercentage(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(cloudCoverPercentage);
         if (ensureInRange(DefaultImageDescription.class, "cloudCoverPercentage", 0, 100, newValue)) {
             cloudCoverPercentage = newValue;
         }
@@ -347,7 +347,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setCompressionGenerationQuantity(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(compressionGenerationQuantity);
         if (ensurePositive(DefaultImageDescription.class, "compressionGenerationQuantity", false, newValue)) {
             compressionGenerationQuantity = newValue;
         }
@@ -370,7 +370,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  the new triangulation indicator.
      */
     public void setTriangulationIndicator(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(triangulationIndicator);
         triangulationIndicator = newValue;
     }
 
@@ -393,7 +393,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  {@code true} if radiometric calibration data are available.
      */
     public void setRadiometricCalibrationDataAvailable(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(radiometricCalibrationDataAvailable);
         radiometricCalibrationDataAvailable = newValue;
     }
 
@@ -414,7 +414,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  {@code true} if camera calibration information are available.
      */
     public void setCameraCalibrationInformationAvailable(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(cameraCalibrationInformationAvailable);
         cameraCalibrationInformationAvailable = newValue;
     }
 
@@ -435,7 +435,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  {@code true} if film distortion information are available.
      */
     public void setFilmDistortionInformationAvailable(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(filmDistortionInformationAvailable);
         filmDistortionInformationAvailable = newValue;
     }
 
@@ -456,7 +456,7 @@ public class DefaultImageDescription extends DefaultCoverageDescription implemen
      * @param  newValue  {@code true} if lens distortion information are available.
      */
     public void setLensDistortionInformationAvailable(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(lensDistortionInformationAvailable);
         lensDistortionInformationAvailable = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeDimension.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeDimension.java
index a259c73..8a7c913 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeDimension.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeDimension.java
@@ -159,7 +159,7 @@ public class DefaultRangeDimension extends ISOMetadata implements RangeDimension
      * @param  newValue  the new sequence identifier.
      */
     public void setSequenceIdentifier(final MemberName newValue) {
-        checkWritePermission();
+        checkWritePermission(sequenceIdentifier);
         sequenceIdentifier = newValue;
     }
 
@@ -185,7 +185,7 @@ public class DefaultRangeDimension extends ISOMetadata implements RangeDimension
      * @since 0.5
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeElementDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeElementDescription.java
index 3d44d38..e03ca93 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeElementDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultRangeElementDescription.java
@@ -145,7 +145,7 @@ public class DefaultRangeElementDescription extends ISOMetadata implements Range
      * @param  newValue  the new name value.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -166,7 +166,7 @@ public class DefaultRangeElementDescription extends ISOMetadata implements Range
      * @param  newValue  the new definition value.
      */
     public void setDefinition(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(definition);
         definition = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultSampleDimension.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultSampleDimension.java
index 16f67e0..9ee9902 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultSampleDimension.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/content/DefaultSampleDimension.java
@@ -244,7 +244,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setNumberOfValues(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(numberOfValues);
         if (ensurePositive(DefaultSampleDimension.class, "numberOfValues", false, newValue)) {
             numberOfValues = newValue;
         }
@@ -267,7 +267,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new new minimum value.
      */
     public void setMinValue(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(minValue);
         minValue = newValue;
     }
 
@@ -288,7 +288,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new new maximum value.
      */
     public void setMaxValue(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(maxValue);
         maxValue = newValue;
     }
 
@@ -310,7 +310,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new mean value of data values in each dimension included in the resource.
      */
     public void setMeanValue(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(meanValue);
         meanValue = newValue;
     }
 
@@ -332,7 +332,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new standard deviation of data values in each dimension included in the resource.
      */
     public void setStandardDeviation(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(standardDeviation);
         standardDeviation = newValue;
     }
 
@@ -353,7 +353,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new units of data in the dimension.
      */
     public void setUnits(final Unit<?> newValue) {
-        checkWritePermission();
+        checkWritePermission(units);
         units = newValue;
     }
 
@@ -374,7 +374,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new scale factor which has been applied to the cell value.
      */
     public void setScaleFactor(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(scaleFactor);
         scaleFactor = newValue;
     }
 
@@ -395,7 +395,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new physical value corresponding to a cell value of zero.
      */
     public void setOffset(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(offset);
         offset = newValue;
     }
 
@@ -421,7 +421,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new transfer function value.
      */
     public void setTransferFunctionType(final TransferFunctionType newValue) {
-        checkWritePermission();
+        checkWritePermission(transferFunctionType);
         transferFunctionType = newValue;
     }
 
@@ -447,7 +447,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @throws IllegalArgumentException if the given value is zero or negative.
      */
     public void setBitsPerValue(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(bitsPerValue);
         if (ensurePositive(DefaultSampleDimension.class, "bitsPerValue", true, newValue)) {
             bitsPerValue = newValue;
         }
@@ -479,7 +479,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setNominalSpatialResolution(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(nominalSpatialResolution);
         if (ensurePositive(DefaultSampleDimension.class, "nominalSpatialResolution", true, newValue)) {
             nominalSpatialResolution = newValue;
         }
@@ -503,7 +503,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new type of other attribute description.
      */
     public void setOtherPropertyType(final RecordType newValue) {
-        checkWritePermission();
+        checkWritePermission(otherPropertyType);
         otherPropertyType = newValue;
     }
 
@@ -527,7 +527,7 @@ public class DefaultSampleDimension extends DefaultRangeDimension implements Sam
      * @param  newValue  the new instance of other/attributeType.
      */
     public void setOtherProperty(final Record newValue) {
-        checkWritePermission();
+        checkWritePermission(otherProperty);
         otherProperty = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java
index 49d55a9..b46cd11 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java
@@ -180,7 +180,7 @@ public class DefaultDataFile extends ISOMetadata implements DataFile {
      * @since 1.0
      */
     public void setFileName(final URI newValue) {
-        checkWritePermission();
+        checkWritePermission(fileName);
         fileName = newValue;
     }
 
@@ -205,7 +205,7 @@ public class DefaultDataFile extends ISOMetadata implements DataFile {
      * @since 1.0
      */
     public void setFileDescription(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(fileDescription);
         fileDescription = newValue;
     }
 
@@ -231,7 +231,7 @@ public class DefaultDataFile extends ISOMetadata implements DataFile {
      * @param  newValue  the new file type.
      */
     public void setFileType(final String newValue)  {
-        checkWritePermission();
+        checkWritePermission(fileType);
         fileType = newValue;
     }
 
@@ -281,7 +281,7 @@ public class DefaultDataFile extends ISOMetadata implements DataFile {
      */
     @Deprecated
     public void setFileFormat(final Format newValue) {
-        checkWritePermission();
+        checkWritePermission(fileFormat);
         fileFormat = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDigitalTransferOptions.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDigitalTransferOptions.java
index b5bb2fb..1dca3e0 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDigitalTransferOptions.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDigitalTransferOptions.java
@@ -180,7 +180,7 @@ public class DefaultDigitalTransferOptions extends ISOMetadata implements Digita
      * @param  newValue  the new units of distribution.
      */
     public void setUnitsOfDistribution(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(unitsOfDistribution);
         unitsOfDistribution = newValue;
     }
 
@@ -205,7 +205,7 @@ public class DefaultDigitalTransferOptions extends ISOMetadata implements Digita
      * @throws IllegalArgumentException if the given value is NaN or negative.
      */
     public void setTransferSize(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(transferSize);
         if (ensurePositive(DefaultDigitalTransferOptions.class, "transferSize", true, newValue)) {
             transferSize = newValue;
         }
@@ -308,7 +308,7 @@ public class DefaultDigitalTransferOptions extends ISOMetadata implements Digita
      * @since 0.5
      */
     public void setTransferFrequency(final PeriodDuration newValue) {
-        checkWritePermission();
+        checkWritePermission(transferFrequency);
         transferFrequency = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistribution.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistribution.java
index efa1a55..70af366 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistribution.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultDistribution.java
@@ -166,7 +166,7 @@ public class DefaultDistribution extends ISOMetadata implements Distribution {
      * @since 0.5
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
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 d641f4e..3d47d7d 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
@@ -169,7 +169,7 @@ public class DefaultDistributor extends ISOMetadata implements Distributor {
      * @param  newValue  the new distributor contact.
      */
     public void setDistributorContact(final Responsibility newValue) {
-        checkWritePermission();
+        checkWritePermission(distributorContact);
         distributorContact = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultFormat.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultFormat.java
index 359f099..5db6209 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultFormat.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultFormat.java
@@ -204,7 +204,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      * @since 0.5
      */
     public void setFormatSpecificationCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(formatSpecificationCitation);
         formatSpecificationCitation = newValue;
     }
 
@@ -262,7 +262,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      */
     @Deprecated
     public void setSpecification(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(formatSpecificationCitation);
         setFormatSpecificationCitation((citation, value) -> citation.setTitle(value), newValue);
     }
 
@@ -301,7 +301,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      */
     @Deprecated
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(formatSpecificationCitation);
         setFormatSpecificationCitation((citation, value) ->
                 citation.setAlternateTitles(LegacyPropertyAdapter.asCollection(value)), newValue);
     }
@@ -340,7 +340,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      */
     @Deprecated
     public void setVersion(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(formatSpecificationCitation);
         setFormatSpecificationCitation((citation, value) -> citation.setEdition(value), newValue);
     }
 
@@ -361,7 +361,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      * @param  newValue  the new amendment number.
      */
     public void setAmendmentNumber(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(amendmentNumber);
         amendmentNumber = newValue;
     }
 
@@ -385,7 +385,7 @@ public class DefaultFormat extends ISOMetadata implements Format {
      * @param  newValue  the new file decompression technique.
      */
     public void setFileDecompressionTechnique(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(fileDecompressionTechnique);
         fileDecompressionTechnique = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultMedium.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultMedium.java
index d8d92df..b301b20 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultMedium.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultMedium.java
@@ -196,7 +196,7 @@ public class DefaultMedium extends ISOMetadata implements Medium {
      * @param  newValue  the new name.
      */
     public void setName(final MediumName newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -226,7 +226,7 @@ public class DefaultMedium extends ISOMetadata implements Medium {
      * @since 0.5
      */
     public void setDensity(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(density);
         if (ensurePositive(DefaultMedium.class, "density", true, newValue)) {
             density = newValue;
         }
@@ -294,7 +294,7 @@ public class DefaultMedium extends ISOMetadata implements Medium {
      * @param  newValue  the new density units.
      */
     public void setDensityUnits(final Unit<?> newValue) {
-        checkWritePermission();
+        checkWritePermission(densityUnits);
         densityUnits = newValue;
     }
 
@@ -317,7 +317,7 @@ public class DefaultMedium extends ISOMetadata implements Medium {
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setVolumes(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(volumes);
         if (ensurePositive(DefaultMedium.class, "volumes", false, newValue)) {
             volumes = newValue;
         }
@@ -360,7 +360,7 @@ public class DefaultMedium extends ISOMetadata implements Medium {
      * @param  newValue  the new medium note.
      */
     public void setMediumNote(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(mediumNote);
         mediumNote = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
index f5447ea..ca3ca7f 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
@@ -183,7 +183,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @see #setCurrency(Currency)
      */
     public void setFees(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(fees);
         fees = newValue;
     }
 
@@ -219,7 +219,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @since 0.5
      */
     public void setCurrency(final Currency newValue) {
-        checkWritePermission();
+        checkWritePermission(currency);
         currency = newValue;
     }
 
@@ -240,7 +240,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @param  newValue  the new planned available time.
      */
     public void setPlannedAvailableDateTime(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(plannedAvailableDateTime);
         plannedAvailableDateTime = toMilliseconds(newValue);
     }
 
@@ -261,7 +261,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @param  newValue  the new ordering instructions.
      */
     public void setOrderingInstructions(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(orderingInstructions);
         orderingInstructions = newValue;
     }
 
@@ -282,7 +282,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @param  newValue  the new turnaround.
      */
     public void setTurnaround(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(turnaround);
         turnaround = newValue;
     }
 
@@ -310,7 +310,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @since 0.5
      */
     public void setOrderOptionType(final RecordType newValue) {
-        checkWritePermission();
+        checkWritePermission(orderOptionType);
         orderOptionType = newValue;
     }
 
@@ -340,7 +340,7 @@ public class DefaultStandardOrderProcess extends ISOMetadata implements Standard
      * @since 0.5
      */
     public void setOrderOptions(final Record newValue) {
-        checkWritePermission();
+        checkWritePermission(orderOptions);
         orderOptions = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/AbstractGeographicExtent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/AbstractGeographicExtent.java
index fd437ec..0e7d1a5 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/AbstractGeographicExtent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/AbstractGeographicExtent.java
@@ -159,7 +159,7 @@ public class AbstractGeographicExtent extends ISOMetadata implements GeographicE
      * @param newValue {@code true} if the bounding polygon encompasses an area covered by the data.
      */
     public void setInclusion(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(inclusion);
         inclusion = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultExtent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultExtent.java
index 7620f5f..7470204 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultExtent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultExtent.java
@@ -214,7 +214,7 @@ public class DefaultExtent extends ISOMetadata implements Extent {
      * @param  newValue  the new description.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -279,6 +279,15 @@ public class DefaultExtent extends ISOMetadata implements Extent {
     }
 
     /**
+     * Returns a non-null value if this extent is non-empty.
+     * This implementation does not test if the elements are themselves empty.
+     */
+    private Boolean isNonEmpty() {
+        return (geographicElements != null) || (verticalElements != null) || (temporalElements != null)
+                || (description != null) ? Boolean.TRUE : null;
+    }
+
+    /**
      * Adds geographic, vertical or temporal extents inferred from the given envelope.
      * This method inspects the {@linkplain Envelope#getCoordinateReferenceSystem() envelope CRS}
      * and creates a {@link GeographicBoundingBox}, {@link VerticalExtent} or {@link TemporalExtent}
@@ -295,7 +304,7 @@ public class DefaultExtent extends ISOMetadata implements Extent {
      * @see DefaultTemporalExtent#setBounds(Envelope)
      */
     public void addElements(final Envelope envelope) throws TransformException {
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         ArgumentChecks.ensureNonNull("envelope", envelope);
         ReferencingServices.getInstance().addElements(envelope, this);
     }
@@ -318,7 +327,7 @@ public class DefaultExtent extends ISOMetadata implements Extent {
      * @since 0.8
      */
     public void intersect(final Extent other) {
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         ArgumentChecks.ensureNonNull("other", other);
         final InternationalString od = other.getDescription();
         if (od != null && !(description instanceof NilObject)) {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java
index 3682a80..e27b0fb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicBoundingBox.java
@@ -37,6 +37,7 @@ import org.apache.sis.metadata.InvalidMetadataException;
 import org.apache.sis.xml.NilReason;
 
 import static java.lang.Double.doubleToLongBits;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDefined;
 
 
 /**
@@ -298,7 +299,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      *         or {@linkplain Double#NaN NaN} to undefine.
      */
     public void setWestBoundLongitude(double newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(westBoundLongitude));
         if (newValue != Longitude.MAX_VALUE) {                  // Do not normalize +180° to -180°.
             newValue = Longitude.normalize(newValue);
         }
@@ -331,7 +332,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      *         or {@linkplain Double#NaN NaN} to undefine.
      */
     public void setEastBoundLongitude(double newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(eastBoundLongitude));
         if (newValue != Longitude.MAX_VALUE) {                      // Do not normalize +180° to -180°.
             newValue = Longitude.normalize(newValue);
         }
@@ -363,7 +364,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      *         or {@linkplain Double#NaN NaN} to undefine.
      */
     public void setSouthBoundLatitude(final double newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(southBoundLatitude));
         southBoundLatitude = Latitude.clamp(newValue);
         if (southBoundLatitude > northBoundLatitude) {
             northBoundLatitude = Double.NaN;
@@ -395,7 +396,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      *         or {@linkplain Double#NaN NaN} to undefine.
      */
     public void setNorthBoundLatitude(final double newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(northBoundLatitude));
         northBoundLatitude = Latitude.clamp(newValue);
         if (northBoundLatitude < southBoundLatitude) {
             southBoundLatitude = Double.NaN;
@@ -488,7 +489,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
                           final double northBoundLatitude)
             throws IllegalArgumentException
     {
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         verifyBounds(southBoundLatitude, northBoundLatitude);
         this.westBoundLongitude = westBoundLongitude;
         this.eastBoundLongitude = eastBoundLongitude;
@@ -521,7 +522,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      */
     public void setBounds(final Envelope envelope) throws TransformException {
         ArgumentChecks.ensureNonNull("envelope", envelope);
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         ReferencingServices.getInstance().setBounds(envelope, this);
         setInclusion(Boolean.TRUE);                                     // Set only on success.
     }
@@ -648,7 +649,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      * @see org.apache.sis.geometry.GeneralEnvelope#add(Envelope)
      */
     public void add(final GeographicBoundingBox box) {
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         ArgumentChecks.ensureNonNull("box", box);
         double λmin = box.getWestBoundLongitude();
         double λmax = box.getEastBoundLongitude();
@@ -706,7 +707,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      * @see org.apache.sis.geometry.GeneralEnvelope#intersect(Envelope)
      */
     public void intersect(final GeographicBoundingBox box) throws IllegalArgumentException {
-        checkWritePermission();
+        checkWritePermission(isNonEmpty());
         ArgumentChecks.ensureNonNull("box", box);
         if (getInclusion(getInclusion()) != getInclusion(box.getInclusion())) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatiblePropertyValue_1, "inclusion"));
@@ -736,6 +737,18 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
     }
 
     /**
+     * Returns an arbitrary non-null value if this bounding box is non-empty.
+     * The return value can be given to {@link #checkWritePermission(Object)}
+     * before to set the bounds of this geographic extent.
+     */
+    private Boolean isNonEmpty() {
+        return Double.isNaN(eastBoundLongitude) &&
+               Double.isNaN(westBoundLongitude) &&
+               Double.isNaN(northBoundLatitude) &&
+               Double.isNaN(southBoundLatitude) ? null : Boolean.TRUE;
+    }
+
+    /**
      * Returns {@code true} if this metadata is empty. This metadata is considered empty if
      * every bound values are {@linkplain Double#NaN NaN}. Note that this is different than
      * the <cite>Java2D</cite> or <cite>envelope</cite> definition of "emptiness", since we
@@ -748,10 +761,7 @@ public class DefaultGeographicBoundingBox extends AbstractGeographicExtent imple
      */
     @Override
     public boolean isEmpty() {
-        return Double.isNaN(eastBoundLongitude) &&
-               Double.isNaN(westBoundLongitude) &&
-               Double.isNaN(northBoundLatitude) &&
-               Double.isNaN(southBoundLatitude);
+        return isNonEmpty() == null;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java
index 2780e20..e4aa216 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java
@@ -202,7 +202,7 @@ public class DefaultGeographicDescription extends AbstractGeographicExtent imple
      * @param  newValue  the new geographic identifier.
      */
     public void setGeographicIdentifier(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(geographicIdentifier);
         geographicIdentifier = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java
index 46c0559..b27b81b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultSpatialTemporalExtent.java
@@ -181,7 +181,7 @@ public class DefaultSpatialTemporalExtent extends DefaultTemporalExtent implemen
      * @since 0.5
      */
     public void setVerticalExtent(final VerticalExtent newValue) {
-        checkWritePermission();
+        checkWritePermission(verticalExtent);
         verticalExtent = newValue;
     }
 
@@ -221,7 +221,7 @@ public class DefaultSpatialTemporalExtent extends DefaultTemporalExtent implemen
      */
     @Override
     public void setBounds(final Envelope envelope) throws TransformException {
-        checkWritePermission();
+        checkWritePermission(spatialExtent);
         ReferencingServices.getInstance().setBounds(envelope, this);
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
index 5155edd..8b42ffa 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
@@ -154,7 +154,7 @@ public class DefaultTemporalExtent extends ISOMetadata implements TemporalExtent
      * @param  newValue  the new content date.
      */
     public void setExtent(final TemporalPrimitive newValue) {
-        checkWritePermission();
+        checkWritePermission(extent);
         extent = newValue;
     }
 
@@ -240,7 +240,7 @@ public class DefaultTemporalExtent extends ISOMetadata implements TemporalExtent
      * @see DefaultVerticalExtent#setBounds(Envelope)
      */
     public void setBounds(final Envelope envelope) throws TransformException {
-        checkWritePermission();
+        checkWritePermission(extent);
         ReferencingServices.getInstance().setBounds(envelope, this);
     }
 
@@ -259,7 +259,7 @@ public class DefaultTemporalExtent extends ISOMetadata implements TemporalExtent
      * @since 0.8
      */
     public void intersect(final TemporalExtent other) {
-        checkWritePermission();
+        checkWritePermission(extent);
         final TemporalPrimitive ot = other.getExtent();
         if (ot != null && !(extent instanceof NilObject)) {
             if (extent == null || (ot instanceof NilObject)) {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java
index 1c729a2..55e5c62 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultVerticalExtent.java
@@ -181,7 +181,7 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent
      * @param  newValue  the new minimum value.
      */
     public void setMinimumValue(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(minimumValue);
         minimumValue = newValue;
     }
 
@@ -203,7 +203,7 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent
      * @param  newValue  the new maximum value.
      */
     public void setMaximumValue(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(maximumValue);
         maximumValue = newValue;
     }
 
@@ -229,11 +229,19 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent
      * @param  newValue  the new vertical CRS.
      */
     public void setVerticalCRS(final VerticalCRS newValue) {
-        checkWritePermission();
+        checkWritePermission(verticalCRS);
         verticalCRS = newValue;
     }
 
     /**
+     * Returns an arbitrary value, or {@code null} if both minimum and maximum are null.
+     * This is used for verifying if the bounds are already set or partially set.
+     */
+    private Double value() {
+        return (minimumValue != null) ? minimumValue : maximumValue;
+    }
+
+    /**
      * Sets this vertical extent to values inferred from the specified envelope. The envelope can
      * be multi-dimensional, in which case the {@linkplain Envelope#getCoordinateReferenceSystem()
      * envelope CRS} must have a vertical component.
@@ -249,7 +257,7 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent
      * @see DefaultTemporalExtent#setBounds(Envelope)
      */
     public void setBounds(final Envelope envelope) throws TransformException {
-        checkWritePermission();
+        checkWritePermission(value());
         ReferencingServices.getInstance().setBounds(envelope, this);
     }
 
@@ -272,7 +280,7 @@ public class DefaultVerticalExtent extends ISOMetadata implements VerticalExtent
      * @since 0.8
      */
     public void intersect(final VerticalExtent other) throws MismatchedReferenceSystemException {
-        checkWritePermission();
+        checkWritePermission(value());
         ArgumentChecks.ensureNonNull("other", other);
         Double min = other.getMinimumValue();
         Double max = other.getMaximumValue();
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 df8472f..eabfc35 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
@@ -334,7 +334,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * @param  newValue  the new citation.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
@@ -355,7 +355,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * @param  newValue  the new summary of resource(s).
      */
     public void setAbstract(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(abstracts);
         abstracts = newValue;
     }
 
@@ -376,7 +376,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * @param  newValue  the new summary of intention.
      */
     public void setPurpose(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(purpose);
         purpose = newValue;
     }
 
@@ -610,7 +610,7 @@ public class AbstractIdentification extends ISOMetadata implements Identificatio
      * @since 0.5
      */
     public void setProcessingLevel(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(processingLevel);
         processingLevel = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
index 9d38770..0e62d89 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
@@ -194,7 +194,7 @@ public class DefaultAggregateInformation extends DefaultAssociatedResource imple
      */
     @Deprecated
     public void setAggregateDataSetIdentifier(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(null);
         Citation name = getAggregateDataSetName();
         if (newValue != null) {
             if (!(name instanceof DefaultCitation)) {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java
index bb833c3..fd47118 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java
@@ -172,7 +172,7 @@ public class DefaultAssociatedResource extends ISOMetadata implements Associated
      * @param  newValue  the new citation information, or {@code null}.
      */
     public void setName(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -194,7 +194,7 @@ public class DefaultAssociatedResource extends ISOMetadata implements Associated
      * @param  newValue  the new type of relation.
      */
     public void setAssociationType(final AssociationType newValue) {
-        checkWritePermission();
+        checkWritePermission(associationType);
         associationType = newValue;
     }
 
@@ -216,7 +216,7 @@ public class DefaultAssociatedResource extends ISOMetadata implements Associated
      * @param  newValue  the new type of initiative.
      */
     public void setInitiativeType(final InitiativeType newValue) {
-        checkWritePermission();
+        checkWritePermission(initiativeType);
         initiativeType = newValue;
     }
 
@@ -238,7 +238,7 @@ public class DefaultAssociatedResource extends ISOMetadata implements Associated
      * @param  newValue  the new reference to the metadata.
      */
     public void setMetadataReference(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(metadataReference);
         metadataReference = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultBrowseGraphic.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultBrowseGraphic.java
index 1dfc78b..36dd5d7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultBrowseGraphic.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultBrowseGraphic.java
@@ -174,7 +174,7 @@ public class DefaultBrowseGraphic extends ISOMetadata implements BrowseGraphic {
      * @param  newValue  the new filename.
      */
     public void setFileName(final URI newValue) {
-        checkWritePermission();
+        checkWritePermission(fileName);
         fileName = newValue;
     }
 
@@ -195,7 +195,7 @@ public class DefaultBrowseGraphic extends ISOMetadata implements BrowseGraphic {
      * @param  newValue  the new file description.
      */
     public void setFileDescription(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(fileDescription);
         fileDescription = newValue;
     }
 
@@ -223,7 +223,7 @@ public class DefaultBrowseGraphic extends ISOMetadata implements BrowseGraphic {
      * @param  newValue  the new file type.
      */
     public void setFileType(final String newValue)  {
-        checkWritePermission();
+        checkWritePermission(fileType);
         fileType = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultCoupledResource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultCoupledResource.java
index 4ee2f81..7e48e70 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultCoupledResource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultCoupledResource.java
@@ -179,8 +179,8 @@ public class DefaultCoupledResource extends ISOMetadata implements CoupledResour
      * @param  newValue  the new identifier of the resource.
      */
     public void setScopedName(final ScopedName newValue) {
-        checkWritePermission();
-        this.scopedName = newValue;
+        checkWritePermission(scopedName);
+        scopedName = newValue;
     }
 
     /**
@@ -241,8 +241,8 @@ public class DefaultCoupledResource extends ISOMetadata implements CoupledResour
      * @param  newValue  the new service operation.
      */
     public void setOperation(final OperationMetadata newValue) {
-        checkWritePermission();
-        this.operation = newValue;
+        checkWritePermission(operation);
+        operation = newValue;
     }
 
 
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 e8640b2..2e6edb2 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
@@ -248,7 +248,7 @@ public class DefaultDataIdentification extends AbstractIdentification implements
      * @param  newValue  the new environment description.
      */
     public void setEnvironmentDescription(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(environmentDescription);
         environmentDescription = newValue;
     }
 
@@ -269,7 +269,7 @@ public class DefaultDataIdentification extends AbstractIdentification implements
      * @param  newValue  the new supplemental information.
      */
     public void setSupplementalInformation(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(supplementalInformation);
         supplementalInformation = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywordClass.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywordClass.java
index 8fd8704..79dde2c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywordClass.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywordClass.java
@@ -159,7 +159,7 @@ public class DefaultKeywordClass extends ISOMetadata implements KeywordClass {
      * @param  newValue  the new keyword category in natural language.
      */
     public void setClassName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(className);
         className = newValue;
     }
 
@@ -180,7 +180,7 @@ public class DefaultKeywordClass extends ISOMetadata implements KeywordClass {
      * @param  newValue  the new URI of concept in the ontology.
      */
     public void setConceptIdentifier(final URI newValue) {
-        checkWritePermission();
+        checkWritePermission(conceptIdentifier);
         conceptIdentifier = newValue;
     }
 
@@ -201,7 +201,7 @@ public class DefaultKeywordClass extends ISOMetadata implements KeywordClass {
      * @param  newValue  the new reference that binds the keyword class to a formal conceptualization.
      */
     public void setOntology(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(ontology);
         ontology = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywords.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywords.java
index 1a204ca..a09af15 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywords.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultKeywords.java
@@ -195,7 +195,7 @@ public class DefaultKeywords extends ISOMetadata implements Keywords {
      * @param newValue  the new keyword type.
      */
     public void setType(final KeywordType newValue) {
-        checkWritePermission();
+        checkWritePermission(type);
         type = newValue;
     }
 
@@ -216,7 +216,7 @@ public class DefaultKeywords extends ISOMetadata implements Keywords {
      * @param newValue  the new thesaurus name.
      */
     public void setThesaurusName(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(thesaurusName);
         thesaurusName = newValue;
     }
 
@@ -243,7 +243,7 @@ public class DefaultKeywords extends ISOMetadata implements Keywords {
      * @since 0.5
      */
     public void setKeywordClass(final KeywordClass newValue) {
-        checkWritePermission();
+        checkWritePermission(keywordClass);
         keywordClass = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationChainMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationChainMetadata.java
index e5c341f..fe61784 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationChainMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationChainMetadata.java
@@ -159,7 +159,7 @@ public class DefaultOperationChainMetadata extends ISOMetadata implements Operat
      * @param  newValue  the new name used by the service for this chain.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -180,7 +180,7 @@ public class DefaultOperationChainMetadata extends ISOMetadata implements Operat
      * @param  newValue  the new a narrative explanation of the services in the chain and resulting output
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationMetadata.java
index 7869f67..67439a6 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultOperationMetadata.java
@@ -196,7 +196,7 @@ public class DefaultOperationMetadata extends ISOMetadata implements OperationMe
      * @param  newValue  the new unique identifier for this interface.
      */
     public void setOperationName(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(operationName);
         operationName = newValue;
     }
 
@@ -237,7 +237,7 @@ public class DefaultOperationMetadata extends ISOMetadata implements OperationMe
      * @param  newValue  the new free text description of the intent of the operation and the results of the operation.
      */
     public void setOperationDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(operationDescription);
         operationDescription = newValue;
     }
 
@@ -259,7 +259,7 @@ public class DefaultOperationMetadata extends ISOMetadata implements OperationMe
      * @param  newValue  the new name used to invoke this interface within the context of the DCP.
      */
     public void setInvocationName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(invocationName);
         invocationName = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java
index 2bb11f3..1d12aa0 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java
@@ -219,7 +219,7 @@ public class DefaultResolution extends ISOMetadata implements Resolution {
      * @param  newValue  the new value.
      */
     private void setProperty(final byte code, final Object newValue) {
-        checkWritePermission();
+        checkWritePermission(value);
         if (value != null && property != code) {
             if (newValue == null) {
                 return;                                     // Do not erase the other property.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentification.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentification.java
index 9937bd0..0a74b2b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentification.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentification.java
@@ -239,7 +239,7 @@ public class DefaultServiceIdentification extends AbstractIdentification impleme
      * @param  newValue  the new service type name.
      */
     public void setServiceType(final GenericName newValue) {
-        checkWritePermission();
+        checkWritePermission(serviceType);
         serviceType = newValue;
     }
 
@@ -285,7 +285,7 @@ public class DefaultServiceIdentification extends AbstractIdentification impleme
      * @since 0.5
      */
     public void setAccessProperties(final StandardOrderProcess newValue) {
-        checkWritePermission();
+        checkWritePermission(accessProperties);
         accessProperties = newValue;
     }
 
@@ -306,7 +306,7 @@ public class DefaultServiceIdentification extends AbstractIdentification impleme
      * @param  newValue  the new type of coupling between service and associated data.
      */
     public void setCouplingType(final CouplingType newValue) {
-        checkWritePermission();
+        checkWritePermission(couplingType);
         couplingType = newValue;
     }
 
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 99a93e9..8b53c12 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
@@ -32,6 +32,7 @@ import org.apache.sis.util.iso.Types;
 
 import static org.apache.sis.internal.metadata.MetadataUtilities.toDate;
 import static org.apache.sis.internal.metadata.MetadataUtilities.toMilliseconds;
+import static org.apache.sis.internal.metadata.MetadataUtilities.isDateDefined;
 
 
 /**
@@ -203,7 +204,7 @@ public class DefaultUsage extends ISOMetadata implements Usage {
      * @param  newValue  the new specific usage.
      */
     public void setSpecificUsage(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(specificUsage);
         specificUsage = newValue;
     }
 
@@ -224,7 +225,7 @@ public class DefaultUsage extends ISOMetadata implements Usage {
      * @param  newValue  the new usage date.
      */
     public void setUsageDate(final Date newValue)  {
-        checkWritePermission();
+        checkWritePermission(isDateDefined(usageDate));
         usageDate = toMilliseconds(newValue);
     }
 
@@ -245,8 +246,8 @@ public class DefaultUsage extends ISOMetadata implements Usage {
      * @param  newValue  the new user determined limitations.
      */
     public void setUserDeterminedLimitations(final InternationalString newValue) {
-        checkWritePermission();
-        this.userDeterminedLimitations = newValue;
+        checkWritePermission(userDeterminedLimitations);
+        userDeterminedLimitations = newValue;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultAlgorithm.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultAlgorithm.java
index f87d7c5..01c7cc7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultAlgorithm.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultAlgorithm.java
@@ -137,7 +137,7 @@ public class DefaultAlgorithm extends ISOMetadata implements Algorithm {
      * @param  newValue  the new citation value.
      */
     public void setCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(citation);
         citation = newValue;
     }
 
@@ -158,7 +158,7 @@ public class DefaultAlgorithm extends ISOMetadata implements Algorithm {
      * @param  newValue  the new description value.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultLineage.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultLineage.java
index 0bf71ea..24a9ceb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultLineage.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultLineage.java
@@ -189,7 +189,7 @@ public class DefaultLineage extends ISOMetadata implements Lineage {
      * @param  newValue  the new statement.
      */
     public void setStatement(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(statement);
         statement = newValue;
     }
 
@@ -215,7 +215,7 @@ public class DefaultLineage extends ISOMetadata implements Lineage {
      * @since 0.5
      */
     public void setScope(final Scope newValue) {
-        checkWritePermission();
+        checkWritePermission(scope);
         scope = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultNominalResolution.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultNominalResolution.java
index 190d34f..399f88e 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultNominalResolution.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultNominalResolution.java
@@ -148,7 +148,7 @@ public class DefaultNominalResolution extends ISOMetadata implements NominalReso
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      */
     public void setScanningResolution(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(scanningResolution);
         if (ensurePositive(DefaultNominalResolution.class, "scanningResolution", true, newValue)) {
             scanningResolution = newValue;
         }
@@ -175,7 +175,7 @@ public class DefaultNominalResolution extends ISOMetadata implements NominalReso
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      */
     public void setGroundResolution(final Double newValue) {
-        checkWritePermission();
+        checkWritePermission(groundResolution);
         if (ensurePositive(DefaultNominalResolution.class, "groundResolution", true, newValue)) {
             groundResolution = newValue;
         }
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 d63446c..2798e42 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
@@ -225,7 +225,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * @param  newValue  the new description.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -246,7 +246,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * @param  newValue  the new rationale.
      */
     public void setRationale(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(rationale);
         rationale = newValue;
     }
 
@@ -271,7 +271,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * @since 1.0
      */
     public void setStepDateTime(final TemporalPrimitive newValue) {
-        checkWritePermission();
+        checkWritePermission(stepDateTime);
         stepDateTime = newValue;
     }
 
@@ -369,7 +369,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * @since 0.5
      */
     public void setScope(final Scope newValue) {
-        checkWritePermission();
+        checkWritePermission(scope);
         scope = newValue;
     }
 
@@ -434,7 +434,7 @@ public class DefaultProcessStep extends ISOMetadata implements ProcessStep {
      * @param  newValue  the new processing information value.
      */
     public void setProcessingInformation(final Processing newValue) {
-        checkWritePermission();
+        checkWritePermission(processingInformation);
         processingInformation = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepReport.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepReport.java
index abc249f..676027f 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepReport.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepReport.java
@@ -142,7 +142,7 @@ public class DefaultProcessStepReport extends ISOMetadata implements ProcessStep
      * @param  newValue  the new name value.
      */
     public void setName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(name);
         name = newValue;
     }
 
@@ -163,7 +163,7 @@ public class DefaultProcessStepReport extends ISOMetadata implements ProcessStep
      * @param  newValue  the new description value.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -184,7 +184,7 @@ public class DefaultProcessStepReport extends ISOMetadata implements ProcessStep
      * @param  newValue  the new file type value.
      */
     public void setFileType(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(fileType);
         fileType = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessing.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessing.java
index c4a734f..9aab3ef 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessing.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultProcessing.java
@@ -203,7 +203,7 @@ public class DefaultProcessing extends ISOMetadata implements Processing {
      * @param  newValue  the new procedure description value.
      */
     public void setProcedureDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(procedureDescription);
         procedureDescription = newValue;
     }
 
@@ -244,7 +244,7 @@ public class DefaultProcessing extends ISOMetadata implements Processing {
      * @param  newValue  the new runtime parameter value.
      */
     public void setRunTimeParameters(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(runTimeParameters);
         runTimeParameters = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
index 99fe75b..538e294 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
@@ -233,7 +233,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @param  newValue  the new description.
      */
     public void setDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(description);
         description = newValue;
     }
 
@@ -259,7 +259,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @since 0.5
      */
     public void setSourceSpatialResolution(final Resolution newValue) {
-        checkWritePermission();
+        checkWritePermission(sourceSpatialResolution);
         sourceSpatialResolution = newValue;
     }
 
@@ -297,7 +297,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      */
     @Deprecated
     public void setScaleDenominator(final RepresentativeFraction newValue)  {
-        checkWritePermission();
+        checkWritePermission(sourceSpatialResolution);
         Resolution resolution = null;
         if (newValue != null) {
             resolution = sourceSpatialResolution;
@@ -334,7 +334,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @param  newValue  the new reference system.
      */
     public void setSourceReferenceSystem(final ReferenceSystem newValue) {
-        checkWritePermission();
+        checkWritePermission(sourceReferenceSystem);
         sourceReferenceSystem = newValue;
     }
 
@@ -355,7 +355,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @param  newValue  the new source citation.
      */
     public void setSourceCitation(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(sourceCitation);
         sourceCitation = newValue;
     }
 
@@ -406,7 +406,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @since 0.5
      */
     public void setScope(final Scope newValue){
-        checkWritePermission();
+        checkWritePermission(scope);
         scope = newValue;
     }
 
@@ -450,7 +450,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      */
     @Deprecated
     public void setSourceExtents(final Collection<? extends Extent> newValues) {
-        checkWritePermission();
+        checkWritePermission(scope);
         Scope scope = this.scope;
         if (!(scope instanceof DefaultScope)) {
             scope = new DefaultScope(scope);
@@ -496,7 +496,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @param  newValue  the new processed level value.
      */
     public void setProcessedLevel(final Identifier newValue) {
-        checkWritePermission();
+        checkWritePermission(processedLevel);
         processedLevel = newValue;
     }
 
@@ -517,7 +517,7 @@ public class DefaultSource extends ISOMetadata implements Source {
      * @param  newValue  the new nominal resolution value.
      */
     public void setResolution(final NominalResolution newValue) {
-        checkWritePermission();
+        checkWritePermission(resolution);
         resolution = newValue;
     }
 
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 259ad5d..7f4504f 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
@@ -198,7 +198,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      * @param  newValue  the new maintenance frequency.
      */
     public void setMaintenanceAndUpdateFrequency(final MaintenanceFrequency newValue) {
-        checkWritePermission();
+        checkWritePermission(maintenanceAndUpdateFrequency);
         maintenanceAndUpdateFrequency = newValue;
     }
 
@@ -262,7 +262,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      */
     @Deprecated
     public void setDateOfNextUpdate(final Date newValue) {
-        checkWritePermission();
+        checkWritePermission(maintenanceDates);
         Collection<CitationDate> dates = maintenanceDates;
         if (dates != null) {
             final Iterator<CitationDate> it = dates.iterator();
@@ -307,7 +307,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      * @param  newValue  the new user defined maintenance frequency.
      */
     public void setUserDefinedMaintenanceFrequency(final PeriodDuration newValue) {
-        checkWritePermission();
+        checkWritePermission(userDefinedMaintenanceFrequency);
         userDefinedMaintenanceFrequency = newValue;
     }
 
@@ -383,7 +383,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      */
     @Deprecated
     public void setUpdateScopes(final Collection<? extends ScopeCode> newValues) {
-        checkWritePermission();
+        checkWritePermission(maintenanceScopes);
         ((LegacyPropertyAdapter<ScopeCode,?>) getUpdateScopes()).setValues(newValues);
     }
 
@@ -438,7 +438,7 @@ public class DefaultMaintenanceInformation extends ISOMetadata implements Mainte
      */
     @Deprecated
     public void setUpdateScopeDescriptions(final Collection<? extends ScopeDescription> newValues) {
-        checkWritePermission();
+        checkWritePermission(maintenanceScopes);
         ((LegacyPropertyAdapter<ScopeDescription,?>) getUpdateScopeDescriptions()).setValues(newValues);
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScope.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScope.java
index 054bb90..7aee4f8 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScope.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScope.java
@@ -161,7 +161,7 @@ public class DefaultScope extends ISOMetadata implements Scope {
      * @param  newValue  the new level.
      */
     public void setLevel(final ScopeCode newValue) {
-        checkWritePermission();
+        checkWritePermission(level);
         level = newValue;
     }
 
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 6b2c2e0..2000a20 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
@@ -295,7 +295,7 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * @param  newValue  the new dataset.
      */
     public void setDataset(final String newValue) {
-        checkWritePermission();
+        checkWritePermission(value);
         if (newValue != null || property == DATASET) {
             warningOnOverwrite(DATASET);
             property = DATASET;
@@ -461,7 +461,7 @@ public class DefaultScopeDescription extends ISOMetadata implements ScopeDescrip
      * @param newValue Other class of information.
      */
     public void setOther(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(value);
         if (newValue != null || property == OTHER) {
             warningOnOverwrite(OTHER);
             property = OTHER;
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
index 0412bd4..8d11995 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
@@ -430,7 +430,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValue  the new measure identification.
      */
     public void setMeasureIdentification(final Identifier newValue)  {
-        checkWritePermission();
+        checkWritePermission(measureIdentification);
         measureIdentification = newValue;
     }
 
@@ -453,7 +453,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValue  the new measure description.
      */
     public void setMeasureDescription(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(measureDescription);
         measureDescription = newValue;
     }
 
@@ -476,7 +476,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValue  the new evaluation method type.
      */
     public void setEvaluationMethodType(final EvaluationMethodType newValue)  {
-        checkWritePermission();
+        checkWritePermission(evaluationMethodType);
         evaluationMethodType = newValue;
     }
 
@@ -499,7 +499,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValue  the new evaluation method description.
      */
     public void setEvaluationMethodDescription(final InternationalString newValue)  {
-        checkWritePermission();
+        checkWritePermission(evaluationMethodDescription);
         evaluationMethodDescription = newValue;
     }
 
@@ -522,7 +522,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValue  the new evaluation procedure.
      */
     public void setEvaluationProcedure(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(evaluationProcedure);
         evaluationProcedure = newValue;
     }
 
@@ -553,7 +553,7 @@ public class AbstractElement extends ISOMetadata implements Element {
      * @param  newValues  the new dates, or {@code null}.
      */
     public void setDates(final Collection<? extends Date> newValues) {
-        checkWritePermission();
+        checkWritePermission(dates);
         if (newValues != dates) {               // Mandatory check for avoiding the call to 'dates.clear()'.
             writeDates(newValues);
         }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultConformanceResult.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultConformanceResult.java
index 83f2e29..bb15568 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultConformanceResult.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultConformanceResult.java
@@ -166,7 +166,7 @@ public class DefaultConformanceResult extends AbstractResult implements Conforma
      * @param  newValue  the new specification.
      */
     public void setSpecification(final Citation newValue) {
-        checkWritePermission();
+        checkWritePermission(specification);
         specification = newValue;
     }
 
@@ -187,7 +187,7 @@ public class DefaultConformanceResult extends AbstractResult implements Conforma
      * @param  newValue  the new explanation.
      */
     public void setExplanation(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(explanation);
         explanation = newValue;
     }
 
@@ -207,7 +207,7 @@ public class DefaultConformanceResult extends AbstractResult implements Conforma
      * @param newValue {@code true} if the test pass.
      */
     public void setPass(final Boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(pass);
         pass = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultCoverageResult.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultCoverageResult.java
index f997a42..e36d1a1 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultCoverageResult.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultCoverageResult.java
@@ -166,7 +166,7 @@ public class DefaultCoverageResult extends AbstractResult implements CoverageRes
      * @param  newValue  the new spatial representation type value.
      */
     public void setSpatialRepresentationType(final SpatialRepresentationType newValue) {
-        checkWritePermission();
+        checkWritePermission(spatialRepresentationType);
         spatialRepresentationType = newValue;
     }
 
@@ -187,7 +187,7 @@ public class DefaultCoverageResult extends AbstractResult implements CoverageRes
      * @param  newValue  the new spatial representation value.
      */
     public void setResultSpatialRepresentation(final SpatialRepresentation newValue) {
-        checkWritePermission();
+        checkWritePermission(resultSpatialRepresentation);
         resultSpatialRepresentation = newValue;
     }
 
@@ -210,7 +210,7 @@ public class DefaultCoverageResult extends AbstractResult implements CoverageRes
      * @param  newValue  the new content description value.
      */
     public void setResultContentDescription(final CoverageDescription newValue) {
-        checkWritePermission();
+        checkWritePermission(resultContentDescription);
         resultContentDescription = newValue;
     }
 
@@ -231,7 +231,7 @@ public class DefaultCoverageResult extends AbstractResult implements CoverageRes
      * @param  newValue  the new result format value.
      */
     public void setResultFormat(final Format newValue) {
-        checkWritePermission();
+        checkWritePermission(resultFormat);
         resultFormat = newValue;
     }
 
@@ -252,7 +252,7 @@ public class DefaultCoverageResult extends AbstractResult implements CoverageRes
      * @param  newValue  the new result file value.
      */
     public void setResultFile(final DataFile newValue) {
-        checkWritePermission();
+        checkWritePermission(resultFile);
         resultFile = newValue;
     }
 }
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 4149399..9429bda 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
@@ -178,7 +178,7 @@ public class DefaultDataQuality extends ISOMetadata implements DataQuality {
      * @param  newValue  the new scope.
      */
     public void setScope(final Scope newValue) {
-        checkWritePermission();
+        checkWritePermission(scope);
         scope = newValue;
     }
 
@@ -221,7 +221,7 @@ public class DefaultDataQuality extends ISOMetadata implements DataQuality {
      * @param  newValue  the new lineage.
      */
     public void setLineage(final Lineage newValue) {
-        checkWritePermission();
+        checkWritePermission(lineage);
         lineage = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultQuantitativeResult.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultQuantitativeResult.java
index 63409a5..aadbc2a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultQuantitativeResult.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultQuantitativeResult.java
@@ -193,7 +193,7 @@ public class DefaultQuantitativeResult extends AbstractResult implements Quantit
      * @param  newValue  the new value type.
      */
     public void setValueType(final RecordType newValue) {
-        checkWritePermission();
+        checkWritePermission(valueType);
         valueType = newValue;
     }
 
@@ -214,7 +214,7 @@ public class DefaultQuantitativeResult extends AbstractResult implements Quantit
      * @param  newValue  the new value unit.
      */
     public void setValueUnit(final Unit<?> newValue) {
-        checkWritePermission();
+        checkWritePermission(valueUnit);
         valueUnit = newValue;
     }
 
@@ -237,7 +237,7 @@ public class DefaultQuantitativeResult extends AbstractResult implements Quantit
      * @param  newValue  the new error statistic.
      */
     public void setErrorStatistic(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(errorStatistic);
         errorStatistic = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultDimension.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultDimension.java
index 892fb24..4d344a0 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultDimension.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultDimension.java
@@ -189,7 +189,7 @@ public class DefaultDimension extends ISOMetadata implements Dimension {
      * @param  newValue  the new dimension name.
      */
     public void setDimensionName(final DimensionNameType newValue) {
-        checkWritePermission();
+        checkWritePermission(dimensionName);
         dimensionName = newValue;
     }
 
@@ -212,7 +212,7 @@ public class DefaultDimension extends ISOMetadata implements Dimension {
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setDimensionSize(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(dimensionSize);
         if (ensurePositive(DefaultDimension.class, "dimensionSize", false, newValue)) {
             dimensionSize = newValue;
         }
@@ -238,8 +238,8 @@ public class DefaultDimension extends ISOMetadata implements Dimension {
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      */
     public void setResolution(final Double newValue) {
-        checkWritePermission();
-        if (ensurePositive(DefaultDimension.class, "dimensionSize", true, newValue)) {
+        checkWritePermission(resolution);
+        if (ensurePositive(DefaultDimension.class, "resolution", true, newValue)) {
             resolution = newValue;
         }
     }
@@ -269,7 +269,7 @@ public class DefaultDimension extends ISOMetadata implements Dimension {
      * @since 0.5
      */
     public void setDimensionTitle(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(dimensionTitle);
         dimensionTitle = newValue;
     }
 
@@ -295,7 +295,7 @@ public class DefaultDimension extends ISOMetadata implements Dimension {
      * @since 0.5
      */
     public void setDimensionDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(dimensionDescription);
         dimensionDescription = newValue;
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCP.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCP.java
index 6b27b06..469a0e3 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCP.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCP.java
@@ -141,7 +141,7 @@ public class DefaultGCP extends ISOMetadata implements GCP {
      * @param  newValue  the new geographic coordinates values.
      */
     public void setGeographicCoordinates(final DirectPosition newValue) {
-        checkWritePermission();
+        checkWritePermission(geographicCoordinates);
         geographicCoordinates = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCPCollection.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCPCollection.java
index c62295b..22d7793 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCPCollection.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGCPCollection.java
@@ -157,7 +157,7 @@ public class DefaultGCPCollection extends AbstractGeolocationInformation impleme
      * @param  newValue  the new collection identifier value.
      */
     public void setCollectionIdentification(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(collectionIdentification);
         collectionIdentification = newValue;
     }
 
@@ -178,7 +178,7 @@ public class DefaultGCPCollection extends AbstractGeolocationInformation impleme
      * @param  newValue  the new collection name.
      */
     public void setCollectionName(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(collectionName);
         collectionName = newValue;
     }
 
@@ -199,7 +199,7 @@ public class DefaultGCPCollection extends AbstractGeolocationInformation impleme
      * @param  newValue  the new coordinate reference system value.
      */
     public void setCoordinateReferenceSystem(final ReferenceSystem newValue) {
-        checkWritePermission();
+        checkWritePermission(coordinateReferenceSystem);
         coordinateReferenceSystem = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeometricObjects.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeometricObjects.java
index f3af057..0ed0d14 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeometricObjects.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeometricObjects.java
@@ -152,7 +152,7 @@ public class DefaultGeometricObjects extends ISOMetadata implements GeometricObj
      * @param  newValue  the new geometric object type.
      */
     public void setGeometricObjectType(final GeometricObjectType newValue) {
-        checkWritePermission();
+        checkWritePermission(geometricObjectType);
         geometricObjectType = newValue;
     }
 
@@ -175,7 +175,7 @@ public class DefaultGeometricObjects extends ISOMetadata implements GeometricObj
      * @throws IllegalArgumentException if the given value is zero or negative.
      */
     public void setGeometricObjectCount(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(geometricObjectCount);
         if (ensurePositive(DefaultGeometricObjects.class, "geometricObjectCount", true, newValue)) {
             geometricObjectCount = newValue;
         }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
index be472d7..e1ceea0 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
@@ -219,7 +219,7 @@ public class DefaultGeorectified extends DefaultGridSpatialRepresentation implem
      * @param newValue {@code true} if check points are available.
      */
     public void setCheckPointAvailable(final boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(CHECK_POINT_MASK));
         if (newValue) {
             booleans |= CHECK_POINT_MASK;
         } else {
@@ -255,7 +255,7 @@ public class DefaultGeorectified extends DefaultGridSpatialRepresentation implem
      * @param  newValue  the new check point description.
      */
     public void setCheckPointDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(checkPointDescription);
         checkPointDescription = newValue;
         if (newValue != null) {
             booleans |= CHECK_POINT_MASK;
@@ -308,7 +308,7 @@ public class DefaultGeorectified extends DefaultGridSpatialRepresentation implem
      * @param  newValue  the new center point.
      */
     public void setCenterPoint(final Point newValue) {
-        checkWritePermission();
+        checkWritePermission(centerPoint);
         centerPoint = newValue;
     }
 
@@ -329,7 +329,7 @@ public class DefaultGeorectified extends DefaultGridSpatialRepresentation implem
      * @param  newValue  the new point in a pixel.
      */
     public void setPointInPixel(final PixelOrientation newValue) {
-        checkWritePermission();
+        checkWritePermission(pointInPixel);
         pointInPixel = newValue;
     }
 
@@ -350,7 +350,7 @@ public class DefaultGeorectified extends DefaultGridSpatialRepresentation implem
      * @param  newValue  the new general description.
      */
     public void setTransformationDimensionDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(transformationDimensionDescription);
         transformationDimensionDescription = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeoreferenceable.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeoreferenceable.java
index ebd42db..fe3f168 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeoreferenceable.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeoreferenceable.java
@@ -187,7 +187,7 @@ public class DefaultGeoreferenceable extends DefaultGridSpatialRepresentation im
      * @param newValue {@code true} if control points are available.
      */
     public void setControlPointAvailable(final boolean newValue) {
-       checkWritePermission();
+       checkWritePermission(isDefined(CONTROL_POINT_MASK));
         if (newValue) {
             booleans |= CONTROL_POINT_MASK;
         } else {
@@ -212,7 +212,7 @@ public class DefaultGeoreferenceable extends DefaultGridSpatialRepresentation im
      * @param newValue {@code true} if orientation parameter are available.
      */
     public void setOrientationParameterAvailable(final boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(OPERATION_MASK));
         if (newValue) {
             booleans |= OPERATION_MASK;
         } else {
@@ -237,7 +237,7 @@ public class DefaultGeoreferenceable extends DefaultGridSpatialRepresentation im
      * @param  newValue  the new orientation parameter description.
      */
     public void setOrientationParameterDescription(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(orientationParameterDescription);
         orientationParameterDescription = newValue;
     }
 
@@ -258,7 +258,7 @@ public class DefaultGeoreferenceable extends DefaultGridSpatialRepresentation im
      * @param  newValue  the new georeferenced parameters.
      */
     public void setGeoreferencedParameters(final Record newValue) {
-        checkWritePermission();
+        checkWritePermission(georeferencedParameters);
         georeferencedParameters = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGridSpatialRepresentation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGridSpatialRepresentation.java
index 53d5ca7..1d1a6d7 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGridSpatialRepresentation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGridSpatialRepresentation.java
@@ -203,7 +203,7 @@ public class DefaultGridSpatialRepresentation extends AbstractSpatialRepresentat
      * @throws IllegalArgumentException if the given value is negative.
      */
     public void setNumberOfDimensions(final Integer newValue) {
-        checkWritePermission();
+        checkWritePermission(numberOfDimensions);
         if (ensurePositive(DefaultGridSpatialRepresentation.class, "numberOfDimensions", false, newValue)) {
             numberOfDimensions = newValue;
         }
@@ -226,9 +226,7 @@ public class DefaultGridSpatialRepresentation extends AbstractSpatialRepresentat
      * @param  newValues  the new axis dimension properties.
      */
     public void setAxisDimensionProperties(final List<? extends Dimension> newValues) {
-        checkWritePermission();
-        axisDimensionProperties = (List<Dimension>)
-                writeCollection(newValues, axisDimensionProperties, Dimension.class);
+        axisDimensionProperties = writeList(newValues, axisDimensionProperties, Dimension.class);
     }
 
     /**
@@ -248,11 +246,18 @@ public class DefaultGridSpatialRepresentation extends AbstractSpatialRepresentat
      * @param  newValue  the new cell geometry.
      */
     public void setCellGeometry(final CellGeometry newValue) {
-        checkWritePermission();
+        checkWritePermission(cellGeometry);
         cellGeometry = newValue;
     }
 
     /**
+     * Returns {@link Boolean#TRUE} if the given flag is set, or {@code null} otherwise.
+     */
+    final Boolean isDefined(final byte mask) {
+        return (booleans & mask) != 0 ? Boolean.TRUE : null;
+    }
+
+    /**
      * Returns indication of whether or not parameters for transformation exists.
      *
      * @return whether or not parameters for transformation exists.
@@ -269,7 +274,7 @@ public class DefaultGridSpatialRepresentation extends AbstractSpatialRepresentat
      * @param newValue {@code true} if the transformation parameters are available.
      */
     public void setTransformationParameterAvailable(final boolean newValue) {
-        checkWritePermission();
+        checkWritePermission(isDefined(TRANSFORMATION_MASK));
         if (newValue) {
             booleans |= TRANSFORMATION_MASK;
         } else {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultVectorSpatialRepresentation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultVectorSpatialRepresentation.java
index c853abd..28071f1 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultVectorSpatialRepresentation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultVectorSpatialRepresentation.java
@@ -132,7 +132,7 @@ public class DefaultVectorSpatialRepresentation extends AbstractSpatialRepresent
      * @param  newValue  the new topology level.
      */
     public void setTopologyLevel(final TopologyLevel newValue) {
-        checkWritePermission();
+        checkWritePermission(topologyLevel);
         topologyLevel = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
index 1ca0e4a..4a43928 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
@@ -183,11 +183,15 @@ final class MetadataFallback extends MetadataSource {
                 break;
             }
             case Constants.PROJ4: {
-                title = "Proj";
+                title     = "Proj";
+                code      = "Proj4";
+                codeSpace = "OSGeo";
                 break;
             }
             case "IHO S-57": {
-                title = "S-57";
+                title = code     = "S-57";
+                codeSpace        = "IHO";
+                version          = "3.1";
                 presentationForm = PresentationForm.DOCUMENT_DIGITAL;
                 break;
             }


Mime
View raw message