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