001 /*
002 * GeoAPI - Java interfaces for OGC/ISO standards
003 * http://www.geoapi.org
004 *
005 * This file is hereby placed into the Public Domain.
006 * This means anyone is free to do whatever they wish with this file.
007 *
008 * The NetCDF wrappers are provided as code examples, in the hope to facilitate
009 * GeoAPI implementations backed by other libraries. Implementors can take this
010 * source code and use it for any purpose, commercial or non-commercial, copyrighted
011 * or open-source, with no legal obligation to acknowledge the borrowing/copying
012 * in any way.
013 */
014 package org.opengis.wrapper.netcdf;
015
016 import java.util.Map;
017 import java.util.List;
018 import java.util.Iterator;
019 import java.util.LinkedHashMap;
020 import java.io.IOException;
021 import ucar.nc2.NetcdfFile;
022
023 import org.opengis.metadata.*;
024 import org.opengis.metadata.extent.*;
025 import org.opengis.metadata.spatial.*;
026 import org.opengis.metadata.content.*;
027 import org.opengis.metadata.quality.*;
028 import org.opengis.metadata.lineage.*;
029 import org.opengis.metadata.citation.*;
030 import org.opengis.metadata.constraint.*;
031 import org.opengis.metadata.identification.*;
032 import org.opengis.util.GenericName;
033 import org.opengis.test.metadata.RootValidator;
034 import org.opengis.test.Validators;
035
036 import org.junit.Test;
037
038 import static org.opengis.test.Assert.*;
039
040
041 /**
042 * Tests the {@link NetcdfMetadata} class.
043 * The main properties tested by this class are:
044 *
045 * <ul>
046 * <li>The {@linkplain Metadata#getIdentificationInfo() identification} identifier, title, abstract and date.</li>
047 * <li>The {@linkplain ResponsibleParty responsible party} name, role and email address.</li>
048 * <li>The {@linkplain GeographicBoundingBox geographic bounding box}.</li>
049 * </ul>
050 *
051 * <b><u>Inheriting tests in external projects</u></b><br>
052 * In order to test their own implementation, external projects can override the
053 * {@link #wrap(NetcdfFile)} method as in the example below:
054 *
055 * <blockquote><pre>public class MyTest extends NetcdfMetadataTest {
056 * @Override
057 * protected Metadata wrap(NetcdfFile file) throws IOException {
058 * return new MyWrapper(file);
059 * }
060 *}</pre></blockquote>
061 *
062 * In addition, implementors can alter the expected and actual attribute values before they
063 * are compared, and alter the way the comparison is performed. More specifically, every
064 * {@code testXXX()} method in this class proceeds in two steps:
065 *
066 * <ul>
067 * <li>First, {@linkplain #fetchMetadataProperties(String) fill a map of all property values}
068 * which are going to be tested.</li>
069 * <li>Then, {@linkplain #compareProperties(String,double) compare the expected and actual values},
070 * considering all properties as optional (i.e. no exception is thrown if the implementation
071 * didn't mapped a NetCDF attribute to a metadata property).</li>
072 * </ul>
073 *
074 * Subclasses can override the {@link #fetchMetadataProperties(String)} and
075 * {@link #compareProperties(String,double)} methods in order to modify the
076 * default behavior, or for performing additional checks.
077 *
078 * @author Martin Desruisseaux (Geomatys)
079 * @version 3.1
080 * @since 3.1
081 */
082 public strictfp class NetcdfMetadataTest extends IOTestCase {
083 /**
084 * The validator to use for validating the {@link Metadata} instance.
085 * This validator is specified at construction time.
086 */
087 protected final RootValidator validator;
088
089 /**
090 * The metadata object being tested. This field is set to the value returned
091 * by {@link #wrap(NetcdfFile)} when a {@code testXXX()} method is executed.
092 */
093 protected Metadata metadata;
094
095 /**
096 * The properties that are expected for the test being run.
097 * The content of this map is filled by the {@code testXXX()} method.
098 */
099 protected final Map<String,Object> expectedProperties;
100
101 /**
102 * The actual properties found in the {@linkplain #metadata}.
103 * The content of this map is filled by the {@link #fetchMetadataProperties(String)} method.
104 */
105 protected final Map<String,Object> actualProperties;
106
107 /**
108 * Creates a new test case using the default validator.
109 * This constructor sets the {@link RootValidator#requireMandatoryAttributes} field
110 * to {@code false}, since NetCDF metadata are sometime incomplete.
111 */
112 public NetcdfMetadataTest() {
113 this(new RootValidator(Validators.DEFAULT));
114 validator.requireMandatoryAttributes = false;
115 }
116
117 /**
118 * Creates a new test case using the given validator. This constructor is provided for
119 * subclasses wanting to use different validation methods. It is caller responsibility
120 * to configure the given validator (for example whether to
121 * {@linkplain RootValidator#requireMandatoryAttributes require mandatory attributes} or not).
122 *
123 * @param validator The validator to use for validating the {@link Metadata} instance.
124 */
125 protected NetcdfMetadataTest(final RootValidator validator) {
126 this.validator = validator;
127 expectedProperties = new LinkedHashMap<String,Object>(32);
128 actualProperties = new LinkedHashMap<String,Object>(32);
129 }
130
131 /**
132 * Wraps the given NetCDF file into a GeoAPI Metadata object. The default implementation
133 * creates a {@link NetcdfMetadata} instance. Subclasses can override this method for
134 * creating their own instance.
135 *
136 * @param file The NetCDF file to wrap.
137 * @return A metadata implementation created from the attributes found in the given file.
138 * @throws IOException If an error occurred while wrapping the given NetCDF file.
139 */
140 protected Metadata wrap(final NetcdfFile file) throws IOException {
141 return new NetcdfMetadata(file);
142 }
143
144 /**
145 * Returns the single element from the given collection, or {@code null} if none.
146 * The default implementation makes the following choice:
147 *
148 * <ul>
149 * <li>If the given collection is null or empty, returns {@code null}.</li>
150 * <li>If the given collection contains exactly one element, returns that element.</li>
151 * <li>Otherwise, throws {@link AssertionError}.</li>
152 * </ul>
153 *
154 * Subclasses can override this method if they want to select the element in a different way.
155 *
156 * @param <E> The type of collection elements.
157 * @param collection The collection from which to get the singleton.
158 * @return The singleton element from the collection, or {@code null} if none.
159 */
160 protected <E> E getSingleton(final Iterable<? extends E> collection) {
161 if (collection != null) {
162 final Iterator<? extends E> it = collection.iterator();
163 if (it.hasNext()) {
164 final E element = it.next();
165 assertFalse("The collection has more than one element.", it.hasNext());
166 return element;
167 }
168 }
169 return null;
170 }
171
172 /**
173 * Puts the given (key,value) pair in the map of actual properties, provided that the value is non-null.
174 */
175 private void put(final String key, Object value) {
176 if (value != null) {
177 if (value instanceof CharSequence || value instanceof GenericName) {
178 value = value.toString();
179 } else if (value instanceof Double) {
180 if (Double.isNaN((Double) value)) {
181 return;
182 }
183 }
184 assertNull(actualProperties.put(key, value));
185 }
186 }
187
188 /**
189 * Fills the {@link #actualProperties} map with the property values found in the current {@link #metadata}.
190 * This method fetches only the metadata properties which are mapped to NetCDF attributes,
191 * and intentionally ignores all other metadata.
192 *
193 * @param filename The NetCDF file being tested, typically as one of the constants defined
194 * in the {@link IOTestCase} class.
195 */
196 protected void fetchMetadataProperties(final String filename) {
197 put("metadataStandardName", metadata.getMetadataStandardName());
198 put("metadataStandardVersion", metadata.getMetadataStandardVersion());
199 put("fileIdentifier", metadata.getFileIdentifier());
200 /*
201 * Metadata / Contact.
202 */
203 ResponsibleParty party = getSingleton(metadata.getContacts());
204 if (party != null) {
205 put("contact.role", party.getRole());
206 put("contact.individualName", party.getIndividualName());
207 put("contact.organisationName", party.getOrganisationName());
208 final Contact contact = party.getContactInfo();
209 if (contact != null) {
210 final Address address = contact.getAddress();
211 if (address != null) {
212 put("contact.contactInfo.address.electronicMailAddress", getSingleton(address.getElectronicMailAddresses()));
213 }
214 }
215 }
216 final Identification identification = getSingleton(metadata.getIdentificationInfo());
217 if (identification != null) {
218 put("identificationInfo.abstract", identification.getAbstract());
219 /*
220 * Metadata / Data Identification / Point of Contact.
221 */
222 party = getSingleton(identification.getPointOfContacts());
223 if (party != null) {
224 put("identificationInfo.pointOfContact.role", party.getRole());
225 put("identificationInfo.pointOfContact.individualName", party.getIndividualName());
226 put("identificationInfo.pointOfContact.organisationName", party.getOrganisationName());
227 final Contact contact = party.getContactInfo();
228 if (contact != null) {
229 final Address address = contact.getAddress();
230 if (address != null) {
231 put("identificationInfo.pointOfContact.contactInfo.address.electronicMailAddress",
232 getSingleton(address.getElectronicMailAddresses()));
233 }
234 }
235 }
236 /*
237 * Metadata / Data Identification / Citation.
238 */
239 final Citation citation = identification.getCitation();
240 if (citation != null) {
241 put("identificationInfo.citation.title", citation.getTitle());
242 final Identifier identifier = getSingleton(citation.getIdentifiers());
243 if (identifier != null) {
244 put("identificationInfo.citation.identifier.code", identifier.getCode());
245 final Citation authority = identifier.getAuthority();
246 if (authority != null) {
247 put("identificationInfo.citation.identifier.authority", authority.getTitle());
248 }
249 }
250 final CitationDate date = getSingleton(citation.getDates());
251 if (date != null) {
252 put("identificationInfo.citation.date.date", date.getDate());
253 put("identificationInfo.citation.date.dateType", date.getDateType());
254 }
255 /*
256 * Metadata / Data Identification / Citation / Responsibly party.
257 */
258 party = getSingleton(citation.getCitedResponsibleParties());
259 if (party != null) {
260 put("identificationInfo.citation.citedResponsibleParty.role", party.getRole());
261 put("identificationInfo.citation.citedResponsibleParty.individualName", party.getIndividualName());
262 put("identificationInfo.citation.citedResponsibleParty.organisationName", party.getOrganisationName());
263 final Contact contact = party.getContactInfo();
264 if (contact != null) {
265 final Address address = contact.getAddress();
266 if (address != null) {
267 put("identificationInfo.citation.citedResponsibleParty.contactInfo.address.electronicMailAddress",
268 getSingleton(address.getElectronicMailAddresses()));
269 }
270 }
271 }
272 }
273 /*
274 * Metadata / Data Identification / Descriptive Keywords.
275 */
276 final Keywords keywords = getSingleton(identification.getDescriptiveKeywords());
277 if (keywords != null) {
278 put("identificationInfo.descriptiveKeywords.type", keywords.getType());
279 put("identificationInfo.descriptiveKeywords.thesaurusName", keywords.getThesaurusName().getTitle());
280 put("identificationInfo.descriptiveKeywords.keyword", getSingleton(keywords.getKeywords()));
281 }
282 /*
283 * Metadata / Data Identification / Resource Constraints / Use Limitation.
284 */
285 final Constraints constraints = getSingleton(identification.getResourceConstraints());
286 if (constraints != null) {
287 put("identificationInfo.resourceConstraints.useLimitation", getSingleton(constraints.getUseLimitations()));
288 }
289 /*
290 * Metadata / Data Identification / Extents.
291 */
292 if (identification instanceof DataIdentification) {
293 final DataIdentification data = (DataIdentification) identification;
294 put("identificationInfo.supplementalInformation", data.getSupplementalInformation());
295 put("identificationInfo.spatialRepresentationType", getSingleton(data.getSpatialRepresentationTypes()));
296 final Extent extent = getSingleton(data.getExtents());
297 if (extent != null) {
298 final GeographicExtent geoExtent = getSingleton(extent.getGeographicElements());
299 if (geoExtent != null) {
300 /*
301 * Metadata / Data Identification / Extents / Geographic Bounding Box.
302 */
303 put("identificationInfo.extent.geographicElement.extentTypeCode", geoExtent.getInclusion());
304 if (geoExtent instanceof GeographicBoundingBox) {
305 final GeographicBoundingBox bbox = (GeographicBoundingBox) geoExtent;
306 put("identificationInfo.extent.geographicElement.westBoundLongitude", bbox.getWestBoundLongitude());
307 put("identificationInfo.extent.geographicElement.eastBoundLongitude", bbox.getEastBoundLongitude());
308 put("identificationInfo.extent.geographicElement.southBoundLatitude", bbox.getSouthBoundLatitude());
309 put("identificationInfo.extent.geographicElement.northBoundLatitude", bbox.getNorthBoundLatitude());
310 }
311 /*
312 * Metadata / Data Identification / Extents / Vertical Extent.
313 */
314 final VerticalExtent vext = getSingleton(extent.getVerticalElements());
315 if (vext != null) {
316 put("identificationInfo.extent.verticalElement.minimumValue", vext.getMinimumValue());
317 put("identificationInfo.extent.verticalElement.maximumValue", vext.getMaximumValue());
318 }
319 }
320 }
321 }
322 }
323 /*
324 * Metadata / Quality / Lineage.
325 */
326 final DataQuality quality = getSingleton(metadata.getDataQualityInfo());
327 if (quality != null) {
328 final Lineage lineage = quality.getLineage();
329 if (lineage != null) {
330 put("dataQualityInfo.lineage.statement", lineage.getStatement());
331 }
332 }
333 /*
334 * Metadata / Grid Spatial Representation.
335 */
336 final SpatialRepresentation spatial = getSingleton(metadata.getSpatialRepresentationInfo());
337 if (spatial instanceof GridSpatialRepresentation) {
338 final GridSpatialRepresentation gridSpatial = (GridSpatialRepresentation) spatial;
339 put("spatialRepresentationInfo.numberOfDimensions", gridSpatial.getNumberOfDimensions());
340 final List<? extends Dimension> axes = gridSpatial.getAxisDimensionProperties();
341 if (axes != null) { // Should never be null, but let be safe in case an implementation choose to do so.
342 int dimension = 0;
343 for (final Dimension axis : axes) {
344 if (axis != null) {
345 put("spatialRepresentationInfo.axisDimensionProperties[" + dimension + "].dimensionName", axis.getDimensionName());
346 put("spatialRepresentationInfo.axisDimensionProperties[" + dimension + "].dimensionSize", axis.getDimensionSize());
347 put("spatialRepresentationInfo.axisDimensionProperties[" + dimension + "].resolution", axis.getResolution());
348 }
349 dimension++;
350 }
351 }
352 }
353 /*
354 * Metadata / Content information / Range dimensions.
355 */
356 final ContentInformation content = getSingleton(metadata.getContentInfo());
357 if (content instanceof CoverageDescription) {
358 final RangeDimension band = getSingleton(((CoverageDescription) content).getDimensions());
359 if (band != null) {
360 put("contentInfo.dimension.descriptor", band.getDescriptor());
361 put("contentInfo.dimension.sequenceIdentifier", band.getSequenceIdentifier());
362 }
363 }
364 }
365
366 /**
367 * Compares the properties found in the {@linkplain #metadata} with the expected properties.
368 * The default implementation removes all properties found from the properties maps.
369 * Consequently, after this method call the maps contain the following entries:
370 *
371 * <ul>
372 * <li>The {@link #expectedProperties} map contains all properties not found in the NetCDF file.</li>
373 * <li>The {@link #actualProperties} map contains all properties from the NetCDF file which have not
374 * been verified.</li>
375 * </ul>
376 *
377 * Subclasses can override this method if they want to modify the values before the comparison
378 * is performed, or for ensuring that their mandatory values have been removed from the maps
379 * (i.e. have been compared) after the comparison.
380 *
381 *
382 * @param filename The NetCDF file being tested, typically as one of the constants defined
383 * in the {@link IOTestCase} class.
384 * @param eps Tolerance factor for comparing floating-point numbers.
385 */
386 protected void compareProperties(final String filename, final double eps) {
387 for (final Iterator<Map.Entry<String,Object>> it=actualProperties.entrySet().iterator(); it.hasNext();) {
388 final Map.Entry<String,Object> entry = it.next();
389 final String key = entry.getKey();
390 final Object expectedValue = expectedProperties.remove(key);
391 if (expectedValue != null) {
392 final Object actualValue = entry.getValue();
393 assertEquals(key, expectedValue.getClass(), actualValue.getClass());
394 if (expectedValue instanceof Double) {
395 assertEquals(key, (Double) expectedValue, (Double) actualValue, eps);
396 } else {
397 assertEquals(key, expectedValue, actualValue);
398 }
399 it.remove();
400 }
401 }
402 }
403
404 /*
405 * Note: this test case shall not verify the hard-coded constants (metadataStandardName,
406 * metadataStandardVersion, hierarchyLevel) since they are obviously implementation-dependent.
407 */
408
409 /**
410 * Tests the {@value org.opengis.wrapper.netcdf.IOTestCase#THREDDS} file (XML format).
411 * The current implementation tests:
412 *
413 * <ul>
414 * <li>The {@linkplain Metadata#getFileIdentifier() file identifier}.</li>
415 * <li>The {@linkplain ResponsibleParty responsible party} name, role and email address.</li>
416 * <li>The {@linkplain GeographicBoundingBox geographic bounding box}.</li>
417 * <li>The {@linkplain Dimension axis dimensions} names, sizes and resolution.</li>
418 * <li>The {@linkplain Lineage lineage} statement.</li>
419 * </ul>
420 *
421 * Note that implementations don't need to support all those metadata.
422 * See the class javadoc for more information.
423 *
424 * @throws IOException If the test file can not be read.
425 */
426 @Test
427 public void testTHREDDS() throws IOException {
428 final Map<String,Object> expected = expectedProperties;
429 assertNull(expected.put("fileIdentifier", "crm_v1"));
430 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.role", Role.ORIGINATOR));
431 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.individualName", "David Neufeld"));
432 assertNull(expected.put("identificationInfo.pointOfContact.individualName", "David Neufeld"));
433 assertNull(expected.put("contact.individualName", "David Neufeld"));
434 assertNull(expected.put("contact.contactInfo.address.electronicMailAddress", "xxxxx.xxxxxxx@noaa.gov"));
435 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.contactInfo.address.electronicMailAddress", "xxxxx.xxxxxxx@noaa.gov"));
436 assertNull(expected.put("identificationInfo.pointOfContact.contactInfo.address.electronicMailAddress", "xxxxx.xxxxxxx@noaa.gov"));
437 assertNull(expected.put("identificationInfo.extent.geographicElement.extentTypeCode", Boolean.TRUE));
438 assertNull(expected.put("identificationInfo.extent.geographicElement.westBoundLongitude", -80.0));
439 assertNull(expected.put("identificationInfo.extent.geographicElement.eastBoundLongitude", -64.0));
440 assertNull(expected.put("identificationInfo.extent.geographicElement.southBoundLatitude", 40.0));
441 assertNull(expected.put("identificationInfo.extent.geographicElement.northBoundLatitude", 48.0));
442 assertNull(expected.put("spatialRepresentationInfo.numberOfDimensions", 2));
443 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionName", DimensionNameType.COLUMN));
444 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionName", DimensionNameType.ROW));
445 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionSize", 19201));
446 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionSize", 9601));
447 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].resolution", 8.332899328159992E-4));
448 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].resolution", 8.332465368190813E-4));
449 assertNull(expected.put("dataQualityInfo.lineage.statement", "xyz2grd -R-80/-64/40/48 -I3c -Gcrm_v1.grd"));
450 final NetcdfFile file = open(THREDDS);
451 try {
452 metadata = wrap(file);
453 validator.validate(metadata);
454 fetchMetadataProperties(THREDDS);
455 compareProperties(THREDDS, 1E-12);
456 if (getClass() == NetcdfMetadataTest.class) {
457 NonInheritable.assertProcessedAllRelevant(actualProperties, "crm_v1.grd", false, false);
458 }
459 } finally {
460 file.close();
461 }
462 }
463
464 /**
465 * Tests the {@value org.opengis.wrapper.netcdf.IOTestCase#NCEP} file (binary format).
466 * The current implementation tests:
467 *
468 * <ul>
469 * <li>The {@linkplain Metadata#getIdentificationInfo() identification} identifier, title, abstract and date.</li>
470 * <li>The {@linkplain Citation citation} title, date and abstract.</li>
471 * <li>The {@linkplain Keywords keywords} type and thesaurus.</li>
472 * <li>The {@linkplain ResponsibleParty responsible party} name and role.</li>
473 * <li>The {@linkplain GeographicBoundingBox geographic bounding box}.</li>
474 * <li>The {@linkplain VerticalExtent vertical extent}.</li>
475 * <li>The {@linkplain Constraints constraints} use limitation.</li>
476 * <li>The {@linkplain Lineage lineage} statement.</li>
477 * <li>The {@linkplain RangeDimension range dimensions}.</li>
478 * </ul>
479 *
480 * Note that implementations don't need to support all those metadata.
481 * See the class javadoc for more information.
482 *
483 * @throws IOException If the test file can not be read.
484 */
485 @Test
486 public void testNCEP() throws IOException {
487 final Map<String,Object> expected = expectedProperties;
488 assertNull(expected.put("fileIdentifier", "edu.ucar.unidata:NCEP/SST/Global_5x2p5deg/SST_Global_5x2p5deg_20050922_0000.nc"));
489 assertNull(expected.put("identificationInfo.citation.identifier.code", "NCEP/SST/Global_5x2p5deg/SST_Global_5x2p5deg_20050922_0000.nc"));
490 assertNull(expected.put("identificationInfo.citation.identifier.authority", "edu.ucar.unidata"));
491 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.role", Role.ORIGINATOR));
492 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.individualName", "NOAA/NWS/NCEP"));
493 assertNull(expected.put("identificationInfo.pointOfContact.individualName", "NOAA/NWS/NCEP"));
494 assertNull(expected.put("contact.individualName", "NOAA/NWS/NCEP"));
495 assertNull(expected.put("identificationInfo.citation.date.date", NetcdfMetadata.parseDate("2005-09-22T00:00")));
496 assertNull(expected.put("identificationInfo.citation.date.dateType", DateType.CREATION));
497 assertNull(expected.put("identificationInfo.citation.title", "Sea Surface Temperature Analysis Model"));
498 assertNull(expected.put("identificationInfo.abstract", "NCEP SST Global 5.0 x 2.5 degree model data"));
499 assertNull(expected.put("identificationInfo.descriptiveKeywords.type", KeywordType.THEME));
500 assertNull(expected.put("identificationInfo.descriptiveKeywords.thesaurusName", "GCMD Science Keywords"));
501 assertNull(expected.put("identificationInfo.descriptiveKeywords.keyword", "EARTH SCIENCE > Oceans > Ocean Temperature > Sea Surface Temperature"));
502 assertNull(expected.put("identificationInfo.resourceConstraints.useLimitation", "Freely available"));
503 assertNull(expected.put("identificationInfo.extent.geographicElement.extentTypeCode", Boolean.TRUE));
504 assertNull(expected.put("identificationInfo.extent.geographicElement.westBoundLongitude", -180.0));
505 assertNull(expected.put("identificationInfo.extent.geographicElement.eastBoundLongitude", +180.0));
506 assertNull(expected.put("identificationInfo.extent.geographicElement.southBoundLatitude", -90.0));
507 assertNull(expected.put("identificationInfo.extent.geographicElement.northBoundLatitude", +90.0));
508 assertNull(expected.put("identificationInfo.extent.verticalElement.minimumValue", 0.0));
509 assertNull(expected.put("identificationInfo.extent.verticalElement.maximumValue", 0.0));
510 assertNull(expected.put("identificationInfo.spatialRepresentationType", SpatialRepresentationType.GRID));
511 assertNull(expected.put("spatialRepresentationInfo.numberOfDimensions", 3));
512 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionSize", 73));
513 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionSize", 73));
514 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[2].dimensionSize", 1));
515 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionName", DimensionNameType.COLUMN));
516 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionName", DimensionNameType.ROW));
517 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[2].dimensionName", DimensionNameType.TIME));
518 assertNull(expected.put("contentInfo.dimension.sequenceIdentifier", "SST"));
519 assertNull(expected.put("contentInfo.dimension.descriptor", "Sea temperature"));
520 assertNull(expected.put("dataQualityInfo.lineage.statement",
521 "2003-04-07 12:12:50 - created by gribtocdl " +
522 "2005-09-26T21:50:00 - edavis - add attributes for dataset discovery"));
523 final NetcdfFile file = open(NCEP);
524 try {
525 metadata = wrap(file);
526 validator.validate(metadata);
527 fetchMetadataProperties(NCEP);
528 compareProperties(NCEP, 0.0);
529 if (getClass() == NetcdfMetadataTest.class) {
530 NonInheritable.assertProcessedAllRelevant(actualProperties, null, false, false);
531 }
532 } finally {
533 file.close();
534 }
535 }
536
537 /**
538 * Tests the {@value org.opengis.wrapper.netcdf.IOTestCase#LANDSAT} file (binary format).
539 *
540 * @throws IOException If the test file can not be read.
541 */
542 @Test
543 public void testLandsat() throws IOException {
544 final Map<String,Object> expected = expectedProperties;
545 assertNull(expected.put("contentInfo.dimension.sequenceIdentifier", "Band1"));
546 assertNull(expected.put("contentInfo.dimension.descriptor", "GDAL Band Number 1"));
547 final NetcdfFile file = open(LANDSAT);
548 try {
549 metadata = wrap(file);
550 // Do not validate, because the metadata is known to be invalid
551 // since the test file is not providing suffisient information.
552 fetchMetadataProperties(LANDSAT);
553 compareProperties(LANDSAT, 0.0);
554 if (getClass() == NetcdfMetadataTest.class) {
555 NonInheritable.assertProcessedAllRelevant(actualProperties, null, true, true);
556 }
557 } finally {
558 file.close();
559 }
560 }
561
562 /**
563 * Tests the {@value org.opengis.wrapper.netcdf.IOTestCase#CIP} file (binary format).
564 *
565 * @throws IOException If the test file can not be read.
566 */
567 @Test
568 public void testCIP() throws IOException {
569 final Map<String,Object> expected = expectedProperties;
570 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.role", Role.ORIGINATOR));
571 assertNull(expected.put("identificationInfo.citation.citedResponsibleParty.organisationName", "UCAR"));
572 assertNull(expected.put("identificationInfo.pointOfContact.organisationName", "UCAR"));
573 assertNull(expected.put("contact.organisationName", "UCAR"));
574 assertNull(expected.put("identificationInfo.supplementalInformation", "Created by Mdv2NetCDF"));
575 assertNull(expected.put("identificationInfo.extent.geographicElement.extentTypeCode", Boolean.TRUE));
576 assertNull(expected.put("identificationInfo.extent.geographicElement.westBoundLongitude", -140.290));
577 assertNull(expected.put("identificationInfo.extent.geographicElement.eastBoundLongitude", -56.658));
578 assertNull(expected.put("identificationInfo.extent.geographicElement.southBoundLatitude", 15.944));
579 assertNull(expected.put("identificationInfo.extent.geographicElement.northBoundLatitude", 58.364));
580 assertNull(expected.put("identificationInfo.extent.verticalElement.minimumValue", -15.0));
581 assertNull(expected.put("identificationInfo.extent.verticalElement.maximumValue", 35.0));
582 assertNull(expected.put("spatialRepresentationInfo.numberOfDimensions", 4));
583 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionName", DimensionNameType.COLUMN));
584 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionName", DimensionNameType.ROW));
585 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[2].dimensionName", DimensionNameType.VERTICAL));
586 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[3].dimensionName", DimensionNameType.TIME));
587 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[0].dimensionSize", 61));
588 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[1].dimensionSize", 45));
589 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[2].dimensionSize", 6));
590 assertNull(expected.put("spatialRepresentationInfo.axisDimensionProperties[3].dimensionSize", 1));
591 assertNull(expected.put("contentInfo.dimension.sequenceIdentifier", "CIP"));
592 assertNull(expected.put("contentInfo.dimension.descriptor", "Current Icing Product"));
593 assertNull(expected.put("dataQualityInfo.lineage.statement", "U.S. National Weather Service - NCEP (WMC)"));
594 final NetcdfFile file = open(CIP);
595 try {
596 metadata = wrap(file);
597 validator.validate(metadata);
598 fetchMetadataProperties(CIP);
599 compareProperties(CIP, 0.001);
600 if (getClass() == NetcdfMetadataTest.class) {
601 NonInheritable.assertProcessedAllRelevant(actualProperties, null, true, false);
602 }
603 } finally {
604 file.close();
605 }
606 }
607 }