              [:gco:Date (second (re-matches #"(\d\d\d\d-\d\d-\d\d)T.*" (str (:PublicationDate pub-ref))))]]
             [:gmd:dateType
              [:gmd:CI_DateTypeCode
-              {:codeList (str (:iso code-lists) "#CI_DateTypeCode")
+              {:codeList (str (:iso u/code-lists) "#CI_DateTypeCode")
                :codeListValue "publication"} "publication"]]]])
         [:gmd:edition (char-string (:Edition pub-ref))]
         (when (:DOI pub-ref)

   :xmlns:swe "http://schemas.opengis.net/sweCommon/2.0/"
   :xmlns:gsr "http://www.isotc211.org/2005/gsr"})

(def echo-attributes-info
  [:eos:otherPropertyType
   [:gco:RecordType {:xlink:href "http://earthdata.nasa.gov/metadata/schema/eos/1.0/eos.xsd#xpointer(//element[@name='AdditionalAttributes'])"}
    "Echo Additional Attributes"]])

(def code-lists
  "The uri base of the code-lists used in the generation of ISO xml"
  {:earthdata "http://earthdata.nasa.gov/metadata/resources/Codelists.xml"
   :ngdc "http://www.ngdc.noaa.gov/metadata/published/xsd/schema/resources/Codelist/gmxCodelists.xml"
   :iso "http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml"})

(defn- date-mapping
  "Returns the date element mapping for the given name and date value in string format."
  [date-name value]

        [:gmd:ISBN (char-string (:ISBN pub-ref))]]]
      [:gmd:associationType
       [:gmd:DS_AssociationTypeCode
        {:codeList (str (:ngdc u/code-lists) "#DS_AssociationTypeCode")
         :codeListValue "Input Collection"} "Input Collection"]]]]))

