You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by benjamin jailly <be...@gmail.com> on 2012/02/15 14:42:36 UTC
rdf:seq member's index and Jena rules
Hello everyone,
I'm trying to deal with rdf:seq and Jena Rules.
I want to test a condition on the member rdf:_(n) of the seq and do
something on the member rdf:_(n+1)
I thought I could write something like that:
(?seq rdf:_n ?X) (?seq rdf:_(n+1) ?Y) (?X my:condition 'true'^^xs:boolean)
-> (?Y my:literal 'true'^^xs:boolean)
I tried to work with rdfs:ContainerMembershipProperty
(?seq ?p ?X) (?p rdf:type rdfs:ContainerMembershipProperty)
but I didn't manage to get the index of the member.
Should I use regex on rdf:_ ?
I'm using the RDFSCMPPreprocessHook.
Thanks for your help
br,
Benjamin
Re: rdf:seq member's index and Jena rules
Posted by benjamin jailly <be...@gmail.com>.
ok, this is resolved if I write my rule this way:
(?Z ?m ?X) (?Z ?n ?Y) (?n rdf:type rdfs:ContainerMembershipProperty) (?m
rdf:type rdfs:ContainerMembershipProperty) (?Z rdf:type rdf:Seq) (?X
my:condition 'true'^^xs:boolean) isNext(?Z, ?Y, ?X) -> (?Y my:parameter
'true'^^xs:boolean)
I had to specify that ?m and ?n are different properties of type
rdfs:ContainerMembershipProperty.
Now I am able to get the rdf:_(n) by parsing context.getEnv()and compare
values of n for different member of the seq
Thank you for your help.
Benjamin
On Thu, Feb 16, 2012 at 11:02 AM, benjamin jailly <benjamin.jailly@gmail.com
> wrote:
> I figured that the builtin isNext(?seq, ?X, ?Y) I'm creating is called
> only if X = Y. weird...
> In my test, my rdf:seq has 3 members. If I try to see what is inside the
> Environment:
>
> System.out.println("Context env: " + context.getEnv().toString());
>
> I obtain in the console:
>
> -5824a9a0:135858b0e5e:-7ffe rdf:_1 http://example.com/resA
> http://example.com/resA
> -5824a9a0:135858b0e5e:-7ffe rdf:_2 http://example.com/resB
> http://example.com/resB
> -5824a9a0:135858b0e5e:-7ffe rdf:_3 http://example.com/resC
> http://example.com/resC
>
> where I guess -5824a9a0:135858b0e5e:-7ffe is my rdf:seq.
>
> Is it a normal behaviour ?
>
> Benjamin
>
>
> On Thu, Feb 16, 2012 at 9:05 AM, Dave Reynolds <da...@gmail.com>wrote:
>
>> On 15/02/12 17:29, benjamin jailly wrote:
>>
>>> Thank you for your reply Dave.
>>>
>>> based on your advice, I'm trying to create a builtin in the form:
>>> isNext(?seq, ?X, ?Y) that returns true if Y is the element right after X
>>> in the rdf:seq seq.
>>>
>>>
>>> So I extended the BaseBuiltin class and wrote my functions like this :
>>>
>>> @Override
>>> public boolean bodyCall(Node[] args, int length, RuleContext
>>> context) {
>>> checkArgs(length, context);
>>> Node seq = getArg(0, args, context);
>>> Node n1 = getArg(1, args, context);
>>> Node n2 = getArg(2, args, context);
>>> return isNext(seq, n1, n2, context);
>>> }
>>> /**
>>> * Return true if element2 is right after element1 in the seq
>>> */
>>> protected static boolean isNext(Node node, Node element1, Node
>>> element2, RuleContext context ) {
>>> Model m = ModelFactory.**createDefaultModel();
>>> RDFNode seq = m.asRDFNode(node);
>>> RDFNode elt1 = m.asRDFNode(element1);
>>> RDFNode elt2 = m.asRDFNode(element2);
>>>
>>
>> Creating a new model for each call to the builtin is a little expensive,
>> better to just work at the Node level.
>>
>> if (seq == null || seq.equals(RDF.Nodes.nil) ||
>>> !seq.canAs(Seq.class) ) {
>>> m.close();
>>> return false;
>>> } else {
>>> // get indexes of elt1 and elt2
>>> int i1 = seq.as <http://seq.as>(Seq.class).**indexOf(elt1);
>>> int i2 = seq.as <http://seq.as>(Seq.class).**indexOf(elt2);
>>>
>>> System.out.println("res: " + i1 + "," + i2);
>>>
>>
>> That won't work because the new empty model in which those RDFNodes sits
>> has no statements in it to support the indexOf operations.
>>
>> It would be better to do the test by extracting the sequence number from
>> the URI of the Nodes.
>>
>> [Note that one of the many complications with Seq is that the sequence
>> numbers need not be contiguous. That doesn't affect your builtin and might
>> not affect your rules if you have control over the data but if you are
>> expecting to process data "from the wild" then it will be something to bear
>> in mind.]
>>
>> Dave
>>
>
>
Re: rdf:seq member's index and Jena rules
Posted by benjamin jailly <be...@gmail.com>.
I figured that the builtin isNext(?seq, ?X, ?Y) I'm creating is called only
if X = Y. weird...
In my test, my rdf:seq has 3 members. If I try to see what is inside the
Environment:
System.out.println("Context env: " + context.getEnv().toString());
I obtain in the console:
-5824a9a0:135858b0e5e:-7ffe rdf:_1 http://example.com/resA
http://example.com/resA
-5824a9a0:135858b0e5e:-7ffe rdf:_2 http://example.com/resB
http://example.com/resB
-5824a9a0:135858b0e5e:-7ffe rdf:_3 http://example.com/resC
http://example.com/resC
where I guess -5824a9a0:135858b0e5e:-7ffe is my rdf:seq.
Is it a normal behaviour ?
Benjamin
On Thu, Feb 16, 2012 at 9:05 AM, Dave Reynolds <da...@gmail.com>wrote:
> On 15/02/12 17:29, benjamin jailly wrote:
>
>> Thank you for your reply Dave.
>>
>> based on your advice, I'm trying to create a builtin in the form:
>> isNext(?seq, ?X, ?Y) that returns true if Y is the element right after X
>> in the rdf:seq seq.
>>
>>
>> So I extended the BaseBuiltin class and wrote my functions like this :
>>
>> @Override
>> public boolean bodyCall(Node[] args, int length, RuleContext context)
>> {
>> checkArgs(length, context);
>> Node seq = getArg(0, args, context);
>> Node n1 = getArg(1, args, context);
>> Node n2 = getArg(2, args, context);
>> return isNext(seq, n1, n2, context);
>> }
>> /**
>> * Return true if element2 is right after element1 in the seq
>> */
>> protected static boolean isNext(Node node, Node element1, Node
>> element2, RuleContext context ) {
>> Model m = ModelFactory.**createDefaultModel();
>> RDFNode seq = m.asRDFNode(node);
>> RDFNode elt1 = m.asRDFNode(element1);
>> RDFNode elt2 = m.asRDFNode(element2);
>>
>
> Creating a new model for each call to the builtin is a little expensive,
> better to just work at the Node level.
>
> if (seq == null || seq.equals(RDF.Nodes.nil) ||
>> !seq.canAs(Seq.class) ) {
>> m.close();
>> return false;
>> } else {
>> // get indexes of elt1 and elt2
>> int i1 = seq.as <http://seq.as>(Seq.class).**indexOf(elt1);
>> int i2 = seq.as <http://seq.as>(Seq.class).**indexOf(elt2);
>>
>> System.out.println("res: " + i1 + "," + i2);
>>
>
> That won't work because the new empty model in which those RDFNodes sits
> has no statements in it to support the indexOf operations.
>
> It would be better to do the test by extracting the sequence number from
> the URI of the Nodes.
>
> [Note that one of the many complications with Seq is that the sequence
> numbers need not be contiguous. That doesn't affect your builtin and might
> not affect your rules if you have control over the data but if you are
> expecting to process data "from the wild" then it will be something to bear
> in mind.]
>
> Dave
>
Re: rdf:seq member's index and Jena rules
Posted by Dave Reynolds <da...@gmail.com>.
On 15/02/12 17:29, benjamin jailly wrote:
> Thank you for your reply Dave.
>
> based on your advice, I'm trying to create a builtin in the form:
> isNext(?seq, ?X, ?Y) that returns true if Y is the element right after X
> in the rdf:seq seq.
>
>
> So I extended the BaseBuiltin class and wrote my functions like this :
>
> @Override
> public boolean bodyCall(Node[] args, int length, RuleContext context) {
> checkArgs(length, context);
> Node seq = getArg(0, args, context);
> Node n1 = getArg(1, args, context);
> Node n2 = getArg(2, args, context);
> return isNext(seq, n1, n2, context);
> }
> /**
> * Return true if element2 is right after element1 in the seq
> */
> protected static boolean isNext(Node node, Node element1, Node
> element2, RuleContext context ) {
> Model m = ModelFactory.createDefaultModel();
> RDFNode seq = m.asRDFNode(node);
> RDFNode elt1 = m.asRDFNode(element1);
> RDFNode elt2 = m.asRDFNode(element2);
Creating a new model for each call to the builtin is a little expensive,
better to just work at the Node level.
> if (seq == null || seq.equals(RDF.Nodes.nil) ||
> !seq.canAs(Seq.class) ) {
> m.close();
> return false;
> } else {
> // get indexes of elt1 and elt2
> int i1 = seq.as <http://seq.as>(Seq.class).indexOf(elt1);
> int i2 = seq.as <http://seq.as>(Seq.class).indexOf(elt2);
> System.out.println("res: " + i1 + "," + i2);
That won't work because the new empty model in which those RDFNodes sits
has no statements in it to support the indexOf operations.
It would be better to do the test by extracting the sequence number from
the URI of the Nodes.
[Note that one of the many complications with Seq is that the sequence
numbers need not be contiguous. That doesn't affect your builtin and
might not affect your rules if you have control over the data but if you
are expecting to process data "from the wild" then it will be something
to bear in mind.]
Dave
Re: rdf:seq member's index and Jena rules
Posted by benjamin jailly <be...@gmail.com>.
Thank you for your reply Dave.
based on your advice, I'm trying to create a builtin in the form:
isNext(?seq, ?X, ?Y) that returns true if Y is the element right after X in
the rdf:seq seq.
So I extended the BaseBuiltin class and wrote my functions like this :
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
Node seq = getArg(0, args, context);
Node n1 = getArg(1, args, context);
Node n2 = getArg(2, args, context);
return isNext(seq, n1, n2, context);
}
/**
* Return true if element2 is right after element1 in the seq
*/
protected static boolean isNext(Node node, Node element1, Node
element2, RuleContext context ) {
Model m = ModelFactory.createDefaultModel();
RDFNode seq = m.asRDFNode(node);
RDFNode elt1 = m.asRDFNode(element1);
RDFNode elt2 = m.asRDFNode(element2);
if (seq == null || seq.equals(RDF.Nodes.nil) ||
!seq.canAs(Seq.class) ) {
m.close();
return false;
} else {
// get indexes of elt1 and elt2
int i1 = seq.as(Seq.class).indexOf(elt1);
int i2 = seq.as(Seq.class).indexOf(elt2);
System.out.println("res: " + i1 + "," + i2);
if (i2 == (i1+1) && i1>0 && i2>0) {
m.close();
return true;
}
m.close();
return false;
}
}
but the console shows that i1 = i2 = 0...
I think the problem comes from the conversion between Node and RDFNode but
I'm not really sure about it.
any idea ?
thanks,
Benjamin
On Wed, Feb 15, 2012 at 3:30 PM, Dave Reynolds <da...@gmail.com>wrote:
> On 15/02/12 13:42, benjamin jailly wrote:
>
>> Hello everyone,
>>
>>
>> I'm trying to deal with rdf:seq and Jena Rules.
>> I want to test a condition on the member rdf:_(n) of the seq and do
>> something on the member rdf:_(n+1)
>>
>> I thought I could write something like that:
>>
>> (?seq rdf:_n ?X) (?seq rdf:_(n+1) ?Y) (?X my:condition
>> 'true'^^xs:boolean)
>> -> (?Y my:literal 'true'^^xs:boolean)
>>
>
> Nice idea! Sadly we don't support that right now.
>
>
> I tried to work with rdfs:**ContainerMembershipProperty
>> (?seq ?p ?X) (?p rdf:type rdfs:**ContainerMembershipProperty)
>>
>> but I didn't manage to get the index of the member.
>>
>
>
> Should I use regex on rdf:_ ?
>>
>
> Maybe, but probably will end up cleaner for you to create a custom builtin
> which can map between the rdf:_ URIs and the sequence number.
>
> Dave
>
Re: rdf:seq member's index and Jena rules
Posted by Dave Reynolds <da...@gmail.com>.
On 15/02/12 13:42, benjamin jailly wrote:
> Hello everyone,
>
>
> I'm trying to deal with rdf:seq and Jena Rules.
> I want to test a condition on the member rdf:_(n) of the seq and do
> something on the member rdf:_(n+1)
>
> I thought I could write something like that:
>
> (?seq rdf:_n ?X) (?seq rdf:_(n+1) ?Y) (?X my:condition 'true'^^xs:boolean)
> -> (?Y my:literal 'true'^^xs:boolean)
Nice idea! Sadly we don't support that right now.
> I tried to work with rdfs:ContainerMembershipProperty
> (?seq ?p ?X) (?p rdf:type rdfs:ContainerMembershipProperty)
>
> but I didn't manage to get the index of the member.
> Should I use regex on rdf:_ ?
Maybe, but probably will end up cleaner for you to create a custom
builtin which can map between the rdf:_ URIs and the sequence number.
Dave