use crate::pid::PID;
use crate::validation::{is_license, rules, validate_agent_identifier, IntoValidationReport, Validate, ValidationReport};
use acorn_core::prelude::alloc::{String, Vec};
use bon::Builder;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_trim::{option_string_trim, string_trim};
use serde_with::skip_serializing_none;
use strum::EnumIs;
#[derive(Clone, Debug, Deserialize, EnumIs, Eq, JsonSchema, PartialEq, Serialize)]
pub enum ActivityDateType {
StartDate,
EndDate,
Created,
Updated,
Issued,
Coverage,
Accepted,
Available,
Collected,
Copyrighted,
Submitted,
Valid,
Withdrawn,
Other,
}
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum RelatedResourceCategory {
Sponsors,
Partners,
Related,
}
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum RightsAccess {
Open,
Embargoed,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct ActivityContributor {
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub name: String,
#[validate(nested)]
#[builder(default)]
pub identifiers: Vec<AgentIdentifier>,
#[validate(nested)]
#[builder(default)]
pub affiliations: Vec<TypedIdentifier>,
#[validate(nested)]
#[builder(default)]
pub roles: Vec<DatedAgentRole>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct ActivityOrganization {
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub name: String,
#[validate(nested)]
#[builder(default)]
pub identifiers: Vec<TypedIdentifier>,
#[validate(nested)]
#[builder(default)]
pub roles: Vec<DatedOrganizationRole>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
#[validate(schema(function = "validate_agent_identifier", skip_on_field_errors = false))]
pub struct AgentIdentifier {
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub value: String,
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme_uri: Option<String>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct ControlledSubject {
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub subject: String,
#[serde(default, deserialize_with = "option_string_trim")]
pub subject_scheme: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme_uri: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub value_uri: Option<String>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct DatedAgentRole {
#[validate(nested)]
pub agent: AgentIdentifier,
#[serde(default, deserialize_with = "option_string_trim")]
pub role: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub role_scheme_uri: Option<String>,
#[validate(timestamp)]
#[serde(default, deserialize_with = "option_string_trim")]
pub start_date: Option<String>,
#[validate(timestamp)]
#[serde(default, deserialize_with = "option_string_trim")]
pub end_date: Option<String>,
pub contact: Option<bool>,
pub leader: Option<bool>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct DatedOrganizationRole {
#[validate(nested)]
pub organization: TypedIdentifier,
#[serde(default, deserialize_with = "option_string_trim")]
pub role: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub role_scheme_uri: Option<String>,
#[validate(timestamp)]
#[serde(default, deserialize_with = "option_string_trim")]
pub start_date: Option<String>,
#[validate(timestamp)]
#[serde(default, deserialize_with = "option_string_trim")]
pub end_date: Option<String>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct StructuredRights {
#[serde(default, deserialize_with = "option_string_trim")]
pub rights: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub rights_uri: Option<String>,
#[validate(custom(function = "is_license"))]
#[serde(default, deserialize_with = "option_string_trim")]
pub rights_identifier: Option<String>,
#[serde(default, deserialize_with = "option_string_trim")]
pub rights_identifier_scheme: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme_uri: Option<String>,
pub access: Option<RightsAccess>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct TypedActivityDate {
pub date_type: ActivityDateType,
#[validate(timestamp)]
#[serde(deserialize_with = "string_trim")]
pub date: String,
#[serde(default, deserialize_with = "option_string_trim")]
pub information: Option<String>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
#[validate(schema(function = "TypedIdentifier::is_valid", skip_on_field_errors = false))]
pub struct TypedIdentifier {
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub value: String,
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme: Option<String>,
#[validate(url)]
#[serde(default, deserialize_with = "option_string_trim")]
pub scheme_uri: Option<String>,
}
#[skip_serializing_none]
#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
#[builder(start_fn = init, on(String, into))]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct TypedRelatedResource {
#[validate(nested)]
pub identifier: TypedIdentifier,
#[validate(nonempty)]
#[serde(deserialize_with = "string_trim")]
pub relation_type: String,
#[serde(default, deserialize_with = "option_string_trim")]
pub relation_type_information: Option<String>,
#[serde(default, deserialize_with = "option_string_trim")]
pub resource_type_general: Option<String>,
pub category: Option<RelatedResourceCategory>,
}
impl TypedIdentifier {
pub(crate) fn is_valid(&self, _context: &()) -> Result<(), ValidationReport> {
match self.scheme.as_deref().map(PID::from) {
| Some(PID::RRID) => rules::rrid(&self.value).map_err(|error| error.into_report("value")),
| _ => Ok(()),
}
}
}