From e671af034b9224574555d727c7cfbf39c4c0988d Mon Sep 17 00:00:00 2001 From: "Yen, David (398B-Affiliate)" Date: Sun, 16 Oct 2022 23:29:35 -0700 Subject: [PATCH] compiled version --- pom.xml | 4 +- .../metadata/aggregator/IsoSwotXPath.java | 10 + .../aggregator/MetadataFilesToEcho.java | 281 +++++++- .../aggregator/SwotArchiveXmlXPath.java | 4 + .../metadata/aggregator/UMMGranule.java | 73 +- .../metadata/aggregator/UMMGranuleFile.java | 58 +- .../aggregator/factory/UmmgPojoFactory.java | 61 ++ .../generated/AdditionalAttributeType.java | 109 +++ .../nasa/cumulus/metadata/util/JSONUtils.java | 21 +- .../cumulus/metadata/test/JSONUtilsTest.java | 44 ++ .../test/MetadataFilesToEchoTest.java | 651 +++++++++++------- .../nasa/cumulus/metadata/test/UMMTest.java | 53 +- ...210612T080137_O_APID1402.PTM_1.archive.xml | 6 +- ...02836_20160905T002846_TI0000_01.nc.iso.xml | 599 ++++++++++++++++ 14 files changed, 1686 insertions(+), 288 deletions(-) create mode 100644 src/main/java/gov/nasa/cumulus/metadata/aggregator/IsoSwotXPath.java create mode 100644 src/main/java/gov/nasa/cumulus/metadata/aggregator/factory/UmmgPojoFactory.java create mode 100644 src/main/java/gov/nasa/cumulus/metadata/umm/generated/AdditionalAttributeType.java create mode 100644 src/test/java/gov/nasa/cumulus/metadata/test/JSONUtilsTest.java create mode 100644 src/test/resources/SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc.iso.xml diff --git a/pom.xml b/pom.xml index 3cd1bfc..02d4af6 100755 --- a/pom.xml +++ b/pom.xml @@ -44,13 +44,13 @@ com.amazonaws aws-java-sdk-s3 - 1.12.285 + 1.12.321 com.amazonaws aws-java-sdk-secretsmanager - 1.12.285 + 1.12.321 org.apache.httpcomponents diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/IsoSwotXPath.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/IsoSwotXPath.java new file mode 100644 index 0000000..bb37098 --- /dev/null +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/IsoSwotXPath.java @@ -0,0 +1,10 @@ +package gov.nasa.cumulus.metadata.aggregator; + +public final class IsoSwotXPath extends IsoXPath { + public static final String POLYGON = "/gmd:DS_Series/gmd:composedOf/gmd:DS_DataSet/gmd:has/gmi:MI_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:geographicElement/gmd:EX_BoundingPolygon/gmd:polygon/gml:Polygon/gml:exterior/gml:LinearRing/gml:posList"; + public static final String CYCLE_PASS_TILE_SCENE = "/gmi:MI_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:geographicElement/gmd:EX_GeographicDescription[@id=\"SWOTTrack\"]/gmd:geographicIdentifier/gmd:MD_Identifier/gmd:code/gco:CharacterString"; + public static final String CREATION_DATE_TIME = "/gmi:MI_Metadata/gmd:dateStamp/gco:DateTime"; + public static final String BEGINNING_DATE_TIME = "/gmi:MI_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:beginPosition"; + public static final String ENDING_DATE_TIME = "/gmi:MI_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:extent/gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:endPosition"; + +} diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/MetadataFilesToEcho.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/MetadataFilesToEcho.java index 59fe754..5a0db7f 100644 --- a/src/main/java/gov/nasa/cumulus/metadata/aggregator/MetadataFilesToEcho.java +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/MetadataFilesToEcho.java @@ -7,9 +7,7 @@ import java.math.BigDecimal; import java.net.URISyntaxException; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashSet; -import java.util.TimeZone; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,11 +17,17 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.*; +import gov.nasa.cumulus.metadata.aggregator.factory.UmmgPojoFactory; +import gov.nasa.cumulus.metadata.umm.generated.AdditionalAttributeType; +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; import gov.nasa.cumulus.metadata.util.BoundingTools; import gov.nasa.cumulus.metadata.util.JSONUtils; import gov.nasa.podaac.inventory.model.*; +import org.apache.commons.collections.iterators.ObjectArrayIterator; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -46,6 +50,7 @@ public class MetadataFilesToEcho { boolean forceBB = false; boolean rangeIs360 = false; boolean isIsoFile = false; + UmmgPojoFactory ummgPojoFactory = UmmgPojoFactory.getInstance(); public MetadataFilesToEcho() { this(false); @@ -171,13 +176,22 @@ public void readCommonMetadataFile(String file, String s3Location) throws IOExce (Double)((JSONObject)metadata.get("boundingBox")).get("EasternLongitude"), (Double)((JSONObject)metadata.get("boundingBox")).get("WesternLongitude")); + /** + * so far, universal-data-handler is not generating .mp file with tiles yet + * just cycle and passes. + * Passes are under cycle. If there is no cycle then there is no pass + */ + TrackType trackType = null; if (metadata.get("cycle") != null) { - granule.setCycle(((Long) metadata.get("cycle")).intValue()); - } - - if (metadata.get("pass") != null) { - granule.setPass(((Long) metadata.get("pass")).intValue()); + int cycleInt = ((Long)metadata.get("cycle")).intValue(); + Integer iPass = null; + if (metadata.get("pass") != null) { + int passInt = ((Long)metadata.get("pass")).intValue(); + iPass = new Integer(passInt); + } + trackType = createTrackType(new Integer(cycleInt), iPass); } + granule.setTrackType(trackType); if (metadata.get(Constants.Metadata.ORBIT) != null) { granule.setOrbitNumber(((Long) metadata.get(Constants.Metadata.ORBIT)).intValue()); @@ -192,6 +206,7 @@ public void readCommonMetadataFile(String file, String s3Location) throws IOExce } } + /** * For a certain mission/collections, the workflow might not go through data handler step. * Hence, we are using the input granule's files:[] as single point of truth for file size and checksum info @@ -251,6 +266,10 @@ public void setGranuleFileSizeAndChecksum(JSONArray input_granules) { AdapterLogger.LogInfo(this.className + " GranuleArchive HashSet Size:" + granule.getGranuleArchiveSet().size()); AdapterLogger.LogInfo(this.className + " GranuleArchive HashSet:" + granule.getGranuleArchiveSet()); } + public void readIsoMetadataFile(String file, String s3Location, String collection_short_name) + throws ParserConfigurationException, IOException, SAXException, XPathExpressionException { + Document doc = makeDoc(file); + } /** * Entry point for translating ISO granule files to UMM-G @@ -461,10 +480,139 @@ public void readIsoMendsMetadataFile(String s3Location, Document doc, XPath xpat } ((IsoGranule) granule).setPGEVersionClass(xpath.evaluate(IsoMendsXPath.PGE_VERSION_CLASS, doc)); - } + // Process ISO cycle, pass and tile + String cyclePassTileSceneStr =StringUtils.trim(xpath.evaluate(IsoSwotXPath.CYCLE_PASS_TILE_SCENE, doc)); + createIsoCyclePassTile(cyclePassTileSceneStr); + } - private void readIsoSmapMetadataFile(String s3Location, Document doc, XPath xpath) throws XPathExpressionException { + /** + * Marshell the cycle pass tile string from ISO xml into UMMG POJO. + * Example input :"Cycle: 5 Pass: [40, Tiles: 4-5L 4-8R] [41, Tiles: 6R 6L] [42, Tiles: 7F]" + *"Cycle: 5 Pass: [40, Tiles: 4-5L 4-5R] [41, Tiles: 6R 6L] [42, Tiles: 7F] Cycle: 6 Pass: [50, Tiles: 4-5L 4-5R] [51, Tiles: 6R 6L] [52, Tiles: 7F]"; + * @param cyclePassTileStr + * @return + */ + public IsoGranule createIsoCyclePassTile(String cyclePassTileStr) { + AdapterLogger.LogInfo(this.className + " iso cycle pass tile string:" + cyclePassTileStr); + String toBeProcessedStr = StringUtils.upperCase(StringUtils.trim(cyclePassTileStr)); + Pattern p_cycle = Pattern.compile("CYCLE\\s*:\\s*\\d+\\s*?"); + Matcher m_cycle = p_cycle.matcher(toBeProcessedStr); + String cycleStr = ""; + ArrayList cycleStrs = new ArrayList<>(); + while(m_cycle.find()) { + cycleStr = m_cycle.group(); + AdapterLogger.LogInfo("Cycle:" + cycleStr); + cycleStrs.add(cycleStr.trim()); + } + int numberOfCycles = cycleStrs.size(); + int i = 0; + // Current UMMG schema 1.6.3 supports only one cycle. Although it is possible that + // one granule contains 2 cycles as the edge case. + ArrayList cyclePassStrs = new ArrayList<>(); + while(i +1 < numberOfCycles) { + String cyclePassStr = StringUtils.substring(toBeProcessedStr, + StringUtils.indexOf(toBeProcessedStr, cycleStrs.get(i)), + StringUtils.indexOf(toBeProcessedStr, cycleStrs.get(i+1))); + AdapterLogger.LogInfo("cyclePass processing candidate:" + cyclePassStr); + cyclePassStrs.add(cyclePassStr); + toBeProcessedStr = StringUtils.replace(toBeProcessedStr, cyclePassStr, ""); + i++; + } + toBeProcessedStr = StringUtils.trim(toBeProcessedStr); + // Processed the last Cycle OR if there is only one cycle, we are processing the first==last cycle here + if(StringUtils.isNotEmpty(toBeProcessedStr) && StringUtils.startsWithIgnoreCase(toBeProcessedStr, "CYCLE")) { + AdapterLogger.LogInfo("Processing the last or first cycle" + toBeProcessedStr); + cyclePassStrs.add(toBeProcessedStr); + } + TrackType trackType = null; + List additionalAttributeTypes = new ArrayList<>(); + for(String cps : cyclePassStrs) { + trackType = createTrackType(cps, p_cycle); + UmmgPojoFactory ummgPojoFactory = UmmgPojoFactory.getInstance(); + additionalAttributeTypes= + ummgPojoFactory.trackTypeToAdditionalAttributeType(trackType); + } + ((IsoGranule)granule).setTrackType(trackType); + ((IsoGranule)granule).setAdditionalAttributeTypes(additionalAttributeTypes); + return (IsoGranule)granule; + } + + public TrackType createTrackType(String cyclePassTileStr, Pattern p_cycle) { + Matcher m_cycle = p_cycle.matcher(cyclePassTileStr); + String cycleStr=null; + while(m_cycle.find()) { + cycleStr = m_cycle.group(); + } + String cycleNoStr = StringUtils.trim( + StringUtils.replace( + StringUtils.replaceIgnoreCase(cycleStr, "CYCLE","") + ,":","")); + AdapterLogger.LogInfo("Cycle:" + cycleNoStr); + TrackType trackType = new TrackType(); + trackType.setCycle(NumberUtils.createInteger(cycleNoStr)); + + Pattern p_pass = Pattern.compile("\\[.*?\\]"); + Matcher m_pass = p_pass.matcher(cyclePassTileStr); + /** + * The matcher will resolve to the following tokens: + * [40, TILES: 4-5L 4-5R] + * [41, TILES: 6R 6L] + * [42, TILES: 7F] + * The following loop process each token by extracting the passes and tilles + */ + ArrayList trackPassTileTypes = new ArrayList<>(); + while(m_pass.find()) { + TrackPassTileType trackPassTileType = new TrackPassTileType(); + String passTilesStr = m_pass.group(); + passTilesStr =StringUtils.replace( + StringUtils.replace(passTilesStr,"[",""),"]",""); + passTilesStr = passTilesStr.replaceAll("TILES\\s*:\\s*?", ""); + String[] passTiles = StringUtils.split(passTilesStr, ","); + String passStr = StringUtils.trim(passTiles[0]); + trackPassTileType.setPass(NumberUtils.createInteger(passStr)); + List tiles = getTiles(StringUtils.trim(passTiles[1])); + trackPassTileType.setTiles(tiles); + trackPassTileTypes.add(trackPassTileType); + } + trackType.setPasses(trackPassTileTypes); + return trackType; + } + + /** + * 5-8L 4K means, tile 5L, 6L, 7L, 8L and 4K. because dash means a range separator + * + * @param tilesStr ex 5-6L 4K + * @return + */ + public List getTiles(String tilesStr) { + AdapterLogger.LogInfo(this.className + " decoding tiles string:" + tilesStr); + ArrayList tiles = new ArrayList<>(); + String[] tileRanges = StringUtils.split(tilesStr, " "); + // Using Apache Commons Collections + ObjectArrayIterator iterator = new ObjectArrayIterator(tileRanges); + + while (iterator.hasNext()) { + String tileRangStr=(String) iterator.next(); + if(StringUtils.containsIgnoreCase(tileRangStr,"-")){ + String[] tileRangeTokens = StringUtils.split(tileRangStr, "-"); + String endTileStr = tileRangeTokens[tileRangeTokens.length -1]; + // find the letter for the last token + String tileMarkChar = endTileStr.substring(endTileStr.length() - 1); + Integer startTileNum = NumberUtils.createInteger(StringUtils.trim(tileRangeTokens[0])); + Integer endTileNumStr = NumberUtils.createInteger( + StringUtils.trim( + StringUtils.substring(endTileStr, 0, endTileStr.length()-1))); + for(Integer i = startTileNum; i<=endTileNumStr; i++ ) { + tiles.add(i + tileMarkChar); + } + } else { // if it is not a range of tiles like : 5-8L + tiles.add(tileRangStr); + } + } + return tiles; + } + private void readIsoSmapMetadataFile(String s3Location, Document doc, XPath xpath) throws XPathExpressionException { GranuleReference gr = new GranuleReference(); gr.setDescription("S3 datafile."); gr.setPath(s3Location); @@ -533,14 +681,101 @@ public void readSwotArchiveXmlFile(String file) throws ParserConfigurationExcept XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new NamespaceResolver(doc)); + granule = createSwotArchiveGranule(doc, xpath); + // No spatial extent exists for SWOT L0 data so set as global + setGranuleBoundingBox(90.0, -90.0, 180.0, -180.0); + } + + UMMGranule createSwotArchiveGranule(Document doc, XPath xpath) + throws XPathExpressionException{ granule.setStartTime(DatatypeConverter.parseDateTime(xpath.evaluate(SwotArchiveXmlXPath.BEGINNING_DATE_TIME, doc)).getTime()); granule.setStopTime(DatatypeConverter.parseDateTime(xpath.evaluate(SwotArchiveXmlXPath.ENDING_DATE_TIME, doc)).getTime()); granule.setCreateTime(DatatypeConverter.parseDateTime(xpath.evaluate(SwotArchiveXmlXPath.CREATION_DATE_TIME, doc)).getTime()); + String cycleStr =StringUtils.trim(xpath.evaluate(SwotArchiveXmlXPath.ARCHIVE_CYCLE, doc)); + String passStr =StringUtils.trim(xpath.evaluate(SwotArchiveXmlXPath.ARCHIVE_PASS, doc)); + String tileStr =StringUtils.trim(xpath.evaluate(SwotArchiveXmlXPath.ARCHIVE_TILE, doc)); + + ArrayListtrackPassTileTypes = new ArrayList<>(); + TrackType trackType = null; + if (StringUtils.isNotEmpty(passStr)) { + ArrayListtiles = null; + if(StringUtils.isNotEmpty(tileStr)) { + tiles = new ArrayList<>(); + tiles.add(tileStr); + } + TrackPassTileType trackPassTileType = + ummgPojoFactory.createTrackPassTileType(NumberUtils.createInteger(passStr), tiles); + trackPassTileTypes.add(trackPassTileType); + } + if (StringUtils.isNotEmpty(cycleStr)) { + trackType = ummgPojoFactory.createTrackType(NumberUtils.createInteger(cycleStr), trackPassTileTypes); + } + granule.setTrackType(trackType); + return granule; + } + + /** + * SWOT ISO.xml comes to this function where swot archive.xml goes to readSwotAchiveXmlFile + * @param file + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + * @throws XPathExpressionException + */ + public void readSwotIsoXmlFile(String file) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + docBuilderFactory.setNamespaceAware(true); + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(new File(file)); + XPath xpath = XPathFactory.newInstance().newXPath(); + xpath.setNamespaceContext(new NamespaceResolver(doc)); + + granule = createSwotIsoGranule(doc, xpath); // No spatial extent exists for SWOT L0 data so set as global setGranuleBoundingBox(90.0, -90.0, 180.0, -180.0); } + private UMMGranule createSwotIsoGranule(Document doc, XPath xpath) + throws XPathExpressionException{ + granule.setStartTime(DatatypeConverter.parseDateTime(xpath.evaluate(IsoSwotXPath.BEGINNING_DATE_TIME, doc)).getTime()); + granule.setStopTime(DatatypeConverter.parseDateTime(xpath.evaluate(IsoSwotXPath.ENDING_DATE_TIME, doc)).getTime()); + granule.setCreateTime(DatatypeConverter.parseDateTime(xpath.evaluate(IsoSwotXPath.CREATION_DATE_TIME, doc)).getTime()); + String cyclePassTileSceneStr =StringUtils.trim(xpath.evaluate(IsoSwotXPath.CYCLE_PASS_TILE_SCENE, doc)); + + TrackType trackType = marshellCyclePassTileSceneStrToAchiveType(cyclePassTileSceneStr); + +// ArrayListtrackPassTileTypes = new ArrayList<>(); +// TrackType trackType = null; +// if (StringUtils.isNotEmpty(""passStr"")) { +// ArrayListtiles = null; +// if(StringUtils.isNotEmpty(tileStr)) { +// tiles = new ArrayList<>(); +// tiles.add(tileStr); +// } +// TrackPassTileType trackPassTileType = +// ummgPojoFactory.createTrackPassTileType(NumberUtils.createInteger(passStr), tiles); +// trackPassTileTypes.add(trackPassTileType); +// } +// if (StringUtils.isNotEmpty(cycleStr)) { +// trackType = ummgPojoFactory.createTrackType(NumberUtils.createInteger(cycleStr), trackPassTileTypes); +// } + granule.setTrackType(trackType); + return granule; + } + + /** + * Marshall : Cycle: 5 Pass: [40, Tiles: 4-5L 4-5R] [41, Tiles: 6R 6L] [42, Tiles: 7F] + * to TrackType + * @param input + * @return + */ + public TrackType marshellCyclePassTileSceneStrToAchiveType(String input) { + input =StringUtils.upperCase(StringUtils.trim(input)); + input = input.replaceAll("\\s+", " "); + + return null; + } /** * Parses Sentinel-6 XFDU manifest for metadata. * @@ -588,13 +823,11 @@ public void readSentinelManifest(String file) throws ParserConfigurationExceptio // Ignore if unable to parse for footprint since it isn't required for ingest } - String cycle = xpath.evaluate(ManifestXPath.CYCLE, doc); - if (!cycle.isEmpty()) - granule.setCycle(Integer.parseInt(cycle)); + String cycle = StringUtils.trim(xpath.evaluate(ManifestXPath.CYCLE, doc)); + String pass = StringUtils.trim(xpath.evaluate(ManifestXPath.PASS, doc)); - String pass = xpath.evaluate(ManifestXPath.PASS, doc); - if (!pass.isEmpty()) - granule.setPass(Integer.parseInt(pass)); + TrackType trackType = createTrackType(NumberUtils.createInteger(cycle), NumberUtils.createInteger(pass)); + granule.setTrackType(trackType); String productName = null; try { @@ -610,6 +843,22 @@ public void readSentinelManifest(String file) throws ParserConfigurationExceptio granule.getGranuleCharacterSet().add(createGranuleCharacter(productName, UMMGranuleFile.PROVIDER_DATA_SOURCE)); } + /** + * create a TrackType when there is only one cycle and one pass. + * no representation of tiles. + * @param iCycle + * @param iPass + */ + private TrackType createTrackType(Integer iCycle, Integer iPass) { + ArrayList trackPassTileTypes = new ArrayList<>(); + TrackPassTileType trackPassTileType = + ummgPojoFactory.createTrackPassTileType(iPass, null); + trackPassTileTypes.add(trackPassTileType); + TrackType trackType = ummgPojoFactory.createTrackType(iCycle, trackPassTileTypes); + AdapterLogger.LogDebug("When only one cycle/pass, created TrackType: " + trackType); + return trackType; + } + private void setGranuleBoundingBox(double north, double south, double east, double west) { AdapterLogger.LogInfo("set bounding box 4 coordinates for UMMGranule object"); granule.setBbxNorthernLatitude(north); diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/SwotArchiveXmlXPath.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/SwotArchiveXmlXPath.java index c827c74..f00d95e 100644 --- a/src/main/java/gov/nasa/cumulus/metadata/aggregator/SwotArchiveXmlXPath.java +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/SwotArchiveXmlXPath.java @@ -10,5 +10,9 @@ public final class SwotArchiveXmlXPath { public static final String DATA_FILE_FILE_NAME = "/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/LocalGranuleID"; public static final String DATA_FILE_FILE_DESCRIPTION = "/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/Description"; + public static final String ARCHIVE_CYCLE="/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/CycleID"; + public static final String ARCHIVE_PASS="/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/PassID"; + public static final String ARCHIVE_TILE="/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/TileID"; + public static final String archiveScene="/GranuleMetaDataFile/GranuleURMetaData/ECSDataGranule/SceneID"; } diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranule.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranule.java index d03b802..194d410 100644 --- a/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranule.java +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranule.java @@ -1,16 +1,30 @@ package gov.nasa.cumulus.metadata.aggregator; +import gov.nasa.cumulus.metadata.umm.generated.AdditionalAttributeType; +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; import gov.nasa.podaac.inventory.model.Granule; import java.math.BigDecimal; +import java.util.List; public class UMMGranule extends Granule { - private Integer cycle; - private Integer pass; + //private Integer cycle; +// private Integer pass; + /** + * A generated type which represents the cycle and pass + */ + private TrackType trackType; + /** + * A generated type which represents the pass and associate Tiles under Track + */ + private TrackPassTileType trackPassTileType; + private List additionalAttributeTypes; private Integer orbitNumber; private Integer startOrbit; private Integer endOrbit; + private String tile; /* Bounding Box 4 points */ private Double bbxNorthernLatitude; private Double bbxSouthernLatitude; @@ -19,21 +33,21 @@ public class UMMGranule extends Granule { private BigDecimal equatorCrossingLongitude; private String equatorCrossingDateTime; - public Integer getPass() { - return pass; - } - - public void setPass(Integer pass) { - this.pass = pass; - } - - public Integer getCycle() { - return cycle; - } - - public void setCycle(Integer cycle) { - this.cycle = cycle; - } +// public Integer getPass() { +// return pass; +// } +// +// public void setPass(Integer pass) { +// this.pass = pass; +// } + +// public Integer getCycle() { +// return cycle; +// } +// +// public void setCycle(Integer cycle) { +// this.cycle = cycle; +// } public Integer getOrbitNumber() { return orbitNumber; @@ -57,6 +71,31 @@ public Integer getEndOrbit() { public void setEndOrbit(Integer endOrbit) { this.endOrbit = endOrbit; } + + public String getTile() { + return tile; + } + + public void setTile(String tile) { + this.tile = tile; + } + + public TrackType getTrackType() { + return trackType; + } + + public void setTrackType(TrackType trackType) { + this.trackType = trackType; + } + + public List getAdditionalAttributeTypes() { + return additionalAttributeTypes; + } + + public void setAdditionalAttributeTypes(List additionalAttributeTypes) { + this.additionalAttributeTypes = additionalAttributeTypes; + } + public Double getBbxNorthernLatitude() { return bbxNorthernLatitude; } diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranuleFile.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranuleFile.java index 85b362f..fb0d360 100644 --- a/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranuleFile.java +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/UMMGranuleFile.java @@ -1,9 +1,16 @@ package gov.nasa.cumulus.metadata.aggregator; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.algorithm.CGAlgorithms; import cumulus_message_adapter.message_parser.AdapterLogger; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGCollectionAdapter; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGListAdapter; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGMapAdapter; import gov.nasa.cumulus.metadata.util.BoundingTools; +import gov.nasa.cumulus.metadata.util.JSONUtils; import gov.nasa.cumulus.metadata.util.TimeConversion; import gov.nasa.cumulus.metadata.exception.GEOProcessException; import gov.nasa.cumulus.metadata.umm.model.UMMGranuleArchive; @@ -22,6 +29,7 @@ import java.math.RoundingMode; import java.net.URISyntaxException; import java.util.*; +import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -93,6 +101,9 @@ public JSONObject defineGranule() // Populate the Spatial metadata granuleJson.put("SpatialExtent", exportSpatial()); + // Populate the tile into AdditionalAttributes +// granule.put + /** * Populate the Orbital Metadata @@ -366,7 +377,7 @@ private boolean shouldAddBBx(Granule granule) { return shouldAddBBx; } - private JSONObject exportSpatial() { + private JSONObject exportSpatial() throws ParseException{ JSONObject spatialExtent = new JSONObject(); JSONObject geometry = new JSONObject(); JSONObject horizontalSpatialDomain = new JSONObject(); @@ -528,17 +539,29 @@ private JSONObject exportSpatial() { // Export track if cycle and pass exists if (granule instanceof UMMGranule) { - UMMGranule ummGranule = (UMMGranule) granule; - if (ummGranule.getCycle() != null && ummGranule.getPass() != null) { - JSONObject track = new JSONObject(); - horizontalSpatialDomain.put("Track", track); - track.put("Cycle", ummGranule.getCycle()); - JSONArray passes = new JSONArray(); - track.put("Passes", passes); - JSONObject pass = new JSONObject(); - pass.put("Pass", ummGranule.getPass()); - passes.add(pass); +// Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() +// .registerTypeHierarchyAdapter(Collection.class, new UMMGCollectionAdapter()) +// .registerTypeHierarchyAdapter(List.class, new UMMGListAdapter()) +// .registerTypeHierarchyAdapter(Map.class, new UMMGMapAdapter()) +// .create(); +// JsonObject trackJsonObj = gsonBuilder.toJsonTree(((UMMGranule) granule).getTrackType()).getAsJsonObject(); +// JSONObject track = JSONUtils.GsonToJSONObj(trackJsonObj); + /** + * Track include cycle and passes(array). + */ + if(((UMMGranule) granule).getTrackType() != null ) { + horizontalSpatialDomain.put("Track", createUMMGTrack((UMMGranule) granule)); } +// if (ummGranule.getCycle() != null && ummGranule.getPass() != null) { +// JSONObject track = new JSONObject(); +// horizontalSpatialDomain.put("Track", track); +// track.put("Cycle", ummGranule.getCycle()); +// JSONArray passes = new JSONArray(); +// track.put("Passes", passes); +// JSONObject pass = new JSONObject(); +// pass.put("Pass", ummGranule.getPass()); +// passes.add(pass); +// } } // Export footprint if it exists @@ -550,10 +573,21 @@ private JSONObject exportSpatial() { break; } } - return spatialExtent; } + public JSONObject createUMMGTrack(UMMGranule ummGranule) throws ParseException { + Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() + .registerTypeHierarchyAdapter(Collection.class, new UMMGCollectionAdapter()) + .registerTypeHierarchyAdapter(List.class, new UMMGListAdapter()) + .registerTypeHierarchyAdapter(Map.class, new UMMGMapAdapter()) + .create(); + JsonObject trackJsonObj = gsonBuilder.toJsonTree(ummGranule.getTrackType()).getAsJsonObject(); + JSONObject track = JSONUtils.GsonToJSONObj(trackJsonObj); + AdapterLogger.LogInfo("TrackType:" + track.toString()); + return track; + } + /** * This function will first translate the line string to a List * and add BoundingRectangles to geometry object when diff --git a/src/main/java/gov/nasa/cumulus/metadata/aggregator/factory/UmmgPojoFactory.java b/src/main/java/gov/nasa/cumulus/metadata/aggregator/factory/UmmgPojoFactory.java new file mode 100644 index 0000000..fb022f1 --- /dev/null +++ b/src/main/java/gov/nasa/cumulus/metadata/aggregator/factory/UmmgPojoFactory.java @@ -0,0 +1,61 @@ +package gov.nasa.cumulus.metadata.aggregator.factory; + +import gov.nasa.cumulus.metadata.umm.generated.AdditionalAttributeType; +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; + +import java.util.ArrayList; +import java.util.List; + +public class UmmgPojoFactory { + private static UmmgPojoFactory _self = null; + + private UmmgPojoFactory(){} + + public static UmmgPojoFactory getInstance() { + if (_self == null){ + _self = new UmmgPojoFactory(); + } + return _self; + } + + /** + * create a single pass -> tiles:[] association + * @param pass + * @param tiles + * @return + */ + public TrackPassTileType createTrackPassTileType(Integer pass, List tiles) { + TrackPassTileType trackPassTileType = new TrackPassTileType(); + trackPassTileType.setPass(pass); + if(tiles !=null && tiles.size() >0) { + trackPassTileType.setTiles(tiles); + } + return trackPassTileType; + } + + /** + * Create the TrackType POJO which represents the cycle and passes array + * each pass is a combination of Pass and Tiles Array + * @return + */ + public TrackType createTrackType(Integer cycle, List trackPassTileTypes) { + TrackType trackType = new TrackType(); + trackType.setCycle(cycle); + trackType.setPasses(trackPassTileTypes); + return trackType; + } + + public List trackTypeToAdditionalAttributeType(TrackType trackType) { + List trackPassTileTypes = trackType.getPasses(); + ArrayList additionalAttributeTypes = new ArrayList<>(); + trackPassTileTypes.stream().forEach(trackPassTileType -> { + AdditionalAttributeType additionalAttributeType = new AdditionalAttributeType(); + List tilesStrs = trackPassTileType.getTiles(); + additionalAttributeType.setName("TILE"); + additionalAttributeType.setValues(tilesStrs); + additionalAttributeTypes.add(additionalAttributeType); + }); + return additionalAttributeTypes; + } +} diff --git a/src/main/java/gov/nasa/cumulus/metadata/umm/generated/AdditionalAttributeType.java b/src/main/java/gov/nasa/cumulus/metadata/umm/generated/AdditionalAttributeType.java new file mode 100644 index 0000000..21e88fc --- /dev/null +++ b/src/main/java/gov/nasa/cumulus/metadata/umm/generated/AdditionalAttributeType.java @@ -0,0 +1,109 @@ + +package gov.nasa.cumulus.metadata.umm.generated; + +import java.util.ArrayList; +import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + + +/** + * A reference to an additional attribute in the parent collection. The attribute reference may contain a granule specific value that will override the value in the parent collection for this granule. An attribute with the same name must exist in the parent collection. + * + */ +public class AdditionalAttributeType { + + /** + * The additional attribute's name. + * (Required) + * + */ + @SerializedName("Name") + @Expose + private String name; + /** + * Values of the additional attribute. + * (Required) + * + */ + @SerializedName("Values") + @Expose + private List values = new ArrayList(); + + /** + * The additional attribute's name. + * (Required) + * + */ + public String getName() { + return name; + } + + /** + * The additional attribute's name. + * (Required) + * + */ + public void setName(String name) { + this.name = name; + } + + /** + * Values of the additional attribute. + * (Required) + * + */ + public List getValues() { + return values; + } + + /** + * Values of the additional attribute. + * (Required) + * + */ + public void setValues(List values) { + this.values = values; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(AdditionalAttributeType.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("name"); + sb.append('='); + sb.append(((this.name == null)?"":this.name)); + sb.append(','); + sb.append("values"); + sb.append('='); + sb.append(((this.values == null)?"":this.values)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.name == null)? 0 :this.name.hashCode())); + result = ((result* 31)+((this.values == null)? 0 :this.values.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof AdditionalAttributeType) == false) { + return false; + } + AdditionalAttributeType rhs = ((AdditionalAttributeType) other); + return (((this.name == rhs.name)||((this.name!= null)&&this.name.equals(rhs.name)))&&((this.values == rhs.values)||((this.values!= null)&&this.values.equals(rhs.values)))); + } + +} diff --git a/src/main/java/gov/nasa/cumulus/metadata/util/JSONUtils.java b/src/main/java/gov/nasa/cumulus/metadata/util/JSONUtils.java index 676d866..2351bee 100644 --- a/src/main/java/gov/nasa/cumulus/metadata/util/JSONUtils.java +++ b/src/main/java/gov/nasa/cumulus/metadata/util/JSONUtils.java @@ -1,10 +1,13 @@ package gov.nasa.cumulus.metadata.util; +import com.google.gson.JsonObject; import gov.nasa.cumulus.metadata.aggregator.UMMUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import java.util.ArrayList; -import java.util.Iterator; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.util.*; public class JSONUtils { @@ -91,4 +94,18 @@ public static boolean identifierOk(JSONObject json) { boolean valOk = UMMUtils.notNullOrEmpty((String) json.get("Identifier")); return keyOk && valOk; } + + /** + * Translate from google gson JsonObject to org.json.simple.JSONObject + * @param input + * @return + * @throws ParseException + */ + public static JSONObject GsonToJSONObj(JsonObject input) throws ParseException { + JSONParser parser = new JSONParser(); + JSONObject jo = (JSONObject) parser.parse(input.toString());; + return jo; + } + + } diff --git a/src/test/java/gov/nasa/cumulus/metadata/test/JSONUtilsTest.java b/src/test/java/gov/nasa/cumulus/metadata/test/JSONUtilsTest.java new file mode 100644 index 0000000..82acfc6 --- /dev/null +++ b/src/test/java/gov/nasa/cumulus/metadata/test/JSONUtilsTest.java @@ -0,0 +1,44 @@ +package gov.nasa.cumulus.metadata.test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + + +import com.google.gson.JsonParser; +import com.google.gson.JsonObject; + +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; +import gov.nasa.cumulus.metadata.util.JSONUtils; +import org.apache.commons.io.FileUtils; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.ParseException; +import org.junit.Test; + +public class JSONUtilsTest { + @Test + public void testGsonToJSONObj() throws IOException, ParseException{ + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("20200101000000-JPL-L2P_GHRSST-SSTskin-MODIS_A-D-v02.0-fv01.0.cmr.json").getFile()); + String cmrStr = FileUtils.readFileToString(file, "UTF-8"); + JsonObject jsonObject = JsonParser.parseString(cmrStr).getAsJsonObject(); + JSONObject translatedSimpleJsonObj = JSONUtils.GsonToJSONObj(jsonObject); + /** + * After translation, do a few "Point checks" + */ + assertEquals(translatedSimpleJsonObj.containsKey("SpatialExtent"), true); + JSONObject spatialExtent = (JSONObject)translatedSimpleJsonObj.get("SpatialExtent"); + JSONObject horizontalSpatialDomain = (JSONObject)spatialExtent.get("HorizontalSpatialDomain"); + JSONObject geometry = (JSONObject)horizontalSpatialDomain.get("Geometry"); + JSONArray boundingRectangles = (JSONArray)geometry.get("BoundingRectangles"); + assertEquals(boundingRectangles.size(), 2); + JSONObject dataGranule = (JSONObject)translatedSimpleJsonObj.get("DataGranule"); + String productionDateTime = (String)dataGranule.get("ProductionDateTime"); + assertEquals(productionDateTime, "2020-02-29T12:20:15.000Z"); + } + +} diff --git a/src/test/java/gov/nasa/cumulus/metadata/test/MetadataFilesToEchoTest.java b/src/test/java/gov/nasa/cumulus/metadata/test/MetadataFilesToEchoTest.java index d51bd34..c71b385 100644 --- a/src/test/java/gov/nasa/cumulus/metadata/test/MetadataFilesToEchoTest.java +++ b/src/test/java/gov/nasa/cumulus/metadata/test/MetadataFilesToEchoTest.java @@ -6,248 +6,439 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import gov.nasa.cumulus.metadata.aggregator.MetadataFilesToEcho; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import gov.nasa.cumulus.metadata.aggregator.*; -import gov.nasa.cumulus.metadata.aggregator.UMMGranule; -import gov.nasa.cumulus.metadata.aggregator.UMMUtils; +import gov.nasa.cumulus.metadata.aggregator.factory.UmmgPojoFactory; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGCollectionAdapter; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGListAdapter; +import gov.nasa.cumulus.metadata.umm.adapter.UMMGMapAdapter; +import gov.nasa.cumulus.metadata.umm.generated.AdditionalAttributeType; +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; +import org.apache.commons.collections.iterators.ObjectArrayIterator; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.Test; +import sun.java2d.jules.JulesRenderingEngine; + +import javax.sound.midi.Track; public class MetadataFilesToEchoTest { - - @Test - public void testParseCommonHandlerFiles(){ - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.mp").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readCommonMetadataFile(file.getAbsolutePath(), "s3://a/path/to/s3"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - assertEquals(new Long(1491622211000l),mfte.getGranule().getStartTimeLong()); - } - - - @Test - public void testParseFootprintFiles(){ - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.fp.xml").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readFootprintFile(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - assertEquals(2,mfte.getGranule().getGranuleCharacterSet().size()); - } - @Test - public void testSetDatasetValues() throws ParseException { - JSONParser parser = new JSONParser(); - JSONObject boundingBox = (JSONObject) parser.parse("{\"boundingBox\": { \"latMin\": -90.0, \"lonMin\": -180.0, \"latMax\": 90.0, \"lonMax\": 180.0}}"); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - - mfte.setDatasetValues("MODIS_T-JPL-L2P-v2019.0", "2019.0", false, (JSONObject) boundingBox.get("boundingBox")); - assertEquals("MODIS_T-JPL-L2P-v2019.0", mfte.getDataset().getShortName()); - assertEquals("2019.0", UMMUtils.getDatasetVersion(mfte.getDataset())); - - assertEquals(UMMGranule.class, mfte.getGranule().getClass()); - UMMGranule granule = (UMMGranule) mfte.getGranule(); - assertEquals(-180, granule.getBbxWesternLongitude().intValue()); - assertEquals(90, granule.getBbxNorthernLatitude().intValue()); - assertEquals(180, granule.getBbxEasternLongitude().intValue()); - assertEquals(-90, granule.getBbxSouthernLatitude().intValue()); - } - @Test - public void testParseConfigFiles(){ - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readConfiguration(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - assertEquals("MODIS_T-JPL-L2P-v2014.0",mfte.getDataset().getShortName()); - assertEquals("4.2", mfte.getDataset().getCitationSet().iterator().next().getVersion()); - } + @Test + public void testParseCommonHandlerFiles() { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.mp").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readCommonMetadataFile(file.getAbsolutePath(), "s3://a/path/to/s3"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + assertEquals(new Long(1491622211000l), mfte.getGranule().getStartTimeLong()); + } + + + @Test + public void testParseFootprintFiles() { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.fp.xml").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readFootprintFile(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + assertEquals(2, mfte.getGranule().getGranuleCharacterSet().size()); + } + + @Test + public void testSetDatasetValues() throws ParseException { + JSONParser parser = new JSONParser(); + JSONObject boundingBox = (JSONObject) parser.parse("{\"boundingBox\": { \"latMin\": -90.0, \"lonMin\": -180.0, \"latMax\": 90.0, \"lonMax\": 180.0}}"); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + + mfte.setDatasetValues("MODIS_T-JPL-L2P-v2019.0", "2019.0", false, (JSONObject) boundingBox.get("boundingBox")); + assertEquals("MODIS_T-JPL-L2P-v2019.0", mfte.getDataset().getShortName()); + assertEquals("2019.0", UMMUtils.getDatasetVersion(mfte.getDataset())); + + assertEquals(UMMGranule.class, mfte.getGranule().getClass()); + UMMGranule granule = (UMMGranule) mfte.getGranule(); + assertEquals(-180, granule.getBbxWesternLongitude().intValue()); + assertEquals(90, granule.getBbxNorthernLatitude().intValue()); + assertEquals(180, granule.getBbxEasternLongitude().intValue()); + assertEquals(-90, granule.getBbxSouthernLatitude().intValue()); + } + + @Test + public void testParseConfigFiles() { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readConfiguration(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + assertEquals("MODIS_T-JPL-L2P-v2014.0", mfte.getDataset().getShortName()); + assertEquals("4.2", mfte.getDataset().getCitationSet().iterator().next().getVersion()); + } + + @Test + public void testCreateJson() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readConfiguration(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + File file2 = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.mp").getFile()); + try { + mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0"); + + JSONObject granule = mfte.createJson(); + System.out.println(granule.toJSONString()); + assertEquals("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0", granule.get("GranuleUR")); + } + + @Test + /** + * use a fake cmr.cfg file + */ + public void testCreateJsonWithOrbitNumber() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readConfiguration(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + File file2 = new File(classLoader.getResource("RSS_SMAP_SSS_L2C_r00870_20150401T004312_2015091_FNL_V04.0.nc.mp").getFile()); + try { + mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("SMAP_RSS_L2_SSS_V4"); + + JSONObject granule = mfte.createJson(); + System.out.println(granule.toJSONString()); + JSONArray orbitArray = (JSONArray) granule.get("OrbitCalculatedSpatialDomains"); + Integer orbitNumber = (Integer) ((JSONObject) orbitArray.get(0)).get("OrbitNumber"); + assertEquals(orbitNumber, new Integer(870)); + } + + @Test + /** + * use a fake cmr.cfg file + */ + public void testCreateJsonWithStartEndOrbitNumber() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readConfiguration(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + File file2 = new File(classLoader.getResource("RSS_smap_SSS_L3_monthly_2015_04_FNL_v04.0.nc.mp").getFile()); + try { + mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("SMAP_RSS_L3_SSS_SMI_MONTHLY_V4"); + + JSONObject granule = mfte.createJson(); + System.out.println(granule.toJSONString()); + JSONArray orbitArray = (JSONArray) granule.get("OrbitCalculatedSpatialDomains"); + Integer beginOrbit = (Integer) ((JSONObject) orbitArray.get(0)).get("BeginOrbitNumber"); + Integer endOrbit = (Integer) ((JSONObject) orbitArray.get(0)).get("EndOrbitNumber"); + assertEquals(beginOrbit, new Integer("870")); + assertEquals(endOrbit, new Integer("1308")); + } + + @Test + public void testCreateJsonWithCyclePass() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + try { + mfte.readConfiguration(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + File file2 = new File(classLoader.getResource("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638.nc.mp").getFile()); + try { + mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638"); + + JSONObject granule = mfte.createJson(); + assertEquals("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638", granule.get("GranuleUR")); + + JSONObject track = (JSONObject) ((JSONObject) ((JSONObject) granule.get("SpatialExtent")).get("HorizontalSpatialDomain")).get("Track"); + assertEquals(new Long(374), track.get("Cycle")); + assertEquals(new Long(172), ((JSONObject) ((JSONArray) track.get("Passes")).get(0)).get("Pass")); + } + + @Test + public void testSwotArchive() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402.PTM_1.archive.xml").getFile()); + File cfgFile = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + + try { + mfte.readConfiguration(cfgFile.getAbsolutePath()); + mfte.readSwotArchiveXmlFile(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402"); + + JSONObject granule = mfte.createJson(); + Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() + .registerTypeHierarchyAdapter(Collection.class, new UMMGCollectionAdapter()) + .registerTypeHierarchyAdapter(List.class, new UMMGListAdapter()) + .registerTypeHierarchyAdapter(Map.class, new UMMGMapAdapter()) + .create(); + String jsonStr = gsonBuilder.toJson(granule); + assertEquals("SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402", granule.get("GranuleUR")); + + JSONObject track = (JSONObject) ((JSONObject) ((JSONObject) granule.get("SpatialExtent")).get("HorizontalSpatialDomain")).get("Track"); + assertEquals(new Long(22), track.get("Cycle")); + assertEquals(new Long(33), ((JSONObject) ((JSONArray) track.get("Passes")).get(0)).get("Pass")); + } + + @Test + public void testReadSwotIsoXmlFile() + throws ParseException, IOException, URISyntaxException { + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc.iso.xml").getFile()); + File cfgFile = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(); + + try { + mfte.readConfiguration(cfgFile.getAbsolutePath()); + mfte.readSwotIsoXmlFile(file.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + + mfte.getGranule().setName("SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01"); + + JSONObject granule = mfte.createJson(); + Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() + .registerTypeHierarchyAdapter(Collection.class, new UMMGCollectionAdapter()) + .registerTypeHierarchyAdapter(List.class, new UMMGListAdapter()) + .registerTypeHierarchyAdapter(Map.class, new UMMGMapAdapter()) + .create(); + String jsonStr = gsonBuilder.toJson(granule); + assertEquals("SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01", granule.get("GranuleUR")); + + JSONObject track = (JSONObject) ((JSONObject) ((JSONObject) granule.get("SpatialExtent")).get("HorizontalSpatialDomain")).get("Track"); + assertEquals(new Long(22), track.get("Cycle")); + assertEquals(new Long(33), ((JSONObject) ((JSONArray) track.get("Passes")).get(0)).get("Pass")); + } + + @Test + public void testMarshellCyclePassTileSceneStrToAchiveType1() { + String input = "Cycle: 5 Pass: [40, Tiles: 4-5L 4-8R] [41, Tiles: 6R 6L] [42, Tiles: 7F]"; + ClassLoader classLoader = getClass().getClassLoader(); + File cfgFile = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); + MetadataFilesToEcho mfte = new MetadataFilesToEcho(true); + + try { + mfte.readConfiguration(cfgFile.getAbsolutePath()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + IsoGranule isoGranule = mfte.createIsoCyclePassTile(input); + TrackType trackType = isoGranule.getTrackType(); + assertEquals(trackType.getCycle(), new Integer(5)); + List trackPassTileTypes = trackType.getPasses(); + assertEquals(trackPassTileTypes.size(), 3); + TrackPassTileType trackPassTileType=trackPassTileTypes.get(0); + assertEquals(trackPassTileType.getPass(), new Integer(40)); + List tiles = trackPassTileType.getTiles(); + assertEquals(tiles.size(), 7); + assertEquals(tiles.get(0), "4L"); + assertEquals(tiles.get(6), "8R"); + List additionalAttributeTypes = isoGranule.getAdditionalAttributeTypes(); + assertEquals(additionalAttributeTypes.size(), 3); + } @Test - public void testCreateJson() - throws ParseException, IOException, URISyntaxException { - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readConfiguration(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - File file2 = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.mp").getFile()); - try { - mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - mfte.getGranule().setName("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0"); - - JSONObject granule = mfte.createJson(); - System.out.println(granule.toJSONString()); - assertEquals("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0", granule.get("GranuleUR")); - } - @Test - /** - * use a fake cmr.cfg file - */ - public void testCreateJsonWithOrbitNumber() - throws ParseException, IOException, URISyntaxException { - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readConfiguration(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - File file2 = new File(classLoader.getResource("RSS_SMAP_SSS_L2C_r00870_20150401T004312_2015091_FNL_V04.0.nc.mp").getFile()); - try { - mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - mfte.getGranule().setName("SMAP_RSS_L2_SSS_V4"); - - JSONObject granule = mfte.createJson(); - System.out.println(granule.toJSONString()); - JSONArray orbitArray = (JSONArray) granule.get("OrbitCalculatedSpatialDomains"); - Integer orbitNumber = (Integer) ((JSONObject)orbitArray.get(0)).get("OrbitNumber"); - assertEquals(orbitNumber, new Integer((int)870)); - } - @Test - /** - * use a fake cmr.cfg file - */ - public void testCreateJsonWithStartEndOrbitNumber() - throws ParseException, IOException, URISyntaxException { - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readConfiguration(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - File file2 = new File(classLoader.getResource("RSS_smap_SSS_L3_monthly_2015_04_FNL_v04.0.nc.mp").getFile()); - try { - mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - mfte.getGranule().setName("SMAP_RSS_L3_SSS_SMI_MONTHLY_V4"); - - JSONObject granule = mfte.createJson(); - System.out.println(granule.toJSONString()); - JSONArray orbitArray = (JSONArray) granule.get("OrbitCalculatedSpatialDomains"); - Integer beginOrbit = (Integer) ((JSONObject)orbitArray.get(0)).get("BeginOrbitNumber"); - Integer endOrbit = (Integer) ((JSONObject)orbitArray.get(0)).get("EndOrbitNumber"); - assertEquals(beginOrbit, new Integer("870")); - assertEquals(endOrbit, new Integer("1308")); - } - @Test - public void testCreateJsonWithCyclePass() - throws ParseException, IOException, URISyntaxException { - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); - MetadataFilesToEcho mfte = new MetadataFilesToEcho(); - try { - mfte.readConfiguration(file.getAbsolutePath()); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - File file2 = new File(classLoader.getResource("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638.nc.mp").getFile()); - try { - mfte.readCommonMetadataFile(file2.getAbsolutePath(), "s3://a/path/to/s3"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - - mfte.getGranule().setName("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638"); - - JSONObject granule = mfte.createJson(); - assertEquals("JA1_GPN_2PeP374_172_20120303_112035_20120303_121638", granule.get("GranuleUR")); - - JSONObject track = (JSONObject) ((JSONObject) ((JSONObject) granule.get("SpatialExtent")).get("HorizontalSpatialDomain")).get("Track"); - assertEquals(374, track.get("Cycle")); - assertEquals(172, ((JSONObject) ((JSONArray) track.get("Passes")).get(0)).get("Pass")); + public void testMarshellCyclePassTileSceneStrToAchiveType2() { + String input = "Cycle: 5 Pass: [40, Tiles: 4-5L 4-8R] [41, Tiles: 6R 6L] [42, Tiles: 7F]"; +// input = "Cycle: 5 Pass: [40, Tiles: 4-5L 4-5R] [41, Tiles: 6R 6L] [42, Tiles: 7F] Cycle: 6 Pass: [50, Tiles: 4-5L 4-5R] [51, Tiles: 6R 6L] [52, Tiles: 7F]"; + String toBeProcessedStr = StringUtils.upperCase(StringUtils.trim(input)); + Pattern p_cycle = Pattern.compile("CYCLE\\s*:\\s*\\d+\\s*?"); + Matcher m_cycle = p_cycle.matcher(toBeProcessedStr); + String cycleStr = ""; + ArrayList cycleStrs = new ArrayList<>(); + while(m_cycle.find()) { + cycleStr = m_cycle.group(); + System.out.println(cycleStr); + cycleStrs.add(cycleStr.trim()); + } + int numberOfCycles = cycleStrs.size(); + int i = 0; + // Current UMMG schema 1.6.3 supports only one cycle. Although it is possible that + // one granule contains 2 cycles as the edge case. + ArrayList cyclePassStrs = new ArrayList<>(); + while(i +1 < numberOfCycles) { + String cyclePassStr = StringUtils.substring(toBeProcessedStr, + StringUtils.indexOf(toBeProcessedStr, cycleStrs.get(i)), + StringUtils.indexOf(toBeProcessedStr, cycleStrs.get(i+1))); + System.out.println("cyclePass processing candidat:" + cyclePassStr); + cyclePassStrs.add(cyclePassStr); + toBeProcessedStr = StringUtils.replace(toBeProcessedStr, cyclePassStr, ""); + i++; + } + toBeProcessedStr = StringUtils.trim(toBeProcessedStr); + // Processed the last Cycle OR if there is only one cycle, we are processing the first==last cycle here + if(StringUtils.isNotEmpty(toBeProcessedStr) && StringUtils.startsWithIgnoreCase(toBeProcessedStr, "CYCLE")) { + System.out.println("Processing the last or first cycle" + toBeProcessedStr); + cyclePassStrs.add(toBeProcessedStr); + } + cyclePassStrs.forEach(cps -> + { + TrackType trackType = createTrackType(cps, p_cycle); + UmmgPojoFactory ummgPojoFactory = UmmgPojoFactory.getInstance(); + List additionalAttributeTypes= + ummgPojoFactory.trackTypeToAdditionalAttributeType(trackType); + }); + cycleStr = StringUtils.replace(cycleStr, "CYCLE", ""); + cycleStr = StringUtils.trim(StringUtils.replace(cycleStr, ":", "")); + System.out.println(cycleStr); } - -// @Test -// public void testGenerate(){ -// ClassLoader classLoader = getClass().getClassLoader(); -// File commonFile = new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.mp").getFile()); -// File footprintFile= new File(classLoader.getResource("20170408033000-JPL-L2P_GHRSST-SSTskin-MODIS_T-N-v02.0-fv01.0.nc.fp.xml").getFile()); -// File cfgFile = new File(classLoader.getResource("MODIS_T-JPL-L2P-v2014.0.cmr.cfg").getFile()); -// File msgFile = new File(classLoader.getResource("cumulus_message_example.json").getFile()); -// -// -// MetadataFilesToEcho mfte = new MetadataFilesToEcho(); -// -// try { -// CumulusMessage message = new Gson().fromJson(IOUtils.toString(new FileInputStream(msgFile), "UTF-8"), CumulusMessage.class); -// -// //assume a single granule... -// CumulusGranule cg = message.getPayload().getGranules().get(0); -// for(CumulusGranuleFile cgf:cg.getFiles()){ -// -// if(cgf.getFilename().endsWith(".mp")) -// continue; -// -// -// GranuleReference gr = new GranuleReference(); -// gr.setPath(cgf.getFilename()); -// gr.setStatus(GranuleStatus.ONLINE.toString()); -// gr.setType(GranuleArchiveType.DATA.toString()); -// mfte.getGranule().add(gr); -// } -// -// mfte.readConfiguration(cfgFile.getAbsolutePath()); -// mfte.readFootprintFile(footprintFile.getAbsolutePath()); -// mfte.readCommonMetadataFile(commonFile.getAbsolutePath(), "s3://a/path/to/s3"); -// mfte.processGranule(); -// if(!mfte.validateXML()){ -// fail(); -// } -// } catch (Exception e) { -// e.printStackTrace(); -// fail(); -// } -// System.out.println(mfte.getXML()); -// } - - - + + public TrackType createTrackType(String cyclePassTileStr, Pattern p_cycle) { + Matcher m_cycle = p_cycle.matcher(cyclePassTileStr); + String cycleStr=null; + while(m_cycle.find()) { + cycleStr = m_cycle.group(); + } + String cycleNoStr = StringUtils.trim( + StringUtils.replace( + StringUtils.replaceIgnoreCase(cycleStr, "CYCLE","") + ,":","")); + System.out.println("Cycle:" + cycleNoStr); + TrackType trackType = new TrackType(); + trackType.setCycle(NumberUtils.createInteger(cycleNoStr)); + + Pattern p_pass = Pattern.compile("\\[.*?\\]"); + Matcher m_pass = p_pass.matcher(cyclePassTileStr); + /** + * The matcher will resolve to the following tokens: + * [40, TILES: 4-5L 4-5R] + * [41, TILES: 6R 6L] + * [42, TILES: 7F] + * The following loop process each token by extracting the passes and tilles + */ + ArrayList trackPassTileTypes = new ArrayList<>(); + while(m_pass.find()) { + TrackPassTileType trackPassTileType = new TrackPassTileType(); + String passTilesStr = m_pass.group(); + passTilesStr =StringUtils.replace( + StringUtils.replace(passTilesStr,"[",""),"]",""); + passTilesStr = passTilesStr.replaceAll("TILES\\s*:\\s*?", ""); + String[] passTiles = StringUtils.split(passTilesStr, ","); + String passStr = StringUtils.trim(passTiles[0]); + trackPassTileType.setPass(NumberUtils.createInteger(passStr)); + List tiles = getTiles(StringUtils.trim(passTiles[1])); + trackPassTileType.setTiles(tiles); + trackPassTileTypes.add(trackPassTileType); + } + trackType.setPasses(trackPassTileTypes); + System.out.println("xxxxxx"); + return trackType; + } + + /** + * 5-8L 4K means, tile 5L, 6L, 7L, 8L and 4K. because dash means a range separator + * + * @param tilesStr ex 5-6L 4K + * @return + */ + public List getTiles(String tilesStr) { + ArrayList tiles = new ArrayList<>(); + String[] tileRanges = StringUtils.split(tilesStr, " "); + // Using Apache Commons Collections + ObjectArrayIterator iterator = new ObjectArrayIterator(tileRanges); + + while (iterator.hasNext()) { + String tileRangStr=(String) iterator.next(); + if(StringUtils.containsIgnoreCase(tileRangStr,"-")){ + String[] tileRangeTokens = StringUtils.split(tileRangStr, "-"); + String endTileStr = tileRangeTokens[tileRangeTokens.length -1]; + // find the letter for the last token + String tileMarkChar = endTileStr.substring(endTileStr.length() - 1); + Integer startTileNum = NumberUtils.createInteger(StringUtils.trim(tileRangeTokens[0])); + Integer endTileNumStr = NumberUtils.createInteger( + StringUtils.trim( + StringUtils.substring(endTileStr, 0, endTileStr.length()-1))); + for(Integer i = startTileNum; i<=endTileNumStr; i++ ) { + tiles.add(i + tileMarkChar); + } + } else { // if it is not a range of tiles like : 5-8L + tiles.add(tileRangStr); + } + + } + return tiles; + } + + + } diff --git a/src/test/java/gov/nasa/cumulus/metadata/test/UMMTest.java b/src/test/java/gov/nasa/cumulus/metadata/test/UMMTest.java index 3ac3fd8..aaac6fe 100644 --- a/src/test/java/gov/nasa/cumulus/metadata/test/UMMTest.java +++ b/src/test/java/gov/nasa/cumulus/metadata/test/UMMTest.java @@ -10,13 +10,15 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; -import gov.nasa.cumulus.metadata.aggregator.CMRLambdaRestClient; -import gov.nasa.cumulus.metadata.aggregator.CMRRestClientProvider; -import gov.nasa.cumulus.metadata.aggregator.UMMGranuleFile; +import gov.nasa.cumulus.metadata.aggregator.*; +import gov.nasa.cumulus.metadata.umm.generated.TrackPassTileType; +import gov.nasa.cumulus.metadata.umm.generated.TrackType; +import org.apache.commons.lang3.StringUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -26,9 +28,6 @@ import org.xml.sax.SAXException; import org.mockito.Mockito; - -import gov.nasa.cumulus.metadata.aggregator.MetadataFilesToEcho; - public class UMMTest { @Test @@ -803,4 +802,46 @@ public void testAddLine() { assertEquals(63.6579, ((JSONObject) points.get(1)).get("Longitude")); assertEquals(-64.9117, ((JSONObject) points.get(1)).get("Latitude")); } + /** + * Test the creation of Track JSONObject through POJO + * the POJO is TrackType which is a member of UMMGranule + */ + + @Test + public void testCreateTrack() throws ParseException{ + TrackType trackType = new TrackType(); + trackType.setCycle(new Integer(22)); + TrackPassTileType trackPassTileType1 = new TrackPassTileType(); + trackPassTileType1.setPass(11); + List tiles1 = new ArrayList<>(); + tiles1.add("tile1-1"); + tiles1.add("tile1-2"); + trackPassTileType1.setTiles(tiles1); + TrackPassTileType trackPassTileType2 = new TrackPassTileType(); + trackPassTileType2.setPass(22); + List tiles2 = new ArrayList<>(); + tiles2.add("tile2-1"); + tiles2.add("tile2-2"); + trackPassTileType2.setTiles(tiles2); + ArrayList trackPassTileTypeArrayList = new ArrayList<>(); + trackPassTileTypeArrayList.add(trackPassTileType1); + trackPassTileTypeArrayList.add(trackPassTileType2); + trackType.setPasses(trackPassTileTypeArrayList); + UMMGranule ummGranule = new UMMGranule(); + ummGranule.setTrackType(trackType); + UMMGranuleFile ummGranuleFile = new UMMGranuleFile(ummGranule, null, true); + + JSONObject trackJsonObj = ummGranuleFile.createUMMGTrack(ummGranule); + assertEquals(trackJsonObj.containsKey("Cycle"), true); + assertEquals(trackJsonObj.containsKey("Passes"), true); + JSONArray passes = (JSONArray) trackJsonObj.get("Passes"); + assertEquals(passes.size(), 2); + JSONObject pass0 = (JSONObject)passes.get(0); + JSONObject pass1 = (JSONObject)passes.get(1); + assertTrue(((Long)pass1.get("Pass")).longValue()==(new Long(22)).longValue()); + JSONArray tiles = (JSONArray)pass1.get("Tiles"); + assertEquals(tiles.size(), 2); + String tile = (String)tiles.get(1); + assertTrue(StringUtils.equals(tile, "tile2-2")); + } } diff --git a/src/test/resources/SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402.PTM_1.archive.xml b/src/test/resources/SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402.PTM_1.archive.xml index 5ee8e7e..5ab71bd 100644 --- a/src/test/resources/SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402.PTM_1.archive.xml +++ b/src/test/resources/SWOT_IVK_20210612T081400_20210612T072103_20210612T080137_O_APID1402.PTM_1.archive.xml @@ -14,9 +14,9 @@ unknown unknown Size: 1024 SizeUnit: B - unknown - unknown - unknown + 22 + 33 + jasper 33 O diff --git a/src/test/resources/SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc.iso.xml b/src/test/resources/SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc.iso.xml new file mode 100644 index 0000000..2cd14b4 --- /dev/null +++ b/src/test/resources/SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc.iso.xml @@ -0,0 +1,599 @@ + + + + + + + SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc + + + + eng + + + + utf8 + + + + dataset + + + + + + 2016-09-05T00:28:46.000000Z + + + + ISO 19115-2 Geographic Information - Metadata Part 2 Extensions for imagery and gridded data + + + ISO 19115-2:2009(E) + + + + + + + + + + + + + + + 2016-09-05T00:28:46.000000Z + + + creation + + + + + + + + + + SWOT_L2_HR_PIXCVec_001_113_164R_20160905T002836_20160905T002846_TI0000_01.nc + + + gov.nasa.esdis.umm.producergranuleid + + + ProducerGranuleId + + + + + + + + DG00 + + + gov.nasa.esdis.umm.crid + + + CRID + + + + + + + + ICV01 CollectionVersion filler + + + gov.nasa.esdis.umm.otherid + + + OtherId: ScienceAlgorithmVersionId + + + + + + + 3.1.0 + + + gov.nasa.esdis.umm.otherid + + + OtherId: PGEVersionId + + + + + + + 0.4 + + + gov.nasa.esdis.umm.otherid + + + OtherId: SASVersionId + + + + + + + 01 + + + gov.nasa.esdis.umm.otherid + + + OtherId: ProductCounter + + + + + + + + + + + + + + + + asNeeded + + + ReprocessingPlanned: ICV09 ISO_SWOT_ReprocessingPlanNote filler + + + + + + + + + https://webmap.ornl.gov/sdat/pimg/TBD + + + Size: TBD> SizeUnit: KB Description: TBD + + + Format: PNG MimeType: image/png + + + + + + + + https://webmap.ornl.gov/sdat/pimg/TBD + + + Size: TBD> SizeUnit: KB Description: TBD + + + Format: PNG MimeType: image/png + + + + + + + + + ICV05 ISO_SWOT_Project_keyword_1 + + + ICV06 ISO_SWOT_Project_keyword_2 + + + ICV07 ISO_SWOT_Project_keyword_3 + + + project + + + + + NASA Project Keywords + + + + + + NASA + + + User Support Office + + + + + + + https://support.earthdata.nasa.gov/ + + + Earthdata Support + + + File an issue or provide feedback + + + information + + + + + + + custodian + + + + + + + + + + + + + ICV13 campaign_keyword1 + + + ICV14 campaign_keyword2 + + + ICV15 campaign_keyword3 + + + campaign + + + + + + + + + ICV02 ISO_SWOT_Platform_keyword_1 + + + ICV03 ISO_SWOT_Platform_keyword_2 + + + ICV04 ISO_SWOT_Platform_keyword_3 + + + platform + + + + + NASA Platform Keywords + + + + + + NASA + + + User Support Office + + + + + + + https://support.earthdata.nasa.gov/ + + + Earthdata Support + + + File an issue or provide feedback + + + information + + + + + + + custodian + + + + + + + + + + + + + ICV16 karin_keyword_1 + + + ICV17 karin_keyword_2 + + + ICV18 karin_keyword_3 + + + instrument + + + + + NASA Instrument Keywords + + + + + + NASA + + + User Support Office + + + + + + + https://support.earthdata.nasa.gov/ + + + Earthdata Support + + + File an issue or provide feedback + + + information + + + + + + + custodian + + + + + + + + + + + + + + PGE_L2_HR_PIXCVec + + + gov.nasa.esdis.umm.collectionshortname + + + CollectionShortName + + + + + LargerWorkCitation + + + + + + + + + + ICV01 CollectionVersion filler + + + gov.nasa.esdis.umm.collectionversion + + + CollectionVersion + + + + + LargerWorkCitation + + + + + + + + + + + + + + + + + + + + ICV11 ISO_SWOT_projectHomePageUrl filler + + + ICV12 ISO_SWOT_projectHomePageUrlDescription filler + + + information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICV11 ISO_SWOT_projectHomePageUrl filler + + + ICV12 ISO_SWOT_projectHomePageUrlDescription filler + + + information + + + + + + + + + + + + + + + + eng + + + + utf8 + + + + + + + + + + + + + + Cycle: 5 Pass: [40, Tiles: 4-5L 4-5R] [41, Tiles: 6R 6L] [42, Tiles: 7F] Cycle: 6 Pass: [50, Tiles: 4-5L 4-5R] [51, Tiles: 6R 6L] [52, Tiles: 7F] + + + gov.nasa.esdis.umm.swottrack + + + SWOTTrack + + + + + + + + + + + + + 2016-09-05T00:28:36.000000Z + 2016-09-05T00:28:46.000000Z + + + + + + + + +