You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jena.apache.org by Claude Warren <cl...@xenei.com> on 2013/09/21 11:08:08 UTC

Contract test issue: Returning the model.

There are several methods listed in the Model and ModelCon interfaces that
return the model for chaining purposes.

I want to test that the model is returned.

Assuming the a method call:

Model m = // create a model
Model m2 = m.f(x)

I believe the requirement is for
m2 == m to be true

A similar requirement is for items created on the model be "of" the model
(not necessarily in the model).  For example ModelCon.createStatement(
Resource, Property, String ) should return a statement such that

Model m = // create model
Statement s = m.createStatement( Resource, Property, String )
should return a statement such that the statement is not in the model
(m.contains(s) == false) but is of the model (s.getModel() == m)

The question is should the second test be s.getModel() == m or
s.getModel().equals(m)?  There is one case getAlt()
Model m = // create model;
Alt a = m.getAlt( Resource );

where both a.getModel() == m  and a.getMode().equals(m) are false.  However
a.getModel.isIsomorphicWith( m ) is true.

I believe that in both cases the correct tests should be
m2 == m
and
x.getModel() == m

Comments?

Claude

-- 
I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren

Re: Modularization

Posted by Andy Seaborne <an...@apache.org>.
On 21/09/13 18:55, Andy Seaborne wrote:
>
>>> Digression:
>>>
>>> Is this the right time to split the Model-API (APIs?) from the core
>>> graph-level machinery into a separate module?
>
>
>> (I don't understand this
>> question).  Are you saying you would like to see all the interfaces and
>> helper classes in a module and the memory implementation in another?
>> Do we
>> want to do this?  If not, what do you mean?
>>
>> Claude
>
> I was wondering if modularizing along the lines of a (new) core with
> graph-level, including the GraphMem implementation.  More modules, with
> a pure interface module is also possible but you can't test much without
> an implementation and complete mocking is a lot of work, so why not use
> one memory implementation as the functional reference impl?
>
> The split then might be (and I haven't tried):
>
> c.h.h.j.graph
> c.h.h.j.mem
> c.h.h.j.datatypes
>
> and
>
> c.h.h.j.rdf
> c.h.h.j.ontology
> c.h.h.j.enhanced
>
> (and maybe ARP+xmloutput in their own module)
>
> I'm sure there is entanglement and I'm guessing it's not trivial in
> places - I know there is around AnonIds, which I think should be kept in
> the RDF API (compatibility) but de-emphasised/deprecated from the Graph
> SPI).
>
> The RDF API is not something that seems to be an extension point.  The
> API/SPI design allows multiple APIs in different styles.  I'd love to
> see an idiomatic scala API over graph/triple/node.  Or clojure.  Or a
> new Java one (for example , targetting Java8).
>
> So, if that is desirable, how do we make it clean, clear and easy to do
> that?  One step is being clear-cut about the current RDF API.

Looks a lot cleaner than I feared - the graph-level code just seems to 
have a couple of non-trivial connections to the Model level:

1/ AnonId in a few places
2/ (datatype) XMLLiteral checking uses ARP
3/ Some util code in the wrong paxckages for a split (i.e. class Util)

and c.h.h.j.reasoner goes into jena-rdf-api

	Andy



Re: Modularization

