Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filippodebortoli/feature/foriri deref #101

Closed
wants to merge 4 commits into from
Closed
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
4 changes: 3 additions & 1 deletion src/io/owx/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,9 @@ pub mod test {
} = cl
{
assert!(match dr {
DataRange::Datatype(dt) => dt.is_s(OWL2Datatype::Literal.as_ref()),
DataRange::Datatype(dt) => {
dt.is(&OWL2Datatype::Literal)
}
_ => false,
});
} else {
Expand Down
190 changes: 165 additions & 25 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,17 @@ pub struct IRI<A>(pub(crate) A);
/// The `ForIRI` is a trait that that provides the bounds for the
/// majority of methods in Horned_OWL.
pub trait ForIRI:
AsRef<str> + Borrow<str> + Clone + Debug + Eq + From<String> + Hash + PartialEq + Ord + PartialOrd
AsRef<str>
+ Borrow<str>
+ Clone
+ Debug
+ Deref<Target = str>
+ Eq
+ From<String>
+ Hash
+ PartialEq
+ Ord
+ PartialOrd
{
}

Expand All @@ -135,6 +145,7 @@ impl<T: ?Sized> ForIRI for T where
+ Borrow<str>
+ Clone
+ Debug
+ Deref<Target = str>
+ Eq
+ From<String>
+ Hash
Expand All @@ -159,13 +170,13 @@ impl<A: ForIRI> Deref for IRI<A> {
type Target = str;

fn deref(&self) -> &Self::Target {
self.0.borrow()
self.0.deref()
}
}

impl<A: ForIRI> AsRef<str> for IRI<A> {
fn as_ref(&self) -> &str {
self.0.borrow()
self.0.as_ref()
}
}

Expand Down Expand Up @@ -205,6 +216,51 @@ impl<A: ForIRI> Display for IRI<A> {
}
}

impl<A: ForIRI> IRI<A> {
/// Compare this IRI to another
///
/// Return true if two IRIs are lexically identical.
///
/// IRIs can more simply be compared through equality
/// (==). However, these must by type identical IRIs, where as
/// this method can compare more widely.
///
/// # Example
/// ```
/// # use horned_owl::model::Build;
/// let b_rc = Build::new_rc();
/// let b_arc = Build::new_arc();
///
/// // Equality works
/// assert_eq!(b_rc.iri("http://example.com"), b_rc.iri("http://example.com"));
///
/// // But this comparison cannot be with equality
/// assert!(b_rc.iri("http://example.com").is(&b_arc.iri("http://example.com")));
/// ```
///
/// Use `is_as` to compare to strings
pub fn is<O: ForIRI>(&self, other: &IRI<O>) -> bool {
**self == **other
}

/// Compare this IRI to a String
///
/// Return true if the IRI is lexically identical to the String
///
/// #Example
/// ```
/// # use horned_owl::model::Build;
/// let b = Build::new_rc();
///
/// assert!(b.iri("http://example.com").is_as("http://example.com"));
/// ```
///
/// Use `is` to compare to another IRI
pub fn is_as<S: AsRef<str>>(&self, other: S) -> bool {
**self == *other.as_ref()
}
}

/// `Build` creates new `IRI` and `NamedEntity` instances.
///
/// There is caching for performance. An `IRI` or `NamedEntity` with a
Expand Down Expand Up @@ -542,19 +598,71 @@ macro_rules! named {
}
}

