oxigdal_metadata/lib.rs
1//! Comprehensive metadata standards support for OxiGDAL.
2//!
3//! This crate provides support for multiple geospatial and data catalog metadata standards:
4//!
5//! - **ISO 19115** - Geographic Information - Metadata
6//! - **FGDC** - Federal Geographic Data Committee
7//! - **INSPIRE** - EU INSPIRE Directive
8//! - **DataCite** - DOI metadata for research data
9//! - **DCAT** - W3C Data Catalog Vocabulary
10//!
11//! # Features
12//!
13//! - Metadata extraction from datasets (GeoTIFF, NetCDF, HDF5, STAC)
14//! - Metadata validation and quality scoring
15//! - Cross-standard transformation
16//! - XML and JSON serialization
17//!
18//! # Examples
19//!
20//! ```no_run
21//! use oxigdal_metadata::*;
22//!
23//! # fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
24//! // Create ISO 19115 metadata
25//! let iso = iso19115::Iso19115Metadata::builder()
26//! .title("Sentinel-2 Imagery")
27//! .abstract_text("Satellite imagery from Sentinel-2")
28//! .keywords(vec!["satellite", "sentinel-2"])
29//! .build()?;
30//!
31//! // Validate
32//! let validation = validate::validate_iso19115(&iso)?;
33//! if !validation.is_complete() {
34//! println!("Missing fields: {:?}", validation.missing_fields());
35//! }
36//!
37//! # Ok(())
38//! # }
39//! ```
40
41#![cfg_attr(not(feature = "std"), no_std)]
42#![warn(missing_docs)]
43
44#[cfg(feature = "std")]
45extern crate std;
46
47pub mod datacite;
48pub mod dcat;
49pub mod error;
50pub mod extract;
51pub mod fgdc;
52pub mod inspire;
53pub mod iso19115;
54pub mod transform;
55pub mod validate;
56
57pub use error::{MetadataError, Result};
58
59/// Common metadata types and utilities.
60pub mod common {
61 use serde::{Deserialize, Serialize};
62
63 /// Contact information.
64 #[derive(Debug, Clone, Serialize, Deserialize)]
65 pub struct ContactInfo {
66 /// Individual name
67 pub individual_name: Option<String>,
68 /// Organization name
69 pub organization_name: Option<String>,
70 /// Position name
71 pub position_name: Option<String>,
72 /// Email address
73 pub email: Option<String>,
74 /// Phone number
75 pub phone: Option<String>,
76 /// Address
77 pub address: Option<Address>,
78 /// Online resource
79 pub online_resource: Option<String>,
80 }
81
82 /// Address information.
83 #[derive(Debug, Clone, Serialize, Deserialize)]
84 pub struct Address {
85 /// Delivery point (street address)
86 pub delivery_point: Option<String>,
87 /// City
88 pub city: Option<String>,
89 /// Administrative area (state/province)
90 pub administrative_area: Option<String>,
91 /// Postal code
92 pub postal_code: Option<String>,
93 /// Country
94 pub country: Option<String>,
95 }
96
97 /// Bounding box for geographic extent.
98 #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
99 pub struct BoundingBox {
100 /// West longitude
101 pub west: f64,
102 /// East longitude
103 pub east: f64,
104 /// South latitude
105 pub south: f64,
106 /// North latitude
107 pub north: f64,
108 }
109
110 impl BoundingBox {
111 /// Create a new bounding box.
112 ///
113 /// # Arguments
114 ///
115 /// * `west` - West longitude
116 /// * `east` - East longitude
117 /// * `south` - South latitude
118 /// * `north` - North latitude
119 pub fn new(west: f64, east: f64, south: f64, north: f64) -> Self {
120 Self {
121 west,
122 east,
123 south,
124 north,
125 }
126 }
127
128 /// Check if the bounding box is valid.
129 pub fn is_valid(&self) -> bool {
130 self.west <= self.east
131 && self.south <= self.north
132 && self.west >= -180.0
133 && self.east <= 180.0
134 && self.south >= -90.0
135 && self.north <= 90.0
136 }
137 }
138
139 /// Keyword with optional thesaurus.
140 #[derive(Debug, Clone, Serialize, Deserialize)]
141 pub struct Keyword {
142 /// Keyword text
143 pub keyword: String,
144 /// Thesaurus name
145 pub thesaurus: Option<String>,
146 }
147
148 /// Temporal extent.
149 #[derive(Debug, Clone, Serialize, Deserialize)]
150 pub struct TemporalExtent {
151 /// Start date/time
152 pub start: Option<chrono::DateTime<chrono::Utc>>,
153 /// End date/time
154 pub end: Option<chrono::DateTime<chrono::Utc>>,
155 }
156
157 /// License or usage constraints.
158 #[derive(Debug, Clone, Serialize, Deserialize)]
159 pub struct License {
160 /// License name
161 pub name: String,
162 /// License URL
163 pub url: Option<String>,
164 }
165}