############################################################################### ## ## ## ALEXANDRIA DIGITAL LIBRARY ## ## University of California at Santa Barbara ## ## ## ## ------------------------------------------------------------------------- ## ## ## ## Copyright (c) 2005 by the Regents of the University of California ## ## All rights reserved ## ## ## ## Redistribution and use in source and binary forms, with or without ## ## modification, are permitted provided that the following conditions are ## ## met: ## ## ## ## 1. Redistributions of source code must retain the above copyright ## ## notice, this list of conditions, and the following disclaimer. ## ## ## ## 2. Redistributions in binary form must reproduce the above copyright ## ## notice, this list of conditions, and the following disclaimer in ## ## the documentation and/or other materials provided with the ## ## distribution. ## ## ## ## 3. All advertising materials mentioning features or use of this ## ## software must display the following acknowledgement: This product ## ## includes software developed by the Alexandria Digital Library, ## ## University of California at Santa Barbara, and its contributors. ## ## ## ## 4. Neither the name of the University nor the names of its ## ## contributors may be used to endorse or promote products derived ## ## from this software without specific prior written permission. ## ## ## ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY ## ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ## ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE ## ## DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ## ## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ## ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ## ## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ## ## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ## ## ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ## ## POSSIBILITY OF SUCH DAMAGE. ## ## ## ############################################################################### # $Header: /export/home/gjanee/mm/RCS/FGDC_mapping.py,v 1.2 2005/03/10 17:35:02 gjanee Exp $ # DESCRIPTION # # This is a mapping from the FGDC Content Standard for Digital # Geospatial Metadata (CSDGM), version 2 (FGDC-STD-001-1998), to # the ADL bucket, browse, and access metadata views. # # The FGDC standard is defined at # http://www.fgdc.gov/metadata/contstan.html. # # AUTHOR # # Greg Janee # gjanee@alexandria.ucsb.edu # # HISTORY # # $Log: FGDC_mapping.py,v $ # Revision 1.2 2005/03/10 17:35:02 gjanee # Minor improvements. # # Revision 1.1 2005/02/17 18:19:36 gjanee # Initial revision # import re from ADL_mapper import * input() import ADL_buckets TAG = "tag:fgdc.gov,1998:FGDC-STD-001-1998:" # ---------------------------------------- # ADL:TITLES map("adl:titles", "/metadata/idinfo/citation/citeinfo/title", ("[FGDC] Title", TAG+"citation/title")) # ---------------------------------------- # ADL:GEOGRAPHIC-LOCATIONS map("adl:geographic-locations", ["/metadata/idinfo/spdom/bounding", "northbc", "southbc", "eastbc", "westbc"], ("[FGDC] Bounding Coordinates", TAG+"bounding")) # ---------------------------------------- # ADL:DATES def fltRemoveUnknown (v): if v[0].lower() == "unknown": return None else: return v def cvtNumericDate (v): # Converts YYYYMMDD to YYYY-MM-DD; trailing zeros are allowed and # are removed. match = re.match("(\d{4})(\d{2})?(\d{2})?$", v[0]) if match: d = match.group(1) if match.group(2) != None: if int(match.group(2)) > 0: d += "-" + match.group(2) if match.group(3) != None and int(match.group(3)) > 0: d += "-" + match.group(3) else: if match.group(3) != None and int(match.group(3)) > 0: return None return (d,) else: return None _months = ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"] def cvtEnglishMonthYearDate (v): match = re.match("(\w+)\s+(\d{4})$", v[0]) if match and match.group(1).lower() in _months: month = _months.index(match.group(1).lower()) + 1 return (("%s-%02d" % (match.group(2), month)),) else: return None map("adl:dates", "/metadata/idinfo/timeperd/timeinfo/sngdate/caldate", ("[FGDC] Time Period of Content", TAG+"timeperd"), prefilters=fltRemoveUnknown, converters=[cvtNumericDate, cvtEnglishMonthYearDate], id=1) map("adl:dates", "/metadata/idinfo/timeperd/timeinfo/mdattim/sngdate/caldate", ("[FGDC] Time Period of Content", TAG+"timeperd"), prefilters=fltRemoveUnknown, converters=[cvtNumericDate, cvtEnglishMonthYearDate], id=2) def fltRemoveUnknownPresent (v): if v[0] == None or v[0].lower() == "unknown": if v[1] == None or v[1].lower() == "unknown" or\ v[1].lower() == "present": return None else: return (v[1], v[1]) else: if v[1] == None or v[1].lower() == "unknown": return (v[0], v[0]) elif v[1].lower() == "present": return (v[0], "9999") else: return v def cvtNumericRange (v): begin = cvtNumericDate((v[0],)) end = cvtNumericDate((v[1],)) if begin != None and end != None: return (begin[0], end[0]) else: return None def cvtEnglishMonthYearRange (v): begin = cvtEnglishMonthYearDate((v[0],)) end = cvtEnglishMonthYearDate((v[1],)) if begin != None and end != None: return (begin[0], end[0]) else: return None map("adl:dates", ["/metadata/idinfo/timeperd/timeinfo/rngdates", "begdate", "enddate"], ("[FGDC] Time Period of Content", TAG+"timeperd"), prefilters=fltRemoveUnknownPresent, converters=[cvtNumericRange, cvtEnglishMonthYearRange], id=3) # ---------------------------------------- # ADL:TYPES # See for definitions of the FGDC terms. Per Mary # Larsgaard, globes are considered neither maps nor cartographic # works (!). _typeMapping = { "atlas" : "maps", "diagram" : "cartographic works", "map" : "maps", "model" : "cartographic works", "profile" : "images", "raster digital data" : "cartographic works", "remote-sensing image" : "remote-sensing images", "section" : "cartographic works", "vector digital data" : "cartographic works", "view" : "cartographic works" } def fltMapTerm (v): v = _typeMapping.get(v[0].lower(), None) if v != None: return ("ADL Object Type Thesaurus", v) else: return None map("adl:types", "/metadata/idinfo/citation/citeinfo/geoform", ("[FGDC] Geospatial Data Presentation Form", TAG+"citation/geoform"), prefilters=fltMapTerm) # ---------------------------------------- # ADL:FORMATS if present("/metadata/idinfo/citation/citeinfo/onlink"): mapConstant("adl:formats", ("ADL Object Formats", "Online"), id=1) STDORDER = "/metadata/distinfo/stdorder/" DIGFORM = STDORDER + "digform/" if present(STDORDER+"nondig"): mapConstant("adl:formats", ("ADL Object Formats", "Non-digital"), id=2) if present(DIGFORM+"digtopt/offoptn/offmedia"): mapConstant("adl:formats", ("ADL Object Formats", "Digital"), id=3) if present(DIGFORM+"digtopt/onlinopt/computer/networka/networkr"): mapConstant("adl:formats", ("ADL Object Formats", "Online"), id=4) def fltAddVocabulary (v): if v[0] != None: return ("ADL Object Formats", v[1]) else: return None map("adl:formats", [DIGFORM+"digtopt/onlinopt/computer/networka/networkr", ".", "../../../../../digtinfo/formname"], ("[FGDC] Format Name", TAG+"formname"), prefilters=fltAddVocabulary, strict=False, id=5) # ---------------------------------------- # ADL:ASSIGNED-TERMS def fltKeepIfHasThesaurus (v): if v[1] != None and v[1].lower() != "none" and v[0] != None: return (v[0],) else: return None map("adl:assigned-terms", ["/metadata/idinfo/keywords/theme/themekey", ".", "../themekt"], ("[FGDC] Theme Keyword", TAG+"themekey"), prefilters=fltKeepIfHasThesaurus) map("adl:assigned-terms", ["/metadata/idinfo/keywords/place/placekey", ".", "../placekt"], ("[FGDC] Place Keyword", TAG+"placekey"), prefilters=fltKeepIfHasThesaurus) map("adl:assigned-terms", ["/metadata/idinfo/keywords/stratum/stratkey", ".", "../stratkt"], ("[FGDC] Stratum Keyword", TAG+"stratkey"), prefilters=fltKeepIfHasThesaurus) map("adl:assigned-terms", ["/metadata/idinfo/keywords/temporal/tempkey", ".", "../tempkt"], ("[FGDC] Temporal Keyword", TAG+"tempkey"), prefilters=fltKeepIfHasThesaurus) consolidateTextualValues("adl:assigned-terms") # ---------------------------------------- # ADL:SUBJECT-RELATED-TEXT map("adl:subject-related-text", "/metadata/idinfo/descript/abstract", ("[FGDC] Abstract", TAG+"abstract")) map("adl:subject-related-text", "/metadata/idinfo/descript/purpose", ("[FGDC] Purpose", TAG+"purpose")) def fltKeepIfNoThesaurus (v): if (v[1] == None or v[1].lower() == "none") and v[0] != None: return (v[0],) else: return None map("adl:subject-related-text", ["/metadata/idinfo/keywords/theme/themekey", ".", "../themekt"], ("[FGDC] Theme Keyword", TAG+"themekey"), prefilters=fltKeepIfNoThesaurus) map("adl:subject-related-text", ["/metadata/idinfo/keywords/place/placekey", ".", "../placekt"], ("[FGDC] Place Keyword", TAG+"placekey"), prefilters=fltKeepIfNoThesaurus) map("adl:subject-related-text", ["/metadata/idinfo/keywords/stratum/stratkey", ".", "../stratkt"], ("[FGDC] Stratum Keyword", TAG+"stratkey"), prefilters=fltKeepIfNoThesaurus) map("adl:subject-related-text", ["/metadata/idinfo/keywords/temporal/tempkey", ".", "../tempkt"], ("[FGDC] Temporal Keyword", TAG+"tempkey"), prefilters=fltKeepIfNoThesaurus) consolidateTextualValues("adl:subject-related-text") # ---------------------------------------- # ADL:ORIGINATORS map("adl:originators", "/metadata/idinfo/citation/citeinfo/origin", ("[FGDC] Originator", TAG+"citation/origin"), prefilters=fltRemoveUnknown) map("adl:originators", "/metadata/idinfo/citation/citeinfo/pubinfo/publish", ("[FGDC] Publisher", TAG+"citation/publish")) # ---------------------------------------- # ADL:IDENTIFIERS # In theory, '/metadata/distinfo/resdesc' is mappable to the # 'adl:identifiers' bucket (see # http://biology.usgs.gov/fgdc.metadata/version2/distr/resdesfq.htm), # but in practice its usage is too incomplete, inconsistent, and # idiosyncratic. # ---------------------------------------- # REQUIREMENTS & EXPECTATIONS requirement("adl:titles", "1+") expectation("adl:titles", "1") expectation("adl:geographic-locations", "1") expectation("adl:dates", "1+") expectation("adl:subject-related-text", "1+") output()