; ; NOSA HEADER START ; ; The contents of this file are subject to the terms of the NASA Open ; Source Agreement (NOSA), Version 1.3 only (the "Agreement"). You may ; not use this file except in compliance with the Agreement. ; ; You can obtain a copy of the agreement at ; docs/NASA_Open_Source_Agreement_1.3.txt ; or ; http://cdaweb.gsfc.nasa.gov/WebServices/NASA_Open_Source_Agreement_1.3.txt. ; ; See the Agreement for the specific language governing permissions ; and limitations under the Agreement. ; ; When distributing Covered Code, include this NOSA HEADER in each ; file and include the Agreement file at ; docs/NASA_Open_Source_Agreement_1.3.txt. If applicable, add the ; following below this NOSA HEADER, with the fields enclosed by ; brackets "[]" replaced with your own identifying information: ; Portions Copyright [yyyy] [name of copyright owner} ; ; NOSA HEADER END ; ; Copyright (c) 2010-2013 United States Government as represented by the ; National Aeronautics and Space Administration. No copyright is claimed ; in the United States under Title 17, U.S.Code. All Other Rights Reserved. ; ; ;+ ; This class represents the remotely callable interface to ; NASA's ; Space Physics Data Facility (SPDF) ; Coordinated Data Analysis System ; (CDAS). ; ; @copyright Copyright (c) 2010-2013 United States Government as represented ; by the National Aeronautics and Space Administration. No ; copyright is claimed in the United States under Title 17, ; U.S.Code. All Other Rights Reserved. ; ; @author B. Harris ;- ;+ ; Creates an object representing CDAS. ; ; @keyword endpoint {in} {optional} {type=string} ; {default=http://cdaweb.gsfc.nasa.gov/WS/cdasr/1} ; URL of CDAS web service. ; @keyword userAgent {in} {optional} {type=string} {default=WsExample} ; HTTP user-agent value used in communications with CDAS. ; @keyword defaultDataview {in} {optional} {type=string} ; {default=sp_phys} ; default CDAS dataview value to use in subsequent calls ; when no value is specified. ; @returns a reference to a CDAS object. ;- function SpdfCdas::init, $ endpoint = endpoint, $ userAgent = userAgent, $ defaultDataview = defaultDataview compile_opt idl2 self.endpoint = 'http://cdaweb.gsfc.nasa.gov/WS/cdasr/1' self.version = '%VERSION*' self.currentVersionUrl = $ 'http://cdaweb.gsfc.nasa.gov/WebServices/REST/spdfCdasVersion.txt' if keyword_set(endpoint) then self.endpoint = endpoint if ~keyword_set(userAgent) then userAgent = 'WsExample' self.userAgent = 'User-Agent: ' + userAgent + ' (' + $ !version.os + ' ' + !version.arch + ') IDL/' + !version.release self.defaultDataview = 'sp_phys' if keyword_set(defaultDataview) then begin self.defaultDataview = defaultDataview endif return, self end ;+ ; Performs cleanup operations when this object is destroyed. ;- pro SpdfCdas::cleanup compile_opt idl2 end ;+ ; Gets the current endpoint value. ; ; @returns current endpoint string value. ;- function SpdfCdas::getEndpoint compile_opt idl2 return, self.endpoint end ;+ ; Gets the current userAgent value. ; ; @returns current userAgent string value. ;- function SpdfCdas::getUserAgent compile_opt idl2 return, self.userAgent end ;+ ; Gets the current defaultDataview value. ; ; @returns current defaultDataview string value. ;- function SpdfCdas::getDefaultDataview compile_opt idl2 return, self.defaultDataview end ;+ ; Gets the version of this class. ; ; @returns version of this class. ;- function SpdfCdas::getVersion compile_opt idl2 return, self.version end ;+ ; Gets the most up to date version of this class. ; ; @returns most up to date version of this class. ;- function SpdfCdas::getCurrentVersion compile_opt idl2 catch, errorStatus if (errorStatus ne 0) then begin catch, /cancel ; Failed to get current version return, '' endif url = obj_new('IDLnetURL') return, url->get(/string_array, url=self.currentVersionUrl) end ;+ ; Compares getversion() and getCurrentversion() to determine if this ; class is up to date. ; ; @returns true if getversion() >= getCurrentversion(). Otherwise ; false. ;- function SpdfCdas::isUpToDate compile_opt idl2 version = strsplit(self->getversion(), '.', /extract) versionElements = n_elements(version) currentVersion = strsplit(self->getCurrentversion(), '.', /extract) currentVersionElements = n_elements(currentVersion) if versionElements eq 1 or currentVersionElements eq 1 then begin ; Do not know what the versions are so return up-to-date return, 1 endif if versionElements lt currentVersionElements then begin elements = versionElements endif else begin elements = currentVersionElements endelse for i = 0, elements - 1 do begin if 0 + version[i] lt 0 + currentVersion[i] then return, 0 endfor if versionElements lt currentVersionElements then begin return, 0 endif else begin return, 1 endelse end ;+ ; Gets the node's value of the first child of the first item of the ; specified element of the given DOM document. ; ; @private ; ; @param domElement {in} {required} {type=IDLffXMLDOMDocument} ; DOM element to search ; @param tagName {in} {required} {type=string} ; A scalar string containing the tag name of the desired ; element. ; @returns node's string value(s) of the first child of the item(s) ; of the specified element of the given DOM document. An ; empty string is returned if the value cannot be found. ;- function SpdfCdas::getNamedElementsFirstChildValue, $ domElement, tagName compile_opt idl2 nodeList = domElement->getElementsByTagName(tagName) if nodeList->getLength() eq 0 then return, '' values = strarr(nodeList->getLength()) for i = 0, nodeList->getLength() - 1 do begin domNode = nodeList->item(i) child = domNode->getFirstChild() if obj_valid(child) then begin values[i] = child->getNodeValue() endif else begin values[i] = '' endelse endfor if n_elements(values) eq 1 then return, values[0] $ else return, values end ;+ ; Gets a description of all the dataviews that are available. ; ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns array of SpdfDataviewDescription objects. ; If there are no dataviews, an array of length ; one is returned with the first element being a null ; object reference. ;- function SpdfCdas::getDataviews, $ httpErrorReporter=errorReporter compile_opt idl2 url = self.endpoint + '/dataviews' dvDom = self->makeGetRequest('N/A', url, $ errorReporter=errorReporter) if ~obj_valid(dvDom) then return, objarr(1) dataviewElements = $ dvDom->getElementsByTagName('DataviewDescription') dataviews = objarr(dataviewElements->getLength(), /nozero) for i = 0, dataviewElements->getLength() - 1 do begin dvElement = dataviewElements->item(i) id = $ self->getNamedElementsFirstChildValue(dvElement, 'Id') endpointAddress = $ self->getNamedElementsFirstChildValue(dvElement, $ 'EndpointAddress') title = $ self->getNamedElementsFirstChildValue(dvElement, 'Title') subtitle = $ self->getNamedElementsFirstChildValue(dvElement, 'SubTitle') overview = $ self->getNamedElementsFirstChildValue(dvElement, 'Overview') underConstructionStr = $ self->getNamedElementsFirstChildValue(dvElement, $ 'UnderConstruction') if strcmp(underConstructionStr, 'true', /fold_case) eq 1 $ then begin underConstruction = 1b endif else begin underConstruction = 0b endelse noticeUrl = $ self->getNamedElementsFirstChildValue(dvElement, $ 'NoticeUrl') publicAccessStr = $ self->getNamedElementsFirstChildValue(dvElement, $ 'PublicAccess') if (strcmp(publicAccessStr, 'true', /fold_case) eq 1) then begin publicAccess = 1b endif else begin publicAccess = 0b endelse dataviews[i] = $ obj_new('SpdfDataviewDescription', id, endpointAddress, $ title, subtitle, overview, underConstruction, $ noticeUrl, publicAccess) endfor obj_destroy, dvDom return, dataviews end ;+ ; Gets a description of all the observatory groups. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @keyword instrumentTypes {in} {optional} {type=strarr} ; names of instrument-types which restrict the returned ; observatory groups to only those supporting the specified ; instrument-types. Valid values are those returned by ; getInstrumentTypes. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns array of SpdfObservatoryGroupDescription objects. ; If there are no observatory groups, an array of length ; one is returned with the first element being a null ; object reference. ;- function SpdfCdas::getObservatoryGroups, $ dataview = dataview, $ instrumentTypes = iTypes, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + $ '/observatoryGroups?' for i = 0, n_elements(iTypes) - 1 do begin url = url + 'instrumentType=' + iTypes[i] + '&' endfor url = strmid(url, 0, strlen(url) - 1) ogDom = self->makeGetRequest(dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter) if ~obj_valid(ogDom) then return, objarr(1) ogElements = $ ogDom->getElementsByTagName('ObservatoryGroupDescription') observatoryGroups = objarr(ogElements->getLength(), /nozero) for i = 0, ogElements->getLength() - 1 do begin ogElement = ogElements->item(i) name = $ self->getNamedElementsFirstChildValue(ogElement, 'Name') observatoryIds = $ self->getNamedElementsFirstChildValue(ogElement, $ 'ObservatoryId') observatoryGroups[i] = $ obj_new('SpdfObservatoryGroupDescription', name, $ observatoryIds) endfor obj_destroy, ogDom return, observatoryGroups end ;+ ; Gets a description of all the instrument types. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @keyword observatoryGroups {in} {optional} {type=strarr} ; names of observatory-groups which restrict the returned ; instrument types to only those supporting the specified ; observatory-groups. Valid values are those returned by ; getObservatoryGroups. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns array of SpdfInstrumentTypeDescription objects. ; If there are no intrument types, an array of length one ; is returned with the first element being a null object ; reference. ;- function SpdfCdas::getInstrumentTypes, $ dataview = dataview, $ observatoryGroups = oGroups, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + '/instrumentTypes?' for i = 0, n_elements(oGroups) - 1 do begin url = url + 'observatoryGroup=' + oGroups[i] + '&' endfor url = strmid(url, 0, strlen(url) - 1) itDom = self->makeGetRequest(dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter) if ~obj_valid(itDom) then return, objarr(1) itElements = $ itDom->getElementsByTagName('InstrumentTypeDescription') instrumentTypes = objarr(itElements->getLength(), /nozero) for i = 0, itElements->getLength() - 1 do begin itElement = itElements->item(i) name = $ self->getNamedElementsFirstChildValue(itElement, 'Name') instrumentTypes[i] = $ obj_new('SpdfInstrumentTypeDescription', name) endfor obj_destroy, itDom return, instrumentTypes end ;+ ; Gets a description of all the datasets. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @keyword observatoryGroups {in} {optional} {type=strarr} ; names of observatory-groups which restrict the returned ; datasets to only those supporting the specified ; observatory-groups. Valid values are those returned by ; getObservatoryGroups. ; @keyword instrumentTypes {in} {optional} {type=strarr} ; names of instrument-types which restrict the returned ; datasets to only those supporting the specified ; instrument-types. Valid values are those returned by ; getInstrumentTypes. ; @keyword observatories {in} {optional} {type=strarr} ; names of observatories which restrict the returned ; datasets to only those supporting the specified ; observatories. Valid values are those returned by ; getObservatories. ; @keyword instruments {in} {optional} {type=strarr} ; names of instruments which restrict the returned ; datasets to only those supporting the specified ; instruments. Valid values are those returned by ; getInstruments. ; @keyword startDate {in} {optional} {type=julday} ; value that restricts the returned dataset to only ; those that contain data after this date. ; @keyword stopDate {in} {optional} {type=julday} ; value that restricts the returned dataset to only ; those that contain data before this date. ; @keyword idPattern {in} {optional} {type=string} ; a java.util.regex compatible ; regular ; expression that must match the dataset's identifier ; value. Omitting this parameter is equivalent to ".*". ; @keyword labelPattern {in} {optional} {type=string} ; a java.util.regex compatible ; regular ; expression that must match the dataset's label ; text. Omitting this parameter is equivalent to ".*". ; Embedded matching flag expressions (e.g., (?i) for ; case insensitive match mode) are supported and likely ; to be useful in this case. ; @keyword notesPattern {in} {optional} {type=string} ; a java.util.regex compatible ; regular ; expression that must match the dataset's notes ; text. Omitting this parameter is equivalent to ".*". ; Embedded matching flag expressions (e.g., (?i) for ; case insensitive match mode) are supported and likely ; to be useful in this case. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns array of SpdfDatasetDescription objects. If there are no ; datasets, an array of length one is returned with the ; first element being a null object reference. ;- function SpdfCdas::getDatasets, $ dataview = dataview, $ observatoryGroups = observatoryGroups, $ instrumentTypes = instrumentTypes, $ observatories = observatories, $ instruments = instruments, $ startDate = startDate, $ stopDate = stopDate, $ idPattern = idPattern, $ labelPattern = labelPattern, $ notesPattern = notesPattern, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + '/datasets?' for i = 0, n_elements(observatoryGroups) - 1 do begin url = url + 'observatoryGroup=' + observatoryGroups[i] + '&' endfor for i = 0, n_elements(instrumentTypes) - 1 do begin url = url + 'instrumentType=' + instrumentTypes[i] + '&' endfor for i = 0, n_elements(observatories) - 1 do begin url = url + 'observatory=' + observatories[i] + '&' endfor for i = 0, n_elements(instruments) - 1 do begin url = url + 'instrument=' + instruments[i] + '&' endfor if keyword_set(startDate) then begin url = url + 'startDate=' + self->julDay2Iso8601(startDate) + '&' endif if keyword_set(stopDate) then begin url = url + 'stopDate=' + self->julDay2Iso8601(stopDate) + '&' endif if keyword_set(idPattern) then begin url = url + 'idPattern=' + idPattern + '&' endif if keyword_set(labelPattern) then begin url = url + 'labelPattern=' + labelPattern + '&' endif if keyword_set(notesPattern) then begin url = url + 'notesPattern=' + notesPattern + '&' endif url = strmid(url, 0, strlen(url) - 1) dsDom = self->makeGetRequest(dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter) if ~obj_valid(dsDom) then begin return, objarr(1) endif dsElements = $ dsDom->getElementsByTagName('DatasetDescription') datasets = objarr(dsElements->getLength(), /nozero) for i = 0, dsElements->getLength() - 1 do begin dsElement = dsElements->item(i) id = $ self->getNamedElementsFirstChildValue(dsElement, 'Id') observatories = $ self->getNamedElementsFirstChildValue(dsElement, $ 'Observatory') instruments = $ self->getNamedElementsFirstChildValue(dsElement, $ 'Instrument') observatoryGroups = $ self->getNamedElementsFirstChildValue(dsElement, $ 'ObservatoryGroup') instrumentTypes = $ self->getNamedElementsFirstChildValue(dsElement, $ 'InstrumentTypes') label = $ self->getNamedElementsFirstChildValue(dsElement, 'Label') timeInterval = self->getTimeIntervalChild(dsElement) piName = $ self->getNamedElementsFirstChildValue(dsElement, 'PiName') piAffiliation = self->getNamedElementsFirstChildValue($ dsElement, 'PiAffiliation') notes = $ self->getNamedElementsFirstChildValue(dsElement, 'Notes') linkElements = dsElement->getElementsByTagName('DatasetLink') if linkElements->getLength() gt 0 then begin datasetLinks = objarr(linkElements->getLength(), /nozero) for j = 0, linkElements->getLength() - 1 do begin linkElement = linkElements->item(j) title = $ self->getNamedElementsFirstChildValue(linkElement, $ 'Title') text = $ self->getNamedElementsFirstChildValue(linkElement, $ 'Text') url = $ self->getNamedElementsFirstChildValue(linkElement, $ 'Url') datasetLinks[j] = $ obj_new('SpdfDatasetLink', title, text, url) endfor endif else begin datasetLinks = obj_new() endelse datasets[i] = $ obj_new('SpdfDatasetDescription', id, observatories, $ instruments, observatoryGroups, instrumentTypes, $ label, timeInterval, piName, piAffiliation, notes, $ datasetLinks) obj_destroy, datasetLinks endfor obj_destroy, dsDom return, datasets end ;+ ; Gets a description of a dataset's data inventory. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param dataset {in} {type=string} ; identifies the dataset. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns an SpdfInventoryDescription or a null reference if no ; inventory is available. ;- function SpdfCdas::getInventory, $ dataview = dataview, dataset, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + '/datasets/' + $ dataset + '/inventory' inventoryDom = self->makeGetRequest(dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter) inventoryElements = $ inventoryDom->getElementsByTagName('InventoryDescription') if inventoryElements->getLength() eq 0 then begin obj_destroy, inventoryDom return, obj_new() endif inventoryElement = inventoryElements->item(0) id = self->getNamedElementsFirstChildValue(inventoryElement, 'Id') timeIntervalElements = $ inventoryElement->getElementsByTagName('TimeInterval') if timeIntervalElements->getLength() gt 0 then begin timeIntervals = $ objarr(timeIntervalElements->getLength(), /nozero) for i = 0, timeIntervalElements->getLength() - 1 do begin timeIntervals[i] = $ self->getTimeInterval(timeIntervalElements->item(i)) endfor endif else begin timeIntervals = obj_new() endelse obj_destroy, inventoryDom return, obj_new('SpdfInventoryDescription', id, timeIntervals) end ;+ ; Gets a description of a dataset's variables. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param dataset {in} {type=string} ; identifies the dataset. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns array of SpdfVariableDescription objects. If the dataset ; has no variables, an array of one null object is ; returned. ;- function SpdfCdas::getVariables, $ dataview = dataview, dataset, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + '/datasets/' + $ dataset + '/variables' varDom = self->makeGetRequest(dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter) if ~obj_valid(varDom) then return, objarr(1) varElements = $ varDom->getElementsByTagName('VariableDescription') if varElements->getLength() eq 0 then begin obj_destroy, varDom return, objarr(1) endif varDescriptions = objarr(varElements->getLength(), /nozero) for i = 0, varElements->getLength() - 1 do begin varElement = varElements->item(i) name = $ self->getNamedElementsFirstChildValue(varElement, 'Name') shortDescription = $ self->getNamedElementsFirstChildValue(varElement, $ 'ShortDescription') longDescription = $ self->getNamedElementsFirstChildValue(varElement, $ 'LongDescription') parent = $ self->getNamedElementsFirstChildValue(varElement, 'Parent') children = $ self->getNamedElementsFirstChildValue(varElement, $ 'Children') varDescriptions[i] = $ obj_new('SpdfVariableDescription', name, shortDescription, $ longDescription, parent = parent, children = children) endfor obj_destroy, varDom return, varDescriptions end ;+ ; Gets Common Data Format ; data from the specified dataset. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param timeInterval {in} {type=SpdfTimeInterval} ; time range of data to get. ; @param dataset {in} {type=string} ; identifies the dataset from which data is being ; requested. ; @param variables {in} {type=strarr} ; names of variable's whose data is being requested. ; If no names are specified, the data of all variables ; is returned. ; @keyword cdfVersion {in} {optional} {type=int} ; is the CDF file version that any created CDF files ; should be (2 or 3). ; @keyword cdfFormat {in} {optional} {type=string} ; CDF format of returned data. Valid values are: ; Binary, CDFML, GzipCDFML, ZipCDFML. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns SpdfCdasDataResult object. ;- function SpdfCdas::getCdfData, $ dataview = dataview, timeInterval, dataset, variables, $ cdfVersion = cdfVersion, cdfFormat = cdfFormat, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview timeIntervals = [timeInterval] datasetRequest = $ obj_new('SpdfDatasetRequest', dataset, variables) cdfRequest = $ obj_new('SpdfCdfRequest', timeIntervals, datasetRequest, $ cdfVersion = cdfVersion, cdfFormat = cdfFormat) dataRequest = $ obj_new('SpdfCdasDataRequest', cdfRequest) result = self->getData(dataview = dataview, dataRequest, $ authenticator = authenticator, $ httpErrorReporter = errorReporter) obj_destroy, datasetRequest obj_destroy, cdfRequest obj_destroy, dataRequest return, result end ;+ ; Gets a textual representation of data from the specified dataset. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param timeInterval {in} {type=SpdfTimeInterval} ; time range of data to get. ; @param dataset {in} {type=string} ; identifies the dataset from which data is being ; requested. ; @param variables {in} {type=strarr} ; names of variable's whose data is being requested. ; If no names are specified, the data of all variables ; is returned. ; @keyword compression {in} {optional} {type=int} ; the type of compression to use on the result file. ; Valid values are: Uncompressed, Gzip, Bzip2, Zip. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns SpdfCdasDataResult object. ;- function SpdfCdas::getTextData, $ dataview = dataview, timeInterval, dataset, variables, $ compression = compression, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview datasetRequest = $ obj_new('SpdfDatasetRequest', dataset, variables) textRequest = $ obj_new('SpdfTextRequest', timeInterval, datasetRequest, $ compression = compression) dataRequest = $ obj_new('SpdfCdasDataRequest', textRequest) result = self->getData(dataview = dataview, dataRequest, $ authenticator = authenticator, $ httpErrorReporter = errorReporter) obj_destroy, datasetRequest obj_destroy, textRequest obj_destroy, dataRequest return, result end ;+ ; Gets a graphical representation of data from the specified dataset. ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param timeInterval {in} {type=SpdfTimeInterval} ; time range of data to get. ; @param datasetRequests {in} {type=objarr of SpdfDatasetRequest} ; identifies the datasets and variables from which data ; is being requested. ; @keyword graphOptions {in} {optional} {type=int} ; graphing options. Valid values are: ; CoarseNoiseFilter, DoubleHeightYAxis, CombineGraphs. ; @keyword imageFormat {in} {optional} {type=strarr} ; Format options for graph. Valid values are: ; GIF, PNG, PS, PDF. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns SpdfCdasDataResult object. ;- function SpdfCdas::getGraphData, $ dataview = dataview, timeInterval, datasetRequests, $ graphOptions = graphOptions, imageFormat = imageFormat, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview graphRequest = $ obj_new('SpdfGraphRequest', $ timeInterval, datasetRequests, $ graphOptions = graphOptions, imageFormats = imageFormats) dataRequest = $ obj_new('SpdfCdasDataRequest', graphRequest) result = self->getData(dataview = dataview, dataRequest, $ authenticator = authenticator, $ httpErrorReporter = errorReporter) obj_destroy, graphRequest obj_destroy, dataRequest return, result end ;+ ; Converts the given Julian Day value to an ISO 8601 string ; representation. ; ; @private ; ; @param value {in} {type=julDay} ; Julian day value to convert. ; @returns ISO 8601 string representation of the given value ;- function SpdfCdas::julDay2Iso8601, $ value compile_opt idl2 caldat, value, month, day, year, hour, minute, second return, string(year, month, day, hour, minute, second, $ format=self.iso8601Format) end ;+ ; Make a request to CDAS for the specified data. ; ; @private ; ; @keyword dataview {in} {optional} {type=string} ; name of dataview to access. ; @param dataRequest {in} {type=SpdfCdasDataRequest} ; specifies the data to get. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword httpErrorReporter {in} {optional} ; {type=SpdfHttpErrorReporter} ; used to report an HTTP error. ; @returns SpdfCdasDataResult object. ;- function SpdfCdas::getData, $ dataview = dataview, $ dataRequest, $ authenticator = authenticator, $ httpErrorReporter = errorReporter compile_opt idl2 if ~keyword_set(dataview) then dataview = self.defaultDataview url = self.endpoint + '/dataviews/' + dataview + '/datasets' requestDoc = obj_new('IDLffXMLDOMDocument') requestDom = $ requestDoc->appendChild( $ dataRequest->createDomElement(requestDoc)) requestDoc->save, string=xmlRequest obj_destroy, requestDoc dataDoc = self->makePostRequest(dataview, url, xmlRequest, $ authenticator = authenticator, $ errorReporter = errorReporter) if ~obj_valid(dataDoc) then return, obj_new() dataResult = self->getDataResult(dataDoc) obj_destroy, dataDoc return, dataResult end ;+ ; Creates an SpdfCdasDataResult object from the given cdas:DataResult ; XML document. ; ; @private ; ; @param doc {in} {type=IDLffXMLDOMDocument} ; cdas:DataResult XML document. ; @returns SpdfCdasDataResult object. ;- function SpdfCdas::getDataResult, $ doc compile_opt idl2 fileDescriptions = self->getFileDescriptions(doc) messages = self->getDataResultText(doc, 'Message') warnings = self->getDataResultText(doc, 'Warning') statuses = self->getDataResultText(doc, 'Status') errors = self->getDataResultText(doc, 'Error') dataResult = obj_new('SpdfCdasDataResult', $ fileDescriptions, $ messages = messages, warnings = warnings, $ statuses = statuses, errors = errors) return, dataResult end ;+ ; Creates SpdfFileDescription object(s) from the FileDescription ; elements in the given cdas:DataResult XML document. ; ; @private ; ; @param doc {in} {type=IDLffXMLDOMDocument} ; cdas:DataResult XML document. ; @returns objarr of SpdfFileDescription objects. ;- function SpdfCdas::getFileDescriptions, $ doc compile_opt idl2 fileDescriptions = obj_new() fileElements = doc->getElementsByTagName('FileDescription') if fileElements->getLength() gt 0 then begin fileDescriptions = objarr(fileElements->getLength(), /nozero) for i = 0, fileElements->getLength() - 1 do begin fileElement = fileElements->item(i) name = $ self->getNamedElementsFirstChildValue(fileElement, $ 'Name') mimeType = $ self->getNamedElementsFirstChildValue(fileElement, $ 'MimeType') startTime = $ self->getJulDate((fileElement->$ getElementsByTagName('StartTime'))->item(0)) endTime = $ self->getJulDate((fileElement->$ getElementsByTagName('EndTime'))->item(0)) timeInterval = $ obj_new('SpdfTimeInterval', startTime, endTime) length = $ self->getNamedElementsFirstChildValue(fileElement, $ 'Length') lastModified = $ self->getNamedElementsFirstChildValue(fileElement, $ 'LastModified') thumbnailDescription = $ self->getThumbnailDescription(fileElement) thumbnailId = self->getThumbnailId(fileElement) fileDescriptions[i] = obj_new('SpdfFileDescription', $ name, mimeType, timeInterval, length, lastModified, $ thumbnailDescription = thumbnailDescription, $ thumbnailId = thumbnailId) obj_destroy, timeInterval obj_destroy, thumbnailDescription endfor end return, fileDescriptions end ;+ ; Creates an SpdfThumbnailDescription object from the FileDescription ; element in the given cdas:DataResult XML document. ; ; @private ; ; @param fileElement {in} {type=IDLffXMLDOMDocument} ; cdas:FileDescription element from a cdas:DataResult XML ; document. ; @returns SpdfThumbnailDescription object. ;- function SpdfCdas::getThumbnailDescription, $ fileElement compile_opt idl2 thumbnailDescription = obj_new() thumbnailDescriptionElements = $ fileElement->getElementsByTagName('ThumbnailDescription') if thumbnailDescriptionElements->getLength() gt 0 then begin thumbnailDescriptionElement = $ thumbnailDescriptionElements->item(0) type = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'Type') name = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'Name') dataset = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'Dataset') timeInterval = self->getTimeIntervalChild(thumbnailElement) varName = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'VarName') options = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'Options') numFrames = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'NumFrames') numRows = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'NumRows') numCols = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'NumCols') titleHeight = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'TitleHeight') thumbnailHeight = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'ThumbnailHeight') thumbnailWidth = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'ThumbnailWidth') startRecord = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'StartRecord') myScale = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'MyScale') xyStep = $ self->getNamedElementsFirstChildValue(thumbnailElement, $ 'XyStep') thumbnailDescription = obj_new('SpdfThumbnailDescription', $ type, name, dataset, timeInterval, varName, options, $ numFrames, numRows, numCols, titleHeight, thumbnailHeight, $ thumbnailWidth, startRecord, myScale, xyStep) obj_destroy, timeInterval end return, thumbnailDescription end ;+ ; Creates a SpdfTimeInterval object from a child TimeInterval element ; of the given node from a cdas:DataResult XML document. ; ; @private ; ; @param domNode {in} {type=IDLffXMLDOMNode} ; node from a cdas:DataResult XML document. ; @returns a reference to a SpdfTimeInterval object. ;- function SpdfCdas::getTimeIntervalChild, $ domNode compile_opt idl2 timeInterval = obj_new() timeIntervalElements = domNode->getElementsByTagName('TimeInterval') if timeIntervalElements->getLength() gt 0 then begin timeInterval = $ self->getTimeInterval(timeIntervalElements->item(0)) end return, timeInterval end ;+ ; Creates a SpdfTimeInterval object from the given TimeInterval element ; from a cdas:DataResult XML document. ; ; @private ; ; @param timeIntervalElement {in} {type=IDLffXMLDOMNode} ; element from a cdas:DataResult XML document. ; @returns a reference to a SpdfTimeInterval object. ;- function SpdfCdas::getTimeInterval, $ timeIntervalElement compile_opt idl2 startDate = $ self->getJulDate((timeIntervalElement->$ getElementsByTagName('Start'))->item(0)) endDate = $ self->getJulDate((timeIntervalElement->$ getElementsByTagName('End'))->item(0)) return, obj_new('SpdfTimeInterval', startDate, endDate) end ;+ ; Creates a julday object from the given time element from a ; cdas:DataResult XML document. ; ; @private ; ; @param dateTimeElement {in} {type=IDLffXMLDOMNodeList} ; list whose first child is to be converted into a julday ; @returns julday representation of first child of given ; dateTimeElement. ;- function SpdfCdas::getJulDate, $ dateTimeElement compile_opt idl2 dateFormat='(I4, 1X, I2, 1X, I2, 1X, I2, 1X, I2, 1X, I2)' dateTimeStr = (dateTimeElement->getFirstChild())->getNodeValue() reads, dateTimeStr, format=dateFormat, $ year, month, day, hour, minute, second return, julday(month, day, year, hour, minute, second) end ;+ ; Gets the ThumbnailId value from the given cdas:FileDescription ; element. ; ; @private ; ; @param fileElement {in} {type=IDLffXMLDOMNode} ; cdas:FileDescription node. ; @returns ThumbnailId string value. ;- function SpdfCdas::getThumbnailId, $ fileElement compile_opt idl2 return, self->getNamedElementsFirstChildValue(fileElement, $ 'ThumbnailId') end ;+ ; Gets the specified node values from the given cdas:DataResult XML ; document. ; ; @private ; ; @param resultDoc {in} {type=IDLffXMLDOMDocument} ; cdas:DataResult XML document. ; @param type {in} {type=string} ; name of elements whose value is to be gotten. This is ; expected to be one of Message, Warning, Status, or Error. ; @returns strarr of the specified node values from the given document. ;- function SpdfCdas::getDataResultText, $ resultDoc, type return, self->getNamedElementsFirstChildValue(resultDoc, type) end ;+ ; Perform an HTTP GET request to the given URL. This method provides ; functionality similar to doing ; obj_new('IDLffXMLDOMDocument', filename=url) ; except that this method will catch an authorization error (401), ; call the supplied authenticator function, and then retry the ; request with the authentication credentials obtained from the ; call to the callers authentication function. ; ; @private ; ; @param dataview {in} {type=string} ; name of dataview to access. ; @param url {in} {type=string} ; URL of GET request to make. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword errorReporter {in} {optional} {type=string} ; name of IDL procedure to call if an HTTP error occurs. ; @returns reference to IDLffXMLDOMDocument representation of HTTP ; response entity. ;- function SpdfCdas::makeGetRequest, $ dataview, url, $ authenticator = authenticator, $ errorReporter = errorReporter compile_opt idl2 username = '' password = '' catch, errorStatus if (errorStatus ne 0) then begin catch, /cancel reply = $ self->handleHttpError( $ requestUrl, dataview, username, password, $ authenticator = authenticator, $ errorReporter = errorReporter) obj_destroy, requestUrl if reply eq 0 then return, obj_new() endif requestUrl = self->getRequestUrl(url, username, password) result = string(requestUrl->get(/buffer)) obj_destroy, requestUrl return, obj_new('IDLffXMLDOMDocument', string=result) end ;+ ; Perform an HTTP POST request to the given URL. If an authorization ; error (401) occurs, the supplied authenticator function is called, ; and then the request is retried with the authentication credentials ; obtained from the call to the callers authentication function. ; ; @private ; ; @param dataview {in} {type=string} ; name of dataview to access. ; @param url {in} {type=string} ; URL of GET request to make. ; @param xmlRequest {in} {type=string} ; XML entity body to be include in the request. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword errorReporter {in} {optional} {type=string} ; name of IDL procedure to call if an HTTP error occurs. ; @returns reference to IDLffXMLDOMDocument representation of HTTP ; response entity. ;- function SpdfCdas::makePostRequest, $ dataview, url, xmlRequest, $ authenticator = authenticator, $ errorReporter = errorReporter compile_opt idl2 username = '' password = '' catch, errorStatus if (errorStatus ne 0) then begin catch, /cancel reply = $ self->handleHttpError( $ requestUrl, dataview, username, password, $ authenticator = authenticator, $ errorReporter = errorReporter) obj_destroy, requestUrl if reply eq 0 then return, obj_new() endif requestUrl = self->getRequestUrl(url, username, password) requestUrl->setProperty, header='Content-Type: application/xml' ; print, 'POSTing ', xmlRequest ; print, 'to ', url result = requestUrl->put(xmlRequest, /buffer, /post, url=url) obj_destroy, requestUrl return, obj_new('IDLffXMLDOMDocument', filename=result) end ;+ ; Function to handle HTTP request errors. If an authorization error ; (401) has occurred and an authenticator is provided, the given ; authenticator is called to obtain authentication credentials. ; For any other error, if an errorReporter has been provided, it is ; called. ; ; @private ; ; @param request {in} {type=IDLnetURL} ; HTTP request that caused the error. ; @param dataview {in} {type=string} ; name of dataview to access. ; @param username {out} {type=string} ; username value obtained by calling the given authenticator. ; @param password {out} {type=string} ; password value obtained by calling the given authenticator. ; @keyword authenticator {in} {optional} {type=SpdfAuthenticator} ; authenticator that is used when a dataview requiring ; authentication is specified. ; @keyword errorReporter {in} {optional} {type=string} ; name of IDL procedure to call if an HTTP error occurs. ; @returns a value of 1 if username and password has been set and a ; value of 0 if not. ;- function SpdfCdas::handleHttpError, $ request, dataview, username, password, $ authenticator = authenticator, $ errorReporter = errorReporter compile_opt idl2 request->getProperty, $ response_code=responseCode, $ response_header=responseHeader, $ response_filename=responseFilename if responseCode eq 401 && $ keyword_set(authenticator) then begin reply = $ call_method('getCredentials', authenticator, $ dataview, username, password) if reply eq 0 then begin return, 0 endif endif else begin if keyword_set(errorReporter) then begin call_method, 'reportError', errorReporter, $ responseCode, responseHeader, responseFilename endif return, 0 endelse return, 1 end ;+ ; Create an IDLnetUrl object from the given URL with any supplied ; authentication values set. ; ; @private ; ; @param url {in} {type=string} ; URL. ; @param username {in} {type=string} ; username. ; @param password {in} {type=string} ; password. ; @returns reference to a IDLnetUrl with any supplied authentication ; values set. ;- function SpdfCdas::getRequestUrl, $ url, username, password compile_opt idl2 requestUrl = obj_new('IDLnetUrl') urlComponents = parse_url(url) requestUrl->setProperty, $ header=self.userAgent, $ url_scheme=urlComponents.scheme, $ url_host=urlComponents.host, $ url_port=urlComponents.port, $ url_path=urlComponents.path, $ url_query=urlComponents.query if username ne '' then begin requestUrl->setProperty, $ authentication=3, $ url_username=username, $ url_password=password endif return, requestUrl end ;+ ; Defines the SpdfCdas class. ; ; @field endpoint URL of CDAS web service. ; @field defaultDataview CDAS dataview to access when the dataview is ; not specified. ; @field userAgent HTTP ; ; user-agent value to use in communications with CDAS. ; @field version identifies the version of this class. ; @field currentVersionUrl URL to the file identifying the most up to ; date version of this class. ;- pro SpdfCdas__define compile_opt idl2 struct = { SpdfCdas, $ endpoint:'', $ userAgent:'', $ defaultDataview:'', $ version:'', $ currentVersionUrl:'' $ } end