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