001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.metadata;
019
020import java.util.Collection;
021import java.util.Collections;
022import java.util.List;
023import java.util.Map;
024import java.util.Date;
025import java.util.Locale;
026import java.util.LinkedHashSet;
027import java.nio.charset.Charset;
028import java.net.URI;
029
030import org.opengis.util.InternationalString;
031import org.opengis.metadata.acquisition.AcquisitionInformation;
032import org.opengis.metadata.quality.DataQuality;
033import org.opengis.metadata.maintenance.ScopeCode;
034import org.opengis.metadata.constraint.Constraints;
035import org.opengis.metadata.distribution.Distribution;
036import org.opengis.metadata.citation.Citation;
037import org.opengis.metadata.citation.CitationDate;
038import org.opengis.metadata.citation.DateType;
039import org.opengis.metadata.citation.Responsibility;
040import org.opengis.metadata.citation.OnlineResource;
041import org.opengis.metadata.citation.ResponsibleParty;
042import org.opengis.metadata.content.ContentInformation;
043import org.opengis.metadata.spatial.SpatialRepresentation;
044import org.opengis.metadata.identification.CharacterSet;
045import org.opengis.metadata.identification.Identification;
046import org.opengis.metadata.maintenance.MaintenanceInformation;
047import org.opengis.metadata.lineage.Lineage;
048import org.opengis.referencing.ReferenceSystem;
049import org.opengis.geoapi.internal.Legacy;
050import org.opengis.annotation.UML;
051import org.opengis.annotation.Profile;
052
053import static org.opengis.annotation.Obligation.*;
054import static org.opengis.annotation.Specification.*;
055import static org.opengis.annotation.ComplianceLevel.*;
056
057
058/**
059 * Root entity which defines metadata about a resource or resources.
060 *
061 * <p><b>Conditional properties:</b></p>
062 * Following properties have default methods but shall nevertheless be implemented if the corresponding condition is met:
063 * <ul>
064 *   <li>{@linkplain #getLocalesAndCharsets() Locale and character set}:
065 *       mandatory if not defined by encoding and UTF-8 not used.</li>
066 *   <li>{@link #getParentMetadata() Parent metadata}:
067 *       mandatory if there is an upper object.</li>
068 * </ul>
069 *
070 * @author  Martin Desruisseaux (IRD)
071 * @author  Cory Horner (Refractions Research)
072 * @version 3.1
073 * @since   2.0
074 */
075@UML(identifier="MD_Metadata", specification=ISO_19115)
076public interface Metadata {
077    /**
078     * Unique identifier for this metadata record.
079     *
080     * <div class="note"><b>Note:</b>
081     * OGC 07-045 (Catalog Service Specification — ISO metadata application profile) recommends usage
082     * of a UUID (Universal Unique Identifier) as specified by <a href="http://www.ietf.org">IETF</a>
083     * to ensure identifier’s uniqueness.</div>
084     *
085     * @return unique identifier for this metadata record, or {@code null}.
086     */
087    @Profile(level=CORE)
088    @UML(identifier="metadataIdentifier", obligation=OPTIONAL, specification=ISO_19115)
089    default Identifier getMetadataIdentifier() {
090        return null;
091    }
092
093    /**
094     * Unique identifier for this metadata file, or {@code null} if none.
095     *
096     * <div class="note"><b>Note:</b>
097     * OGC 07-045 (Catalog Service Specification — ISO metadata application profile) recommends usage
098     * of a UUID (Universal Unique Identifier) as specified by <a href="http://www.ietf.org">IETF</a>
099     * to ensure identifier’s uniqueness.</div>
100     *
101     * @return unique identifier for this metadata file, or {@code null} in none.
102     *
103     * @deprecated As of ISO 19115:2014, replaced by {@link #getMetadataIdentifier()}
104     *   in order to include the codespace attribute.
105     */
106    @Deprecated(since="3.1")
107    @UML(identifier="fileIdentifier", obligation=OPTIONAL, specification=ISO_19115, version=2003)
108    default String getFileIdentifier() {
109        Identifier id = getMetadataIdentifier();
110        return (id != null) ? id.getCode() : null;
111    }
112
113    /**
114     * Language(s) and character set(s) used for documenting metadata.
115     * The first entry in iteration order shall be the default language and its character set.
116     * All other entries, if any, are alternate language(s) and character set(s) used within the resource.
117     *
118     * <h4>Relationship with ISO 19115</h4>
119     * Each ({@link Locale}, {@link Charset}) entry is equivalent to an instance of ISO {@code PT_Locale} class.
120     * The language code and the character set are mandatory elements in ISO 19115 standard; consequently this map
121     * should not contain null key or null values, but implementations are encouraged to be tolerant for historical
122     * reasons (languages and character sets were defined as separated attributes in legacy ISO 19115:2003 standard).
123     * The same character set may be associated to many languages. ISO 19115-1:2014 identifies those character sets
124     * by references to the <a href="http://www.iana.org/assignments/character-sets">IANA Character Set register</a>,
125     * which is represented in Java by {@link java.nio.charset.Charset}.
126     * Instances can be obtained by a call to {@link Charset#forName(String)}.
127     *
128     * <div class="note"><b>Examples:</b>
129     * {@code UCS-2}, {@code UCS-4}, {@code UTF-7}, {@code UTF-8}, {@code UTF-16},
130     * {@code ISO-8859-1} (a.k.a. {@code ISO-LATIN-1}), {@code ISO-8859-2}, {@code ISO-8859-3}, {@code ISO-8859-4},
131     * {@code ISO-8859-5}, {@code ISO-8859-6}, {@code ISO-8859-7}, {@code ISO-8859-8}, {@code ISO-8859-9},
132     * {@code ISO-8859-10}, {@code ISO-8859-11}, {@code ISO-8859-12}, {@code ISO-8859-13}, {@code ISO-8859-14},
133     * {@code ISO-8859-15}, {@code ISO-8859-16},
134     * {@code JIS_X0201}, {@code Shift_JIS}, {@code EUC-JP}, {@code US-ASCII}, {@code EBCDIC}, {@code EUC-KR},
135     * {@code Big5}, {@code GB2312}.
136     * </div>
137     *
138     * <h4>XML representation</h4>
139     * XML documents shall format languages using the ISO 639-2 language code as returned by {@link Locale#getISO3Language()}.
140     *
141     * @departure integration
142     *   GeoAPI replaces ISO 19115-1:2014 {@code LanguageCode}, {@code CountryCode} and {@code MD_CharacterSetCode}
143     *   code lists by equivalent objects from the standard Java library. The {@code PT_Locale} class, which is a
144     *   container for above code-lists, is replaced by {@link Map} entries in order to avoid to introduce a new class
145     *   and because the character set information is not as relevant in Java than in XML documents.
146     *   For example, the character encoding information is irrelevant to {@code InternationalString}
147     *   because the Java language fixes the encoding of all {@code String} instances to UTF-16.
148     *
149     *   <p>In addition ISO 19115:2014 defines {@code defaultLocale} and {@code otherLocale(s)} as separated attributes,
150     *   but GeoAPI groups them in a single collection for compatibility with standard Java methods like
151     *   <code>{@link Locale#lookup(List, Collection) Locale.lookup(…, Collection&lt;Locale&gt;)}</code>.
152     *   This API design makes easy to provide the collection of {@link Locale} objects with
153     *   <code>getLocalesAndCharsets().{@linkplain Map#keySet() keySet()}</code>.</p>
154     *
155     * @return language(s) and character set(s) used for documenting metadata.
156     *
157     * @condition Mandatory if not defined by encoding and UTF-8 not used.
158     *
159     * @see org.opengis.metadata.identification.DataIdentification#getLocalesAndCharsets()
160     * @see org.opengis.metadata.content.FeatureCatalogueDescription#getLocalesAndCharsets()
161     *
162     * @since 3.1
163     */
164    @Profile(level=CORE)
165    // Obligation note: `defaultLocale` is conditional and `otherLocale` is optional.
166    @UML(identifier="defaultLocale+otherLocale", obligation=CONDITIONAL, specification=ISO_19115)
167    default Map<Locale,Charset> getLocalesAndCharsets() {
168        return Collections.emptyMap();
169    }
170
171    /**
172     * Language used for documenting metadata.
173     *
174     * @return language used for documenting metadata, or {@code null}.
175     *
176     * @deprecated As of GeoAPI 3.1, replaced by {@link #getLocalesAndCharsets()}.
177     */
178    @Deprecated(since="3.1")
179    @UML(identifier="language", obligation=OPTIONAL, specification=ISO_19115, version=2003)
180    default Locale getLanguage() {
181        for (Locale lc : getLocalesAndCharsets().keySet()) {
182            if (lc != null) return lc;
183        }
184        return null;
185    }
186
187    /**
188     * Provides information about an alternatively used localized character string for a linguistic extension.
189     *
190     * @return alternatively used localized character string for a linguistic extension.
191     *
192     * @deprecated As of GeoAPI 3.1, replaced by {@link #getLocalesAndCharsets()}.
193     */
194    @Deprecated(since="3.1")
195    @UML(identifier="locale", obligation=OPTIONAL, specification=ISO_19115, version=2003)
196    default Collection<Locale> getLocales() {
197        Locale first = null;
198        LinkedHashSet<Locale> locales = new LinkedHashSet<>();
199        for (Locale lc : getLocalesAndCharsets().keySet()) {
200            if (first == null) {
201                first = lc;
202            }
203            locales.add(lc);
204        }
205        locales.remove(first);
206        locales.remove(null);
207        return locales;
208    }
209
210    /**
211     * The character coding standard used for the metadata set.
212     *
213     * @return character coding standard used for the metadata, or {@code null}.
214     *
215     * @deprecated As of GeoAPI 3.1, replaced by {@code getLocalesAndCharsets().values()}.
216     */
217    @Deprecated(since="3.1")
218    @UML(identifier="characterSet", obligation=OPTIONAL, specification=ISO_19115, version=2003)
219    default CharacterSet getCharacterSet() {
220        for (Charset cs : getLocalesAndCharsets().values()) {
221            if (cs != null) return CharacterSet.fromCharset(cs);
222        }
223        return null;
224    }
225
226    /**
227     * Identification of the parent metadata record.
228     * This is non-null if this metadata is a subset (child) of another metadata that is described elsewhere.
229     *
230     * @condition Mandatory if there is an upper object.
231     *
232     * @return identification of the parent metadata record, or {@code null} if none.
233     *
234     * @since 3.1
235     */
236    @UML(identifier="parentMetadata", obligation=CONDITIONAL, specification=ISO_19115)
237    default Citation getParentMetadata() {
238        return null;
239    }
240
241    /**
242     * File identifier of the metadata to which this metadata is a subset (child).
243     *
244     * <div class="note"><b>Note:</b>
245     * OGC 07-045 (Catalog Service Specification — ISO metadata application profile) recommends usage
246     * of a UUID (Universal Unique Identifier) as specified by <a href="http://www.ietf.org">IETF</a>
247     * to ensure identifier’s uniqueness.</div>
248     *
249     * @return identifier of the metadata to which this metadata is a subset, or {@code null}.
250     *
251     * @condition {@linkplain #getHierarchyLevels() Hierarchy level} is not equal to
252     *            {@link ScopeCode#DATASET}.
253     *
254     * @deprecated As of ISO 19115:2014, replaced by {@link #getParentMetadata()}.
255     */
256    @Deprecated(since="3.1")
257    @UML(identifier="parentIdentifier", obligation=CONDITIONAL, specification=ISO_19115, version=2003)
258    default String getParentIdentifier() {
259        Citation parentMetadata = getParentMetadata();
260        if (parentMetadata != null) {
261            InternationalString title = parentMetadata.getTitle();
262            if (title != null) {
263                return title.toString();
264            }
265        }
266        return null;
267    }
268
269    /**
270     * The scope or type of resource for which metadata is provided.
271     *
272     * @condition Mandatory if the metadata is about a resource other than a dataset.
273     *
274     * @return scope or type of resource for which metadata is provided.
275     *
276     * @since 3.1
277     */
278    @UML(identifier="metadataScope", obligation=CONDITIONAL, specification=ISO_19115)
279    Collection<? extends MetadataScope> getMetadataScopes();
280
281    /**
282     * Scope to which the metadata applies.
283     * Metadata for which no hierarchy is listed are interpreted to be
284     * "{@linkplain ScopeCode#DATASET dataset}" metadata by default.
285     *
286     * @return scope to which the metadata applies.
287     *
288     * @condition Mandatory if the metadata is about a resource other than a dataset.
289     *
290     * @deprecated As of ISO 19115:2014, replaced by {@link #getMetadataScopes()}
291     *   followed by {@link MetadataScope#getResourceScope()}.
292     */
293    @Deprecated(since="3.1")
294    @UML(identifier="hierarchyLevel", obligation=CONDITIONAL, specification=ISO_19115, version=2003)
295    default Collection<ScopeCode> getHierarchyLevels() {
296        LinkedHashSet<ScopeCode> scopes = new LinkedHashSet<>();
297        getMetadataScopes().forEach((mds) -> {
298            scopes.add(mds.getResourceScope());
299        });
300        return scopes;
301    }
302
303    /**
304     * Name of the hierarchy levels for which the metadata is provided.
305     *
306     * @return hierarchy levels for which the metadata is provided.
307     *
308     * @condition {@linkplain #getHierarchyLevels() Hierarchy level} is not equal to
309     *            {@link ScopeCode#DATASET}.
310     *
311     * @deprecated As of ISO 19115:2014, replaced by {@link #getMetadataScopes()}
312     *   followed by {@link MetadataScope#getName()}.
313     */
314    @Deprecated(since="3.1")
315    @UML(identifier="hierarchyLevelName", obligation=CONDITIONAL, specification=ISO_19115, version=2003)
316    default Collection<String> getHierarchyLevelNames() {
317        LinkedHashSet<String> names = new LinkedHashSet<>();
318        getMetadataScopes().forEach((mds) -> {
319            InternationalString name = mds.getName();
320            if (name != null) {
321                names.add(name.toString());
322            }
323        });
324        return names;
325    }
326
327    /**
328     * Parties responsible for the metadata information.
329     *
330     * <div class="warning"><b>Upcoming API change — generalization</b><br>
331     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@link Responsibility} parent interface.
332     * This change may be applied in GeoAPI 4.0.
333     * </div>
334     *
335     * @return parties responsible for the metadata information.
336     *
337     * @see Identification#getPointOfContacts()
338     */
339    @Profile(level=CORE)
340    @UML(identifier="contact", obligation=MANDATORY, specification=ISO_19115, version=2003)
341    Collection<? extends ResponsibleParty> getContacts();
342
343    /**
344     * Date(s) associated with the metadata.
345     * The collection shall contain at least an element for {@link DateType#CREATION}.
346     *
347     * @return date(s) associated with the metadata.
348     *
349     * @see Citation#getDates()
350     *
351     * @since 3.1
352     */
353    @Profile(level=CORE)
354    @UML(identifier="dateInfo", obligation=MANDATORY, specification=ISO_19115)
355    Collection<? extends CitationDate> getDateInfo();
356
357    /**
358     * Date that the metadata was created.
359     *
360     * @return date that the metadata was created.
361     *
362     * @deprecated As of ISO 19115:2014, replaced by {@link #getDateInfo()}.
363     */
364    @Deprecated(since="3.1")
365    @UML(identifier="dateStamp", obligation=MANDATORY, specification=ISO_19115, version=2003)
366    default Date getDateStamp() {
367        return Legacy.getDate(getDateInfo(), DateType.CREATION);
368    }
369
370    /**
371     * Name of the metadata standard (including profile name) used.
372     *
373     * @return name of the metadata standard used, or {@code null}.
374     *
375     * @deprecated As of ISO 19115:2014, replaced by {@link #getMetadataStandards()}
376     *   followed by {@link Citation#getTitle()}.
377     */
378    @Deprecated(since="3.1")
379    @UML(identifier="metadataStandardName", obligation=OPTIONAL, specification=ISO_19115, version=2003)
380    default String getMetadataStandardName() {
381        for (Citation c : getMetadataStandards()) {
382            InternationalString t = c.getTitle();
383            if (t != null) return t.toString();
384        }
385        return null;
386    }
387
388    /**
389     * Version (profile) of the metadata standard used.
390     *
391     * @return version of the metadata standard used, or {@code null}.
392     *
393     * @deprecated As of ISO 19115:2014, replaced by {@link #getMetadataStandards()}
394     *   followed by {@link Citation#getEdition()}.
395     */
396    @Profile(level=CORE)
397    @Deprecated(since="3.1")
398    @UML(identifier="metadataStandardVersion", obligation=OPTIONAL, specification=ISO_19115, version=2003)
399    default String getMetadataStandardVersion() {
400        for (Citation c : getMetadataStandards()) {
401            InternationalString t = c.getEdition();
402            if (t != null) return t.toString();
403        }
404        return null;
405    }
406
407    /**
408     * Citation(s) for the standard(s) to which the metadata conform.
409     * Metadata standard citations should include an identifier.
410     *
411     * @return the standard(s) to which the metadata conform.
412     *
413     * @see #getMetadataProfiles()
414     *
415     * @since 3.1
416     */
417    @Profile(level=CORE)
418    @UML(identifier="metadataStandard", obligation=OPTIONAL, specification=ISO_19115)
419    default Collection<? extends Citation> getMetadataStandards() {
420        return Collections.emptyList();
421    }
422
423    /**
424     * Citation(s) for the profile(s) of the metadata standard to which the metadata conform.
425     * Metadata profile standard citations should include an identifier.
426     *
427     * @return the profile(s) to which the metadata conform.
428     *
429     * @see #getMetadataStandards()
430     * @see #getMetadataExtensionInfo()
431     *
432     * @since 3.1
433     */
434    @UML(identifier="metadataProfile", obligation=OPTIONAL, specification=ISO_19115)
435    default Collection<? extends Citation> getMetadataProfiles() {
436        return Collections.emptyList();
437    }
438
439    /**
440     * Reference(s) to alternative metadata or metadata in a non-ISO standard for the same resource.
441     *
442     * @return reference(s) to alternative metadata (e.g. Dublin core, FGDC).
443     *
444     * @since 3.1
445     */
446    @UML(identifier="alternativeMetadataReference", obligation=OPTIONAL, specification=ISO_19115)
447    default Collection<? extends Citation> getAlternativeMetadataReferences() {
448        return Collections.emptyList();
449    }
450
451    /**
452     * Online location(s) where the metadata is available.
453     *
454     * @return online location(s) where the metadata is available.
455     *
456     * @since 3.1
457     */
458    @UML(identifier="metadataLinkage", obligation=OPTIONAL, specification=ISO_19115)
459    default Collection<? extends OnlineResource> getMetadataLinkages() {
460        return Collections.emptyList();
461    }
462
463    /**
464     * Uniform Resource Identifier (URI) of the dataset to which the metadata applies.
465     *
466     * @return Uniform Resource Identifier of the dataset, or {@code null}.
467     *
468     * @deprecated As of ISO 19115:2014, replaced by {@link #getIdentificationInfo()} followed by
469     *    {@link Identification#getCitation()} followed by {@link Citation#getOnlineResources()}
470     *    followed by {@link OnlineResource#getLinkage()}.
471     */
472    @Deprecated(since="3.1")
473    @UML(identifier="dataSetURI", obligation=OPTIONAL, specification=ISO_19115, version=2003)
474    default String getDataSetUri() {
475        for (Identification id : getIdentificationInfo()) {
476            Citation citation = id.getCitation();
477            if (citation != null) {
478                for (OnlineResource r : citation.getOnlineResources()) {
479                    URI linkage = r.getLinkage();
480                    if (linkage != null) {
481                        return linkage.toString();
482                    }
483                }
484            }
485        }
486        return null;
487    }
488
489    /**
490     * Digital representation of spatial information in the dataset.
491     *
492     * @return digital representation of spatial information in the dataset.
493     */
494    @UML(identifier="spatialRepresentationInfo", obligation=OPTIONAL, specification=ISO_19115)
495    default Collection<? extends SpatialRepresentation> getSpatialRepresentationInfo() {
496        return Collections.emptyList();
497    }
498
499    /**
500     * Description of the spatial and temporal reference systems used in the dataset.
501     *
502     * @return spatial and temporal reference systems used in the dataset.
503     */
504    @Profile(level=CORE)
505    @UML(identifier="referenceSystemInfo", obligation=OPTIONAL, specification=ISO_19115)
506    default Collection<? extends ReferenceSystem> getReferenceSystemInfo() {
507        return Collections.emptyList();
508    }
509
510    /**
511     * Information describing metadata extensions.
512     *
513     * @return metadata extensions.
514     *
515     * @see #getMetadataProfiles()
516     */
517    @UML(identifier="metadataExtensionInfo", obligation=OPTIONAL, specification=ISO_19115)
518    default Collection<? extends MetadataExtensionInformation> getMetadataExtensionInfo() {
519        return Collections.emptyList();
520    }
521
522    /**
523     * Basic information about the resource(s) to which the metadata applies.
524     *
525     * @return the resource(s) to which the metadata applies.
526     */
527    @Profile(level=CORE)
528    @UML(identifier="identificationInfo", obligation=MANDATORY, specification=ISO_19115)
529    Collection<? extends Identification> getIdentificationInfo();
530
531    /**
532     * Information about the feature and coverage characteristics.
533     *
534     * @return information about the feature and coverage characteristics.
535     */
536    @UML(identifier="contentInfo", obligation=OPTIONAL, specification=ISO_19115)
537    default Collection<? extends ContentInformation> getContentInfo() {
538        return Collections.emptyList();
539    }
540
541    /**
542     * Information about the distributor of and options for obtaining the resource(s).
543     *
544     * <div class="warning"><b>Upcoming API change — multiplicity</b><br>
545     * As of ISO 19115:2014, this singleton has been replaced by a collection.
546     * This change may be applied in GeoAPI 4.0.
547     * </div>
548     *
549     * @return the distributor of and options for obtaining the resource(s), or {@code null}.
550     */
551    @Profile(level=CORE)
552    @UML(identifier="distributionInfo", obligation=OPTIONAL, specification=ISO_19115, version=2003)
553    default Distribution getDistributionInfo() {
554        return null;
555    }
556
557    /**
558     * Overall assessment of quality of a resource(s).
559     *
560     * @return overall assessment of quality of a resource(s).
561     */
562    @Profile(level=CORE)
563    @UML(identifier="dataQualityInfo", obligation=OPTIONAL, specification=ISO_19115)
564    default Collection<? extends DataQuality> getDataQualityInfo() {
565        return Collections.emptyList();
566    }
567
568    /**
569     * Information about the catalogue of rules defined for the portrayal of a resource(s).
570     *
571     * @return the catalogue of rules defined for the portrayal of a resource(s).
572     */
573    @UML(identifier="portrayalCatalogueInfo", obligation=OPTIONAL, specification=ISO_19115)
574    default Collection<? extends PortrayalCatalogueReference> getPortrayalCatalogueInfo() {
575        return Collections.emptyList();
576    }
577
578    /**
579     * Restrictions on the access and use of metadata.
580     *
581     * @return restrictions on the access and use of metadata.
582     *
583     * @see Identification#getResourceConstraints()
584     */
585    @UML(identifier="metadataConstraints", obligation=OPTIONAL, specification=ISO_19115)
586    default Collection<? extends Constraints> getMetadataConstraints() {
587        return Collections.emptyList();
588    }
589
590    /**
591     * Information about the conceptual schema of a dataset.
592     *
593     * @return the conceptual schema of a dataset.
594     */
595    @UML(identifier="applicationSchemaInfo", obligation=OPTIONAL, specification=ISO_19115)
596    default Collection<? extends ApplicationSchemaInformation> getApplicationSchemaInfo() {
597        return Collections.emptyList();
598    }
599
600    /**
601     * Information about the acquisition of the data.
602     *
603     * @return the acquisition of data.
604     */
605    @UML(identifier="acquisitionInformation", obligation=OPTIONAL, specification=ISO_19115_2)
606    default Collection<? extends AcquisitionInformation> getAcquisitionInformation() {
607        return Collections.emptyList();
608    }
609
610    /**
611     * Information about the frequency of metadata updates, and the scope of those updates.
612     *
613     * @return the frequency of metadata updates and their scope, or {@code null}.
614     *
615     * @see Identification#getResourceMaintenances()
616     */
617    @UML(identifier="metadataMaintenance", obligation=OPTIONAL, specification=ISO_19115)
618    default MaintenanceInformation getMetadataMaintenance() {
619        return null;
620    }
621
622    /**
623     * Information about the provenance, sources and/or the production processes applied to the resource.
624     *
625     * @return the provenance, sources and/or the production processes.
626     *
627     * @since 3.1
628     */
629    @UML(identifier="resourceLineage", obligation=OPTIONAL, specification=ISO_19115)
630    default Collection<? extends Lineage> getResourceLineages() {
631        return Collections.emptyList();
632    }
633}