Posted by Claude Warren <cl...@xenei.com>.
I think that if we build a complete set of Contract tests we will have the
ability to test the correctness of implementations.  I agree that many of
the tests (as currently written) are difficult to write without an
implementation.  I also agree that the memory based implementation makes a
good reference implementation.  That is what I have been using while
building the Contract tests (I'll make another checking shortly).



On Sat, Sep 21, 2013 at 6:55 PM, Andy Seaborne <an...@apache.org> wrote:

>
>  Digression:
>>>
>>> Is this the right time to split the Model-API (APIs?) from the core
>>> graph-level machinery into a separate module?
>>>
>>
>
>  (I don't understand this
>> question).  Are you saying you would like to see all the interfaces and
>> helper classes in a module and the memory implementation in another?  Do
>> we
>> want to do this?  If not, what do you mean?
>>
>> Claude
>>
>
> I was wondering if modularizing along the lines of a (new) core with
> graph-level, including the GraphMem implementation.  More modules, with a
> pure interface module is also possible but you can't test much without an
> implementation and complete mocking is a lot of work, so why not use one
> memory implementation as the functional reference impl?
>
> The split then might be (and I haven't tried):
>
> c.h.h.j.graph
> c.h.h.j.mem
> c.h.h.j.datatypes
>
> and
>
> c.h.h.j.rdf
> c.h.h.j.ontology
> c.h.h.j.enhanced
>
> (and maybe ARP+xmloutput in their own module)
>
> I'm sure there is entanglement and I'm guessing it's not trivial in places
> - I know there is around AnonIds, which I think should be kept in the RDF
> API (compatibility) but de-emphasised/deprecated from the Graph SPI).
>
> The RDF API is not something that seems to be an extension point.  The
> API/SPI design allows multiple APIs in different styles.  I'd love to see
> an idiomatic scala API over graph/triple/node.  Or clojure.  Or a new Java
> one (for example , targetting Java8).
>
> So, if that is desirable, how do we make it clean, clear and easy to do
> that?  One step is being clear-cut about the current RDF API.
>
>         Andy
>
>


-- 
I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren

Modularization

Posted by Andy Seaborne <an...@apache.org>.
>> Digression:
>>
>> Is this the right time to split the Model-API (APIs?) from the core
>> graph-level machinery into a separate module?


> (I don't understand this
> question).  Are you saying you would like to see all the interfaces and
> helper classes in a module and the memory implementation in another?  Do we
> want to do this?  If not, what do you mean?
>
> Claude

I was wondering if modularizing along the lines of a (new) core with 
graph-level, including the GraphMem implementation.  More modules, with 
a pure interface module is also possible but you can't test much without 
an implementation and complete mocking is a lot of work, so why not use 
one memory implementation as the functional reference impl?

The split then might be (and I haven't tried):

c.h.h.j.graph
c.h.h.j.mem
c.h.h.j.datatypes

and

c.h.h.j.rdf
c.h.h.j.ontology
c.h.h.j.enhanced

(and maybe ARP+xmloutput in their own module)

I'm sure there is entanglement and I'm guessing it's not trivial in 
places - I know there is around AnonIds, which I think should be kept in 
the RDF API (compatibility) but de-emphasised/deprecated from the Graph 
SPI).

The RDF API is not something that seems to be an extension point.  The 
API/SPI design allows multiple APIs in different styles.  I'd love to 
see an idiomatic scala API over graph/triple/node.  Or clojure.  Or a 
new Java one (for example , targetting Java8).

So, if that is desirable, how do we make it clean, clear and easy to do 
that?  One step is being clear-cut about the current RDF API.

	Andy


Re: Contract test issue: Returning the model.

Posted by Claude Warren <cl...@xenei.com>.
A second set of issues is that methods like model.getBag() return resources
that do not return true for the isX() methods if the resource was not
already in the model.

Bag b = model.getBag( "foo")

expect

b.isBag() == true

but get

b.isBag() == false


This also applies to getAlt() and getSeq().

This does not apply if the resource exists in the graph (e.g. createBag()
was called)

I suspect that the problem is that the statement <foo, RDF.type, RDF.Bag>
is not in the model so isBag() returns false.  I don't know how to fix this
other than to make getBag() and createBag() the same method.

As a side note. The only way I can find to tell that the bag is not in the
graph is to call getBag() and then check that the isBag() method returns
false.

I also note that calling bag.add(false) does not add the <bag, RDF.type,
RDF.Bag> to the model.



On Sat, Sep 21, 2013 at 3:42 PM, Claude Warren <cl...@xenei.com> wrote:

> After a bit more work.... I have the following
>
> Resource r = resource of model 1 ( a memory model)
> Model m2 = model 2 (an empty defaultModel)
>
> Bag bag = m2.getBag( r );
>
> bag.getModel() returns model 1
>
> Looks like getAlt(), getSeq() and getResource() seem to act the same way.
>
> I suspect that those implementations should call inModel() to ensure that
> the model is correct.
>
> Digression:
>
> Is this the right time to split the Model-API (APIs?) from the core
> graph-level machinery into a separate module?  (I don't understand this
> question).  Are you saying you would like to see all the interfaces and
> helper classes in a module and the memory implementation in another?  Do we
> want to do this?  If not, what do you mean?
>
> Claude
>
>
>
> On Sat, Sep 21, 2013 at 2:51 PM, Andy Seaborne <an...@apache.org> wrote:
>
>> On 21/09/13 10:08, Claude Warren wrote:
>>
>>> There are several methods listed in the Model and ModelCon interfaces
>>> that
>>> return the model for chaining purposes.
>>>
>>> I want to test that the model is returned.
>>>
>>> Assuming the a method call:
>>>
>>> Model m = // create a model
>>> Model m2 = m.f(x)
>>>
>>> I believe the requirement is for
>>> m2 == m to be true
>>>
>>
>> Same here - if the contract is also:
>>
>> m.f1() ;
>> m.f2() ;
>> m.f3() ;
>>
>> has the same effect as m.f1().f2().f3() then i don't see theer is mouch
>> choice other than m2==m.
>>
>>
>>
>>> A similar requirement is for items created on the model be "of" the model
>>> (not necessarily in the model).  For example ModelCon.createStatement(
>>> Resource, Property, String ) should return a statement such that
>>>
>>> Model m = // create model
>>> Statement s = m.createStatement( Resource, Property, String )
>>> should return a statement such that the statement is not in the model
>>> (m.contains(s) == false) but is of the model (s.getModel() == m)
>>>
>>> The question is should the second test be s.getModel() == m or
>>> s.getModel().equals(m)?
>>>
>>
>> Isn't Model.equals same as == anyway?  As model can be large, it seems to
>> me there isn't much choice from a practicality standpoint.
>>
>>
>>   There is one case getAlt()
>>> Model m = // create model;
>>> Alt a = m.getAlt( Resource );
>>>
>>> where both a.getModel() == m  and a.getMode().equals(m) are false.
>>>  However
>>> a.getModel.isIsomorphicWith( m ) is true.
>>>
>>> I believe that in both cases the correct tests should be
>>> m2 == m
>>> and
>>> x.getModel() == m
>>>
>>> Comments?
>>>
>>
>> Weird - where in the code base is a different model being created?
>>
>> And is method-chaining broken?
>>
>> m.getAlt(...).add(...)
>>   vs
>> m.getAlt(...)
>> m.add(...)
>>
>>
>>> Claude
>>>
>>>
>> Digression:
>>
>> Is this the right time to split the Model-API (APIs?) from the core
>> graph-level machinery into a separate module?
>>
>>         Andy
>>
>>
>
>
> --
> I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
> LinkedIn: http://www.linkedin.com/in/claudewarren
>



-- 
I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren

Re: Contract test issue: Returning the model.

Posted by Claude Warren <cl...@xenei.com>.
After a bit more work.... I have the following

Resource r = resource of model 1 ( a memory model)
Model m2 = model 2 (an empty defaultModel)

Bag bag = m2.getBag( r );

bag.getModel() returns model 1

Looks like getAlt(), getSeq() and getResource() seem to act the same way.

I suspect that those implementations should call inModel() to ensure that
the model is correct.

Digression:

Is this the right time to split the Model-API (APIs?) from the core
graph-level machinery into a separate module?  (I don't understand this
question).  Are you saying you would like to see all the interfaces and
helper classes in a module and the memory implementation in another?  Do we
want to do this?  If not, what do you mean?

Claude



On Sat, Sep 21, 2013 at 2:51 PM, Andy Seaborne <an...@apache.org> wrote:

> On 21/09/13 10:08, Claude Warren wrote:
>
>> There are several methods listed in the Model and ModelCon interfaces that
>> return the model for chaining purposes.
>>
>> I want to test that the model is returned.
>>
>> Assuming the a method call:
>>
>> Model m = // create a model
>> Model m2 = m.f(x)
>>
>> I believe the requirement is for
>> m2 == m to be true
>>
>
> Same here - if the contract is also:
>
> m.f1() ;
> m.f2() ;
> m.f3() ;
>
> has the same effect as m.f1().f2().f3() then i don't see theer is mouch
> choice other than m2==m.
>
>
>
>> A similar requirement is for items created on the model be "of" the model
>> (not necessarily in the model).  For example ModelCon.createStatement(
>> Resource, Property, String ) should return a statement such that
>>
>> Model m = // create model
>> Statement s = m.createStatement( Resource, Property, String )
>> should return a statement such that the statement is not in the model
>> (m.contains(s) == false) but is of the model (s.getModel() == m)
>>
>> The question is should the second test be s.getModel() == m or
>> s.getModel().equals(m)?
>>
>
> Isn't Model.equals same as == anyway?  As model can be large, it seems to
> me there isn't much choice from a practicality standpoint.
>
>
>   There is one case getAlt()
>> Model m = // create model;
>> Alt a = m.getAlt( Resource );
>>
>> where both a.getModel() == m  and a.getMode().equals(m) are false.
>>  However
>> a.getModel.isIsomorphicWith( m ) is true.
>>
>> I believe that in both cases the correct tests should be
>> m2 == m
>> and
>> x.getModel() == m
>>
>> Comments?
>>
>
> Weird - where in the code base is a different model being created?
>
> And is method-chaining broken?
>
> m.getAlt(...).add(...)
>   vs
> m.getAlt(...)
> m.add(...)
>
>
>> Claude
>>
>>
> Digression:
>
> Is this the right time to split the Model-API (APIs?) from the core
> graph-level machinery into a separate module?
>
>         Andy
>
>


-- 
I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren

Re: Contract test issue: Returning the model.

Posted by Andy Seaborne <an...@apache.org>.
On 21/09/13 10:08, Claude Warren wrote:
> There are several methods listed in the Model and ModelCon interfaces that
> return the model for chaining purposes.
>
> I want to test that the model is returned.
>
> Assuming the a method call:
>
> Model m = // create a model
> Model m2 = m.f(x)
>
> I believe the requirement is for
> m2 == m to be true

Same here - if the contract is also:

m.f1() ;
m.f2() ;
m.f3() ;

has the same effect as m.f1().f2().f3() then i don't see theer is mouch 
choice other than m2==m.

>
> A similar requirement is for items created on the model be "of" the model
> (not necessarily in the model).  For example ModelCon.createStatement(
> Resource, Property, String ) should return a statement such that
>
> Model m = // create model
> Statement s = m.createStatement( Resource, Property, String )
> should return a statement such that the statement is not in the model
> (m.contains(s) == false) but is of the model (s.getModel() == m)
>
> The question is should the second test be s.getModel() == m or
> s.getModel().equals(m)?

Isn't Model.equals same as == anyway?  As model can be large, it seems 
to me there isn't much choice from a practicality standpoint.

>  There is one case getAlt()
> Model m = // create model;
> Alt a = m.getAlt( Resource );
>
> where both a.getModel() == m  and a.getMode().equals(m) are false.  However
> a.getModel.isIsomorphicWith( m ) is true.
>
> I believe that in both cases the correct tests should be
> m2 == m
> and
> x.getModel() == m
>
> Comments?

Weird - where in the code base is a different model being created?

And is method-chaining broken?

m.getAlt(...).add(...)
   vs
m.getAlt(...)
m.add(...)

>
> Claude
>

Digression:

Is this the right time to split the Model-API (APIs?) from the core 
graph-level machinery into a separate module?

	Andy


Re: Contract test issue: Returning the model.

Posted by Claude Warren <cl...@xenei.com>.
The minimal example is a degenerate case of a different bug.

if
Model m = a newly constructed model;
Model m2 = a new constructed model;
Resource r = a resource "of" m2 (e.g. r.getModel() == m2)

then
Alt a = m.getAlt( r );

a.getModel() != m
a.getModel().equals( m ) == false
a.isIsomorphicWith( m ) == true (because both are empty)
a.getModel() == m2 <---- I think this is wrong.

I am going to open a couple of bugs now that I have complete tests for them

Claude


On Sun, Sep 22, 2013 at 11:17 AM, Chris_Dollin <eh...@gmail.com> wrote:

> On Saturday, September 21, 2013 10:08:08 AM Claude Warren wrote:
> > There are several methods listed in the Model and ModelCon interfaces
> that
> > return the model for chaining purposes.
> >
> > I want to test that the model is returned.
> >
> > Assuming the a method call:
> >
> > Model m = // create a model
> > Model m2 = m.f(x)
> >
> > I believe the requirement is for
> > m2 == m to be true
>
> Yes, that's how we've interpreted since ... gosh, pre Jena 2!
>
> > A similar requirement is for items created on the model be "of" the model
> > (not necessarily in the model).
>
> Yes: the RDFNode should refer to that model but need not appear
> in any Statements of the model. Of course it's just layering over
> Node.
>
> > The question is should the second test be s.getModel() == m or
> > s.getModel().equals(m)?
>
> The Model's .equals() is the default Object.equals(), ie identity, ie ==.
> The existence of bnodes means that testing two models for structural
> equality is fragile and while I remember wondering at the time of
> Jena 2 whether .equals() should call isIsomorphicTo that would have been
> rather expensive.
>
> > There is one case getAlt()
> > Model m = // create model;
> > Alt a = m.getAlt( Resource );
> >
> > where both a.getModel() == m  and a.getMode().equals(m) are false.
>  However
> > a.getModel.isIsomorphicWith( m ) is true.
>
> Hmm. Could you show a minimal complete example? A quick look
> at the code doesn't suggest anything but I could be looking in the wrong
> place.
>
> Chris
>



-- 
I like: Like Like - The likeliest place on the web<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren

Re: Contract test issue: Returning the model.

Posted by Chris_Dollin <eh...@gmail.com>.
On Saturday, September 21, 2013 10:08:08 AM Claude Warren wrote:
> There are several methods listed in the Model and ModelCon interfaces that
> return the model for chaining purposes.
> 
> I want to test that the model is returned.
> 
> Assuming the a method call:
> 
> Model m = // create a model
> Model m2 = m.f(x)
> 
> I believe the requirement is for
> m2 == m to be true

Yes, that's how we've interpreted since ... gosh, pre Jena 2!

> A similar requirement is for items created on the model be "of" the model
> (not necessarily in the model). 

Yes: the RDFNode should refer to that model but need not appear
in any Statements of the model. Of course it's just layering over
Node. 

> The question is should the second test be s.getModel() == m or
> s.getModel().equals(m)?  

The Model's .equals() is the default Object.equals(), ie identity, ie ==.
The existence of bnodes means that testing two models for structural
equality is fragile and while I remember wondering at the time of
Jena 2 whether .equals() should call isIsomorphicTo that would have been
rather expensive.

> There is one case getAlt()
> Model m = // create model;
> Alt a = m.getAlt( Resource );
> 
> where both a.getModel() == m  and a.getMode().equals(m) are false.  However
> a.getModel.isIsomorphicWith( m ) is true.

Hmm. Could you show a minimal complete example? A quick look
at the code doesn't suggest anything but I could be looking in the wrong
place.

Chris