impl<A: ForIRI> Deref for $name<A> {

type Target = IRI<A>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

namedenumimpl!($name, NamedEntity, NamedEntityKind);

impl<A:ForIRI> $name<A> {
pub fn is<I>(&self, iri: I) -> bool
where I:Into<IRI<A>>

/// Compare this named entity to another
///
/// Return true if two entities have IRIs which are lexically identical.
///
/// $name can more simply be compared through equality
/// (==). However, these must by type identical named entity, where as
/// this method can compare more widely.
///
/// # Example
/// ```
/// # use horned_owl::model::Build;
/// let build = Build::new_rc();
/// let iri = build.iri("http://www.example.com");
/// let class = build.class(iri.clone());
/// let individual = build.named_individual(iri.clone());
///
/// // Named entities can use equality
/// assert_eq!(class, class);
///
/// // Or this method more widely
/// assert!(class.is(&class));
/// assert!(class.is(&iri));
/// assert!(class.is(&individual));
/// assert!(!class.is(&crate::horned_owl::vocab::OWL::Class));
/// ```
pub fn is<O: ForIRI>(&self, other: &IRI<O>) -> bool
{
self.0 == iri.into()
IRI::<A>::is(self, other)
}

pub fn is_s<S>(&self, iri:S) -> bool
where S:Into<String>
/// Compare this named entity to string
///
/// Return true if this entity have an IRI which is lexically identical to the string.
///
/// # Example
/// ```
/// # use horned_owl::model::Build;
/// let build = Build::new_rc();
/// let class = build.class("http://www.example.com");
///
/// assert!(class.is_as("http://www.example.com"));
/// assert!(!class.is_as("http://www.example.com/not"));
///
/// // We can also use is_as with deref semantics, but
/// // use `is` instead
/// assert!(class.is_as(&*class));
/// ```
///
/// Use `is` to compare $name to other named entities, or IRIs
pub fn is_as<S:AsRef<str>>(&self, other: S) -> bool
{
self.0.0.borrow() == iri.into()
IRI::<A>::is_as(self, other)
}

}
Expand Down Expand Up @@ -681,14 +789,14 @@ impl NamedEntityKind {
}

impl<A: ForIRI> Class<A> {
/// Return true if Class is OWL:Thing
/// Checks if this class entity is `owl:Thing`.
pub fn is_thing(&self) -> bool {
self.0.as_ref() == crate::vocab::OWL::Thing.as_ref()
self.is(&crate::vocab::OWL::Thing)
}

/// Return true if Class is OWL::Nothing
/// Checks if this class entity is `owl:Nothing`.
pub fn is_nothing(&self) -> bool {
self.0.as_ref() == crate::vocab::OWL::Nothing.as_ref()
self.is(&crate::vocab::OWL::Nothing)
}
}

Expand All @@ -700,7 +808,7 @@ impl<A: ForIRI> Deref for AnonymousIndividual<A> {
type Target = str;

fn deref(&self) -> &Self::Target {
self.0.borrow()
self.0.deref()
}
}

Expand All @@ -712,13 +820,13 @@ impl<A: ForIRI> AnonymousIndividual<A> {

impl<A: ForIRI> AsRef<str> for AnonymousIndividual<A> {
fn as_ref(&self) -> &str {
self.0.borrow()
self.0.as_ref()
}
}

impl<A: ForIRI> Borrow<str> for AnonymousIndividual<A> {
fn borrow(&self) -> &str {
self.as_ref()
self.0.borrow()
}
}

Expand All @@ -740,7 +848,7 @@ impl<A: ForIRI> Deref for Individual<A> {

fn deref(&self) -> &Self::Target {
match self {
Individual::Named(ni) => &ni.0,
Individual::Named(ni) => ni,
Individual::Anonymous(ai) => ai,
}
}
Expand Down Expand Up @@ -2057,7 +2165,7 @@ mod test {
let iri_from_iri = build.iri(iri_static.clone());

let s = "http://www.example.com";
let iri_str = build.iri(&s[..]);
let iri_str = build.iri(s);

assert_eq!(iri_string, iri_static);
assert_eq!(iri_string, iri_str);
Expand Down Expand Up @@ -2104,18 +2212,50 @@ mod test {
let s = String::from("http://www.example.com");
let c = Build::new_rc().class(s.clone());

assert!(c.is_s(s));
assert!(c.is_as(&s));
}

#[test]
fn test_is() {
let c = Build::new_rc().class("http://www.example.com");
let i = Build::new().named_individual("http://www.example.com");
let iri = Build::new().iri("http://www.example.com");
let i = Build::new_string().named_individual("http://www.example.com");
let iri = Build::new_arc().iri("http://www.example.com");

// Does is work with different A's
assert!(c.is(&iri));
assert!(c.is(&i));
assert!(i.is(&c));
}

#[test]
fn test_is_as() {
let build = Build::new_rc();

let iri = build.iri("http://www.example.com");
let class = build.class(iri.clone());
let individual = build.named_individual(iri.clone());

// Class comparision with equals
assert_eq!(class, class);

// We can compare IRI to IRI
assert!(iri.is(&iri));
// We can compare Class to IRI
assert!(class.is(&iri));

// We can compare class or individual to each other through Deref semantics
assert!(class.is(&class));
assert!(class.is(&individual));

// Or to vocab, again through deref semantics
assert!(!class.is(&crate::vocab::OWL::Class));

// We can compare to strings
assert!(class.is_as("http://www.example.com"));
assert!(!class.is_as("http://www.fred.com"));

assert!(c.is(iri));
assert!(c.is(i.clone()));
assert!(i.is(c));
// Or other classes if we deref a bit
assert!(class.is_as(&*class));
}

#[test]
Expand Down Expand Up @@ -2152,7 +2292,7 @@ mod test {
assert_eq!(decl1, decl2);

decl1.ann.insert(ann);
assert!(!(decl1 == decl2));
assert!(decl1 != decl2);
}

#[test]
Expand Down
6 changes: 6 additions & 0 deletions src/vocab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ macro_rules! vocabulary_traits {
}
}

impl AsRef<str> for $enum_type {
fn as_ref(&self) -> &str {
self.meta().as_ref()
}
}

impl Borrow<str> for $enum_type {
fn borrow(&self) -> &str {
self.meta().as_ref()
Expand Down
Loading