Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -40,7 +40,6 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.referencing.ObjectFactory;
 import org.opengis.referencing.AuthorityFactory;
 import org.opengis.referencing.IdentifiedObject;
-import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.jaxb.referencing.Code;
 import org.apache.sis.internal.util.Numerics;
@@ -48,7 +47,6 @@ import org.apache.sis.internal.util.Unmo
 import org.apache.sis.internal.metadata.NameToIdentifier;
 import org.apache.sis.internal.referencing.WKTUtilities;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
-import org.apache.sis.internal.referencing.NilReferencingObject;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.io.wkt.Formatter;
@@ -67,7 +65,6 @@ import static org.apache.sis.util.Utilit
 import static org.apache.sis.internal.util.CollectionsExt.nonNull;
 import static org.apache.sis.internal.util.CollectionsExt.nonEmpty;
 import static org.apache.sis.internal.util.CollectionsExt.immutableSet;
-import static org.apache.sis.internal.util.Utilities.appendUnicodeIdentifier;
 
 // Branch-dependent imports
 import org.opengis.referencing.ReferenceIdentifier;
@@ -128,7 +125,7 @@ import org.apache.sis.internal.jdk7.Obje
  * @version 0.7
  * @module
  */
-@XmlType(name="IdentifiedObjectType", propOrder={
+@XmlType(name = "IdentifiedObjectType", propOrder = {
     "description",
     "identifier",
     "names",
@@ -208,9 +205,13 @@ public class AbstractIdentifiedObject ex
 
     /**
      * Comments on or information about this object, or {@code null} if none.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setRemarks(InternationalString)}</p>
+     *
+     * @see #getRemarks()
      */
-    @XmlElement
-    private final InternationalString remarks;
+    private InternationalString remarks;
 
     /**
      * {@code true} if this object is deprecated.
@@ -526,7 +527,7 @@ public class AbstractIdentifiedObject ex
      *
      * @since 0.6
      */
-    @XmlElement
+    @XmlElement(name = "description")
     public InternationalString getDescription() {
         final ReferenceIdentifier name = getName();
         if (name instanceof ImmutableIdentifier) {
@@ -546,7 +547,8 @@ public class AbstractIdentifiedObject ex
      * @return The remarks, or {@code null} if none.
      */
     @Override
-    public InternationalString getRemarks(){
+    @XmlElement(name = "remarks")
+    public InternationalString getRemarks() {
         return remarks;
     }
 
@@ -900,17 +902,16 @@ public class AbstractIdentifiedObject ex
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     AbstractIdentifiedObject() {
-        remarks = null;
         deprecated = false;
     }
 
     /**
      * The {@code gml:id}, which is mandatory. The current implementation 
searches for the first identifier,
-     * regardless its authority. If no identifier is found, then the name is 
used.
-     * If no name is found (which should not occur for valid objects), then 
this method returns {@code null}.
+     * regardless its authority. If no identifier is found, then the name or 
aliases are used. If none of the
+     * above is found (which should not occur for valid objects), then this 
method returns {@code null}.
      *
-     * <p>If an identifier has been found, this method returns the 
concatenation of the following elements
-     * separated by hyphens:</p>
+     * <p>If an identifier or a name has been found, this method returns the 
concatenation of the following
+     * elements separated by hyphens:</p>
      * <ul>
      *   <li>The code space in lower case, retaining only characters that are 
valid for Unicode identifiers.</li>
      *   <li>The object type as defined in OGC's URN (see {@link 
org.apache.sis.internal.util.DefinitionURI})</li>
@@ -928,59 +929,9 @@ public class AbstractIdentifiedObject ex
     @XmlAttribute(name = "id", namespace = Namespaces.GML, required = true)
     @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
     final String getID() {
-        final Context context = Context.current();
-        String candidate = Context.getObjectID(context, this);
-        if (candidate == null) {
-            final StringBuilder id = new StringBuilder();
-            /*
-             * We will iterate over the identifiers first. Only after the 
iteration is over,
-             * if we found no suitable ID, then we will use the primary name 
as a last resort.
-             */
-            if (identifiers != null) {
-                for (final ReferenceIdentifier identifier : identifiers) {
-                    if (appendUnicodeIdentifier(id, '-', 
identifier.getCodeSpace(), ":", true) | // Really |, not ||
-                        appendUnicodeIdentifier(id, '-', 
NameMeaning.toObjectType(getClass()), ":", false) |
-                        appendUnicodeIdentifier(id, '-', identifier.getCode(), 
":", true))
-                    {
-                        /*
-                         * Check for ID uniqueness. If the ID is rejected, 
then we just need to clear
-                         * the buffer and let the iteration continue the 
search for another ID.
-                         */
-                        candidate = id.toString();
-                        if (Context.setObjectForID(context, this, candidate)) {
-                            return candidate;
-                        }
-                    }
-                    id.setLength(0);    // Clear the buffer for another try.
-                }
-            }
-            /*
-             * In last ressort, use the name or an alias. The name will be 
used without codespace since
-             * names are often verbose. If that name is also used, append a 
number until we find a free ID.
-             */
-            if (name == null || !appendUnicodeIdentifier(id, '-', 
name.getCode(), ":", false)) {
-                if (alias != null) {
-                    for (final GenericName a : alias) {
-                        if (appendUnicodeIdentifier(id, '-', a.toString(), 
":", false)) {
-                            break;
-                        }
-                    }
-                }
-            }
-            if (id.length() != 0) {
-                candidate = id.toString();
-                if (!Context.setObjectForID(context, this, candidate)) {
-                    final int s = id.append('-').length();
-                    int n = 0;
-                    do {
-                        if (++n == 100) return null;    //  Arbitrary limit.
-                        candidate = id.append(n).toString();
-                        id.setLength(s);
-                    } while (!Context.setObjectForID(context, this, 
candidate));
-                }
-            }
-        }
-        return candidate;
+        // Implementation is provided in the NameIterator class for reducing 
the size of
+        // AbstractIdentifiedObject.class file in the common case where XML is 
not needed.
+        return NameIterator.getID(Context.current(), this, name, alias, 
identifiers);
     }
 
     /**
@@ -1009,7 +960,7 @@ public class AbstractIdentifiedObject ex
      *   <li>The first identifier, converted to the {@code "urn:} syntax if 
possible.</li>
      * </ul>
      */
-    @XmlElement(name = "identifier")
+    @XmlElement(required = true)
     final Code getIdentifier() {
         return Code.forIdentifiedObject(getClass(), identifiers);
     }
@@ -1057,6 +1008,13 @@ public class AbstractIdentifiedObject ex
      * by all {@linkplain AbstractIdentifiedObject#getAlias() aliases} which 
are instance of {@link Identifier}.
      * Used by JAXB only at (un)marshalling time because GML merges the name 
and aliases in a single {@code <gml:name>}
      * property.
+     *
+     * <div class="section">Why we do not use {@code Identifier[]} array 
instead</div>
+     * It would be easier to define a {@code getNames()} method returning all 
identifiers in an array, and let JAXB
+     * invoke {@code setNames(Identifier[])} at unmarshalling time.  But 
methods expecting an array in argument are
+     * invoked by JAXB only after the full element has been unmarshalled. For 
some {@code AbstractIdentifiedObject}
+     * subclasses, this is too late. For example {@code 
DefaultOperationMethod} may need to know the operation name
+     * before to parse the parameters.
      */
     private final class Names extends AbstractCollection<ReferenceIdentifier> {
         /**
@@ -1094,46 +1052,51 @@ public class AbstractIdentifiedObject ex
          */
         @Override
         public boolean add(final ReferenceIdentifier id) {
-            addName(id);
+            if (NameIterator.isUnnamed(name)) {
+                name = id;
+            } else {
+                /*
+                 * Our Code and RS_Identifier implementations should always 
create NamedIdentifier instance,
+                 * so the 'instanceof' check should not be necessary. But we 
do a paranoiac check anyway.
+                 */
+                final GenericName n = id instanceof GenericName ? 
(GenericName) id : new NamedIdentifier(id);
+                if (alias == null) {
+                    alias = Collections.singleton(n);
+                } else {
+                    /*
+                     * This implementation is inefficient since each addition 
copies the array, but we rarely
+                     * have more than two aliases.  This implementation is 
okay for a small number of aliases
+                     * and ensures that the enclosing AbstractIdentifiedObject 
is unmodifiable except by this
+                     * add(…) method.
+                     *
+                     * Note about alternative approaches
+                     * ---------------------------------
+                     * An alternative approach could be to use an ArrayList 
and replace it by an unmodifiable
+                     * list only after unmarshalling (using an 
afterUnmarshal(Unmarshaller, Object) method),
+                     * but we want to avoid Unmarshaller dependency (for 
reducing classes loading for users
+                     * who are not interrested in XML) and it may actually be 
less efficient for the vast
+                     * majority of cases where there is less than 3 aliases.
+                     */
+                    final int size = alias.size();
+                    final GenericName[] names = alias.toArray(new 
GenericName[size + 1]);
+                    names[size] = n;
+                    alias = UnmodifiableArrayList.wrap(names);
+                }
+            }
             return true;
         }
     }
 
     /**
-     * Implementation of {@link Names#add(Identifier)}, defined in the 
enclosing class
-     * for access to private fields without compiler-generated bridge methods.
+     * Invoked by JAXB for setting the remarks.
+     *
+     * @see #getRemarks()
      */
-    final void addName(final ReferenceIdentifier id) {
-        if (name == NilReferencingObject.UNNAMED) {
-            name = id;
+    private void setRemarks(final InternationalString value) {
+        if (remarks == null) {
+            remarks = value;
         } else {
-            /*
-             * Our Code and RS_Identifier implementations should always create 
NamedIdentifier instance,
-             * so the 'instanceof' check should not be necessary. But we do a 
paranoiac check anyway.
-             */
-            final GenericName n = id instanceof GenericName ? (GenericName) id 
: new NamedIdentifier(id);
-            if (alias == null) {
-                alias = Collections.singleton(n);
-            } else {
-                /*
-                 * This implementation is inefficient since each addition 
copies the array, but we rarely
-                 * have more than two aliases.  This implementation is okay 
for a small number of aliases
-                 * and ensures that the enclosing AbstractIdentifiedObject is 
unmodifiable except by this
-                 * add(…) method.
-                 *
-                 * Note about alternative approaches
-                 * ---------------------------------
-                 * An alternative approach could be to use an ArrayList and 
replace it by an unmodifiable
-                 * list only after unmarshalling (using an 
afterUnmarshal(Unmarshaller, Object) method),
-                 * but we want to avoid Unmarshaller dependency (for reducing 
classes loading for users
-                 * who are not interrested in XML) and it may actually be less 
efficient for the vast
-                 * majority of cases where there is less than 3 aliases.
-                 */
-                final int size = alias.size();
-                final GenericName[] names = alias.toArray(new GenericName[size 
+ 1]);
-                names[size] = n;
-                alias = UnmodifiableArrayList.wrap(names);
-            }
+            
ReferencingUtilities.propertyAlreadySet(AbstractIdentifiedObject.class, 
"setRemarks", "remarks");
         }
     }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractReferenceSystem.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractReferenceSystem.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractReferenceSystem.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractReferenceSystem.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -19,13 +19,17 @@ package org.apache.sis.referencing;
 import java.util.Map;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.metadata.extent.Extent;
+import org.apache.sis.util.Workaround;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.iso.Types;
+import org.apache.sis.internal.jaxb.metadata.EX_Extent;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 
 import static org.apache.sis.util.Utilities.deepEquals;
 import static org.apache.sis.util.collection.Containers.property;
@@ -62,7 +66,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @XmlTransient
@@ -75,18 +79,23 @@ public class AbstractReferenceSystem ext
     /**
      * Area for which the (coordinate) reference system is valid.
      *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDomainOfValidity(Extent)}</p>
+     *
      * @see #getDomainOfValidity()
      */
-    private final Extent domainOfValidity;
+    private Extent domainOfValidity;
 
     /**
      * Description of domain of usage, or limitations of usage,
      * for which this (coordinate) reference system object is valid.
      *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setScope(InternationalString)}</p>
+     *
      * @see #getScope()
      */
-    @XmlElement(required = true)
-    private final InternationalString scope;
+    private InternationalString scope;
 
     /**
      * Constructs a reference system from the given properties.
@@ -172,14 +181,17 @@ public class AbstractReferenceSystem ext
     }
 
     /**
-     * Returns the region or timeframe in which this reference system is valid,
-     * or {@code null} if unspecified.
+     * Returns the region or timeframe in which this reference system is 
valid, or {@code null} if unspecified.
      *
      * @return Area or region or timeframe in which this (coordinate) 
reference system is valid, or {@code null}.
      *
      * @see org.apache.sis.metadata.iso.extent.DefaultExtent
      */
     @Override
+    @XmlElement(name = "domainOfValidity")
+    // For an unknown reason, JAXB does not take the adapter declared in 
package-info for this particular property.
+    @Workaround(library = "JDK", version = "1.8")
+    @XmlJavaTypeAdapter(EX_Extent.class)
     public Extent getDomainOfValidity() {
         return domainOfValidity;
     }
@@ -191,6 +203,7 @@ public class AbstractReferenceSystem ext
      *         (coordinate) reference system object is valid, or {@code null}.
      */
     @Override
+    @XmlElement(name ="scope", required = true)
     public InternationalString getScope() {
         return scope;
     }
@@ -263,7 +276,31 @@ public class AbstractReferenceSystem ext
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     AbstractReferenceSystem() {
-        domainOfValidity = null;
-        scope = null;
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getDomainOfValidity()
+     */
+    private void setDomainOfValidity(final Extent value) {
+        if (domainOfValidity == null) {
+            domainOfValidity = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(AbstractReferenceSystem.class, 
"setDomainOfValidity", "domainOfValidity");
+        }
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getScope()
+     */
+    private void setScope(final InternationalString value) {
+        if (scope == null) {
+            scope = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(AbstractReferenceSystem.class, 
"setScope", "scope");
+        }
     }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -37,7 +37,7 @@ import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Deprecable;
 import org.apache.sis.util.resources.Errors;
 
-import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+import static org.apache.sis.util.ArgumentChecks.*;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk8.JDK8;
@@ -754,32 +754,40 @@ public abstract class Builder<B extends
         int next = 0;
         int insertAt = aliases.size();
         for (int i = -1; i < aliases.size(); i++) {
-            final Object name = (i < 0) ? 
properties.get(IdentifiedObject.NAME_KEY) : aliases.get(i);
-            if (name != null) {  // Actually only the primary name can be null.
-                final boolean isIdentifier = (name instanceof Identifier);
-                if (authority.equals(isIdentifier ? ((Identifier) 
name).getAuthority() : getAuthority())) {
-                    /*
-                     * Found a name associated to the given authority. Process 
to the replacement if we still
-                     * have some elements to take in the 'replacements' array, 
otherwise remove the name.
-                     */
-                    if (next < length) {
-                        final CharSequence code = replacements[next++];
-                        if (!code.toString().equals(isIdentifier ? 
((Identifier) name).getCode() : name.toString())) {
-                            if (i < 0) {
-                                properties.put(IdentifiedObject.NAME_KEY, 
(authority != getAuthority())
-                                        ? new NamedIdentifier(authority, code) 
: code.toString());
-                            } else {
-                                aliases.set(i, createName(authority, code));
-                            }
-                            insertAt = i + 1;
-                        }
+            final Object old = (i < 0) ? 
properties.get(IdentifiedObject.NAME_KEY) : aliases.get(i);
+            if (old == null) {
+                continue;       // Actually only the primary name can be null.
+            }
+            final boolean wasID = (old instanceof Identifier);   // Usually 
true even for aliases.
+            if (!authority.equals(wasID ? ((Identifier) old).getAuthority() : 
getAuthority())) {
+                continue;       // Current name is not for the authority we 
are looking for.
+            }
+            /*
+             * Found a name associated to the given authority. Process to the 
replacement if we still
+             * have some elements to take in the 'replacements' array, 
otherwise remove the name.
+             */
+            if (next < length) {
+                final CharSequence name;
+                ensureNonNullElement("replacements", next, name = 
replacements[next++]);
+                /*
+                 * If the current name matches the specified replacement, we 
can leave the name as-is.
+                 * Only if the name (in its local part) is not the same, 
proceed to the replacement.
+                 */
+                final String code = name.toString();
+                if (!code.equals(wasID ? ((Identifier) old).getCode() : 
old.toString())) {
+                    if (i < 0) {
+                        properties.put(IdentifiedObject.NAME_KEY,
+                                (authority != getAuthority()) ? new 
NamedIdentifier(authority, name) : code);
                     } else {
-                        if (i < 0) {
-                            properties.remove(IdentifiedObject.NAME_KEY);
-                        } else {
-                            aliases.remove(i--);
-                        }
+                        aliases.set(i, createName(authority, name));
                     }
+                    insertAt = i + 1;
+                }
+            } else {
+                if (i < 0) {
+                    properties.remove(IdentifiedObject.NAME_KEY);
+                } else {
+                    aliases.remove(i--);
                 }
             }
         }
@@ -788,7 +796,9 @@ public abstract class Builder<B extends
          * element of the given authority that we found (so we keep together 
the names of the same authority).
          */
         while (next < length) {
-            aliases.add(insertAt++, createName(authority, 
replacements[next++]));
+            final CharSequence name;
+            ensureNonNullElement("replacements", next, name = 
replacements[next++]);
+            aliases.add(insertAt++, createName(authority, name));
         }
         /*
          * If the primary name has been removed as a result of this method 
execution,

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/NameIterator.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -17,24 +17,29 @@
 package org.apache.sis.referencing;
 
 import java.util.Iterator;
+import java.util.Collection;
 import org.opengis.util.GenericName;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.ReferenceIdentifier;
+import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.internal.referencing.NilReferencingObject;
 
+import static org.apache.sis.internal.util.Utilities.appendUnicodeIdentifier;
+
 
 /**
  * An iterator over the {@linkplain IdentifiedObject#getName() name} of an 
identified object followed by
  * {@linkplain IdentifiedObject#getAlias() aliases} which are instance of 
{@link ReferenceIdentifier}.
- * This iterator is used for {@link AbstractIdentifiedObject} marshalling 
because GML merges the name and
- * aliases in a single {@code <gml:name>} property.
+ * This iterator is used for {@link AbstractIdentifiedObject} XML marshalling 
because GML merges the name
+ * and aliases in a single {@code <gml:name>} property. However this iterator 
is useful only if the aliases
+ * are instances of {@link NamedIdentifier}, or any other implementation which 
is both a name and an identifier.
  *
- * <p>Note that this iterator is useful only if the aliases are instances of 
{@link NamedIdentifier},
- * or any other implementation which is both a name and an identifier.</p>
+ * <p>This class also opportunistically provide helper methods for {@link 
AbstractIdentifiedObject} marshalling.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 final class NameIterator implements Iterator<ReferenceIdentifier> {
@@ -55,12 +60,19 @@ final class NameIterator implements Iter
         alias = object.getAlias().iterator();
         next = object.getName();
         // Should never be null in a well-formed IdentifiedObject, but let be 
safe.
-        if (next == null || next == NilReferencingObject.UNNAMED) {
+        if (isUnnamed(next)) {
             next();
         }
     }
 
     /**
+     * Returns {@code true} if the given identifier is null or the {@link 
NilReferencingObject#UNNAMED} instance.
+     */
+    static boolean isUnnamed(final ReferenceIdentifier name) {
+        return (name == null) || (name == NilReferencingObject.UNNAMED);
+    }
+
+    /**
      * Returns {@code true} if there is an other name or alias to return.
      */
     @Override
@@ -108,4 +120,87 @@ final class NameIterator implements Iter
         }
         return c;
     }
+
+    /**
+     * Implementation of {@link AbstractIdentifiedObject#getID()}, provided 
here for reducing the amount of code
+     * to load in the common case where XML support is not needed.
+     *
+     * <p>The current implementation searches for the first identifier, 
regardless its authority.
+     * If no identifier is found, then the name and aliases are used.
+     * Then, this method returns the concatenation of the following elements 
separated by hyphens:</p>
+     * <ul>
+     *   <li>The code space in lower case, retaining only characters that are 
valid for Unicode identifiers.</li>
+     *   <li>The object type as defined in OGC's URN (see {@link 
org.apache.sis.internal.util.DefinitionURI})</li>
+     *   <li>The object code, retaining only characters that are valid for 
Unicode identifiers.</li>
+     * </ul>
+     *
+     * Example: {@code "epsg-crs-4326"}.
+     *
+     * <p>The returned ID needs to be unique only in the XML document being 
marshalled.
+     * Consecutive invocations of this method do not need to return the same 
value,
+     * since it may depends on the marshalling context.</p>
+     *
+     * @param  context     The (un)marshalling context.
+     * @param  object      The object for which to get a {@code gml:id}.
+     * @param  name        The identified object name, or {@code null} if none.
+     * @param  alias       The identified object aliases, or {@code null} if 
none.
+     * @param  identifiers The identifiers, or {@code null} if none.
+     * @return Proposed value for {@code gml:id} attribute, or {@code null} if 
none.
+     */
+    static String getID(final Context context, final IdentifiedObject object, 
final ReferenceIdentifier name,
+            final Collection<? extends GenericName> alias, final Collection<? 
extends ReferenceIdentifier> identifiers)
+    {
+        String candidate = Context.getObjectID(context, object);
+        if (candidate == null) {
+            final StringBuilder id = new StringBuilder();
+            /*
+             * We will iterate over the identifiers first. Only after the 
iteration is over,
+             * if we found no suitable ID, then we will use the primary name 
as a last resort.
+             */
+            if (identifiers != null) {
+                for (final ReferenceIdentifier identifier : identifiers) {
+                    if (appendUnicodeIdentifier(id, '-', 
identifier.getCodeSpace(), ":", true) |    // Really |, not ||
+                        appendUnicodeIdentifier(id, '-', 
NameMeaning.toObjectType(object.getClass()), ":", false) |
+                        appendUnicodeIdentifier(id, '-', identifier.getCode(), 
":", true))
+                    {
+                        /*
+                         * Check for ID uniqueness. If the ID is rejected, 
then we just need to clear
+                         * the buffer and let the iteration continue the 
search for another ID.
+                         */
+                        candidate = id.toString();
+                        if (Context.setObjectForID(context, object, 
candidate)) {
+                            return candidate;
+                        }
+                    }
+                    id.setLength(0);    // Clear the buffer for another try.
+                }
+            }
+            /*
+             * In last ressort, use the name or an alias. The name will be 
used without codespace since
+             * names are often verbose. If that name is also used, append a 
number until we find a free ID.
+             */
+            if (isUnnamed(name) || !appendUnicodeIdentifier(id, '-', 
name.getCode(), ":", false)) {
+                if (alias != null) {
+                    for (final GenericName a : alias) {
+                        if (appendUnicodeIdentifier(id, '-', a.toString(), 
":", false)) {
+                            break;
+                        }
+                    }
+                }
+            }
+            if (id.length() != 0) {
+                candidate = id.toString();
+                if (!Context.setObjectForID(context, object, candidate)) {
+                    final int s = id.append('-').length();
+                    int n = 0;
+                    do {
+                        if (++n == 100) return null;    //  Arbitrary limit.
+                        candidate = id.append(n).toString();
+                        id.setLength(s);
+                    } while (!Context.setObjectForID(context, object, 
candidate));
+                }
+            }
+        }
+        return candidate;
+    }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -80,13 +80,16 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see AbstractCS
  * @see org.apache.sis.referencing.datum.AbstractDatum
  */
-@XmlType(name="AbstractCRSType")
+@XmlType(name = "AbstractCRSType", propOrder = {
+    "domainOfValidity",
+    "scope"
+})
 @XmlRootElement(name = "AbstractCRS")
 @XmlSeeAlso({
     AbstractDerivedCRS.class,
@@ -511,6 +514,12 @@ public class AbstractCRS extends Abstrac
      */
     AbstractCRS() {
         
super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
+        /*
+         * The coordinate system is mandatory for SIS working. We do not 
verify its presence here
+         * because the verification would have to be done in an 
'afterMarshal(…)' method and throwing
+         * an exception in that method causes the whole unmarshalling to fail. 
But the SC_CRS adapter
+         * does some verifications.
+         */
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -59,7 +59,7 @@ import static org.apache.sis.util.Utilit
  * @version 0.6
  * @module
  */
-@XmlType(name="AbstractGeneralDerivedCRSType")
+@XmlType(name = "AbstractGeneralDerivedCRSType")
 @XmlRootElement(name = "AbstractGeneralDerivedCRS")
 @XmlSeeAlso({
     DefaultDerivedCRS.class,
@@ -312,7 +312,7 @@ abstract class AbstractDerivedCRS<C exte
                 
ReferencingUtilities.propertyAlreadySet(AbstractDerivedCRS.class, "setBaseCRS", 
name);
             }
         } else {
-            throw new 
IllegalStateException(Errors.format(Errors.Keys.MissingValueForProperty_1, 
"conversion"));
+            throw new 
IllegalStateException(Errors.format(Errors.Keys.MissingComponentInElement_2, 
getInterface(), "conversion"));
         }
     }
 

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.List;
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import javax.xml.bind.annotation.XmlType;
@@ -112,7 +113,7 @@ import static org.apache.sis.internal.re
  * @version 0.7
  * @module
  */
-@XmlType(name="CompoundCRSType")
+@XmlType(name = "CompoundCRSType")
 @XmlRootElement(name = "CompoundCRS")
 public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
     /**
@@ -341,6 +342,7 @@ public class DefaultCompoundCRS extends
     @SuppressWarnings("unchecked")
     private void readObject(final ObjectInputStream in) throws IOException, 
ClassNotFoundException {
         in.defaultReadObject();
+        final List<? extends CoordinateReferenceSystem> components = 
this.components;
         if (components instanceof CheckedContainer<?>) {
             final Class<?> type = ((CheckedContainer<?>) 
components).getElementType();
             if (type == SingleCRS.class) {
@@ -538,13 +540,11 @@ public class DefaultCompoundCRS extends
             crs = getSingleComponents();
             isStandardCompliant = isStandardCompliant(crs);
         }
-        if (crs != null) {    // Should never be null, except e.g. if 
unmarshalling invalid GML.
-            for (final CoordinateReferenceSystem element : crs) {
-                formatter.newLine();
-                formatter.append(toFormattable(element));
-            }
-            formatter.newLine();    // For writing the ID[…] element on its 
own line.
+        for (final CoordinateReferenceSystem element : crs) {
+            formatter.newLine();
+            formatter.append(toFormattable(element));
         }
+        formatter.newLine();    // For writing the ID[…] element on its own 
line.
         if (!isStandardCompliant) {
             formatter.setInvalidWKT(this, null);
         }
@@ -566,11 +566,19 @@ public class DefaultCompoundCRS extends
     
//////////////////////////////////////////////////////////////////////////////////////////////////
 
     /**
-     * Constructs a new object in which every attributes are set to a null 
value.
-     * <strong>This is not a valid object.</strong> This constructor is 
strictly
-     * reserved to JAXB, which will assign values to the fields using 
reflexion.
+     * Constructs a new object in which every attributes are set to a null or 
empty value.
+     * <strong>This is not a valid object.</strong> This constructor is 
strictly reserved
+     * to JAXB, which will assign values to the fields using reflexion.
      */
     private DefaultCompoundCRS() {
+        components = Collections.emptyList();
+        singles    = Collections.emptyList();
+        /*
+         * At least one component CRS is mandatory for SIS working. We do not 
verify their presence here
+         * because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does
+         * some verifications (indirectly, by testing for coordinate system 
existence).
+         */
     }
 
     /**
@@ -590,7 +598,7 @@ public class DefaultCompoundCRS extends
     @XmlElement(name = "componentReferenceSystem", required = true)
     private CoordinateReferenceSystem[] getXMLComponents() {
         final List<SingleCRS> crs = getSingleComponents();
-        return (crs != null) ? crs.toArray(new 
CoordinateReferenceSystem[crs.size()]) : null;
+        return crs.toArray(new CoordinateReferenceSystem[crs.size()]);
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -452,7 +452,7 @@ public class DefaultDerivedCRS extends A
      * @return The coordinate system.
      */
     @Override
-    @XmlElement(name="coordinateSystem", required = true)
+    @XmlElement(name = "coordinateSystem", required = true)
     @XmlJavaTypeAdapter(CS_CoordinateSystem.class)
     public CoordinateSystem getCoordinateSystem() {
         return super.getCoordinateSystem();

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -26,6 +26,7 @@ import org.opengis.referencing.crs.Engin
 import org.opengis.referencing.datum.EngineeringDatum;
 import org.apache.sis.referencing.cs.*;
 import org.apache.sis.referencing.AbstractReferenceSystem;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.io.wkt.Formatter;
 
@@ -58,7 +59,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @XmlType(name = "EngineeringCRSType", propOrder = {
@@ -74,9 +75,13 @@ public class DefaultEngineeringCRS exten
 
     /**
      * The datum.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDatum(EngineeringDatum)}</p>
+     *
+     * @see #getDatum()
      */
-    @XmlElement(name = "engineeringDatum", required = true)
-    private final EngineeringDatum datum;
+    private EngineeringDatum datum;
 
     /**
      * Creates a coordinate reference system from the given properties, datum 
and coordinate system.
@@ -189,7 +194,8 @@ public class DefaultEngineeringCRS exten
      * @return The datum.
      */
     @Override
-    public final EngineeringDatum getDatum() {
+    @XmlElement(name = "engineeringDatum", required = true)
+    public EngineeringDatum getDatum() {
         return datum;
     }
 
@@ -265,7 +271,25 @@ public class DefaultEngineeringCRS exten
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultEngineeringCRS() {
-        datum = null;
+        /*
+         * The datum and the coordinate system are mandatory for SIS working. 
We do not verify their presence
+         * here because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDatum()
+     */
+    private void setDatum(final EngineeringDatum value) {
+        if (datum == null) {
+            datum = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultEngineeringCRS.class, 
"setDatum", "engineeringDatum");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -55,7 +55,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @XmlType(name = "GeodeticCRSType", propOrder = {
@@ -73,9 +73,13 @@ class DefaultGeodeticCRS extends Abstrac
 
     /**
      * The datum.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDatum(GeodeticDatum)}</p>
+     *
+     * @see #getDatum()
      */
-    @XmlElement(name = "geodeticDatum", required = true)
-    private final GeodeticDatum datum;
+    private GeodeticDatum datum;
 
     /**
      * Creates a coordinate reference system from the given properties, datum 
and coordinate system.
@@ -126,13 +130,15 @@ class DefaultGeodeticCRS extends Abstrac
     /**
      * Returns the datum.
      *
-     * This method is overridden is subclasses for documentation purpose only, 
mostly for showing this method in
-     * the appropriate position in javadoc (instead than at the bottom of the 
page). If {@code DefaultGeodeticCRS}
-     * is made public in a future SIS version, then we should make this method 
final and remove the overridden methods.
+     * This method is overridden is subclasses for documentation purpose only, 
mostly for showing
+     * this method in the appropriate position in javadoc (instead than at the 
bottom of the page).
+     * If {@code DefaultGeodeticCRS} is made public in a future SIS version, 
then we could remove
+     * the overridden methods.
      *
      * @return The datum.
      */
     @Override
+    @XmlElement(name = "geodeticDatum", required = true)
     public GeodeticDatum getDatum() {
         return datum;
     }
@@ -251,7 +257,25 @@ class DefaultGeodeticCRS extends Abstrac
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     DefaultGeodeticCRS() {
-        datum = null;
+        /*
+         * The datum and the coordinate system are mandatory for SIS working. 
We do not verify their presence
+         * here because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDatum()
+     */
+    private void setDatum(final GeodeticDatum value) {
+        if (datum == null) {
+            datum = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultGeodeticCRS.class, 
"setDatum", "geodeticDatum");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -26,6 +26,7 @@ import org.opengis.referencing.crs.Image
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.datum.ImageDatum;
 import org.apache.sis.internal.metadata.WKTKeywords;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.AbstractReferenceSystem;
 import org.apache.sis.io.wkt.Formatter;
@@ -50,7 +51,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @XmlType(name = "ImageCRSType", propOrder = {
@@ -67,9 +68,13 @@ public class DefaultImageCRS extends Abs
 
     /**
      * The datum.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDatum(ImageDatum)}</p>
+     *
+     * @see #getDatum()
      */
-    @XmlElement(name = "imageDatum", required = true)
-    private final ImageDatum datum;
+    private ImageDatum datum;
 
     /**
      * Creates a coordinate reference system from the given properties, datum 
and coordinate system.
@@ -182,7 +187,8 @@ public class DefaultImageCRS extends Abs
      * @return The datum.
      */
     @Override
-    public final ImageDatum getDatum() {
+    @XmlElement(name = "imageDatum", required = true)
+    public ImageDatum getDatum() {
         return datum;
     }
 
@@ -253,7 +259,25 @@ public class DefaultImageCRS extends Abs
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultImageCRS() {
-        datum = null;
+        /*
+         * The datum and the coordinate system are mandatory for SIS working. 
We do not verify their presence
+         * here because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDatum()
+     */
+    private void setDatum(final ImageDatum value) {
+        if (datum == null) {
+            datum = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultImageCRS.class, 
"setDatum", "imageDatum");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -256,7 +256,7 @@ public class DefaultProjectedCRS extends
      * Returns the coordinate system.
      */
     @Override
-    @XmlElement(name="cartesianCS", required = true)
+    @XmlElement(name = "cartesianCS", required = true)
     public final CartesianCS getCoordinateSystem() {
         // See AbstractDerivedCRS.createConversionFromBase(…) for
         // an explanation about why this method is declared final.

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -29,6 +29,7 @@ import org.opengis.referencing.crs.Tempo
 import org.opengis.referencing.datum.TemporalDatum;
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.AbstractReferenceSystem;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.measure.Units;
@@ -56,7 +57,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.datum.DefaultTemporalDatum
@@ -75,9 +76,13 @@ public class DefaultTemporalCRS extends
 
     /**
      * The datum.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDatum(TemporalDatum)}</p>
+     *
+     * @see #getDatum()
      */
-    @XmlElement(name = "temporalDatum", required = true)
-    private final TemporalDatum datum;
+    private TemporalDatum datum;
 
     /**
      * A converter from values in this CRS to values in milliseconds.
@@ -211,7 +216,8 @@ public class DefaultTemporalCRS extends
      * @return The datum.
      */
     @Override
-    public final TemporalDatum getDatum() {
+    @XmlElement(name = "temporalDatum", required = true)
+    public TemporalDatum getDatum() {
         return datum;
     }
 
@@ -321,7 +327,25 @@ public class DefaultTemporalCRS extends
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultTemporalCRS() {
-        datum = null;
+        /*
+         * The datum and the coordinate system are mandatory for SIS working. 
We do not verify their presence
+         * here because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDatum()
+     */
+    private void setDatum(final TemporalDatum value) {
+        if (datum == null) {
+            datum = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultVerticalCRS.class, 
"setDatum", "temporalDatum");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -27,6 +27,7 @@ import org.opengis.referencing.datum.Ver
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.AbstractReferenceSystem;
 import org.apache.sis.internal.metadata.WKTKeywords;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -48,7 +49,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.datum.DefaultVerticalDatum
@@ -67,9 +68,13 @@ public class DefaultVerticalCRS extends
 
     /**
      * The datum.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDatum(VerticalDatum)}</p>
+     *
+     * @see #getDatum()
      */
-    @XmlElement(name = "verticalDatum", required = true)
-    private final VerticalDatum datum;
+    private VerticalDatum datum;
 
     /**
      * Creates a coordinate reference system from the given properties, datum 
and coordinate system.
@@ -182,7 +187,8 @@ public class DefaultVerticalCRS extends
      * @return The datum.
      */
     @Override
-    public final VerticalDatum getDatum() {
+    @XmlElement(name = "verticalDatum", required = true)
+    public VerticalDatum getDatum() {
         return datum;
     }
 
@@ -250,7 +256,25 @@ public class DefaultVerticalCRS extends
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultVerticalCRS() {
-        datum = null;
+        /*
+         * The datum and the coordinate system are mandatory for SIS working. 
We do not verify their presence
+         * here because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail.  
But the SC_CRS adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDatum()
+     */
+    private void setDatum(final VerticalDatum value) {
+        if (datum == null) {
+            datum = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultVerticalCRS.class, 
"setDatum", "verticalDatum");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -119,15 +119,19 @@ final class SubTypes implements Comparat
             if (object instanceof GeocentricCRS) {
                 return DefaultGeocentricCRS.castOrCopy((GeocentricCRS) object);
             }
-            if (object instanceof DefaultGeodeticCRS) {     // Result of XML 
unmarshalling - keep as-is.
-                return (DefaultGeodeticCRS) object;
-            }
             /*
              * The GeographicCRS and GeocentricCRS types are not part of ISO 
19111.
              * ISO uses a single type, GeodeticCRS, for both of them and infer 
the
              * geographic or geocentric type from the coordinate system. We do 
this
-             * check here for instantiating the most appropriate SIS type.
+             * check here for instantiating the most appropriate SIS type, but 
only
+             * if we need to create a new object anyway (see below for 
rational).
              */
+            if (object instanceof DefaultGeodeticCRS) {
+                // Result of XML unmarshalling — keep as-is. We avoid creating 
a new object because it
+                // would break object identities specified in GML document by 
the xlink:href attribute.
+                // However we may revisit this policy in the future. See 
SC_CRS.setElement(AbstractCRS).
+                return (DefaultGeodeticCRS) object;
+            }
             final Map<String,?> properties = 
IdentifiedObjects.getProperties(object);
             final GeodeticDatum datum = ((GeodeticCRS) object).getDatum();
             final CoordinateSystem cs = object.getCoordinateSystem();

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -77,7 +77,9 @@
  * @version 0.7
  * @module
  */
-@XmlSchema(elementFormDefault= XmlNsForm.QUALIFIED, namespace = 
Namespaces.GML, xmlns = {
+@XmlSchema(location = 
"http://schemas.opengis.net/gml/3.2.1/coordinateReferenceSystems.xsd";,
+           elementFormDefault = XmlNsForm.QUALIFIED, namespace = 
Namespaces.GML, xmlns =
+{
     @XmlNs(prefix = "gml", namespaceURI = Namespaces.GML),
     @XmlNs(prefix = "xsi", namespaceURI = Namespaces.XSI)
 })

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -66,7 +66,7 @@ import static org.apache.sis.util.Utilit
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see DefaultCoordinateSystemAxis
@@ -99,9 +99,13 @@ public class AbstractCS extends Abstract
 
     /**
      * The sequence of axes for this coordinate system.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setAxis(CoordinateSystemAxis[])}</p>
+     *
+     * @see #getAxis(int)
      */
-    @XmlElement(name = "axis")
-    private final CoordinateSystemAxis[] axes;
+    private CoordinateSystemAxis[] axes;
 
     /**
      * Other coordinate systems derived from this coordinate systems for other 
axes conventions.
@@ -210,14 +214,18 @@ public class AbstractCS extends Abstract
      */
     protected AbstractCS(final CoordinateSystem cs) {
         super(cs);
-        if (cs instanceof AbstractCS) {
-            axes = ((AbstractCS) cs).axes;  // Share the array.
-        } else {
-            axes = new CoordinateSystemAxis[cs.getDimension()];
-            for (int i=0; i<axes.length; i++) {
-                axes[i] = cs.getAxis(i);
-            }
+        axes = (cs instanceof AbstractCS) ? ((AbstractCS) cs).axes : 
getAxes(cs);
+    }
+
+    /**
+     * Returns the axes of the given coordinate system.
+     */
+    private static CoordinateSystemAxis[] getAxes(final CoordinateSystem cs) {
+        final CoordinateSystemAxis[] axes = new 
CoordinateSystemAxis[cs.getDimension()];
+        for (int i=0; i<axes.length; i++) {
+            axes[i] = cs.getAxis(i);
         }
+        return axes;
     }
 
     /**
@@ -483,5 +491,27 @@ public class AbstractCS extends Abstract
     AbstractCS() {
         
super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
         axes = EMPTY;
+        /*
+         * Coordinate system axes are mandatory for SIS working. We do not 
verify their presence here
+         * (because the verification would have to be done in an 
'afterMarshal(…)' method and throwing
+         * an exception in that method causes the whole unmarshalling to 
fail). But the CS_CoordinateSystem
+         * adapter does some verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at marshalling time.
+     */
+    @XmlElement(name = "axis")
+    private CoordinateSystemAxis[] getAxis() {
+        return getAxes(this);   // Give a chance to users to override 
getAxis(int).
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     */
+    @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
+    private void setAxis(final CoordinateSystemAxis[] values) {
+        axes = values;
     }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -18,6 +18,7 @@ package org.apache.sis.referencing.cs;
 
 import java.util.Map;
 import java.util.List;
+import javax.xml.bind.annotation.XmlTransient;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.apache.sis.internal.metadata.AxisDirections;
@@ -54,6 +55,7 @@ import static org.apache.sis.util.Utilit
  * @version 0.6
  * @module
  */
+@XmlTransient
 public class DefaultCompoundCS extends AbstractCS {
     /**
      * Serial number for inter-operability with different versions.
@@ -168,8 +170,9 @@ public class DefaultCompoundCS extends A
      *
      * @return All coordinate systems in this compound CS.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public List<CoordinateSystem> getComponents() {
-        return components;
+        return components;  // Unmodifiable.
     }
 
     /*

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCoordinateSystemAxis.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -180,22 +180,34 @@ public class DefaultCoordinateSystemAxis
     /**
      * The abbreviation used for this coordinate system axes.
      * Examples are <cite>"X"</cite> and <cite>"Y"</cite>.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setAbbreviation(String)}</p>
+     *
+     * @see #getAbbreviation()
      */
-    @XmlElement(name = "axisAbbrev", required = true)
-    private final String abbreviation;
+    private String abbreviation;
 
     /**
      * Direction of this coordinate system axis. In the case of Cartesian 
projected
      * coordinates, this is the direction of this coordinate system axis 
locally.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDirection(AxisDirection)}</p>
+     *
+     * @see #getDirection()
      */
-    @XmlElement(name = "axisDirection", required = true)
-    private final AxisDirection direction;
+    private AxisDirection direction;
 
     /**
      * The unit of measure used for this coordinate system axis.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setUnit(Unit)}</p>
+     *
+     * @see #getUnit()
      */
-    @XmlAttribute(name= "uom", required = true)
-    private final Unit<?> unit;
+    private Unit<?> unit;
 
     /**
      * Minimal and maximal value for this axis, or negative/positive infinity 
if none.
@@ -208,9 +220,13 @@ public class DefaultCoordinateSystemAxis
 
     /**
      * The range meaning for this axis, or {@code null} if unspecified.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setRangeMeaning(RangeMeaning)}</p>
+     *
+     * @see #getRangeMeaning()
      */
-    @XmlElement
-    private final RangeMeaning rangeMeaning;
+    private RangeMeaning rangeMeaning;
 
     /**
      * Constructs an axis from a set of properties. The properties given in 
argument follow the same rules
@@ -397,6 +413,7 @@ public class DefaultCoordinateSystemAxis
      * @return The direction of this coordinate system axis.
      */
     @Override
+    @XmlElement(name = "axisDirection", required = true)
     public AxisDirection getDirection() {
         return direction;
     }
@@ -408,6 +425,7 @@ public class DefaultCoordinateSystemAxis
      * @return The coordinate system axis abbreviation.
      */
     @Override
+    @XmlElement(name = "axisAbbrev", required = true)
     public String getAbbreviation() {
         return abbreviation;
     }
@@ -420,6 +438,7 @@ public class DefaultCoordinateSystemAxis
      * @return The unit of measure used for ordinate values along this 
coordinate system axis.
      */
     @Override
+    @XmlAttribute(name= "uom", required = true)
     public Unit<?> getUnit() {
         return unit;
     }
@@ -469,6 +488,7 @@ public class DefaultCoordinateSystemAxis
      * @return The meaning of axis value range, or {@code null} if unspecified.
      */
     @Override
+    @XmlElement(name = "rangeMeaning")
     public RangeMeaning getRangeMeaning() {
         return rangeMeaning;
     }
@@ -854,12 +874,66 @@ public class DefaultCoordinateSystemAxis
      */
     private DefaultCoordinateSystemAxis() {
         
super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
-        abbreviation = null;
-        direction    = null;
-        unit         = null;
-        rangeMeaning = null;
         minimumValue = NEGATIVE_INFINITY;
         maximumValue = POSITIVE_INFINITY;
+        /*
+         * Direction and unit of measurement are mandatory for SIS working. We 
do not verify their presence here
+         * because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an exception
+         * in that method causes the whole unmarshalling to fail. But the 
CD_CoordinateSystemAxis adapter does some
+         * verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getAbbreviation()
+     */
+    private void setAbbreviation(final String value) {
+        if (abbreviation == null) {
+            abbreviation = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultCoordinateSystemAxis.class, 
"setAbbreviation", "abbreviation");
+        }
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDirection()
+     */
+    private void setDirection(final AxisDirection value) {
+        if (direction == null) {
+            direction = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultCoordinateSystemAxis.class, 
"setDirection", "direction");
+        }
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getUnit()
+     */
+    private void setUnit(final Unit<?> value) {
+        if (unit == null) {
+            unit = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultCoordinateSystemAxis.class, 
"setUnit", "unit");
+        }
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getRangeMeaning()
+     */
+    private void setRangeMeaning(final RangeMeaning value) {
+        if (rangeMeaning == null) {
+            rangeMeaning = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultCoordinateSystemAxis.class, 
"setRangeMeaning", "rangeMeaning");
+        }
     }
 
     /**

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/package-info.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/package-info.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/package-info.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/package-info.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -34,10 +34,12 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
-@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED, namespace = 
Namespaces.GML, xmlns = {
+@XmlSchema(location = 
"http://schemas.opengis.net/gml/3.2.1/coordinateSystems.xsd";,
+           elementFormDefault = XmlNsForm.QUALIFIED, namespace = 
Namespaces.GML, xmlns =
+{
     @XmlNs(prefix = "gml", namespaceURI = Namespaces.GML),
     @XmlNs(prefix = "xsi", namespaceURI = Namespaces.XSI)
 })

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -65,7 +65,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.cs.AbstractCS
@@ -74,7 +74,7 @@ import org.apache.sis.internal.jdk7.Obje
 @XmlType(name = "AbstractDatumType", propOrder = {
     "domainOfValidity",
     "scope",
-    "anchorDefinition",
+    "anchorPoint",
     "realizationEpoch"
 })
 @XmlRootElement(name = "AbstractDatum")
@@ -99,9 +99,13 @@ public class AbstractDatum extends Abstr
     /**
      * Description, possibly including coordinates, of the point or points 
used to anchor the datum
      * to the Earth. Also known as the "origin", especially for Engineering 
and Image Datums.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setAnchorPoint(InternationalString)}</p>
+     *
+     * @see #getAnchorPoint()
      */
-    @XmlElement
-    private final InternationalString anchorDefinition;
+    private InternationalString anchorDefinition;
 
     /**
      * The time after which this datum definition is valid. This time may be 
precise
@@ -115,15 +119,23 @@ public class AbstractDatum extends Abstr
 
     /**
      * Area or region in which this datum object is valid.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setDomainOfValidity(Extent)}</p>
+     *
+     * @see #getDomainOfValidity()
      */
-    @XmlElement
-    private final Extent domainOfValidity;
+    private Extent domainOfValidity;
 
     /**
      * Description of domain of usage, or limitations of usage, for which this 
datum object is valid.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setScope(InternationalString)}</p>
+     *
+     * @see #getScope()
      */
-    @XmlElement
-    private final InternationalString scope;
+    private InternationalString scope;
 
     /**
      * Creates a datum from the given properties.
@@ -274,6 +286,7 @@ public class AbstractDatum extends Abstr
      * @return Description, possibly including coordinates, of the point or 
points used to anchor the datum to the Earth.
      */
     @Override
+    @XmlElement(name = "anchorDefinition")
     public InternationalString getAnchorPoint() {
         return anchorDefinition;
     }
@@ -302,6 +315,7 @@ public class AbstractDatum extends Abstr
      * @see org.apache.sis.metadata.iso.extent.DefaultExtent
      */
     @Override
+    @XmlElement(name = "domainOfValidity")
     public Extent getDomainOfValidity() {
         return domainOfValidity;
     }
@@ -312,6 +326,7 @@ public class AbstractDatum extends Abstr
      * @return Description of domain of usage, or limitations of usage, for 
which this datum object is valid.
      */
     @Override
+    @XmlElement(name = "scope", required = true)
     public InternationalString getScope() {
         return scope;
     }
@@ -462,14 +477,26 @@ public class AbstractDatum extends Abstr
      */
     AbstractDatum() {
         
super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
-        anchorDefinition = null;
         realizationEpoch = Long.MIN_VALUE;
-        domainOfValidity = null;
-        scope            = null;
     }
 
     /**
      * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getAnchorPoint()
+     */
+    private void setAnchorPoint(final InternationalString value) {
+        if (anchorDefinition == null) {
+            anchorDefinition = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(AbstractDatum.class, 
"setAnchorPoint", "anchorDefinition");
+        }
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getRealizationEpoch()
      */
     private void setRealizationEpoch(final Date value) {
         if (realizationEpoch == Long.MIN_VALUE) {
@@ -478,4 +505,30 @@ public class AbstractDatum extends Abstr
             ReferencingUtilities.propertyAlreadySet(AbstractDatum.class, 
"setRealizationEpoch", "realizationEpoch");
         }
     }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getDomainOfValidity()
+     */
+    private void setDomainOfValidity(final Extent value) {
+        if (domainOfValidity == null) {
+            domainOfValidity = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(AbstractDatum.class, 
"setDomainOfValidity", "domainOfValidity");
+        }
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getScope()
+     */
+    private void setScope(final InternationalString value) {
+        if (scope == null) {
+            scope = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(AbstractDatum.class, 
"setScope", "scope");
+        }
+    }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -31,9 +31,9 @@ import org.opengis.referencing.datum.Ell
 import org.opengis.referencing.ReferenceIdentifier;
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.internal.util.Numerics;
-import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.jaxb.gml.Measure;
 import org.apache.sis.internal.jaxb.referencing.SecondDefiningParameter;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.referencing.IdentifiedObjects;
@@ -112,12 +112,12 @@ import org.apache.sis.internal.jdk7.Obje
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Cédric Briançon (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.referencing.CommonCRS#ellipsoid()
  */
-@XmlType(name="EllipsoidType", propOrder={
+@XmlType(name = "EllipsoidType", propOrder = {
     "semiMajorAxisMeasure",
     "secondDefiningParameter"
 })
@@ -698,8 +698,12 @@ public class DefaultEllipsoid extends Ab
      */
     private DefaultEllipsoid() {
         
super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
-        // We need to let the DefaultEllipsoid fields unitialized
-        // because afterUnmarshal(…) will check for zero values.
+        /*
+         * We need to let the DefaultEllipsoid fields unitialized because 
afterUnmarshal(…)
+         * will check for zero values. We can not thrown an exception from 
'afterUnmarshal'
+         * because it would cause the whole unmarshalling to fail. But the 
CD_Ellipsoid
+         * adapter does some verifications.
+         */
     }
 
     /**
@@ -722,6 +726,7 @@ public class DefaultEllipsoid extends Ab
             }
         }
         if (unit == null) {
+            unit = SI.METRE;
             Measure.missingUOM(DefaultEllipsoid.class, "semiMajorAxis");
         }
     }
@@ -743,13 +748,13 @@ public class DefaultEllipsoid extends Ab
      * @see #afterUnmarshal(Unmarshaller, Object)
      */
     private void setSemiMajorAxisMeasure(final Measure measure) {
-        if (semiMajorAxis != 0) {
-            warnDuplicated("semiMajorAxis");
-        } else {
+        if (semiMajorAxis == 0) {
             final Unit<Length> uom = unit; // In case semi-minor were defined 
before semi-major.
             ensureStrictlyPositive("semiMajorAxis", semiMajorAxis = 
measure.value);
             unit = measure.getUnit(Length.class);
             harmonizeAxisUnits(uom);
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultEllipsoid.class, 
"setSemiMajorAxisMeasure", "semiMajorAxis");
         }
     }
 
@@ -758,7 +763,7 @@ public class DefaultEllipsoid extends Ab
      * returned object contains the values for {@link #semiMinorAxis} or 
{@link #inverseFlattening},
      * according to the {@link #isIvfDefinitive()} value. This method is for 
JAXB marshalling only.
      */
-    @XmlElement(name = "secondDefiningParameter")
+    @XmlElement(name = "secondDefiningParameter", required = true)
     private SecondDefiningParameter getSecondDefiningParameter() {
         return new SecondDefiningParameter(this, true);
     }
@@ -778,9 +783,7 @@ public class DefaultEllipsoid extends Ab
         final Measure measure = second.measure;
         if (measure != null) {
             final boolean isIvfDefinitive = second.isIvfDefinitive();
-            if ((isIvfDefinitive ? inverseFlattening : semiMinorAxis) != 0) {
-                warnDuplicated("secondDefiningParameter");
-            } else {
+            if ((isIvfDefinitive ? inverseFlattening : semiMinorAxis) == 0) {
                 ivfDefinitive = isIvfDefinitive;
                 double value = measure.value;
                 if (isIvfDefinitive) {
@@ -792,6 +795,9 @@ public class DefaultEllipsoid extends Ab
                     ensureStrictlyPositive("semiMinorAxis", semiMinorAxis = 
value);
                     harmonizeAxisUnits(measure.getUnit(Length.class));
                 }
+            } else {
+                ReferencingUtilities.propertyAlreadySet(DefaultEllipsoid.class,
+                        "setSecondDefiningParameter", 
"secondDefiningParameter");
             }
         }
     }
@@ -809,13 +815,4 @@ public class DefaultEllipsoid extends Ab
             semiMinorAxis = uom.getConverterTo(unit).convert(semiMinorAxis);
         }
     }
-
-    /**
-     * Emits a warning telling that the given element is repeated twice.
-     */
-    private static void warnDuplicated(final String element) {
-         // We cheat a bit for the "unmarshal" method name since there is not 
such method...
-        Context.warningOccured(Context.current(), DefaultEllipsoid.class, 
"unmarshal",
-                Errors.class, Errors.Keys.DuplicatedElement_1, element);
-    }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -37,6 +37,7 @@ import org.apache.sis.metadata.iso.exten
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.referencing.ExtentSelector;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.util.logging.Logging;
@@ -122,7 +123,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see DefaultEllipsoid
@@ -153,15 +154,23 @@ public class DefaultGeodeticDatum extend
 
     /**
      * The ellipsoid.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setEllipsoid(Ellipsoid)}</p>
+     *
+     * @see #getEllipsoid()
      */
-    @XmlElement
-    private final Ellipsoid ellipsoid;
+    private Ellipsoid ellipsoid;
 
     /**
      * The prime meridian.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setPrimeMeridian(PrimeMeridian)}</p>
+     *
+     * @see #getPrimeMeridian()
      */
-    @XmlElement
-    private final PrimeMeridian primeMeridian;
+    private PrimeMeridian primeMeridian;
 
     /**
      * Bursa-Wolf parameters for datum shifts, or {@code null} if none.
@@ -313,6 +322,7 @@ public class DefaultGeodeticDatum extend
      * @return The ellipsoid.
      */
     @Override
+    @XmlElement(name = "ellipsoid", required = true)
     public Ellipsoid getEllipsoid() {
         return ellipsoid;
     }
@@ -323,6 +333,7 @@ public class DefaultGeodeticDatum extend
      * @return The prime meridian.
      */
     @Override
+    @XmlElement(name = "primeMeridian", required = true)
     public PrimeMeridian getPrimeMeridian() {
         return primeMeridian;
     }
@@ -590,8 +601,38 @@ public class DefaultGeodeticDatum extend
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultGeodeticDatum() {
-        ellipsoid     = null;
-        primeMeridian = null;
-        bursaWolf     = null;
+        bursaWolf = null;
+        /*
+         * Ellipsoid and PrimeMeridian are mandatory for SIS working. We do 
not verify their presence here
+         * (because the verification would have to be done in an 
'afterMarshal(…)' method and throwing an
+         * exception in that method causes the whole unmarshalling to fail). 
But the CD_GeodeticDatum
+         * adapter does some verifications.
+         */
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getEllipsoid()
+     */
+    private void setEllipsoid(final Ellipsoid value) {
+        if (ellipsoid == null) {
+            ellipsoid = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultGeodeticDatum.class, 
"setEllipsoid", "ellipsoid");
+        }
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getPrimeMeridian()
+     */
+    private void setPrimeMeridian(final PrimeMeridian value) {
+        if (primeMeridian == null) {
+            primeMeridian = value;
+        } else {
+            
ReferencingUtilities.propertyAlreadySet(DefaultGeodeticDatum.class, 
"setPrimeMeridian", "primeMeridian");
+        }
     }
 }

Modified: 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultImageDatum.java
URL: 
http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultImageDatum.java?rev=1709637&r1=1709636&r2=1709637&view=diff
==============================================================================
--- 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultImageDatum.java
 [UTF-8] (original)
+++ 
sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultImageDatum.java
 [UTF-8] Tue Oct 20 16:24:53 2015
@@ -26,6 +26,7 @@ import org.opengis.referencing.Reference
 import org.opengis.referencing.datum.ImageDatum;
 import org.opengis.referencing.datum.PixelInCell;
 import org.apache.sis.internal.metadata.WKTKeywords;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.util.ComparisonMode;
@@ -48,7 +49,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @XmlType(name = "ImageDatumType")
@@ -61,9 +62,13 @@ public class DefaultImageDatum extends A
 
     /**
      * Specification of the way the image grid is associated with the image 
data attributes.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link 
#setPixelInCell(PixelInCell)}</p>
+     *
+     * @see #getPixelInCell()
      */
-    @XmlElement(required = true)
-    private final PixelInCell pixelInCell;
+    private PixelInCell pixelInCell;
 
     /**
      * Creates an image datum from the given properties. The properties map is 
given
@@ -181,6 +186,7 @@ public class DefaultImageDatum extends A
      * @return The way image grid is associated with image data attributes.
      */
     @Override
+    @XmlElement(required = true)
     public PixelInCell getPixelInCell() {
         return pixelInCell;
     }
@@ -266,6 +272,18 @@ public class DefaultImageDatum extends A
      * reserved to JAXB, which will assign values to the fields using 
reflexion.
      */
     private DefaultImageDatum() {
-        pixelInCell = null;
+    }
+
+    /**
+     * Invoked by JAXB only at unmarshalling time.
+     *
+     * @see #getPixelInCell()
+     */
+    private void setPixelInCell(final PixelInCell value) {
+        if (pixelInCell == null) {
+            pixelInCell = value;
+        } else {
+            ReferencingUtilities.propertyAlreadySet(DefaultImageDatum.class, 
"setPixelInCell", "pixelInCell");
+        }
     }
 }



Reply via email to