blob: 635b15f688283033addc0616b1758fa005f346d4 [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.oodt.opendapps.extractors;
//JDK imports
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
//OPENDAP imports
import opendap.dap.Attribute;
import opendap.dap.AttributeTable;
import opendap.dap.DAS;
import opendap.dap.DConnect;
//OODT imports
import org.apache.oodt.cas.metadata.Metadata;
import org.apache.oodt.opendapps.config.OpendapConfig;
import org.apache.oodt.opendapps.config.OpendapConfigMetKeys;
import org.apache.oodt.opendapps.config.OpendapProfileMetKeys;
import org.apache.oodt.opendapps.config.ProcessingInstructions;
import org.apache.oodt.opendapps.util.ProfileUtils;
import org.springframework.util.StringUtils;
/**
* Implementation of {@link MetadataExtractor} to extract metadata from an
* OpenDAP DAS source. Currently this class only extracts metadata from the
* NetCDF global attributes of type String, disregarding all others.
*
* @author Luca Cinquini
*
*/
public class DasMetadataExtractor implements MetadataExtractor {
// constants from NetCDF metadata convention
public static final String NC_GLOBAL = "NC_GLOBAL";
public static final String LONG_NAME = "long_name";
public static final String STANDARD_NAME = "standard_name";
// NetCDF data types
public static final int INT32_TYPE = 6;
public static final int INT64_TYPE = 7;
public static final int FLOAT32_TYPE = 8;
public static final int FLOAT64_TYPE = 9;
public static final int STRING_TYPE = 10;
// output format for all global attributes interpreted as dates
private final static String OUTPUT_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private final static DateFormat outputDatetimeFormat = new SimpleDateFormat(OUTPUT_DATETIME_FORMAT);
private static Logger LOG = Logger.getLogger(DasMetadataExtractor.class
.getName());
/**
* The DAS stream which is the metadata source.
*/
private final DConnect dConn;
public DasMetadataExtractor(DConnect dConn) {
this.dConn = dConn;
}
/**
* The main metadata extraction method.
*
* @param metadata
* : the metadata target, specifically the CAS metadata container.
*/
public void extract(Metadata metadata, OpendapConfig config) {
LOG.log(Level.INFO, "Parsing DAS metadata from: " + dConn.URL());
// list of excluded variables
Set<String> excludedVariables
= config.getProcessingInstructions().getInstructionValues(OpendapConfigMetKeys.EXCLUDE_VARIABLES_ATTR);
try {
DAS das = dConn.getDAS();
@SuppressWarnings("unchecked")
Enumeration<String> names = das.getNames();
while (names.hasMoreElements()) {
String attName = names.nextElement();
LOG.log(Level.FINE, "Extracting DAS attribute: " + attName);
AttributeTable at = das.getAttributeTable(attName);
Enumeration<String> e = at.getNames();
// NetCDF global attributes
// store attribute name, all values for ALL attributes (strings and numerics)
ProcessingInstructions processingInstructions = config.getProcessingInstructions();
if (attName.equals(NC_GLOBAL)) {
while (e.hasMoreElements()) {
String key = e.nextElement();
Attribute att = at.getAttribute(key);
// convert all DAS attribute names to lower case
String lkey = key.toLowerCase();
// look for global attribute name in date/time configuration specification
String dateTimeFormatKey = OpendapConfigMetKeys.DATETIME_FORMAT_ATTR + ":" + lkey;
String dateTimeFormatValue = processingInstructions.getInstructionValue(dateTimeFormatKey);
// add this attribute as properly formatted date/time
if (StringUtils.hasText(dateTimeFormatValue)) {
DateFormat inFormat = new SimpleDateFormat(dateTimeFormatValue);
Enumeration<String> edt = att.getValues();
while (edt.hasMoreElements()) {
String value = edt.nextElement();
try {
Date date = inFormat.parse(value);
ProfileUtils.addIfNotNull(metadata, lkey, outputDatetimeFormat.format(date));
} catch(ParseException pe) {
LOG.log(Level.WARNING,
"Error parsing date/time from DAS attribute: "+key+" value="+value+" error="+pe.getMessage());
}
}
// add this global attribute as string
} else {
ProfileUtils.addIfNotExisting(metadata, lkey, att.getValues());
}
}
// NetCDF coordinates
} else {
if ( attName.equalsIgnoreCase("lat") || attName.equalsIgnoreCase("latitude")
|| attName.equalsIgnoreCase("lon") || attName.equalsIgnoreCase("longitude")
|| attName.equalsIgnoreCase("time")
|| attName.equalsIgnoreCase("alt") || attName.equalsIgnoreCase("altitude")
|| attName.equalsIgnoreCase("lev") || attName.equalsIgnoreCase("level")
|| attName.equalsIgnoreCase("depth")
) {
if (!excludedVariables.contains(attName)) {
// store coordinate name
ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.COORDINATES, attName);
}
} else if (attName.toLowerCase().startsWith("time_") || attName.toLowerCase().endsWith("_time")) {
// ignore for now - it's not a coordinate neither a variable you would want to search on
// NetCDF variables
} else {
if (!excludedVariables.contains(attName)) {
// store variable name
ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.VARIABLES, attName);
// store "standard_name", "long_name"
while (e.hasMoreElements()) {
String key = e.nextElement();
Attribute att = at.getAttribute(key);
if (key.equalsIgnoreCase(STANDARD_NAME)) {
ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.CF_STANDARD_NAMES, att.getValueAt(0));
} else if (key.equalsIgnoreCase(LONG_NAME)) {
ProfileUtils.addIfNotNull(metadata, OpendapProfileMetKeys.VARIABLES_LONG_NAMES, att.getValueAt(0));
}
}
}
}
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Error parsing DAS metadata: " + e.getMessage());
}
}
}