Author: desruisseaux
Date: Mon Oct 16 19:10:29 2017
New Revision: 1812312
URL: http://svn.apache.org/viewvc?rev=1812312&view=rev
Log:
Add support for NetCDF "creator_type", "publisher_type" and "program"
attributes.
Modified:
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreFormat.java
Modified:
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java?rev=1812312&r1=1812311&r2=1812312&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/AttributeNames.java
[UTF-8] Mon Oct 16 19:10:29 2017
@@ -31,6 +31,8 @@ import org.opengis.metadata.Metadata;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.*;
import org.opengis.metadata.content.*;
+import org.opengis.metadata.acquisition.AcquisitionInformation;
+import org.opengis.metadata.acquisition.Operation;
import org.opengis.metadata.distribution.Distributor;
import org.opengis.metadata.distribution.Distribution;
import org.opengis.metadata.constraint.LegalConstraints;
@@ -68,6 +70,7 @@ import org.opengis.metadata.extent.Geogr
* {@linkplain #CONTRIBUTOR "contributor_url"}<br>
* {@linkplain #CREATOR "creator_email"}<br>
* {@linkplain #CREATOR "creator_name"}<br>
+ * {@linkplain #CREATOR "creator_type"}<br>
* {@linkplain #CREATOR "creator_url"}<br>
* {@value #DATA_TYPE}<br>
* {@value #DATE_CREATED}<br>
@@ -77,9 +80,12 @@ import org.opengis.metadata.extent.Geogr
* {@value #FLAG_MEANINGS}<br>
* {@value #FLAG_NAMES}<br>
* {@value #FLAG_VALUES}<br>
- * </td><td style="width: 25%">
* {@linkplain #TITLE "full_name"}<br>
+ * </td><td style="width: 25%">
* {@linkplain #GEOGRAPHIC_IDENTIFIER "geographic_identifier"}<br>
+ * {@value #GEOSPATIAL_BOUNDS}<br>
+ * {@linkplain #GEOSPATIAL_BOUNDS "geospatial_bounds_crs"}<br>
+ * {@linkplain #GEOSPATIAL_BOUNDS "geospatial_bounds_vertical_crs"}<br>
* {@linkplain #LATITUDE "geospatial_lat_max"}<br>
* {@linkplain #LATITUDE "geospatial_lat_min"}<br>
* {@linkplain #LATITUDE "geospatial_lat_resolution"}<br>
@@ -104,9 +110,11 @@ import org.opengis.metadata.extent.Geogr
* {@linkplain #TITLE "name"}<br>
* {@value #NAMING_AUTHORITY}<br>
* {@value #PROCESSING_LEVEL}<br>
+ * {@value #PROGRAM}<br>
* {@value #PROJECT}<br>
* {@linkplain #PUBLISHER "publisher_email"}<br>
* {@linkplain #PUBLISHER "publisher_name"}<br>
+ * {@linkplain #PUBLISHER "publisher_type"}<br>
* {@linkplain #PUBLISHER "publisher_url"}<br>
* {@value #PURPOSE}<br>
* {@value #REFERENCES}<br>
@@ -391,6 +399,22 @@ public class AttributeNames {
public static final String DATE_ISSUED = "date_issued";
/**
+ * The overarching program(s) of which the dataset is a part
+ * (<em>Suggested</em>).
+ *
+ * <p><b>Path in ISO 19115:</b></p> <ul><li>{@link Metadata} /
+ * {@link Metadata#getAcquisitionInformation() acquisitionInformation} /
+ * {@link AcquisitionInformation#getOperations() operation} /
+ * {@link Operation#getCitation() citation} /
+ * {@link Citation#getTitle() title}</li></ul>
+ *
+ * @see <a
href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#program">ESIP
reference</a>
+ *
+ * @since 0.8
+ */
+ public static final String PROGRAM = "program";
+
+ /**
* Holds the attribute names describing a responsible party.
* In the following table, the header lists the constants defined in the
{@link AttributeNames}
* class and the other cells give the values assigned in this class fields
for those constants.
@@ -408,10 +432,15 @@ public class AttributeNames {
* <td >{@code "contributor_name"}</td>
* <td >{@code "publisher_name"}</td>
* </tr><tr>
- * <td >{@link #INSTITUTION}</td>
- * <td class="sep">{@code "institution"}</td>
+ * <td >{@link #TYPE}</td>
+ * <td class="sep">{@code "creator_type"}</td>
* <td ></td>
+ * <td >{@code "publisher_type"}</td>
+ * </tr><tr>
+ * <td >{@link #INSTITUTION}</td>
+ * <td class="sep">{@code "creator_institution"}</td>
* <td ></td>
+ * <td >{@code "publisher_institution"}</td>
* </tr><tr>
* <td >{@link #URL}</td>
* <td class="sep">{@code "creator_url"}</td>
@@ -442,7 +471,7 @@ public class AttributeNames {
* in a netCDF file.</div>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 0.8
*
* @see org.apache.sis.storage.netcdf.AttributeNames.Dimension
*
@@ -456,7 +485,7 @@ public class AttributeNames {
private static final long serialVersionUID = 2680152633273321012L;
/**
- * The attribute name for the responsible's name. Possible values are
+ * The attribute name for the responsible's name. Possible values for
this field are
* {@code "creator_name"}, {@code "contributor_name"} or {@code
"publisher_name"}.
*
* <p><b>Path in ISO 19115:</b></p> <ul><li>{@link ResponsibleParty} /
@@ -465,6 +494,13 @@ public class AttributeNames {
public final String NAME;
/**
+ * The attribute name for the responsible's type. Possible values for
this field are
+ * {@code "creator_type"} or {@code "publisher_type"}. Possible values
in a netCDF file
+ * are {@code "person"}, {@code "group"}, {@code "institution"} or
{@code "position"}.
+ */
+ public final String TYPE;
+
+ /**
* The attribute name for the responsible's institution, or {@code
null} if none.
* Possible value is {@code "institution"}.
*
@@ -512,19 +548,33 @@ public class AttributeNames {
public final Role DEFAULT_ROLE;
/**
+ * @deprecated replaced by the constructor with one more argument (the
type).
+ */
+ @Deprecated
+ public Responsible(final String name, final String institution, final
String url, final String email,
+ final String role, final Role defaultRole)
+ {
+ this(name, null, institution, url, email, role, defaultRole);
+ }
+
+ /**
* Creates a new set of attribute names. Any argument can be {@code
null} if not applicable.
*
* @param name the attribute name for the responsible's name.
+ * @param type the attribute name for the responsible party
type.
* @param institution the attribute name for the responsible's
institution.
* @param url the attribute name for the responsible's URL.
* @param email the attribute name for the responsible's email
address.
- * @param role the attribute name for the responsible's role.
+ * @param role the attribute name for the responsible party
role.
* @param defaultRole the role to use as a fallback if no attribute
value is associated to the {@code role} key.
+ *
+ * @since 0.8
*/
- public Responsible(final String name, final String institution, final
String url, final String email,
- final String role, final Role defaultRole)
+ public Responsible(final String name, final String type, final String
institution, final String url,
+ final String email, final String role, final Role defaultRole)
{
NAME = name;
+ TYPE = type;
INSTITUTION = institution;
URL = url;
EMAIL = email;
@@ -544,8 +594,8 @@ public class AttributeNames {
* @see #PUBLISHER
* @see <a
href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#creator_name">ESIP
reference</a>
*/
- public static final Responsible CREATOR = new
Responsible(ACDD.creator_name,
- "institution", ACDD.creator_url, ACDD.creator_email, null,
Role.ORIGINATOR);
+ public static final Responsible CREATOR = new
Responsible(ACDD.creator_name, "creator_type",
+ "creator_institution", ACDD.creator_url, ACDD.creator_email, null,
Role.ORIGINATOR);
/**
* The set of attribute names for the contributor (<em>Suggested</em>).
@@ -558,7 +608,7 @@ public class AttributeNames {
* @see #PUBLISHER
* @see <a
href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#contributor_name">ESIP
reference</a>
*/
- public static final Responsible CONTRIBUTOR = new
Responsible("contributor_name",
+ public static final Responsible CONTRIBUTOR = new
Responsible("contributor_name", null,
null, "contributor_url", "contributor_email", "contributor_role",
null);
/**
@@ -577,8 +627,8 @@ public class AttributeNames {
* @see #CONTRIBUTOR
* @see <a
href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#publisher_name">ESIP
reference</a>
*/
- public static final Responsible PUBLISHER = new
Responsible(ACDD.publisher_name,
- null, ACDD.publisher_url, ACDD.publisher_email, null,
Role.PUBLISHER);
+ public static final Responsible PUBLISHER = new
Responsible(ACDD.publisher_name, "publisher_type",
+ ACDD.publisher_institution, ACDD.publisher_url,
ACDD.publisher_email, null, Role.PUBLISHER);
/**
* The {@value} attribute name for the scientific project that produced
the data
@@ -685,6 +735,8 @@ public class AttributeNames {
/**
* Data's 2D or 3D geospatial extent in OGC's Well-Known Text (WKT)
geometry format.
+ * The Coordinate Reference System is given by {@code
"geospatial_bounds_crs"},
+ * possibly completed by {@code "geospatial_bounds_vertical_crs"}.
*
* <p><b>Path in ISO 19115:</b></p> <ul><li>{@link Metadata} /
* {@link Metadata#getIdentificationInfo() identificationInfo} /
@@ -692,6 +744,8 @@ public class AttributeNames {
* {@link Extent#getGeographicElements() geographicElement} /
* {@link BoundingPolygon#getPolygons() polygon}</li></ul>
*
+ * @see <a
href="http://wiki.esipfed.org/index.php/Attribute_Convention_for_Data_Discovery#geospatial_bounds">ESIP
reference</a>
+ *
* @since 0.8
*/
public static final String GEOSPATIAL_BOUNDS = "geospatial_bounds";
Modified:
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java?rev=1812312&r1=1812311&r2=1812312&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
[UTF-8] Mon Oct 16 19:10:29 2017
@@ -425,8 +425,10 @@ split: while ((start = CharSequences.sk
* <p>Implementation note: this method tries to reuse the existing {@link
#pointOfContact} instance,
* or part of it, if it is suitable.</p>
*
- * @param keys the group of attribute names to use for fetching the
values.
- * @param isPointOfContact {@code true} for forcing the role to {@link
Role#POINT_OF_CONTACT}.
+ * @param keys the group of attribute names to use for
fetching the values.
+ * @param isPointOfContact {@code true} if this responsible party is the
"main" one. This will force the
+ * role to {@link Role#POINT_OF_CONTACT} and enable the use of
{@code "institution"} attribute as
+ * a fallback if there is no value for {@link
Responsible#INSTITUTION}.
* @return the responsible party, or {@code null} if none.
*
* @see AttributeNames#CREATOR
@@ -434,13 +436,29 @@ split: while ((start = CharSequences.sk
* @see AttributeNames#PUBLISHER
*/
private Responsibility createResponsibleParty(final Responsible keys,
final boolean isPointOfContact) {
- final String individualName = stringValue(keys.NAME);
- final String organisationName = stringValue(keys.INSTITUTION);
- final String email = stringValue(keys.EMAIL);
- final String url = stringValue(keys.URL);
+ String individualName = stringValue(keys.NAME);
+ String organisationName = stringValue(keys.INSTITUTION);
+ final String email = stringValue(keys.EMAIL);
+ final String url = stringValue(keys.URL);
+ if (organisationName == null && isPointOfContact) {
+ organisationName = stringValue("institution");
+ }
if (individualName == null && organisationName == null && email ==
null && url == null) {
return null;
}
+ /*
+ * The "individual" name may actually be an institution name, either
because a "*_type" attribute
+ * said so or because the "individual" name is the same than the
institution name. In such cases,
+ * reorganize the names in order to avoid duplication.
+ */
+ if (organisationName == null) {
+ if (isOrganisation(keys)) {
+ organisationName = individualName;
+ individualName = null;
+ }
+ } else if (organisationName.equalsIgnoreCase(individualName)) {
+ individualName = null;
+ }
Role role = forCodeName(Role.class, stringValue(keys.ROLE));
if (role == null) {
role = isPointOfContact ? Role.POINT_OF_CONTACT :
keys.DEFAULT_ROLE;
@@ -500,7 +518,7 @@ split: while ((start = CharSequences.sk
AbstractParty party = null;
if (individualName != null) party = new
DefaultIndividual(individualName, null, null);
if (organisationName != null) party = new
DefaultOrganisation(organisationName, null, (Individual) party, null);
- if (party == null) party = new AbstractParty(); //
We don't know if this is an individual or an organisation.
+ if (party == null) party = isOrganisation(keys) ?
new DefaultOrganisation() : new DefaultIndividual();
if (contact != null)
party.setContactInfo(singleton(contact));
responsibility = new DefaultResponsibility(role, null, party);
}
@@ -509,6 +527,16 @@ split: while ((start = CharSequences.sk
}
/**
+ * Returns {@code true} if the responsible party described by the given
keys is an organization.
+ * In case of doubt, this method returns {@code false}. This is consistent
with ACDD recommendation,
+ * which set the default value to {@code "person"}.
+ */
+ private boolean isOrganisation(final Responsible keys) {
+ final String type = stringValue(keys.TYPE);
+ return "institution".equalsIgnoreCase(type) ||
"group".equalsIgnoreCase(type);
+ }
+
+ /**
* Adds a {@code DataIdentification/Citation} element if at least one of
the required attributes is non-null.
* This method will initialize the {@link #pointOfContact} field, than
reuse it if non-null and suitable.
*
@@ -768,6 +796,13 @@ split: while ((start = CharSequences.sk
}
/**
+ * Adds information about acquisition (program, platform).
+ */
+ private void addAcquisitionInfo() {
+ addAcquisitionOperation(null, stringValue(PROGRAM));
+ }
+
+ /**
* Adds information about all netCDF variables. This is the {@code
<gmd:contentInfo>} element in XML.
* This method groups variables by their domains, i.e. variables having
the same set of axes are grouped together.
*/
@@ -918,6 +953,7 @@ split: while ((start = CharSequences.sk
addResourceScope(ScopeCode.SERVICE, name);
}
}
+ addAcquisitionInfo();
addContentInfo();
/*
* Add the dimension information, if any. This metadata node
Modified:
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java?rev=1812312&r1=1812311&r2=1812312&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/DecoderTest.java
[UTF-8] Mon Oct 16 19:10:29 2017
@@ -57,7 +57,7 @@ public strictfp class DecoderTest extend
if (isSupplementalFormatSupported("HDF5")) {
selectDataset(CIP);
assertAttributeEquals(/* Only control character */ (String) null,
TITLE);
- assertAttributeEquals("UCAR",
CREATOR.INSTITUTION);
+ assertAttributeEquals("UCAR",
"INSTITUTION");
assertAttributeEquals("U.S. National Weather Service - NCEP
(WMC)", HISTORY);
}
}
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java?rev=1812312&r1=1812311&r2=1812312&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
[UTF-8] Mon Oct 16 19:10:29 2017
@@ -2416,6 +2416,26 @@ parse: for (int i = 0; i < length;)
}
/**
+ * Adds the identifier of the operation used to acquire the dataset.
+ * Examples: "GHRSST", "NOAA CDR", "NASA EOS", "JPSS", "GOES-R".
+ * Storage location is:
+ *
+ * <ul>
+ * <li>{@code metadata/acquisitionInformation/operation/identifier}</li>
+ * </ul>
+ *
+ * @param program identification of the mission, or {@code null} if
none.
+ * @param identifier unique identification of the operation, or {@code
null} for no-operation.
+ */
+ public final void addAcquisitionOperation(final CharSequence program,
String identifier) {
+ if (identifier != null && !(identifier = identifier.trim()).isEmpty())
{
+ final DefaultOperation r = new DefaultOperation();
+ r.setIdentifier(sharedIdentifier(program, identifier));
+ addIfNotPresent(acquisition().getOperations(), r);
+ }
+ }
+
+ /**
* Adds the identifier of the requirement to be satisfied by data
acquisition.
* Storage location is:
*
Modified:
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreFormat.java?rev=1812312&r1=1812311&r2=1812312&view=diff
==============================================================================
---
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreFormat.java
[UTF-8] Mon Oct 16 19:10:29 2017
@@ -77,16 +77,18 @@ public final class StoreFormat extends W
* @param geometry the geometry to parse, or {@code null} if none.
* @param crs the horizontal part of the WKT (2D or 3D), or
{@code null} if none.
* @param additionalCRS the vertical or temporal part of the WKT, or
{@code null} if none.
- * @return the geometry, or {@code null} if none.
+ * @return the geometry, or {@code null} if none or unparseable.
*/
public Geometry parseGeometry(final String geometry, final String crs,
final String additionalCRS) {
- if (geometry != null) {
+ if (geometry != null) try {
final Object obj =
Geometries.implementation(library).parseWKT(geometry);
final GeneralEnvelope envelope = Geometries.getEnvelope(geometry);
if (envelope != null) {
envelope.setCoordinateReferenceSystem(parseCRS(crs,
additionalCRS));
return new GeometryWrapper(obj, envelope);
}
+ } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ log(e);
}
return null;
}
@@ -110,14 +112,13 @@ public final class StoreFormat extends W
components[n++] = (CoordinateReferenceSystem) crs;
}
}
- if (n == 0) {
- return null;
+ if (n != 0) {
+ return CRS.compound(ArraysExt.resize(components, n));
}
- return CRS.compound(ArraysExt.resize(components, n));
} catch (ParseException | ClassCastException |
IllegalArgumentException | FactoryException e) {
log(e);
- return null;
}
+ return null;
}
/**