From 2ce6d092e7319ecd9fa8f7b7e0809ca0d9ac52a0 Mon Sep 17 00:00:00 2001 From: Enrico Girotto Date: Tue, 11 Feb 2025 11:16:04 +0100 Subject: [PATCH] Format code --- .../datacubes/CopernicusCDSDatacube.java | 468 +++++++++--------- 1 file changed, 233 insertions(+), 235 deletions(-) diff --git a/adapters/klab.adapter.copernicus/src/main/java/org/integratedmodelling/adapter/copernicus/datacubes/CopernicusCDSDatacube.java b/adapters/klab.adapter.copernicus/src/main/java/org/integratedmodelling/adapter/copernicus/datacubes/CopernicusCDSDatacube.java index b4ebc1eb6..c92342831 100644 --- a/adapters/klab.adapter.copernicus/src/main/java/org/integratedmodelling/adapter/copernicus/datacubes/CopernicusCDSDatacube.java +++ b/adapters/klab.adapter.copernicus/src/main/java/org/integratedmodelling/adapter/copernicus/datacubes/CopernicusCDSDatacube.java @@ -37,123 +37,120 @@ */ public abstract class CopernicusCDSDatacube extends ChunkedDatacubeRepository { - private String dataset; - private String apiKey; - - public static final String CDS_API_KEY_PROPERTY = "klab.copernicus.cds.apikey"; - public static final String CDS_API_VERSION = "1_1"; - public static final String CDS_API_FORMAT = "zip"; - public static final String CDS_API_KEY_HEADER = "PRIVATE-TOKEN"; - - private int TIMEOUT_SECONDS = 30; - private static Pattern pattern = Pattern.compile(".*(_[0-9]{8}_).*"); - - /* - * tabulate and shut up - */ - String[][] monts = { { "01", "02", "03" }, { "04", "05", "06" }, { "07", "08", "09" }, { "10", "11", "12" } }; - - /** - * These don't have to be right for the months - */ - String[] days = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", - "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31" }; - - public CopernicusCDSDatacube(String dataset, ITimeInstant dataStart, double noDataValue) { - - super(Time.resolution(1, Type.DAY), Time.resolution(3, Type.MONTH), dataStart, - Configuration.INSTANCE.getDataPath("copernicus/" + dataset), noDataValue); - this.dataset = dataset; - - this.apiKey = Configuration.INSTANCE.getProperties().getProperty(CDS_API_KEY_PROPERTY); - if (this.apiKey == null) { - setOnline(false, "Copernicus CDS datacube: no CDS credentials provided in configuration"); - } else { - setOnline(true, null); - } - } - - protected Geoserver initializeGeoserver() { - return Geoserver.create(); - } - - /** - * Put the necessary informations in the map that will be sent as json in the - * CDS API request based on the variable string in the URN. At a minimum it - * should contain the "variable" field so that the CDS API for this dataset will - * recognize it, but it could also encode statistical variants, time points and - * other selectors. - *

- * This is called after setting year, months and day fields for the passed - * chunk. For now these are fixed for 3-month chunks of daily data, changing - * them will need more configuration. - * - * @param variable - * @param payload - */ - protected abstract void configureRequest(String variable, Map payload); - - @Override - protected boolean downloadChunk(int chunk, String variable, File destinationDirectory) { - - Map bodyWrapper = new HashMap<>(); - Map body = new HashMap<>(); - - boolean ret = false; - ITimeInstant date = getChunkStart(chunk); - - /* - * check if it was downloaded and not processed, or added by hand. If we have - * the expected number of files, all with the expected tick number, we have them - * and we can return true. - */ - boolean partial = false; - boolean present = true; - for (int tick : getChunkTicks(chunk)) { - File tickFile = new File(destinationDirectory + File.separator - + getOriginalDataFilename(variable, tick, destinationDirectory)); - if (tickFile.exists()) { - partial = true; - } else { - present = false; - } - } - - if (present) { - return true; - } - - if (partial) { - FileUtils.deleteQuietly(destinationDirectory); - destinationDirectory.mkdirs(); - } - - body.put("year", "" + date.getYear()); - body.put("month", this.monts[(date.getMonth() - 1) / 3]); - body.put("day", this.days); - body.put("version", CDS_API_VERSION); - - configureRequest(variable, body); - - bodyWrapper.put("inputs", body); - String jsonBody = JsonUtils.printAsJson(bodyWrapper); - - Logging.INSTANCE.info("requesting chunk " + chunk + " of " + variable + " to CDS API"); - - // retrieve the job id - String endpoint = getEndpointUrl("/processes/" + this.dataset + "/execute"); - Logging.INSTANCE.info("Ask for job id: " + endpoint + "\n" + jsonBody); - HttpResponse response = Unirest.post(endpoint) - .header(CDS_API_KEY_HEADER, apiKey) - .header("Content-Type", "application/json") - .header("Accept", "application/json") - .body(jsonBody).asJson(); - - if (response.isSuccess()) { - - if (response.getBody().getObject().has("status") && "accepted".equals(response.getBody().getObject().get("status"))) { - // check the status of job - int time = 0; + private String dataset; + private String apiKey; + + public static final String CDS_API_KEY_PROPERTY = "klab.copernicus.cds.apikey"; + public static final String CDS_API_VERSION = "1_1"; + public static final String CDS_API_FORMAT = "zip"; + public static final String CDS_API_KEY_HEADER = "PRIVATE-TOKEN"; + + private int TIMEOUT_SECONDS = 30; + private static Pattern pattern = Pattern.compile(".*(_[0-9]{8}_).*"); + + /* + * tabulate and shut up + */ + String[][] monts = {{"01", "02", "03"}, {"04", "05", "06"}, {"07", "08", "09"}, {"10", "11", "12"}}; + + /** + * These don't have to be right for the months + */ + String[] days = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", + "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"}; + + public CopernicusCDSDatacube(String dataset, ITimeInstant dataStart, double noDataValue) { + + super(Time.resolution(1, Type.DAY), Time.resolution(3, Type.MONTH), dataStart, + Configuration.INSTANCE.getDataPath("copernicus/" + dataset), noDataValue); + this.dataset = dataset; + + this.apiKey = Configuration.INSTANCE.getProperties().getProperty(CDS_API_KEY_PROPERTY); + if (this.apiKey == null) { + setOnline(false, "Copernicus CDS datacube: no CDS credentials provided in configuration"); + } else { + setOnline(true, null); + } + } + + protected Geoserver initializeGeoserver() { + return Geoserver.create(); + } + + /** + * Put the necessary informations in the map that will be sent as json in the + * CDS API request based on the variable string in the URN. At a minimum it + * should contain the "variable" field so that the CDS API for this dataset will + * recognize it, but it could also encode statistical variants, time points and + * other selectors. + *

+ * This is called after setting year, months and day fields for the passed + * chunk. For now these are fixed for 3-month chunks of daily data, changing + * them will need more configuration. + * + * @param variable + * @param payload + */ + protected abstract void configureRequest(String variable, Map payload); + + @Override + protected boolean downloadChunk(int chunk, String variable, File destinationDirectory) { + + Map bodyWrapper = new HashMap<>(); + Map body = new HashMap<>(); + + boolean ret = false; + ITimeInstant date = getChunkStart(chunk); + + /* + * check if it was downloaded and not processed, or added by hand. If we have + * the expected number of files, all with the expected tick number, we have them + * and we can return true. + */ + boolean partial = false; + boolean present = true; + for(int tick : getChunkTicks(chunk)) { + File tickFile = new File( + destinationDirectory + File.separator + getOriginalDataFilename(variable, tick, destinationDirectory)); + if (tickFile.exists()) { + partial = true; + } else { + present = false; + } + } + + if (present) { + return true; + } + + if (partial) { + FileUtils.deleteQuietly(destinationDirectory); + destinationDirectory.mkdirs(); + } + + body.put("year", "" + date.getYear()); + body.put("month", this.monts[(date.getMonth() - 1) / 3]); + body.put("day", this.days); + body.put("version", CDS_API_VERSION); + + configureRequest(variable, body); + + bodyWrapper.put("inputs", body); + String jsonBody = JsonUtils.printAsJson(bodyWrapper); + + Logging.INSTANCE.info("requesting chunk " + chunk + " of " + variable + " to CDS API"); + + // retrieve the job id + String endpoint = getEndpointUrl("/processes/" + this.dataset + "/execute"); + Logging.INSTANCE.info("Ask for job id: " + endpoint + "\n" + jsonBody); + HttpResponse response = Unirest.post(endpoint).header(CDS_API_KEY_HEADER, apiKey) + .header("Content-Type", "application/json").header("Accept", "application/json").body(jsonBody).asJson(); + + if (response.isSuccess()) { + + if (response.getBody().getObject().has("status") && "accepted".equals(response.getBody().getObject().get("status"))) { + // check the status of job + int time = 0; int tryafter = 5; String requestId = response.getBody().getObject().has("jobID") ? response.getBody().getObject().getString("jobID") @@ -164,50 +161,47 @@ protected boolean downloadChunk(int chunk, String variable, File destinationDire return ret; } String status = null; - do { - try { + do { + try { Thread.sleep(tryafter * 1000); } catch (InterruptedException e) { break; } time += tryafter; - /* + /* * inquire about task */ endpoint = getEndpointUrl("/jobs/" + requestId); Logging.INSTANCE.info("Ask for job status: " + endpoint); - response = Unirest.get(endpoint) - .header("PRIVATE-TOKEN", apiKey) - .header("Content-Type", "application/json") + response = Unirest.get(endpoint).header("PRIVATE-TOKEN", apiKey).header("Content-Type", "application/json") .header("Accept", "application/json").asJson(); if (response.isSuccess()) { status = response.getBody().getObject().getString("status"); Logging.INSTANCE.info("Status of retrieval of CDS chunk " + variable + "/" + chunk + ": " + status); - if ("failed".equals(status)){ - break; + if ("failed".equals(status)) { + break; } } else { - Logging.INSTANCE.warn("Ask for job status return an error " + response.getStatus() + ": " + response.getStatusText()); + Logging.INSTANCE.warn( + "Ask for job status return an error " + response.getStatus() + ": " + response.getStatusText()); return false; } - - } while (time < TIMEOUT_SECONDS && !"successful".equals(status) && !"failed".equals(status)); - - // retrieve the job results - endpoint = getEndpointUrl("/jobs/" + requestId + "/results"); - Logging.INSTANCE.info("Ask for job results: " + endpoint + " with key " + apiKey + "\n" + jsonBody); - response = Unirest.get(endpoint) - .header("PRIVATE-TOKEN", apiKey) - .header("Content-Type", "application/json") + + } while (time < TIMEOUT_SECONDS && !"successful".equals(status) && !"failed".equals(status)); + + // retrieve the job results + endpoint = getEndpointUrl("/jobs/" + requestId + "/results"); + Logging.INSTANCE.info("Ask for job results: " + endpoint + " with key " + apiKey + "\n" + jsonBody); + response = Unirest.get(endpoint).header("PRIVATE-TOKEN", apiKey).header("Content-Type", "application/json") .header("Accept", "application/json").asJson(); - if (response.isSuccess()) { - // retrieve the url - String href = null; - JSONObject rBody = response.getBody().getObject(); - try { - href = rBody.getJSONObject("asset").getJSONObject("value").getString("href"); - } catch (JSONException e) { + if (response.isSuccess()) { + // retrieve the url + String href = null; + JSONObject rBody = response.getBody().getObject(); + try { + href = rBody.getJSONObject("asset").getJSONObject("value").getString("href"); + } catch (JSONException e) { Logging.INSTANCE.warn("The result is not API compliant: " + response.getBody().toPrettyString()); return false; } @@ -225,110 +219,114 @@ protected boolean downloadChunk(int chunk, String variable, File destinationDire ret = true; Logging.INSTANCE.info("download of chunk " + chunk + " data for " + variable + " successful"); } catch (Throwable e) { - Logging.INSTANCE.warn("Download of CDS chunk " + variable + "/" + chunk - + " threw exception: " + e.getMessage()); + Logging.INSTANCE.warn( + "Download of CDS chunk " + variable + "/" + chunk + " threw exception: " + e.getMessage()); } } else { Logging.INSTANCE.warn("The returned file is not .zip" + href); return false; } - } else { - Logging.INSTANCE.warn("The job results return an error " + response.getStatus() + ": " + response.getStatusText()); - if (response.getBody().getObject().has("status")) { - StringBuffer details = new StringBuffer().append("Details:\n").append(response.getBody().getObject().getString("status")); - if (response.getBody().getObject().has("traceback")) { - details.append("\nTraceback: ").append(response.getBody().getObject().getString("traceback")); - } - Logging.INSTANCE.warn(details.toString()); - } - return false; - } - } else { - Logging.INSTANCE.error("API request made to CDS Service didn't get accepted: " + response.getBody().toPrettyString()); - return false; - } - } else { - Logging.INSTANCE.error("API request to CDS service returned error " + response.getStatus() + ": " + response.getStatusText()); + } else { + Logging.INSTANCE + .warn("The job results return an error " + response.getStatus() + ": " + response.getStatusText()); + if (response.getBody().getObject().has("status")) { + StringBuffer details = new StringBuffer().append("Details:\n") + .append(response.getBody().getObject().getString("status")); + if (response.getBody().getObject().has("traceback")) { + details.append("\nTraceback: ").append(response.getBody().getObject().getString("traceback")); + } + Logging.INSTANCE.warn(details.toString()); + } + return false; + } + } else { + Logging.INSTANCE + .error("API request made to CDS Service didn't get accepted: " + response.getBody().toPrettyString()); + return false; + } + } else { + Logging.INSTANCE + .error("API request to CDS service returned error " + response.getStatus() + ": " + response.getStatusText()); return false; } - return ret; - } - - public String getEndpointUrl(String request) { - return "https://cds.climate.copernicus.eu/api/retrieve/v1" + request; - } - - @Override - protected boolean processChunk(int chunk, String variable, File destinationDirectory) { - - String[] fields = variable.split("\\."); - String cdsname = fields[0]; - String nativeName = null; - + return ret; + } + + public String getEndpointUrl(String request) { + return "https://cds.climate.copernicus.eu/api/retrieve/v1" + request; + } + + @Override + protected boolean processChunk(int chunk, String variable, File destinationDirectory) { + + String[] fields = variable.split("\\."); + String cdsname = fields[0]; + String nativeName = null; + Logging.INSTANCE.info("chunk " + chunk + " data for " + variable + " being ingested in local Geoserver"); - for (File f : destinationDirectory.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".nc"); - } - })) { - - /* - * parse the file name and get year, month and day - */ - Matcher matcher = pattern.matcher(MiscUtilities.getFileBaseName(f)); - if (!matcher.matches()) { - Logging.INSTANCE.warn("CDS file does not match naming pattern: ignoring " + f); - continue; - } - - // layer naming logic is repeated in #getDataLayer() - String daySignature = matcher.group(1).substring(1, 9); - String layerId = cdsname + "_" + daySignature; - - if (nativeName == null) { - try (GridDataset dataset = GridDataset.open(f.toString())) { - nativeName = dataset.getGrids().get(0).getName(); - } catch (IOException e) { - Logging.INSTANCE.warn("Can't open CDS file : " + f); - return false; - } - } - - if (!geoserver.createCoverageLayer(dataset, layerId, f, nativeName)) { - Logging.INSTANCE.warn("Geoserver ingestion of " + f + " returned a failure code"); - return false; - } - } + for(File f : destinationDirectory.listFiles(new FilenameFilter(){ + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".nc"); + } + })) { + + /* + * parse the file name and get year, month and day + */ + Matcher matcher = pattern.matcher(MiscUtilities.getFileBaseName(f)); + if (!matcher.matches()) { + Logging.INSTANCE.warn("CDS file does not match naming pattern: ignoring " + f); + continue; + } + + // layer naming logic is repeated in #getDataLayer() + String daySignature = matcher.group(1).substring(1, 9); + String layerId = cdsname + "_" + daySignature; + + if (nativeName == null) { + try (GridDataset dataset = GridDataset.open(f.toString())) { + nativeName = dataset.getGrids().get(0).getName(); + } catch (IOException e) { + Logging.INSTANCE.warn("Can't open CDS file : " + f); + return false; + } + } + + if (!geoserver.createCoverageLayer(dataset, layerId, f, nativeName)) { + Logging.INSTANCE.warn("Geoserver ingestion of " + f + " returned a failure code"); + return false; + } + } Logging.INSTANCE.info("Geoserver ingestion of chunk " + chunk + " data for " + variable + " terminated successfully"); - return true; - } - - @Override - protected String getDataLayer(String variable, int tick) { - - String[] fields = variable.split("\\."); - String cdsname = fields[0]; - String file = getOriginalFile(variable, tick); - Matcher matcher = pattern.matcher(MiscUtilities.getFileBaseName(file)); - if (matcher.matches()) { - String daySignature = matcher.group(1).substring(1, 9); - return cdsname + "_" + daySignature; - } - return null; - } - - protected Geoserver getGeoserver() { - return geoserver; - } - - @Override - public String getName() { - return dataset; - } + return true; + } + + @Override + protected String getDataLayer(String variable, int tick) { + + String[] fields = variable.split("\\."); + String cdsname = fields[0]; + String file = getOriginalFile(variable, tick); + Matcher matcher = pattern.matcher(MiscUtilities.getFileBaseName(file)); + if (matcher.matches()) { + String daySignature = matcher.group(1).substring(1, 9); + return cdsname + "_" + daySignature; + } + return null; + } + + protected Geoserver getGeoserver() { + return geoserver; + } + + @Override + public String getName() { + return dataset; + } }