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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new 193b493363 Improve `DefaultObjectDomain` with the use of `NilObject` for telling when the value is missing. 193b493363 is described below commit 193b4933634c42eb835be176246eb54d12fbf358 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Aug 30 12:30:03 2023 +0200 Improve `DefaultObjectDomain` with the use of `NilObject` for telling when the value is missing. --- .../metadata/internal/ImplementationHelper.java | 17 ++- .../metadata/simple/SimpleIdentifiedObject.java | 6 +- .../main/org/apache/sis/io/wkt/Formatter.java | 10 +- .../sis/referencing/AbstractIdentifiedObject.java | 51 ++++--- .../sis/referencing/DefaultObjectDomain.java | 164 +++++++++++++++------ .../referencing/datum/DefaultGeodeticDatum.java | 38 ++--- .../org/apache/sis/util/resources/Vocabulary.java | 20 ++- 7 files changed, 200 insertions(+), 106 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ImplementationHelper.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ImplementationHelper.java index f0516b2311..48750b280d 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ImplementationHelper.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/ImplementationHelper.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.Objects; +import org.apache.sis.xml.NilObject; import org.apache.sis.xml.NilReason; import org.apache.sis.xml.IdentifierSpace; import org.apache.sis.xml.IdentifiedObject; @@ -37,7 +39,7 @@ import org.apache.sis.util.internal.CollectionsExt; * This is not an helper class for <em>usage</em> of metadata. * * @author Martin Desruisseaux (Geomatys) - * @version 1.3 + * @version 1.4 * @since 0.3 */ public final class ImplementationHelper extends Static { @@ -74,6 +76,19 @@ public final class ImplementationHelper extends Static { return (value != Long.MIN_VALUE) ? new Date(value) : null; } + /** + * Returns {@code true} if the given object is non-null and not an instance of {@link NilObject}. + * This is a helper method for use in lambda expressions. + * + * @param value the value to test. + * @return whether the given value is non-null and non-nil. + * + * @see Objects#nonNull(Object) + */ + public static boolean nonNil(final Object value) { + return (value != null) && !(value instanceof NilObject); + } + /** * Returns the given collection if non-null and non-empty, or {@code null} otherwise. * This method is used for calls to {@code checkWritePermission(Object)}. diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java index d1a948204e..68ccb00b6a 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java @@ -97,7 +97,10 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab * revisit {@link #equals(Object, ComparisonMode)} in subclasses.</p> * * @return the domain of validity, or {@code null} if none. + * + * @deprecated Removed from ISO 19111:2019 (moved to {@code ObjectDomain}). */ + @Deprecated public final Extent getDomainOfValidity() { return null; } @@ -123,10 +126,7 @@ public class SimpleIdentifiedObject implements IdentifiedObject, LenientComparab * The default implementation returns {@link Identifier#getDescription()}. * * @return a narrative explanation of the role of this object, or {@code null} if none. - * - * @deprecated Removed from ISO 19111:2019 (moved to {@code ObjectDomain}). */ - @Deprecated public InternationalString getDescription() { final Identifier name = this.name; return (name != null) ? name.getDescription() : null; diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java index f27c538f41..3431b25267 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java @@ -70,7 +70,6 @@ import org.apache.sis.util.iso.Types; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.resources.Vocabulary; import org.apache.sis.util.collection.IntegerList; -import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.util.internal.X364; import org.apache.sis.util.internal.Numerics; import org.apache.sis.util.internal.Constants; @@ -78,14 +77,15 @@ import org.apache.sis.util.internal.StandardDateFormat; import org.apache.sis.system.Configuration; import org.apache.sis.metadata.simple.SimpleExtent; import org.apache.sis.metadata.internal.Resources; +import org.apache.sis.metadata.iso.extent.Extents; +import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.referencing.AbstractIdentifiedObject; import org.apache.sis.referencing.ImmutableIdentifier; -import org.apache.sis.referencing.DefaultObjectDomain; import org.apache.sis.referencing.util.WKTKeywords; import org.apache.sis.referencing.util.WKTUtilities; import org.apache.sis.geometry.AbstractDirectPosition; import org.apache.sis.geometry.AbstractEnvelope; -import org.apache.sis.metadata.iso.extent.Extents; +import org.apache.sis.xml.NilObject; // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.util.ControlledVocabulary; @@ -918,10 +918,10 @@ public class Formatter implements Localized { * @since 1.4 */ public void append(final InternationalString scope, final Extent area) { - if (DefaultObjectDomain.isDefined(scope)) { + if (scope != null && !(scope instanceof NilObject)) { appendOnNewLine(WKTKeywords.Scope, scope, ElementKind.SCOPE); } - if (DefaultObjectDomain.isDefined(area)) { + if (area != null && !(area instanceof NilObject)) { appendOnNewLine(WKTKeywords.Area, area.getDescription(), ElementKind.EXTENT); append(Extents.getGeographicBoundingBox(area), BBOX_ACCURACY); appendVerticalExtent(Extents.getVerticalRange(area)); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java index 0814928ad3..9740d40462 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java @@ -27,7 +27,6 @@ import java.util.Objects; import java.util.Formattable; import java.util.FormattableFlags; import java.util.function.Function; -import java.util.function.Predicate; import java.io.Serializable; import jakarta.xml.bind.annotation.XmlID; import jakarta.xml.bind.annotation.XmlType; @@ -135,7 +134,7 @@ import org.opengis.referencing.ObjectDomain; "identifier", "names", "remarks", - "domain", // GML defines "domainOfValidity" in Datum, AbstractCRS and AbstractCoordinateOperation. + "domainExtent", // GML defines "domainOfValidity" in Datum, AbstractCRS and AbstractCoordinateOperation. "domainScope" // GML defines "scope" in same classes than above. }) @XmlSeeAlso({ @@ -1062,7 +1061,7 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident */ private void setIdentifier(final Code identifier) { if (identifiers != null) { - ImplementationHelper.propertyAlreadySet(AbstractIdentifiedObject.class, "setIdentifier", "identifier"); + propertyAlreadySet("setIdentifier", "identifier"); } else if (identifier != null) { final Identifier id = identifier.getIdentifier(); if (id != null) { @@ -1180,14 +1179,13 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident /** * Finds the first non-null domain element. * - * @param <T> type of domain element to get. - * @param getter {@link ObjectDomain} getter method to invoke. - * @param predicate the non-null and non-undefined check. + * @param <T> type of domain element to get. + * @param getter {@link ObjectDomain} getter method to invoke. * @return first non-null value, or {@code null} if none. */ - private <T> T findFirst(final Function<ObjectDomain,T> getter, final Predicate<T> isDefined) { + private <T> T findFirst(final Function<ObjectDomain,T> getter) { if (domains == null) return null; - return domains.stream().map(getter).filter(isDefined).findFirst().orElse(null); + return domains.stream().map(getter).filter(ImplementationHelper::nonNil).findFirst().orElse(null); } /** @@ -1200,8 +1198,8 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident // 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) - private Extent getDomain() { - return findFirst(ObjectDomain::getDomainOfValidity, DefaultObjectDomain::isDefined); + private Extent getDomainExtent() { + return findFirst(ObjectDomain::getDomainOfValidity); } /** @@ -1214,21 +1212,21 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident */ @XmlElement(name ="scope") private InternationalString getDomainScope() { - return findFirst(ObjectDomain::getScope, DefaultObjectDomain::isDefined); + return findFirst(ObjectDomain::getScope); } /** * Invoked by JAXB only at unmarshalling time. */ - private void setDomain(final Extent value) { + private void setDomainExtent(final Extent value) { InternationalString scope = null; - final ObjectDomain domain = CollectionsExt.first(domains); + final DefaultObjectDomain domain = DefaultObjectDomain.castOrCopy(CollectionsExt.first(domains)); if (domain != null) { - if (DefaultObjectDomain.isDefined(domain.getDomainOfValidity())) { - ImplementationHelper.propertyAlreadySet(AbstractReferenceSystem.class, "setDomainOfValidity", "domainOfValidity"); + if (domain.domainOfValidity != null) { + propertyAlreadySet("setDomain", "domainOfValidity"); return; } - scope = domain.getScope(); + scope = domain.scope; } domains = Collections.singleton(new DefaultObjectDomain(scope, value)); } @@ -1238,13 +1236,13 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident */ private void setDomainScope(final InternationalString value) { Extent area = null; - final ObjectDomain domain = CollectionsExt.first(domains); + final DefaultObjectDomain domain = DefaultObjectDomain.castOrCopy(CollectionsExt.first(domains)); if (domain != null) { - if (DefaultObjectDomain.isDefined(domain.getScope())) { - ImplementationHelper.propertyAlreadySet(AbstractReferenceSystem.class, "setScope", "scope"); + if (domain.scope != null) { + propertyAlreadySet("setDomainScope", "scope"); return; } - area = domain.getDomainOfValidity(); + area = domain.domainOfValidity; } domains = Collections.singleton(new DefaultObjectDomain(value, area)); } @@ -1258,7 +1256,18 @@ public class AbstractIdentifiedObject extends FormattableObject implements Ident if (remarks == null) { remarks = value; } else { - ImplementationHelper.propertyAlreadySet(AbstractIdentifiedObject.class, "setRemarks", "remarks"); + propertyAlreadySet("setRemarks", "remarks"); } } + + /** + * Logs a warning saying that an unmarshalled property was already set. + * + * @param method the caller method, used for logging. + * @param name the property name, used for logging and exception message. + * @throws IllegalStateException if we are not unmarshalling an object. + */ + private static void propertyAlreadySet(final String method, final String name) { + ImplementationHelper.propertyAlreadySet(AbstractIdentifiedObject.class, method, name); + } } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/DefaultObjectDomain.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/DefaultObjectDomain.java index 07ad21a943..b44848b058 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/DefaultObjectDomain.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/DefaultObjectDomain.java @@ -18,6 +18,7 @@ package org.apache.sis.referencing; import java.util.Objects; import java.io.Serializable; +import java.io.ObjectStreamException; import org.opengis.metadata.extent.Extent; import org.opengis.util.InternationalString; import org.apache.sis.util.ComparisonMode; @@ -27,6 +28,8 @@ import org.apache.sis.util.resources.Vocabulary; import org.apache.sis.referencing.util.WKTKeywords; import org.apache.sis.io.wkt.FormattableObject; import org.apache.sis.io.wkt.Formatter; +import org.apache.sis.xml.NilObject; +import org.apache.sis.xml.NilReason; import org.apache.sis.metadata.iso.extent.DefaultExtent; // Specific to the geoapi-3.1 and geoapi-4.0 branches: @@ -34,7 +37,16 @@ import org.opengis.referencing.ObjectDomain; /** - * Default implementation of scope and domain of validity of a CRS-related object. + * Scope and domain of validity of a CRS-related object. + * Those two properties are mandatory according ISO 19111. + * If a property is unspecified (by passing {@code null} to the constructor), + * then this class substitutes the null value by a <i>"not known"</i> text in an + * object implementing the {@link NilObject} interface with {@link NilReason#UNKNOWN}. + * The use of <i>"not known"</i> text is an ISO 19111 recommendation. + * + * <h2>Immutability and thread safety</h2> + * This class is immutable and thus thread-safe if the property values + * given to the constructor are also immutable. * * @author Martin Desruisseaux (Geomatys) * @version 1.4 @@ -48,40 +60,94 @@ public class DefaultObjectDomain extends FormattableObject implements ObjectDoma /** * The text used by default when the scope was not specified. - * The <i>"not known"</i> text is standardized by ISO 19111. + * The <i>"not known"</i> text is recommended by the ISO 19111 standard. * The text may be localized. - * - * @see #isDefined(InternationalString) */ - public static final InternationalString UNKNOWN_SCOPE = Vocabulary.formatInternational(Vocabulary.Keys.NotKnown); + private static final class UnknownScope extends Vocabulary.International implements NilObject { + /** For cross-version interoperability. */ + private static final long serialVersionUID = 7235301883912422934L; + + /** The singleton instance. */ + static final UnknownScope INSTANCE = new UnknownScope(); + + /** Creates the singleton instance. */ + private UnknownScope() { + super(Vocabulary.Keys.NotKnown); + } + + /** + * {@return a reason saying that the extent is unknown}. + */ + @Override + public NilReason getNilReason() { + return NilReason.UNKNOWN; + } + + /** + * Returns the unique instance on deserialization. + * + * @return the object to use after deserialization. + * @throws ObjectStreamException if the serialized object contains invalid data. + */ + private Object readResolve() throws ObjectStreamException { + return INSTANCE; + } + } /** - * The extent used by default when the domain of validity was not specified. - * - * @see #isDefined(Extent) + * The extent used by default when the scope was not specified. */ - public static final Extent UNKNOWN_EXTENT; - static { - final var domainOfValidity = new DefaultExtent(UNKNOWN_SCOPE, null, null, null); - domainOfValidity.transitionTo(DefaultExtent.State.FINAL); - UNKNOWN_EXTENT = domainOfValidity; + private static final class UnknownExtent extends DefaultExtent implements NilObject { + /** For cross-version interoperability. */ + private static final long serialVersionUID = 662383891780679068L; + + /** The singleton instance. */ + static final UnknownExtent INSTANCE = new UnknownExtent(); + + /** Creates the singleton instance. */ + private UnknownExtent() { + super(UnknownScope.INSTANCE, null, null, null); + transitionTo(DefaultExtent.State.FINAL); + } + + /** + * {@return a reason saying that the extent is unknown}. + */ + @Override + public NilReason getNilReason() { + return NilReason.UNKNOWN; + } + + /** + * Returns the unique instance on deserialization. + * + * @return the object to use after deserialization. + * @throws ObjectStreamException if the serialized object contains invalid data. + */ + private Object readResolve() throws ObjectStreamException { + return INSTANCE; + } } /** * Description of domain of usage, or limitations of usage, for which the object is valid. + * This is {@code null} (i.e. is not replaced by the <i>"not known"</i> text) if the value given + * to the {@linkplain #DefaultObjectDomain(InternationalString, Extent) constructor} was null. * * @see #getScope() */ @SuppressWarnings("serial") // Most SIS implementations are serializable. - private final InternationalString scope; + protected final InternationalString scope; /** * Area for which the object is valid. + * This is {@code null} (i.e. is not replaced by the <i>"not known"</i> text) if the value given + * to the {@linkplain #DefaultObjectDomain(InternationalString, Extent) constructor} was null. * * @see #getDomainOfValidity() */ @SuppressWarnings("serial") // Most SIS implementations are serializable. - private final Extent domainOfValidity; + protected final Extent domainOfValidity; /** * Creates a new domain with the given scope and extent. @@ -91,55 +157,64 @@ public class DefaultObjectDomain extends FormattableObject implements ObjectDoma * @param scope description of domain of usage, or limitations of usage. * @param domainOfValidity area for which the object is valid. */ - public DefaultObjectDomain(InternationalString scope, Extent domainOfValidity) { - if (scope == null) { - scope = UNKNOWN_SCOPE; - } - if (domainOfValidity == null) { - domainOfValidity = UNKNOWN_EXTENT; - } + public DefaultObjectDomain(final InternationalString scope, final Extent domainOfValidity) { this.scope = scope; this.domainOfValidity = domainOfValidity; } /** - * Returns a description of usage, or limitations of usage, for which this object is valid. + * Creates a new domain with the same values than the specified one. + * This copy constructor provides a way to convert an arbitrary implementation into a SIS one + * or a user-defined one (as a subclass), usually in order to leverage some implementation-specific API. * - * @return the domain of usage. + * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p> + * + * @param domain the domain to copy. + * + * @see #castOrCopy(ObjectDomain) */ - @Override - public InternationalString getScope() { - return scope; + public DefaultObjectDomain(final ObjectDomain domain) { + scope = domain.getScope(); + domainOfValidity = domain.getDomainOfValidity(); } /** - * Returns the spatial and temporal extent in which this object is valid. + * Returns a SIS datum implementation with the same values than the given arbitrary implementation. + * If the given object is {@code null}, then this method returns {@code null}. + * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged. + * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object. * - * @return the area or time frame of usage. + * @param object the object to get as a SIS implementation, or {@code null} if none. + * @return a SIS implementation containing the values of the given object (may be the + * given object itself), or {@code null} if the argument was null. */ - @Override - public Extent getDomainOfValidity() { - return domainOfValidity; + public static DefaultObjectDomain castOrCopy(final ObjectDomain object) { + return (object == null) || (object instanceof DefaultObjectDomain) + ? (DefaultObjectDomain) object : new DefaultObjectDomain(object); } /** - * Returns {@code true} if the given scope is neither null or not known. + * Returns a description of usage, or limitations of usage, for which this object is valid. + * If no scope was specified to the constructor, then this method returns <i>"not known"</i> + * in an instance implementing the {@link NilObject} interface with {@link NilReason#UNKNOWN}. * - * @param scope the scope to test. - * @return {@code true} if the given scope is not null and not {@link #UNKNOWN_SCOPE}. + * @return the domain of usage. */ - public static boolean isDefined(final InternationalString scope) { - return (scope != null) && (scope != UNKNOWN_SCOPE); + @Override + public InternationalString getScope() { + return (scope != null) ? scope : UnknownScope.INSTANCE; } /** - * Returns {@code true} if the given extent is neither null or not known. + * Returns the spatial and temporal extent in which this object is valid. + * If no extent was specified to the constructor, then this method returns <i>"not known"</i> + * in an instance implementing the {@link NilObject} interface with {@link NilReason#UNKNOWN}. * - * @param domainOfValidity the extent to test. - * @return {@code true} if the given extent is not null and not {@link #UNKNOWN_EXTENT}. + * @return the area or time frame of usage. */ - public static boolean isDefined(final Extent domainOfValidity) { - return (domainOfValidity != null) && (domainOfValidity != UNKNOWN_EXTENT); + @Override + public Extent getDomainOfValidity() { + return (domainOfValidity != null) ? domainOfValidity : UnknownExtent.INSTANCE; } /** @@ -204,8 +279,8 @@ public class DefaultObjectDomain extends FormattableObject implements ObjectDoma * The default implementation writes the following elements: * * <ul> - * <li>The object {@linkplain #getScope() scope}.</li> - * <li>The geographic description of the {@linkplain #getDomainOfValidity() domain of validity}.</li> + * <li>The object {@linkplain #scope}.</li> + * <li>The geographic description of the {@linkplain #domainOfValidity domain of validity}.</li> * <li>The geographic bounding box of the domain of validity.</li> * </ul> * @@ -215,6 +290,7 @@ public class DefaultObjectDomain extends FormattableObject implements ObjectDoma */ @Override protected String formatTo(final Formatter formatter) { + // Use the fields directly in order to keep null values. formatter.append(scope, domainOfValidity); return WKTKeywords.Usage; } diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java index 2c38c567a2..c4b6ef8c56 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java @@ -206,55 +206,41 @@ public class DefaultGeodeticDatum extends AbstractDatum implements GeodeticDatum * <th>Property name</th> * <th>Value type</th> * <th>Returned by</th> - * </tr> - * <tr> + * </tr><tr> * <td>{@value #BURSA_WOLF_KEY}</td> * <td>{@link BursaWolfParameters} (optionally as array)</td> * <td>{@link #getBursaWolfParameters()}</td> - * </tr> - * <tr> + * </tr><tr> * <th colspan="3" class="hsep">Defined in parent classes (reminder)</th> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td> * <td>{@link Identifier} or {@link String}</td> * <td>{@link #getName()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY}</td> * <td>{@link GenericName} or {@link CharSequence} (optionally as array)</td> * <td>{@link #getAlias()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}</td> * <td>{@link Identifier} (optionally as array)</td> * <td>{@link #getIdentifiers()}</td> - * </tr> - * <tr> + * </tr><tr> + * <td>{@value org.opengis.referencing.IdentifiedObject#DOMAINS_KEY}</td> + * <td>{@link org.opengis.referencing.ObjectDomain} (optionally as array)</td> + * <td>{@link #getDomains()}</td> + * </tr><tr> * <td>{@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link #getRemarks()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link #getAnchorPoint()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td> * <td>{@link Date}</td> * <td>{@link #getRealizationEpoch()}</td> * </tr> - * <tr> - * <td>{@value org.opengis.referencing.datum.Datum#DOMAIN_OF_VALIDITY_KEY}</td> - * <td>{@link Extent}</td> - * <td>{@link #getDomainOfValidity()}</td> - * </tr> - * <tr> - * <td>{@value org.opengis.referencing.datum.Datum#SCOPE_KEY}</td> - * <td>{@link InternationalString} or {@link String}</td> - * <td>{@link #getScope()}</td> - * </tr> * </table> * * If Bursa-Wolf parameters are specified, then the prime meridian of their diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java index 4d26c8a2fb..6e0bea56bf 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java @@ -1484,15 +1484,23 @@ public class Vocabulary extends IndexedResourceBundle { } /** - * The international string to be returned by {@link formatInternational}. + * The international string to be returned by {@code formatInternational(…)} methods. + * This implementation details is made public for allowing the creation of subclasses + * implementing some additional interfaces. */ - private static final class International extends ResourceInternationalString { + public static class International extends ResourceInternationalString { + /** For cross-version compatibility. */ private static final long serialVersionUID = -5423999784169092823L; - International(short key) {super(key);} - International(short key, Object args) {super(key, args);} - @Override protected KeyConstants getKeyConstants() {return Keys.INSTANCE;} - @Override protected IndexedResourceBundle getBundle(final Locale locale) { + /** + * Creates a new instance for the given vocabulary resource key. + * + * @param key one of the {@link Keys} values. + */ + protected International(short key) {super(key);} + International(short key, Object args) {super(key, args);} + @Override protected final KeyConstants getKeyConstants() {return Keys.INSTANCE;} + @Override protected final IndexedResourceBundle getBundle(final Locale locale) { return getResources(locale); } }