From 0b0b42e2a1fc13c94f0c8721f083aeb01b198bf7 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Mon, 27 Jun 2022 00:21:03 +0200 Subject: [PATCH] Add :auto_fix for :case_validation option on defvocab --- CHANGELOG.md | 6 ++++-- .../vocabulary/namespace/case_validation.ex | 11 ++++++++++ .../namespace/vocabulary_namespace_test.exs | 21 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b1979..341f335 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,10 @@ The generated namespaces are much more flexible now and compile faster. - `RDF.IRI.starts_with?/2` and `RDF.IRI.ends_with?/2` - `RDF.Graph.build/2` now supports the creation of ad-hoc vocabulary namespaces with a `@prefix` declaration providing the URI of the namespace as a string -- the `case_violations` option of `defvocab` now supports custom handler functions, - either as an inline function or as a function on a separate module +- The `case_violations` option of `defvocab` now supports an `:auto_fix` option + which adapts the first letter of violating term accordingly. It also supports + custom handler functions, either as an inline function or as a function on a + separate module. ### Changed diff --git a/lib/rdf/vocabulary/namespace/case_validation.ex b/lib/rdf/vocabulary/namespace/case_validation.ex index fc601fa..1e78c06 100644 --- a/lib/rdf/vocabulary/namespace/case_validation.ex +++ b/lib/rdf/vocabulary/namespace/case_validation.ex @@ -145,6 +145,10 @@ defmodule RDF.Vocabulary.Namespace.CaseValidation do terms_and_ignored end + defp do_handle_case_violations(terms_and_ignored, violation_groups, :auto_fix, base_iri) do + do_handle_case_violations(terms_and_ignored, violation_groups, &auto_fix_term/2, base_iri) + end + defp do_handle_case_violations(terms_and_ignored, violation_groups, fun, base_iri) when is_function(fun) do {alias_violations, term_violations} = @@ -209,4 +213,11 @@ defmodule RDF.Vocabulary.Namespace.CaseValidation do defp case_violation_warning(:lowercased_alias, term, _, _) do IO.warn("lowercased alias '#{term}' for a non-property resource") end + + defp auto_fix_term(:property, term) do + {first, rest} = String.next_grapheme(term) + {:ok, String.downcase(first) <> rest} + end + + defp auto_fix_term(:resource, term), do: {:ok, :string.titlecase(term)} end diff --git a/test/unit/vocabulary/namespace/vocabulary_namespace_test.exs b/test/unit/vocabulary/namespace/vocabulary_namespace_test.exs index ddba37f..04ee6fc 100644 --- a/test/unit/vocabulary/namespace/vocabulary_namespace_test.exs +++ b/test/unit/vocabulary/namespace/vocabulary_namespace_test.exs @@ -139,6 +139,18 @@ defmodule RDF.Vocabulary.NamespaceTest do base_iri: "http://example.com/ex#", terms: [foo: "bar", baz: "bar", Foo: "Bar", Baz: "Bar"] + defvocab ExampleWithAutoFixedCaseViolations, + base_iri: "http://example.com/ex#", + case_violations: :auto_fix, + data: + RDF.Graph.new([ + {~I, RDF.type(), RDF.Property}, + {~I, RDF.type(), RDF.Property}, + {~I, RDF.type(), RDFS.Resource}, + {~I, RDF.type(), RDFS.Resource} + ]), + alias: [BaazAlias: :baazTest] + defvocab ExampleWithCustomInlineCaseViolationFunction, base_iri: "http://example.com/ex#", case_violations: fn @@ -799,6 +811,15 @@ defmodule RDF.Vocabulary.NamespaceTest do end end + test "auto_fix case violations" do + alias TestNS.ExampleWithAutoFixedCaseViolations, as: Example + + assert Example.fooTest() == RDF.iri(Example.__base_iri__() <> "FooTest") + assert Example.barTest() == RDF.iri(Example.__base_iri__() <> "barTest") + assert RDF.iri(Example.BazTest) == RDF.iri(Example.__base_iri__() <> "bazTest") + assert RDF.iri(Example.BaazAlias) == RDF.iri(Example.__base_iri__() <> "baazTest") + end + test "case violation function (inline)" do alias TestNS.ExampleWithCustomInlineCaseViolationFunction, as: Example