/*
* Copyright (c) 1998 - 2009. University Corporation for Atmospheric Research/Unidata
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package thredds.tds.idd;
import ucar.nc2.dt.GridDataset;
import ucar.nc2.ft.FeatureDataset;
import ucar.nc2.ft.FeatureDatasetFactoryManager;
import ucar.nc2.constants.FeatureType;
import ucar.nc2.units.DateFormatter;
import java.util.Date;
import java.util.List;
import java.util.Formatter;
import java.io.IOException;
import thredds.catalog.*;
import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;
/**
* Utility class for comparing FMRC RUN datasets with FMRC Raw File datasets with matching run time.
*
* @author edavis
* @since 4.0
*/
public class CompareGribVarNamesUtils
{
private CompareGribVarNamesUtils() {}
private final static String GRIB_PREFIX = "catalog/grib/";
private final static String RUN_CATALOG_SUFFIX = "/runs/catalog.xml";
private final static String FILE_CATALOG_SUFFIX = "/files/catalog.xml";
/**
* For the given model ID, get the dataset at the given index in the
* "FMRC Run" catalog and compare it to the dataset with matching
* run time in the "FMRC Raw File" catalog.
*
* @param tdsUrl the URL of the target TDS.
* @param modelId the ID of the target FMRC model to compare.
* @param index the index of the target dataset in the "FMRC Run" catalog.
*/
public static void assertEqualityOfFmrcRunDsAndMatchingFmrcRawFileDsVariableNames(String tdsUrl, String modelId, int index )
{
// 1) Get the dataset at <index> in "FMRC Run" catalog.
GridDataset fmrcRunGridDs = assertFmrcRunDatasetIsAccessible( tdsUrl, modelId, index );
// 2) Extract the date of FMRC run from the dataset URL.
Date runDate = parseTimestampInFmrcRunDatasetUrl( fmrcRunGridDs );
// 3) Locate the dataset with matching run date in IDV datasetScan.
GridDataset scanGridDs = assertFmrcRawFileDatasetForMatchingTimeIsAccessible( tdsUrl, modelId, runDate );
// 4) Compare the matching datasets.
StringBuilder diffLog = new StringBuilder();
boolean isEqual = GridDatasetTestUtils.equalityOfGridDatasetsByGridNameAndShape( scanGridDs, fmrcRunGridDs, diffLog );
assertTrue( diffLog.toString(), isEqual );
}
/**
* Return the dataset at the given index location in the "FMRC Run" catalog
* for the model identified by the modelId String.
*
* @param tdsUrl the URL of the target TDS.
* @param modelId the model ID for the target model FMRC.
* @param index the target index location in the "FMRC Run" catalog.
* @return the target "FMRC Run" dataset.
*/
private static GridDataset assertFmrcRunDatasetIsAccessible( String tdsUrl, String modelId, int index )
{
// Construct URL for the given model's FMRC Run catalog.
String fmrcRunCatUrl = tdsUrl + GRIB_PREFIX + modelId + RUN_CATALOG_SUFFIX;
// Read the "FMRC Run" catalog
InvCatalogImpl cat = InvCatalogFactory.getDefaultFactory( false ).readXML( fmrcRunCatUrl );
assertFalse( "GRIB Collection catalog [" + fmrcRunCatUrl + "] had a fatal error= " + " " +cat.getLog(),
cat.hasFatalError() );
// Make sure the "FMRC Run" catalog has a top dataset and get its children.
List<InvDataset> datasets = cat.getDatasets();
assertEquals( "GRIB Collection catalog [" + fmrcRunCatUrl + "] does not have a top dataset.",
datasets.size(), 1 );
datasets = datasets.get( 0 ).getDatasets();
// Make sure the "FMRC Run" collection has enough children to satisfy request.
assertFalse( "GRIB Collection top dataset [" + fmrcRunCatUrl + "] - requested child index [" + index + "] out of range [0-" + ( datasets.size() - 1 ) + "].",
datasets.size() < index + 1 );
// Get the requested child dataset and make sure it exists, has no children, and is OPeNDAP accessible.
InvDataset requestedChildDs = datasets.get( index );
assertNotNull( "GRIB Collection child [" + index + "] dataset [" + fmrcRunCatUrl + "] is null.",
requestedChildDs );
assertFalse( "GRIB Collection child [" + index + "] dataset [" + requestedChildDs.getFullName() + "] has nested datasets.",
requestedChildDs.hasNestedDatasets() );
InvAccess access = requestedChildDs.getAccess( ServiceType.OPENDAP );
assertNotNull( "GRIB Collection child [" + index + "] dataset [" + requestedChildDs.getFullName() + "] not OPeNDAP accessible.",
access );
System.out.println( "FMRC Run child(" + index + ") dataset : "
+ access.getStandardUrlName() );
// Open the dataset as a gridded dataset.
Formatter errlog = new Formatter();
FeatureDataset dataset = null;
try
{
dataset = FeatureDatasetFactoryManager.open( FeatureType.GRID, access.getStandardUrlName(), null, errlog );
}
catch ( IOException e )
{
fail( "Dataset [" + requestedChildDs.getFullName() + "] failed to open:"
+ "\n*****" + e.getMessage()
+ "\n*****" + errlog.toString() );
}
assertNotNull( "Dataset [" + requestedChildDs.getFullName() + "] failed to open: " + errlog.toString(),
dataset );
assertTrue( "Dataset [" + requestedChildDs.getFullName() + "] not a gridded dataset: " + errlog.toString(),
dataset instanceof GridDataset );
return (GridDataset) dataset;
}
/**
* Return the date indicated by the timestamp in the URL of the given
* "FMRC Run" dataset.
* <p/>
* <p>The dataset URL has the following form:</p>
* <pre>".../<model>_RUN_<yyyy-MM-dd'T'HH:mm:ss>Z"</pre>
*
* @param fmrcRunGridDs the "FMRC Run" dataset.
* @return the run date/time of the given "FMRC Run" dataset.
*/
private static Date parseTimestampInFmrcRunDatasetUrl( GridDataset fmrcRunGridDs )
{
// Parse the timestamp from the URL of a "FMRC Run" dataset
// (".../<model>_RUN_<yyyy-MM-dd'T'HH:mm:ss>Z").
String url = fmrcRunGridDs.getLocationURI();
if ( !url.endsWith( "Z" ) )
fail( "No \"Z\" at end of FMRC Run dataset URL [" + url + "]." );
int start = url.lastIndexOf( "_RUN_" ) + 5;
DateFormatter dateFormatter = new DateFormatter();
String s = url.substring( start, url.length() - 1 );
Date runDate = dateFormatter.getISODate( s);
if (runDate == null)
{
fail( "GRIB Collection dataset URL [" + url + "] did not contain timestamp in expected format: " + s );
}
return runDate;
}
/**
* Return the dataset from the "FMRC Raw File" catalog for the given model ID
* with a run time/date matching the given run date.
*
* @param tdsUrl the URL of the target TDS.
* @param modelId the ID of the target FMRC model.
* @param runDate the Date of the target run time/date.
* @return the desired grid dataset.
*/
private static GridDataset assertFmrcRawFileDatasetForMatchingTimeIsAccessible( String tdsUrl, String modelId, Date runDate )
{
// Construct URL for the given model's "Scan" catalog.
String scanCatalogUrl = tdsUrl + GRIB_PREFIX + modelId + FILE_CATALOG_SUFFIX;
// Read the "Scan" catalog.
InvCatalogImpl cat = InvCatalogFactory.getDefaultFactory( false ).readXML( scanCatalogUrl );
assertFalse( "\"FMRC Raw File\" catalog [" + scanCatalogUrl + "] had a fatal error.", cat.hasFatalError() );
// Make sure the "Scan" catalog contains one top dataset and that it has children.
List<InvDataset> datasets = cat.getDatasets();
assertEquals( "\"FMRC Raw File\" catalog [" + scanCatalogUrl + "] contains more than one dataset.",
datasets.size(), 1 );
InvDataset topDs = datasets.get( 0 );
assertTrue( "\"FMRC Raw File\" top dataset [" + topDs.getFullName() + "] does not have child datasets.",
topDs.hasNestedDatasets() );
// Determine timestamp String to look for in dataset URL
// (".../<model>_<yyyyMMdd_HHmm>.grib[12]").
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat( "yyyyMMdd_HHmm" );
sdf.setTimeZone( java.util.TimeZone.getTimeZone( "GMT" ) );
String timeStamp = sdf.format( runDate );
InvDataset ds = null;
String dsUrl = null;
// Find the desired dataset.
for ( InvDataset curDs : topDs.getDatasets() )
{
// Get OPeNDAP URL for the current dataset.
InvAccess access = curDs.getAccess( ServiceType.OPENDAP );
if ( access == null )
continue;
String curDsUrl = access.getStandardUrlName();
// Does URL have correct format and contain desired timestamp string.
if ( !curDsUrl.matches( ".*\\.grib[12]" ) )
continue;
curDsUrl = curDsUrl.substring( 0, curDsUrl.lastIndexOf( "." ) );
if ( !curDsUrl.endsWith( timeStamp ) )
continue;
// Found the desired dataset.
ds = curDs;
dsUrl = access.getStandardUrlName();
break;
}
System.out.println( "\"FMRC Raw File\" matching [" + timeStamp + "] dataset: " + dsUrl );
// Open the dataset as a gridded dataset.
Formatter errlog = new Formatter();
FeatureDataset gridDs = null;
try
{
gridDs = FeatureDatasetFactoryManager.open( FeatureType.GRID, dsUrl, null, errlog );
}
catch ( IOException e )
{
fail( "Matching dataset [" + ds.getFullName() + "][" + dsUrl + "] failed to open:"
+ "\n*****" + e.getMessage()
+ "\n*****" + errlog.toString() );
}
assertNotNull( "Matching dataset [" + ds.getFullName() + "][" + dsUrl + "] failed to open: " + errlog.toString(),
gridDs );
assertTrue( "Matching dataset [" + ds.getFullName() + "][" + dsUrl + "] not a gridded dataset: " + errlog.toString(),
gridDs instanceof GridDataset );
return (GridDataset) gridDs;
}
}