Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions nemo/src/io/format_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use nemo_physical::{
resource::{Resource, ResourceBuilder, ResourceValidationError},
tabular::filters::FilterTransformPattern,
};
use oxiri::{Iri, IriRef};
use strum::IntoEnumIterator;

use crate::{
Expand Down Expand Up @@ -47,7 +48,12 @@ pub(crate) trait FormatParameter<Tag>:
FromStr<Err = ()> + Debug + ToString + IntoEnumIterator + Copy + Eq + Hash
{
fn required_for(&self, tag: Tag) -> bool;
fn is_value_valid(&self, value: AnyDataValue) -> Result<(), ValidationError>;
fn is_value_valid(
&self,
value: AnyDataValue,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Result<(), ValidationError>;
}

pub(super) fn value_type_matches(
Expand Down Expand Up @@ -234,7 +240,12 @@ impl<Tag> FormatParameter<Tag> for StandardParameter {
false
}

fn is_value_valid(&self, value: AnyDataValue) -> Result<(), ValidationError> {
fn is_value_valid(
&self,
value: AnyDataValue,
_base: Option<Iri<String>>,
_prefixes: HashMap<String, IriRef<String>>,
) -> Result<(), ValidationError> {
value_type_matches(self, &value, self.supported_types())?;

match self {
Expand Down Expand Up @@ -269,6 +280,8 @@ pub(crate) trait FormatBuilder: Debug + Sized + Into<AnyImportExportBuilder> {
tag: Self::Tag,
parameters: &Parameters<Self>,
direction: Direction,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Result<Self, ValidationError>;

fn expected_arity(&self) -> Option<usize>;
Expand Down Expand Up @@ -357,6 +370,8 @@ impl<B: FormatBuilder> Parameters<B> {
_filter_rules: &[Rule],
direction: Direction,
report: &mut ValidationReport,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Option<Self> {
let Ok(format_tag) = B::Tag::from_str(spec.format().name()) else {
report.add(
Expand Down Expand Up @@ -420,7 +435,9 @@ impl<B: FormatBuilder> Parameters<B> {
}
};

if let Err(error) = parameter.is_value_valid(value.clone()) {
if let Err(error) =
parameter.is_value_valid(value.clone(), base.clone(), prefixes.clone())
{
report.add(value_term, error);
has_errors = true;
continue;
Expand Down Expand Up @@ -513,10 +530,20 @@ impl ImportExportBuilder {
filter_rules: &[Rule],
direction: Direction,
report: &mut ValidationReport,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Option<ImportExportBuilder> {
let origin = spec.origin();
let parameters =
Parameters::<B>::validate(predicate, spec, bindings, filter_rules, direction, report)?;
let parameters = Parameters::<B>::validate(
predicate,
spec,
bindings,
filter_rules,
direction,
report,
base.clone(),
prefixes.clone(),
)?;
Comment on lines +537 to +546
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be factored into one or possible several (that'd make it easier to reuse them elsewhere) structs. We can discuss the details in person tomorrow.


let resource_builder =
if let Some(value) = parameters.get_optional(StandardParameter::Resource.into()) {
Expand All @@ -538,7 +565,7 @@ impl ImportExportBuilder {
})
.unwrap_or_else(|| CompressionFormat::from_resource_builder(&resource_builder));

let inner = match B::new(tag, &parameters, direction) {
let inner = match B::new(tag, &parameters, direction, base.clone(), prefixes.clone()) {
Ok(b) => b,
Err(error) => {
report.add_source(origin.clone(), error);
Expand Down Expand Up @@ -629,6 +656,8 @@ impl ImportExportBuilder {
filter_rules: &[Rule],
direction: Direction,
report: &mut ValidationReport,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Option<Self> {
let format_tag = spec.format().name().to_owned();
let Ok(tag) = format_tag.parse::<SupportedFormatTag>() else {
Expand All @@ -651,6 +680,8 @@ impl ImportExportBuilder {
filter_rules,
direction,
report,
base,
prefixes,
),
SupportedFormatTag::Rdf(tag) => Self::new_with_tag::<RdfHandler>(
predicate,
Expand All @@ -660,6 +691,8 @@ impl ImportExportBuilder {
filter_rules,
direction,
report,
base,
prefixes,
),
SupportedFormatTag::Json(tag) => Self::new_with_tag::<JsonHandler>(
predicate,
Expand All @@ -669,6 +702,8 @@ impl ImportExportBuilder {
filter_rules,
direction,
report,
base,
prefixes,
),
SupportedFormatTag::Sparql(tag) => Self::new_with_tag::<SparqlBuilder>(
predicate,
Expand All @@ -678,6 +713,8 @@ impl ImportExportBuilder {
filter_rules,
direction,
report,
base,
prefixes,
),
}
}
Expand Down
15 changes: 12 additions & 3 deletions nemo/src/io/formats/dsv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod value_format;
pub(crate) mod writer;

use std::{
collections::HashMap,
io::{BufReader, Read, Write},
sync::Arc,
};
Expand All @@ -14,6 +15,7 @@ use nemo_physical::{
datavalues::{AnyDataValue, DataValue},
tabular::filters::FilterTransformPattern,
};
use oxiri::{Iri, IriRef};
use reader::DsvReader;
use strum_macros::EnumIter;
use value_format::DsvValueFormats;
Expand Down Expand Up @@ -178,12 +180,17 @@ impl FormatParameter<DsvTag> for DsvParameter {
}
}

fn is_value_valid(&self, value: AnyDataValue) -> Result<(), ValidationError> {
fn is_value_valid(
&self,
value: AnyDataValue,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
Comment on lines +186 to +187
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, but we would want to consider moving these into a FormatContext (or something like that) struct if we ever add more parameters

) -> Result<(), ValidationError> {
value_type_matches(self, &value, self.supported_types())?;

match self {
DsvParameter::BaseParamType(base) => {
FormatParameter::<DsvTag>::is_value_valid(base, value)
DsvParameter::BaseParamType(base_param) => {
FormatParameter::<DsvTag>::is_value_valid(base_param, value, base, prefixes)
}
DsvParameter::Limit => value
.to_u64()
Expand Down Expand Up @@ -238,6 +245,8 @@ impl FormatBuilder for DsvBuilder {
tag: Self::Tag,
parameters: &Parameters<DsvBuilder>,
_direction: Direction,
_base: Option<Iri<String>>,
_prefixes: HashMap<String, IriRef<String>>,
) -> Result<Self, ValidationError> {
let value_formats = parameters.get_optional(DsvParameter::Format).map(|value| {
DsvValueFormats::try_from(value).expect("value formats have already been validated")
Expand Down
5 changes: 4 additions & 1 deletion nemo/src/io/formats/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

pub(crate) mod reader;

use std::{io::Read, sync::Arc};
use std::{collections::HashMap, io::Read, sync::Arc};

use nemo_physical::{
datasources::table_providers::TableProvider, tabular::filters::FilterTransformPattern,
};
use oxiri::{Iri, IriRef};
use reader::JsonReader;

use crate::{
Expand Down Expand Up @@ -71,6 +72,8 @@ impl FormatBuilder for JsonHandler {
_tag: Self::Tag,
_parameters: &Parameters<Self>,
direction: Direction,
_base: Option<Iri<String>>,
_prefixes: HashMap<String, IriRef<String>>,
) -> Result<Self, ValidationError> {
if matches!(direction, Direction::Export) {
return Err(ValidationError::UnsupportedJsonExport);
Expand Down
16 changes: 12 additions & 4 deletions nemo/src/io/formats/rdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub(crate) mod value_format;
pub(crate) mod writer;

use std::{
collections::HashMap,
io::{Read, Write},
sync::Arc,
};
Expand All @@ -19,7 +20,7 @@ use nemo_physical::{
tabular::filters::FilterTransformPattern,
};

use oxiri::Iri;
use oxiri::{Iri, IriRef};
use reader::RdfReader;
use strum::VariantArray;
use strum_macros::VariantArray;
Expand Down Expand Up @@ -187,12 +188,17 @@ impl FormatParameter<RdfTag> for RdfParameter {
)
}

fn is_value_valid(&self, value: AnyDataValue) -> Result<(), ValidationError> {
fn is_value_valid(
&self,
value: AnyDataValue,
base: Option<Iri<String>>,
prefixes: HashMap<String, IriRef<String>>,
) -> Result<(), ValidationError> {
value_type_matches(self, &value, self.supported_types())?;

match self {
RdfParameter::BaseParamType(base) => {
FormatParameter::<RdfTag>::is_value_valid(base, value)
RdfParameter::BaseParamType(base_param) => {
FormatParameter::<RdfTag>::is_value_valid(base_param, value, base, prefixes)
}
RdfParameter::Limit => value
.to_u64()
Expand Down Expand Up @@ -222,6 +228,8 @@ impl FormatBuilder for RdfHandler {
tag: Self::Tag,
parameters: &Parameters<RdfHandler>,
_direction: Direction,
_base: Option<Iri<String>>,
_prefixes: HashMap<String, IriRef<String>>,
) -> Result<Self, ValidationError> {
let variant = match tag {
RdfTag::Rdf => {
Expand Down
Loading
Loading