blob: cbb8e5466718b2e5ba1e9da8b35ca12d21107f1c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.metadata.iso.identification;
import java.util.Map;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.nio.charset.Charset;
import java.util.stream.Collectors;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.identification.CharacterSet;
import org.opengis.metadata.identification.TopicCategory;
import org.opengis.metadata.identification.DataIdentification;
import org.apache.sis.internal.jaxb.lan.LocaleAndCharset;
import org.apache.sis.internal.jaxb.lan.OtherLocales;
import org.apache.sis.internal.jaxb.lan.PT_Locale;
import org.apache.sis.internal.jaxb.FilterByVersion;
import org.apache.sis.internal.xml.LegacyNamespaces;
import org.apache.sis.internal.metadata.Dependencies;
/**
* Information required to identify a dataset.
* The following properties are mandatory or conditional (i.e. mandatory under some circumstances)
* in a well-formed metadata according ISO 19115:
*
* <div class="preformat">{@code MD_DataIdentification}
* {@code   ├─citation………………………………………} Citation data for the resource(s).
* {@code   │   ├─title……………………………………} Name by which the cited resource is known.
* {@code   │   └─date………………………………………} Reference date for the cited resource.
* {@code   ├─abstract………………………………………} Brief narrative summary of the content of the resource(s).
* {@code   ├─language………………………………………} Language(s) used within the dataset.
* {@code   ├─characterSet……………………………} Full name of the character coding standard(s) used for the dataset.
* {@code   ├─topicCategory…………………………} Main theme(s) of the dataset.
* {@code   └─extent……………………………………………} Bounding polygon, vertical, and temporal extent of the dataset.
* {@code       ├─description……………………} The spatial and temporal extent for the referring object.
* {@code       ├─geographicElement……} Geographic component of the extent of the referring object.
* {@code       ├─temporalElement…………} Temporal component of the extent of the referring object.
* {@code       └─verticalElement…………} Vertical component of the extent of the referring object.</div>
*
* <p><b>Limitations:</b></p>
* <ul>
* <li>Instances of this class are not synchronized for multi-threading.
* Synchronization, if needed, is caller's responsibility.</li>
* <li>Serialized objects of this class are not guaranteed to be compatible with future Apache SIS releases.
* Serialization support is appropriate for short term storage or RMI between applications running the
* same version of Apache SIS. For long term storage, use {@link org.apache.sis.xml.XML} instead.</li>
* </ul>
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Touraïvane (IRD)
* @author Cédric Briançon (Geomatys)
* @author Cullen Rombach (Image Matters)
* @version 1.0
* @since 0.3
* @module
*/
@XmlType(name = "MD_DataIdentification_Type", propOrder = {
"languages", // Legacy ISO 19115:2003
"characterSet", // Legacy ISO 19115:2003
"defaultLocale", // New in ISO 19115:2014
"otherLocales", // New in ISO 19115:2014
"environmentDescription",
"supplementalInformation"
/*
* In ISO 19115:2003, we had an "topicCategory" attribute before "environmentDescription"
* and an "extent" attribute before "supplementalInformation". In ISO 19115:2014 revision,
* those attributes moved to the parent class. Apache SIS 1.0 aligns itself on the latest
* standard, but the consequence is that attribute order is wrong when marshalling an ISO
* 19139:2007 document. We could workaround by defining private methods, but it confuses
* PropertyAccessor. We choose to avoid this complication in this class and handle element
* reordering in org.apache.sis.xml.TransformingWriter instead.
*/
})
@XmlRootElement(name = "MD_DataIdentification")
public class DefaultDataIdentification extends AbstractIdentification implements DataIdentification {
/**
* Serial number for compatibility with different versions.
*/
private static final long serialVersionUID = 7302901752833238436L;
/**
* Language(s) and character set(s) used within the dataset.
*/
private Map<Locale,Charset> locales;
/**
* Description of the dataset in the producer’s processing environment, including items
* such as the software, the computer operating system, file name, and the dataset size
*/
private InternationalString environmentDescription;
/**
* Any other descriptive information about the dataset.
*/
private InternationalString supplementalInformation;
/**
* Constructs an initially empty data identification.
*/
public DefaultDataIdentification() {
}
/**
* Creates a data identification initialized to the specified values.
*
* @param citation the citation data for the resource(s), or {@code null} if none.
* @param abstracts a brief narrative summary of the content of the resource(s), or {@code null} if none.
* @param language the language used within the dataset, or {@code null} if none.
* @param topicCategory the main theme of the dataset, or {@code null} if none.
*/
public DefaultDataIdentification(final Citation citation,
final CharSequence abstracts,
final Locale language,
final TopicCategory topicCategory)
{
super(citation, abstracts);
if (language != null) {
locales = writeMap(Collections.singletonMap(language, null), null, Locale.class);
}
super.setTopicCategories(singleton(topicCategory, TopicCategory.class));
}
/**
* Constructs a new instance initialized with the values from the specified metadata object.
* This is a <cite>shallow</cite> copy constructor, since the other metadata contained in the
* given object are not recursively copied.
*
* @param object the metadata to copy values from, or {@code null} if none.
*
* @see #castOrCopy(DataIdentification)
*/
public DefaultDataIdentification(final DataIdentification object) {
super(object);
if (object != null) {
locales = copyMap(object.getLocalesAndCharsets(), Locale.class);
environmentDescription = object.getEnvironmentDescription();
supplementalInformation = object.getSupplementalInformation();
}
}
/**
* Returns a SIS metadata implementation with the values of the given arbitrary implementation.
* This method performs the first applicable action in the following choices:
*
* <ul>
* <li>If the given object is {@code null}, then this method returns {@code null}.</li>
* <li>Otherwise if the given object is already an instance of
* {@code DefaultDataIdentification}, then it is returned unchanged.</li>
* <li>Otherwise a new {@code DefaultDataIdentification} instance is created using the
* {@linkplain #DefaultDataIdentification(DataIdentification) copy constructor}
* and returned. Note that this is a <cite>shallow</cite> copy operation, since the other
* metadata contained in the given object are not recursively copied.</li>
* </ul>
*
* @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.
*/
public static DefaultDataIdentification castOrCopy(final DataIdentification object) {
if (object == null || object instanceof DefaultDataIdentification) {
return (DefaultDataIdentification) object;
}
return new DefaultDataIdentification(object);
}
/**
* Returns the language(s) and character set(s) used within the dataset.
* The first element in iteration order is the default language.
* All other elements, if any, are alternate language(s) used within the resource.
*
* @return language(s) and character set(s) used within the dataset.
*
* @since 1.0
*/
@Override
// @XmlElement at the end of this class.
public Map<Locale,Charset> getLocalesAndCharsets() {
return locales = nonNullMap(locales, Locale.class);
}
/**
* Sets the language(s) and character set(s) used within the dataset.
* The first element in iteration order should be the default language.
* All other elements, if any, are alternate language(s) used within the resource.
*
* @param newValues the new language(s) and character set(s) used within the dataset.
*
* @since 1.0
*/
public void setLocalesAndCharsets(final Map<? extends Locale, ? extends Charset> newValues) {
locales = writeMap(newValues, locales, Locale.class);
}
/**
* Returns the language(s) used within the resource.
* The first element in iteration order shall be the default language.
* All other elements, if any, are alternate language(s) used within the resource.
*
* <p>The language string representations should use ISO 639-2 language code as
* returned by {@link Locale#getISO3Language()}.</p>
*
* @return language(s) used.
*
* @deprecated Replaced by {@code getLocalesAndCharsets().keySet()}.
*/
@Override
@Deprecated
@Dependencies("getLocalesAndCharsets")
@XmlElement(name = "language", namespace = LegacyNamespaces.GMD)
public Collection<Locale> getLanguages() {
return FilterByVersion.LEGACY_METADATA.accept() ? LocaleAndCharset.getLanguages(getLocalesAndCharsets()) : null;
}
/**
* Sets the language(s) used within the resource.
*
* @param newValues the new languages.
*
* @deprecated Replaced by putting keys in {@link #getLocalesAndCharsets()} map.
*/
@Deprecated
public void setLanguages(final Collection<? extends Locale> newValues) {
// TODO: delete after SIS 1.0 release (method not needed by JAXB).
setLocalesAndCharsets(LocaleAndCharset.setLanguages(getLocalesAndCharsets(), newValues));
}
/**
* Returns the character coding standard used for the dataset.
*
* <div class="warning"><b>Upcoming API change — JDK integration</b><br>
* The element type may change to the {@link Charset} class in GeoAPI 4.0.
* </div>
*
* @return character coding standard(s) used.
*
* @deprecated Replaced by {@code getLocalesAndCharsets().values()}.
*/
@Override
@Deprecated
@Dependencies("getLocalesAndCharsets")
// @XmlElement at the end of this class.
public Collection<CharacterSet> getCharacterSets() {
return getLocalesAndCharsets().values().stream().map(CharacterSet::fromCharset).collect(Collectors.toSet());
}
/**
* Sets the character coding standard used for the dataset.
*
* <div class="warning"><b>Upcoming API change — JDK integration</b><br>
* The element type may change to the {@link Charset} class in GeoAPI 4.0.
* </div>
*
* @param newValues the new character sets.
*
* @deprecated Replaced by putting values in {@link #getLocalesAndCharsets()} map.
*/
@Deprecated
public void setCharacterSets(final Collection<? extends CharacterSet> newValues) {
// TODO: delete after SIS 1.0 release (method not needed by JAXB).
Collection<Charset> c = null;
if (newValues != null) {
c = newValues.stream().map(CharacterSet::toCharset).collect(Collectors.toSet());
}
setLocalesAndCharsets(LocaleAndCharset.setCharacterSets(getLocalesAndCharsets(), c));
}
/**
* Returns a description of the resource in the producer's processing environment. This includes
* items such as the software, the computer operating system, file name, and the dataset size.
*
* @return description of the resource in the producer's processing environment, or {@code null}.
*/
@Override
@XmlElement(name = "environmentDescription")
public InternationalString getEnvironmentDescription() {
return environmentDescription;
}
/**
* Sets the description of the resource in the producer’s processing environment.
*
* @param newValue the new environment description.
*/
public void setEnvironmentDescription(final InternationalString newValue) {
checkWritePermission(environmentDescription);
environmentDescription = newValue;
}
/**
* Any other descriptive information about the resource.
*
* @return other descriptive information, or {@code null}.
*/
@Override
@XmlElement(name = "supplementalInformation")
public InternationalString getSupplementalInformation() {
return supplementalInformation;
}
/**
* Sets any other descriptive information about the resource.
*
* @param newValue the new supplemental information.
*/
public void setSupplementalInformation(final InternationalString newValue) {
checkWritePermission(supplementalInformation);
supplementalInformation = newValue;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////// ////////
//////// XML support with JAXB ////////
//////// ////////
//////// The following methods are invoked by JAXB using reflection (even if ////////
//////// they are private) or are helpers for other methods invoked by JAXB. ////////
//////// Those methods can be safely removed if Geographic Markup Language ////////
//////// (GML) support is not needed. ////////
//////// ////////
//////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the default locale for this record (used in ISO 19115-3 format).
*/
@XmlElement(name = "defaultLocale")
private PT_Locale getDefaultLocale() {
return FilterByVersion.CURRENT_METADATA.accept() ? PT_Locale.first(getLocalesAndCharsets()) : null;
}
/**
* Sets the default locale for this record (used in ISO 19115-3 format).
*/
@SuppressWarnings("unused")
private void setDefaultLocale(final PT_Locale newValue) {
setLocalesAndCharsets(OtherLocales.setFirst(locales, newValue));
}
/**
* Gets the other locales for this record (used in ISO 19115-3 format).
*/
@XmlElement(name = "otherLocale")
private Collection<PT_Locale> getOtherLocales() {
return FilterByVersion.CURRENT_METADATA.accept() ? OtherLocales.filter(getLocalesAndCharsets()) : null;
}
/**
* Returns the character coding for the metadata set (used in legacy ISO 19157 format).
*
* @see #getCharacterSets()
*/
@XmlElement(name = "characterSet", namespace = LegacyNamespaces.GMD)
private Collection<Charset> getCharacterSet() {
return FilterByVersion.LEGACY_METADATA.accept() ? LocaleAndCharset.getCharacterSets(getLocalesAndCharsets()) : null;
}
}