389 lines
12 KiB
Java
389 lines
12 KiB
Java
package org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.URL;
|
|
import java.net.URLConnection;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.nio.file.StandardOpenOption;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.NetCDFValueReader;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReader;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderBoolean;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderByte;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderChar;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderDouble;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderFloat;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderInt;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderLong;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderShort;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.server.netcdf.behavior.ValueReaderString;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.exception.ServiceException;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.AttributeData;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.DimensionData;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.NetCDFData;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.NetCDFDetailData;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.NetCDFId;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.NetCDFValues;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.RangeData;
|
|
import org.gcube.portlets.widgets.netcdfbasicwidgets.shared.netcdf.VariableData;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import ucar.ma2.Array;
|
|
import ucar.ma2.Range;
|
|
import ucar.nc2.Attribute;
|
|
import ucar.nc2.Dimension;
|
|
import ucar.nc2.NetcdfFile;
|
|
import ucar.nc2.Variable;
|
|
|
|
/**
|
|
*
|
|
* @author Giancarlo Panichi
|
|
*
|
|
*
|
|
*/
|
|
public class NetCDFResource {
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(NetCDFId.class);
|
|
|
|
private URL publicLink;
|
|
private Path ncFile = null;
|
|
private NetcdfFile netcdfFile;
|
|
private NetCDFId netCDFId = null;
|
|
|
|
/*
|
|
* { System.loadLibrary("gdaljni"); }
|
|
*/
|
|
|
|
|
|
public NetCDFResource(URL publicLink) throws ServiceException {
|
|
this.publicLink = publicLink;
|
|
retrievePublicLink();
|
|
this.netCDFId = new NetCDFId(ncFile.toAbsolutePath().toString());
|
|
|
|
}
|
|
|
|
public NetCDFResource(NetCDFId netCDFId) throws ServiceException {
|
|
this.netCDFId = netCDFId;
|
|
ncFile = Paths.get(netCDFId.getId());
|
|
|
|
}
|
|
|
|
public NetCDFId getNetCDFId() {
|
|
return netCDFId;
|
|
}
|
|
|
|
private void retrievePublicLink() throws ServiceException {
|
|
try {
|
|
ncFile = Files.createTempFile("NetCDFFile_", ".nc");
|
|
|
|
logger.debug("NetCDF Temp file: " + ncFile.toAbsolutePath().toString());
|
|
|
|
URLConnection uc = publicLink.openConnection();
|
|
try (InputStream is = uc.getInputStream()) {
|
|
BufferedInputStream bis = new BufferedInputStream(is);
|
|
OutputStream os = Files.newOutputStream(ncFile, StandardOpenOption.WRITE);
|
|
BufferedOutputStream bos = new BufferedOutputStream(os);
|
|
int data;
|
|
while ((data = bis.read()) != -1) {
|
|
bos.write(data);
|
|
}
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
logger.error("Error retriving publicLink: " + publicLink);
|
|
logger.error(e.getLocalizedMessage(), e);
|
|
throw new ServiceException("Error retrieving publicLink: " + e.getLocalizedMessage(), e);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* public void gdalExplore() { stringBuilder.append("GDAL: " +
|
|
* gdal.VersionInfo()); gdal.AllRegister(); stringBuilder.append("FILE: " +
|
|
* filename);
|
|
*
|
|
* Dataset dataset = gdal.Open(filename);//
|
|
* stringBuilder.append("Projection: " + dataset.GetProjection());
|
|
* stringBuilder.append("ProjectionRef: " + dataset.GetProjectionRef());
|
|
*
|
|
* Vector<?> vector = dataset.GetMetadata_List(); for (Object i : vector) {
|
|
* stringBuilder.append("MetaData: " + i); }
|
|
*
|
|
* int numBands = dataset.getRasterCount();
|
|
* stringBuilder.append("NumBands: " + numBands); }
|
|
*/
|
|
|
|
private void openNetcdfFile() throws ServiceException {
|
|
try {
|
|
netcdfFile = NetcdfFile.open(ncFile.toAbsolutePath().toString());
|
|
return;
|
|
} catch (Throwable e) {
|
|
logger.error("Error in NetcdfFile open: " + ncFile.toAbsolutePath().toString());
|
|
logger.error(e.getLocalizedMessage(), e);
|
|
throw new ServiceException("Error in NetcdfFile open", e);
|
|
}
|
|
|
|
}
|
|
|
|
public void close() throws ServiceException {
|
|
try {
|
|
deleteCNFile();
|
|
} catch (Throwable e) {
|
|
logger.error(e.getLocalizedMessage(), e);
|
|
throw new ServiceException("Error in close: " + e.getLocalizedMessage(), e);
|
|
}
|
|
|
|
}
|
|
|
|
private void closeNetcdfFile() throws ServiceException {
|
|
try {
|
|
logger.debug("Close NetcdfFile");
|
|
if (netcdfFile != null) {
|
|
netcdfFile.close();
|
|
}
|
|
return;
|
|
} catch (Throwable e) {
|
|
logger.error("Error in netcdfFile close: " + e.getLocalizedMessage(), e);
|
|
throw new ServiceException(e.getLocalizedMessage(), e);
|
|
}
|
|
|
|
}
|
|
|
|
private void deleteCNFile() throws ServiceException {
|
|
try {
|
|
if (ncFile != null) {
|
|
logger.debug("Delete ncFile: " + ncFile.toAbsolutePath().toString());
|
|
Files.delete(ncFile);
|
|
}
|
|
} catch (Throwable e) {
|
|
logger.error("Error deleting ncFile: " + e.getLocalizedMessage(), e);
|
|
throw new ServiceException(e.getLocalizedMessage(), e);
|
|
}
|
|
}
|
|
|
|
public NetCDFData exploreNetCDF() throws ServiceException {
|
|
openNetcdfFile();
|
|
NetCDFData netCDFData = process();
|
|
closeNetcdfFile();
|
|
return netCDFData;
|
|
}
|
|
|
|
private NetCDFData process() {
|
|
NetCDFDetailData netCDFDetailData = processDetail();
|
|
ArrayList<DimensionData> dimensions = processDimensions();
|
|
ArrayList<VariableData> variables = processVariables();
|
|
NetCDFData netCDFData = new NetCDFData(netCDFId, netCDFDetailData, dimensions, variables);
|
|
return netCDFData;
|
|
|
|
}
|
|
|
|
private NetCDFDetailData processDetail() {
|
|
|
|
// String info = netcdfFile.getDetailInfo();
|
|
String typeId = netcdfFile.getFileTypeId();
|
|
String typeDescription = netcdfFile.getFileTypeDescription();
|
|
String typeVersion = netcdfFile.getFileTypeVersion();
|
|
// String title = netcdfFile.getTitle();
|
|
|
|
List<Attribute> globalAttrs = netcdfFile.getGlobalAttributes();
|
|
ArrayList<AttributeData> attributeDataList=readAttributes(globalAttrs);
|
|
|
|
NetCDFDetailData netCDFDetailData = new NetCDFDetailData(typeId, typeDescription, typeVersion, attributeDataList);
|
|
return netCDFDetailData;
|
|
|
|
}
|
|
|
|
private ArrayList<AttributeData> readAttributes(List<Attribute> attributes) {
|
|
ArrayList<AttributeData> attributeDataList = new ArrayList<>();
|
|
|
|
for (int i = 0; i < attributes.size(); i++) {
|
|
Attribute attr = attributes.get(i);
|
|
String values = new String();
|
|
if (attr.isArray()) {
|
|
Array vals = attr.getValues();
|
|
values = vals.toString();
|
|
} else {
|
|
if (attr.isString()) {
|
|
values = attr.getStringValue();
|
|
} else {
|
|
Number num = attr.getNumericValue();
|
|
switch (attr.getDataType()) {
|
|
case BYTE:
|
|
values = String.valueOf(num.byteValue());
|
|
break;
|
|
case SHORT:
|
|
values = String.valueOf(num.shortValue());
|
|
break;
|
|
case INT:
|
|
values = String.valueOf(num.intValue());
|
|
break;
|
|
case FLOAT:
|
|
values = String.valueOf(num.floatValue());
|
|
break;
|
|
case DOUBLE:
|
|
values = String.valueOf(num.doubleValue());
|
|
break;
|
|
case LONG:
|
|
values = String.valueOf(num.longValue());
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
AttributeData attributeData=new AttributeData(i, attr.getFullName(), attr.getDataType().name(), values);
|
|
attributeDataList.add(attributeData);
|
|
}
|
|
|
|
return attributeDataList;
|
|
}
|
|
|
|
private ArrayList<VariableData> processVariables() {
|
|
ArrayList<VariableData> varsData = new ArrayList<>();
|
|
List<Variable> variables = netcdfFile.getVariables();
|
|
for (int i = 0; i < variables.size(); i++) {
|
|
Variable variable = variables.get(i);
|
|
ArrayList<DimensionData> dimsData = new ArrayList<>();
|
|
List<Dimension> dims = variable.getDimensions();
|
|
for (int j = 0; j < dims.size(); j++) {
|
|
Dimension dim = dims.get(j);
|
|
DimensionData dimData = new DimensionData(j, dim.getFullName(), dim.getLength(), dim.isUnlimited(),
|
|
dim.isVariableLength(), dim.isShared());
|
|
dimsData.add(dimData);
|
|
}
|
|
|
|
List<Attribute> attributes = variable.getAttributes();
|
|
ArrayList<AttributeData> attrsData = readAttributes(attributes);
|
|
|
|
List<Range> ranges=variable.getRanges();
|
|
ArrayList<RangeData> rangesData=new ArrayList<>();
|
|
|
|
for(int k=0;k<ranges.size();k++){
|
|
Range range=ranges.get(k);
|
|
RangeData rangeData=new RangeData(k,range.length(),range.first(),range.stride(),range.getName() );
|
|
rangesData.add(rangeData);
|
|
}
|
|
|
|
VariableData variableData = new VariableData(i, variable.getFullName(), variable.getUnitsString(),
|
|
variable.getDataType().name(), variable.getDimensionsString(), variable.getRank(),
|
|
variable.isCoordinateVariable(), variable.isScalar(), variable.isImmutable(),
|
|
variable.isUnlimited(), variable.isUnsigned(), variable.isVariableLength(),
|
|
variable.isMemberOfStructure(), dimsData, attrsData,rangesData);
|
|
|
|
varsData.add(variableData);
|
|
|
|
}
|
|
return varsData;
|
|
}
|
|
|
|
private ArrayList<DimensionData> processDimensions() {
|
|
ArrayList<DimensionData> dimsData = new ArrayList<>();
|
|
List<Dimension> dims = netcdfFile.getDimensions();
|
|
for (int i = 0; i < dims.size(); i++) {
|
|
Dimension dim = dims.get(i);
|
|
DimensionData dimData = new DimensionData(i, dim.getFullName(), dim.getLength(), dim.isUnlimited(),
|
|
dim.isVariableLength(), dim.isShared());
|
|
dimsData.add(dimData);
|
|
|
|
}
|
|
return dimsData;
|
|
|
|
}
|
|
|
|
public NetCDFValues readDataVariable(VariableData variableData, boolean sample, int limit) throws ServiceException {
|
|
openNetcdfFile();
|
|
NetCDFValues netCDFValues = readDataInVariable(variableData, sample, limit);
|
|
closeNetcdfFile();
|
|
return netCDFValues;
|
|
|
|
}
|
|
|
|
private NetCDFValues readDataInVariable(VariableData variableData, boolean sample, int limit)
|
|
throws ServiceException {
|
|
List<Variable> vars = netcdfFile.getVariables();
|
|
Variable foundVar = null;
|
|
for (Variable var : vars) {
|
|
if (var.getFullName().compareTo(variableData.getFullName()) == 0) {
|
|
foundVar = var;
|
|
break;
|
|
}
|
|
}
|
|
if (foundVar == null) {
|
|
throw new ServiceException("Variable " + variableData.getFullName() + "not found!");
|
|
}
|
|
|
|
return elaborateVariable(foundVar, sample, limit);
|
|
}
|
|
|
|
private NetCDFValues elaborateVariable(Variable variable, boolean sample, int limit) {
|
|
ValueReader valueReader = new ValueReader();
|
|
switch (variable.getDataType()) {
|
|
case BOOLEAN:
|
|
valueReader = new ValueReaderBoolean();
|
|
break;
|
|
case BYTE:
|
|
valueReader = new ValueReaderByte();
|
|
break;
|
|
case CHAR:
|
|
valueReader = new ValueReaderChar();
|
|
break;
|
|
case DOUBLE:
|
|
valueReader = new ValueReaderDouble();
|
|
break;
|
|
case ENUM1:
|
|
break;
|
|
case ENUM2:
|
|
break;
|
|
case ENUM4:
|
|
break;
|
|
case FLOAT:
|
|
valueReader = new ValueReaderFloat();
|
|
break;
|
|
case INT:
|
|
valueReader = new ValueReaderInt();
|
|
break;
|
|
case LONG:
|
|
valueReader = new ValueReaderLong();
|
|
break;
|
|
case OBJECT:
|
|
break;
|
|
case OPAQUE:
|
|
break;
|
|
case SEQUENCE:
|
|
break;
|
|
case SHORT:
|
|
valueReader = new ValueReaderShort();
|
|
break;
|
|
case STRING:
|
|
valueReader = new ValueReaderString();
|
|
break;
|
|
case STRUCTURE:
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
NetCDFValues netCDFValues = null;
|
|
NetCDFValueReader netCDFValueReader = new NetCDFValueReader();
|
|
if (sample) {
|
|
netCDFValues = netCDFValueReader.sample(variable, limit, valueReader);
|
|
} else {
|
|
netCDFValues = netCDFValueReader.apply(variable, valueReader);
|
|
}
|
|
|
|
return netCDFValues;
|
|
|
|
}
|
|
|
|
}
|