(defn extent-description-string
  "Returns the ISO extent description string (a \"key=value,key=value\" string) for the given UMM-C
  collection record."
  [c]
  (let [vsd (first (-> c :SpatialExtent :VerticalSpatialDomains))
        m {"VerticalSpatialDomainType" (:Type vsd)
           "VerticalSpatialDomainValue" (:Value vsd)
           "SpatialCoverageType" (-> c :SpatialExtent :SpatialCoverageType)
           "SpatialGranuleSpatialRepresentation" (-> c :SpatialExtent :GranuleSpatialRepresentation)}]
    (str/join "," (for [[k v] m
                        :when (some? v)]
                    (str k "=" (str/replace v #"[,=]" ""))))))

(defn- science-keyword->iso-keyword-string
  "Returns an ISO science keyword string from the given science keyword."
  [science-keyword]
  (let [{category :Category
         topic :Topic
         term :Term
         variable-level-1 :VariableLevel1
         variable-level-2 :VariableLevel2
         variable-level-3 :VariableLevel3
         detailed-variable :DetailedVariable} science-keyword]
    (str/join iso/keyword-separator (map #(or % iso/nil-science-keyword-field)
                                         [category topic term variable-level-1 variable-level-2
                                          variable-level-3 detailed-variable]))))

(defn umm-c-to-iso19115-2-xml
  "Returns the generated ISO19115-2 xml from UMM collection record c."
  [c]
  (let [platforms (platform/platforms-with-id (:Platforms c))]
    (xml
      [:gmi:MI_Metadata
       iso19115-2-xml-namespaces
       [:gmd:fileIdentifier (char-string (:EntryTitle c))]
       [:gmd:language (char-string "eng")]
       [:gmd:characterSet
        [:gmd:MD_CharacterSetCode {:codeList (str (:ngdc u/code-lists) "#MD_CharacterSetCode")
                                   :codeListValue "utf8"} "utf8"]]
       [:gmd:hierarchyLevel
        [:gmd:MD_ScopeCode {:codeList (str (:ngdc u/code-lists) "#MD_ScopeCode")
                            :codeListValue "series"} "series"]]
       [:gmd:contact {:gco:nilReason "missing"}]
       [:gmd:dateStamp
        [:gco:DateTime "2014-08-25T15:25:44.641-04:00"]]
       [:gmd:metadataStandardName (char-string "ISO 19115-2 Geographic Information - Metadata Part 2 Extensions for imagery and gridded data")]
       [:gmd:metadataStandardVersion (char-string "ISO 19115-2:2009(E)")]
       (spatial/coordinate-system-element c)
       [:gmd:identificationInfo
        [:gmd:MD_DataIdentification
         [:gmd:citation
          [:gmd:CI_Citation
           [:gmd:title (char-string (:EntryTitle c))]
           (date-mapping "revision" "2000-12-31T19:00:00-05:00")
           (date-mapping "creation" "2000-12-31T19:00:00-05:00")
           [:gmd:identifier
            [:gmd:MD_Identifier
             [:gmd:code (char-string (:EntryId c))]
             [:gmd:version (char-string (:Version c))]]]]]
         [:gmd:abstract (char-string (:Abstract c))]
         [:gmd:purpose {:gco:nilReason "missing"} (char-string (:Purpose c))]
         [:gmd:status
          (when-let [collection-progress (:CollectionProgress c)]
            [:gmd:MD_ProgressCode
             {:codeList (str (:ngdc u/code-lists) "#MD_ProgressCode")
              :codeListValue (str/lower-case collection-progress)}
             collection-progress])]
         (generate-projects-keywords (:Projects c))
         (when-let [science-keywords (:ScienceKeywords c)]
           [:gmd:descriptiveKeywords (u/generate-descriptive-keywords
                                       "theme"
                                       (map science-keyword->iso-keyword-string science-keywords))])
         (u/generate-descriptive-keywords "place" (:SpatialKeywords c))
         (u/generate-descriptive-keywords "temporal" (:TemporalKeywords c))
         (u/generate-descriptive-keywords (:AncillaryKeywords c))
         (platform/generate-platform-keywords platforms)
         (platform/generate-instrument-keywords platforms)
         [:gmd:resourceConstraints
          [:gmd:MD_LegalConstraints
           [:gmd:useLimitation (char-string (:UseConstraints c))]
           [:gmd:useLimitation
            [:gco:CharacterString (str "Restriction Comment:" (-> c :AccessConstraints :Description))]]
           [:gmd:otherConstraints
            [:gco:CharacterString (str "Restriction Flag:" (-> c :AccessConstraints :Value))]]]]
         (generate-publication-references (:PublicationReferences c))
         [:gmd:language (char-string (or (:DataLanguage c) "eng"))]
         [:gmd:extent
          [:gmd:EX_Extent {:id "boundingExtent"}
           [:gmd:description
            [:gco:CharacterString (extent-description-string c)]]
           (spatial/spatial-extent-elements c)
           (for [temporal (:TemporalExtents c)
                 rdt (:RangeDateTimes temporal)]
             [:gmd:temporalElement
              [:gmd:EX_TemporalExtent
               [:gmd:extent
                [:gml:TimePeriod {:gml:id (u/generate-id)}
                 [:gml:beginPosition (:BeginningDateTime rdt)]
                 [:gml:endPosition (su/nil-to-empty-string (:EndingDateTime rdt))]]]]])
           (for [temporal (:TemporalExtents c)
                 date (:SingleDateTimes temporal)]
             [:gmd:temporalElement
              [:gmd:EX_TemporalExtent
               [:gmd:extent
                [:gml:TimeInstant {:gml:id (u/generate-id)}
                 [:gml:timePosition date]]]]])]]
         [:gmd:processingLevel
          [:gmd:MD_Identifier
           [:gmd:code (char-string (-> c :ProcessingLevel :Id))]
           [:gmd:description (char-string (-> c :ProcessingLevel :ProcessingLevelDescription))]]]]]
       [:gmd:contentInfo
        [:gmd:MD_ImageDescription
         [:gmd:attributeDescription ""]
         [:gmd:contentType ""]
         [:gmd:processingLevelCode
          [:gmd:MD_Identifier
           [:gmd:code (char-string (-> c :ProcessingLevel :Id))]
           [:gmd:description (char-string (-> c :ProcessingLevel :ProcessingLevelDescription))]]]]]
       (generate-distributions (:Distributions c))
       [:gmd:dataQualityInfo
        [:gmd:DQ_DataQuality
         [:gmd:scope
          [:gmd:DQ_Scope
           [:gmd:level
            [:gmd:MD_ScopeCode
             {:codeList (str (:ngdc u/code-lists) "#MD_ScopeCode")
              :codeListValue "series"}
             "series"]]]]
         [:gmd:report
          [:gmd:DQ_AccuracyOfATimeMeasurement
           [:gmd:measureIdentification
            [:gmd:MD_Identifier
             [:gmd:code
              (char-string "PrecisionOfSeconds")]]]
           [:gmd:result
            [:gmd:DQ_QuantitativeResult
             [:gmd:valueUnit ""]
             [:gmd:value
              [:gco:Record {:xsi:type "gco:Real_PropertyType"}
               [:gco:Real (:PrecisionOfSeconds (first (:TemporalExtents c)))]]]]]]]]]
       [:gmi:acquisitionInformation
        [:gmi:MI_AcquisitionInformation
         (platform/generate-instruments platforms)
         (generate-projects (:Projects c))
         (platform/generate-platforms platforms)]]])))

