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.identification;
019
020import java.util.ArrayList;
021import java.util.Collection;
022import java.util.Collections;
023import java.util.Iterator;
024import java.time.temporal.TemporalAmount;
025import org.opengis.util.InternationalString;
026import org.opengis.metadata.Identifier;
027import org.opengis.metadata.MetadataScope;
028import org.opengis.metadata.citation.Citation;
029import org.opengis.metadata.citation.Responsibility;
030import org.opengis.metadata.citation.ResponsibleParty;
031import org.opengis.metadata.spatial.SpatialRepresentationType;
032import org.opengis.metadata.maintenance.MaintenanceInformation;
033import org.opengis.metadata.maintenance.ScopeCode;
034import org.opengis.metadata.constraint.Constraints;
035import org.opengis.metadata.distribution.Format;
036import org.opengis.metadata.extent.Extent;
037import org.opengis.annotation.UML;
038import org.opengis.annotation.Profile;
039import org.opengis.annotation.Classifier;
040import org.opengis.annotation.Stereotype;
041
042import static org.opengis.annotation.Obligation.*;
043import static org.opengis.annotation.Specification.*;
044import static org.opengis.annotation.ComplianceLevel.*;
045
046
047/**
048 * Basic information required to uniquely identify a resource or resources.
049 *
050 * @author  Martin Desruisseaux (IRD)
051 * @author  Cory Horner (Refractions Research)
052 * @version 3.1
053 * @since   2.0
054 */
055@Classifier(Stereotype.ABSTRACT)
056@UML(identifier="MD_Identification", specification=ISO_19115)
057public interface Identification {
058    /**
059     * Citation for the resource.
060     *
061     * @return citation for the resource.
062     */
063    @Profile(level=CORE)
064    @UML(identifier="citation", obligation=MANDATORY, specification=ISO_19115)
065    Citation getCitation();
066
067    /**
068     * Brief narrative summary of the resource.
069     *
070     * @return brief narrative summary of the resource.
071     */
072    @Profile(level=CORE)
073    @UML(identifier="abstract", obligation=MANDATORY, specification=ISO_19115)
074    InternationalString getAbstract();
075
076    /**
077     * Summary of the intentions with which the resource was developed.
078     *
079     * @return the intentions with which the resource was developed, or {@code null}.
080     */
081    @UML(identifier="purpose", obligation=OPTIONAL, specification=ISO_19115)
082    default InternationalString getPurpose() {
083        return null;
084    }
085
086    /**
087     * Recognition of those who contributed to the resource.
088     *
089     * <div class="warning"><b>Upcoming API change — internationalization</b><br>
090     * The return type will be changed to {@code Collection<? extends InternationalString>} in GeoAPI 4.0.
091     * </div>
092     *
093     * @return recognition of those who contributed to the resource.
094     */
095    @UML(identifier="credit", obligation=OPTIONAL, specification=ISO_19115)
096    default Collection<String> getCredits() {
097        return Collections.emptyList();
098    }
099
100    /**
101     * Status of the resource.
102     *
103     * @return status of the resource.
104     */
105    @UML(identifier="status", obligation=OPTIONAL, specification=ISO_19115)
106    default Collection<Progress> getStatus() {
107        return Collections.emptySet();          // Use Set instead of List for hash-safe final classes.
108    }
109
110    /**
111     * Identification of, and means of communication with, person(s) and organisations
112     * associated with the resource(s).
113     *
114     * <div class="warning"><b>Upcoming API change — generalization</b><br>
115     * As of ISO 19115:2014, {@code ResponsibleParty} is replaced by the {@link Responsibility} parent interface.
116     * This change may be applied in GeoAPI 4.0.
117     * </div>
118     *
119     * @return means of communication with person(s) and organisations(s) associated with the resource.
120     *
121     * @see org.opengis.metadata.Metadata#getContacts()
122     */
123    @Profile(level=CORE)
124    @UML(identifier="pointOfContact", obligation=OPTIONAL, specification=ISO_19115, version=2003)
125    default Collection<? extends ResponsibleParty> getPointOfContacts() {
126        return Collections.emptyList();
127    }
128
129    /**
130     * Methods used to spatially represent geographic information.
131     *
132     * @return methods used to spatially represent geographic information.
133     *
134     * @since 3.1
135     */
136    @UML(identifier="spatialRepresentationType", obligation=OPTIONAL, specification=ISO_19115)
137    default Collection<SpatialRepresentationType> getSpatialRepresentationTypes() {
138        return Collections.emptySet();          // Use Set instead of List for hash-safe final classes.
139    }
140
141    /**
142     * Factor which provides a general understanding of the density of spatial data in the resource.
143     * May also describe the range of resolutions in which a digital resource may be used.
144     *
145     * <div class="note"><b>Note:</b>
146     * this element should be repeated when describing upper and lower range.
147     * </div>
148     *
149     * @return factor which provides a general understanding of the density of spatial resource.
150     *
151     * @since 3.1
152     */
153    @Profile(level=CORE)
154    @UML(identifier="spatialResolution", obligation=OPTIONAL, specification=ISO_19115)
155    default Collection<? extends Resolution> getSpatialResolutions() {
156        return Collections.emptyList();
157    }
158
159    /**
160     * Smallest resolvable temporal period in a resource.
161     *
162     * @return smallest resolvable temporal period in a resource.
163     *
164     * @departure integration
165     *   The type defined by ISO 19115 is {@code TM_Duration}, an interface defined by ISO 19108.
166     *   That ISO type can be mapped to the {@link java.time.Period} or {@link java.time.Duration}
167     *   classes from the standard Java library.
168     *
169     * @since 3.1
170     */
171    @UML(identifier="temporalResolution", obligation=OPTIONAL, specification=ISO_19115)
172    default Collection<? extends TemporalAmount> getTemporalResolutions() {
173        return Collections.emptyList();
174    }
175
176    /**
177     * Main theme(s) of the resource.
178     *
179     * @return main theme(s).
180     *
181     * @condition Mandatory if {@link MetadataScope#getResourceScope()} equals {@link ScopeCode#DATASET}
182     *            or {@link ScopeCode#SERIES}.
183     *
184     * @since 3.1
185     */
186    @Profile(level=CORE)
187    @UML(identifier="topicCategory", obligation=CONDITIONAL, specification=ISO_19115)
188    Collection<TopicCategory> getTopicCategories();
189
190    /**
191     * Spatial and temporal extent of the resource.
192     *
193     * @return spatial and temporal extent of the resource.
194     *
195     * @condition Mandatory with either a
196     * {@linkplain org.opengis.metadata.extent.GeographicBoundingBox geographic bounding box} or a
197     * {@linkplain org.opengis.metadata.extent.GeographicDescription geographic description} if
198     * {@link MetadataScope#getResourceScope()} equals {@link ScopeCode#DATASET} or {@link ScopeCode#SERIES}.
199     *
200     * @since 3.1
201     */
202    @Profile(level=CORE)
203    @UML(identifier="extent", obligation=CONDITIONAL, specification=ISO_19115)
204    Collection<? extends Extent> getExtents();
205
206    /**
207     * Other documentation associated with the resource.
208     *
209     * <div class="note"><b>Example:</b>
210     * related articles, publications, user guides, data dictionaries.
211     * </div>
212     *
213     * @return other documentation associated with the resource.
214     *
215     * @since 3.1
216     */
217    @UML(identifier="additionalDocumentation", obligation=OPTIONAL, specification=ISO_19115)
218    default Collection<? extends Citation> getAdditionalDocumentations() {
219        return Collections.emptyList();
220    }
221
222    /**
223     * Code that identifies the level of processing in the producers coding system of a resource.
224     *
225     * <div class="note"><b>Example:</b>
226     * NOAA level 1B.
227     * </div>
228     *
229     * @return code that identifies the level of processing in the producers coding system of a resource.
230     *
231     * @since 3.1
232     *
233     * @see org.opengis.metadata.content.CoverageDescription#getProcessingLevelCode()
234     */
235    @UML(identifier="processingLevel", obligation=OPTIONAL, specification=ISO_19115)
236    default Identifier getProcessingLevel() {
237        return null;
238    }
239
240    /**
241     * Information about the frequency of resource updates, and the scope of those updates.
242     *
243     * @return frequency and scope of resource updates.
244     */
245    @UML(identifier="resourceMaintenance", obligation=OPTIONAL, specification=ISO_19115)
246    default Collection<? extends MaintenanceInformation> getResourceMaintenances() {
247        return Collections.emptyList();
248    }
249
250    /**
251     * Graphic that illustrates the resource(s) (should include a legend for the graphic).
252     *
253     * @return a graphic that illustrates the resource(s).
254     */
255    @UML(identifier="graphicOverview", obligation=OPTIONAL, specification=ISO_19115)
256    default Collection<? extends BrowseGraphic> getGraphicOverviews() {
257        return Collections.emptyList();
258    }
259
260    /**
261     * Description of the format of the resource(s).
262     *
263     * @return description of the format.
264     *
265     * @see org.opengis.metadata.distribution.Distribution#getDistributionFormats()
266     */
267    @UML(identifier="resourceFormat", obligation=OPTIONAL, specification=ISO_19115)
268    default Collection<? extends Format> getResourceFormats() {
269        return Collections.emptyList();
270    }
271
272    /**
273     * Category keywords, their type, and reference source.
274     *
275     * @return category keywords, their type, and reference source.
276     */
277    @UML(identifier="descriptiveKeywords", obligation=OPTIONAL, specification=ISO_19115)
278    default Collection<? extends Keywords> getDescriptiveKeywords() {
279        return Collections.emptyList();
280    }
281
282    /**
283     * Basic information about specific application(s) for which the resource(s)
284     * has/have been or is being used by different users.
285     *
286     * @return information about specific application(s) for which the resource(s)
287     *         has/have been or is being used.
288     */
289    @UML(identifier="resourceSpecificUsage", obligation=OPTIONAL, specification=ISO_19115)
290    default Collection<? extends Usage> getResourceSpecificUsages() {
291        return Collections.emptyList();
292    }
293
294    /**
295     * Information about constraints which apply to the resource(s).
296     *
297     * @return constraints which apply to the resource(s).
298     */
299    @UML(identifier="resourceConstraints", obligation=OPTIONAL, specification=ISO_19115)
300    default Collection<? extends Constraints> getResourceConstraints() {
301        return Collections.emptyList();
302    }
303
304    /**
305     * Associated resource information.
306     *
307     * @return associated resource information.
308     *
309     * @since 3.1
310     */
311    @UML(identifier="associatedResource", obligation=OPTIONAL, specification=ISO_19115)
312    default Collection<? extends AssociatedResource> getAssociatedResources() {
313        return Collections.emptyList();
314    }
315
316    /**
317     * Aggregate dataset information.
318     *
319     * @return aggregate dataset information.
320     *
321     * @deprecated As of ISO 19115:2014, replaced by {@link #getAssociatedResources()}.
322     */
323    @Deprecated(since="3.1")
324    @UML(identifier="aggregationInfo", obligation=OPTIONAL, specification=ISO_19115, version=2003)
325    default Collection<? extends AggregateInformation> getAggregationInfo() {
326        ArrayList<AggregateInformation> info = new ArrayList<>();
327        for (final AssociatedResource res : getAssociatedResources()) {
328            info.add(new AggregateInformation() {
329                @Override public Citation        getName()                 {return res.getName();}
330                @Override public AssociationType getAssociationType()      {return res.getAssociationType();}
331                @Override public InitiativeType  getInitiativeType()       {return res.getInitiativeType();}
332                @Override public Citation        getMetadataReference()    {return res.getMetadataReference();}
333                @Override public Citation        getAggregateDataSetName() {return res.getName();}
334                @Override public Identifier      getAggregateDataSetIdentifier() {
335                    Citation name = res.getName();
336                    if (name != null) {
337                        Iterator<? extends Identifier> it = name.getIdentifiers().iterator();
338                        if (it.hasNext()) return it.next();
339                    }
340                    return null;
341                }
342            });
343        }
344        return info;
345    }
346}