pub mod core;
pub mod reference_system;
pub mod spatial_representation;
pub use self::core::*;
pub use reference_system::*;
pub use spatial_representation::*;
use crate::common::{BoundingBox, ContactInfo, Keyword, TemporalExtent};
use crate::error::{MetadataError, Result};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Iso19115Metadata {
pub file_identifier: Option<String>,
pub language: Option<String>,
pub character_set: Option<CharacterSet>,
pub hierarchy_level: HierarchyLevel,
pub contact: Vec<ResponsibleParty>,
pub date_stamp: chrono::DateTime<chrono::Utc>,
pub metadata_standard_name: String,
pub metadata_standard_version: String,
pub identification_info: Vec<DataIdentification>,
pub distribution_info: Option<Distribution>,
pub data_quality_info: Option<DataQuality>,
pub reference_system_info: Vec<ReferenceSystem>,
}
impl Default for Iso19115Metadata {
fn default() -> Self {
Self {
file_identifier: None,
language: Some("eng".to_string()),
character_set: Some(CharacterSet::Utf8),
hierarchy_level: HierarchyLevel::Dataset,
contact: Vec::new(),
date_stamp: chrono::Utc::now(),
metadata_standard_name: "ISO 19115:2014".to_string(),
metadata_standard_version: "2014".to_string(),
identification_info: Vec::new(),
distribution_info: None,
data_quality_info: None,
reference_system_info: Vec::new(),
}
}
}
pub struct Iso19115Builder {
metadata: Iso19115Metadata,
}
impl Iso19115Metadata {
pub fn builder() -> Iso19115Builder {
Iso19115Builder {
metadata: Self::default(),
}
}
}
impl Iso19115Builder {
pub fn title(mut self, title: impl Into<String>) -> Self {
if self.metadata.identification_info.is_empty() {
self.metadata
.identification_info
.push(DataIdentification::default());
}
self.metadata.identification_info[0].citation.title = title.into();
self
}
pub fn abstract_text(mut self, abstract_text: impl Into<String>) -> Self {
if self.metadata.identification_info.is_empty() {
self.metadata
.identification_info
.push(DataIdentification::default());
}
self.metadata.identification_info[0].abstract_text = abstract_text.into();
self
}
pub fn keywords(mut self, keywords: Vec<impl Into<String>>) -> Self {
if self.metadata.identification_info.is_empty() {
self.metadata
.identification_info
.push(DataIdentification::default());
}
let kw = keywords
.into_iter()
.map(|k| Keyword {
keyword: k.into(),
thesaurus: None,
})
.collect();
self.metadata.identification_info[0].keywords.push(kw);
self
}
pub fn bbox(mut self, bbox: BoundingBox) -> Self {
if self.metadata.identification_info.is_empty() {
self.metadata
.identification_info
.push(DataIdentification::default());
}
self.metadata.identification_info[0]
.extent
.geographic_extent = Some(bbox);
self
}
pub fn temporal_extent(mut self, extent: TemporalExtent) -> Self {
if self.metadata.identification_info.is_empty() {
self.metadata
.identification_info
.push(DataIdentification::default());
}
self.metadata.identification_info[0].extent.temporal_extent = Some(extent);
self
}
pub fn contact(mut self, contact: ResponsibleParty) -> Self {
self.metadata.contact.push(contact);
self
}
pub fn file_identifier(mut self, id: impl Into<String>) -> Self {
self.metadata.file_identifier = Some(id.into());
self
}
pub fn build(self) -> Result<Iso19115Metadata> {
if self.metadata.identification_info.is_empty() {
return Err(MetadataError::MissingField(
"identification_info".to_string(),
));
}
Ok(self.metadata)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum CharacterSet {
Utf8,
Iso8859_1,
Utf16,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum HierarchyLevel {
Dataset,
Series,
Service,
Application,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResponsibleParty {
pub individual_name: Option<String>,
pub organization_name: Option<String>,
pub position_name: Option<String>,
pub contact_info: Option<ContactInfo>,
pub role: Role,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum Role {
ResourceProvider,
Custodian,
Owner,
User,
Distributor,
Originator,
PointOfContact,
PrincipalInvestigator,
Processor,
Publisher,
Author,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Citation {
pub title: String,
pub alternate_title: Option<String>,
pub date: Vec<CitationDate>,
pub edition: Option<String>,
pub identifier: Vec<String>,
pub cited_responsible_party: Vec<ResponsibleParty>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CitationDate {
pub date: chrono::DateTime<chrono::Utc>,
pub date_type: DateType,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum DateType {
Creation,
Publication,
Revision,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Distribution {
pub format: Vec<Format>,
pub distributor: Vec<Distributor>,
pub transfer_options: Vec<TransferOptions>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Format {
pub name: String,
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Distributor {
pub distributor_contact: ResponsibleParty,
pub distribution_order_process: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransferOptions {
pub online: Vec<OnlineResource>,
pub transfer_size: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OnlineResource {
pub linkage: String,
pub protocol: Option<String>,
pub name: Option<String>,
pub description: Option<String>,
pub function: OnlineFunction,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OnlineFunction {
Download,
Information,
OfflineAccess,
Order,
Search,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataQuality {
pub scope: Scope,
pub lineage: Option<Lineage>,
pub report: Vec<QualityReport>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Scope {
pub level: HierarchyLevel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Lineage {
pub statement: String,
pub process_step: Vec<ProcessStep>,
pub source: Vec<Source>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessStep {
pub description: String,
pub date_time: Option<chrono::DateTime<chrono::Utc>>,
pub processor: Vec<ResponsibleParty>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Source {
pub description: String,
pub scale_denominator: Option<i32>,
pub source_citation: Option<Citation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QualityReport {
pub measure_identification: String,
pub result: String,
}