This thread got me thinking -- couldn't we have reusable,
dereferenceable SPARQL optimizations/rewrites as SPARQL CONSTRUCTs
over SPIN RDF? Which would be mappings between the original syntax
tree and the optimized syntax tree.

On Mon, Feb 1, 2016 at 8:55 PM, Carlo.Allocca <carlo.allo...@open.ac.uk> wrote:
> Dear Andy, Lorenz and All,
>
> Thank you very much for your help and support.
> I would like to share the first achievement based on your suggestions.
>
> I have implemented
>
> 1) public Element transform(ElementPathBlock eltPB)
> 2) public Element transform(ElementGroup arg0, List<Element> arg1)
>
> running it over a number of example queries I obtain the expected results.
> For example, for the input query
>
>         String qString6 = "prefix 
> rdfs:<http://www.w3.org/2000/01/rdf-schema#> "
>                 + "prefix ex:<http://www.semanticweb.org/dataset1/> "
>                 + "prefix rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#> "
>                 + " SELECT DISTINCT ?ind ?boss ?g where "
>                 + "{ "
>                 + " {?ind rdf:type ?z. } "
>                     + "UNION "
>                     + " {"
>                             + " { ?boss ex:isBossOf1 ?ind .}"
>                             + " UNION {?boss ex:isBossOf ?ind ."
>                             + " Filter(?boss=\"mathieu\") }"
>                        + "}"
>                 + "}";
>
> when removing the triple (?boss ex:isBossOf ?ind .”), I get
>
> SELECT DISTINCT  ?ind ?boss ?g
> WHERE
>   {   { ?ind  rdf:type  ?z }
>     UNION
>       {   { ?boss  ex:isBossOf1  ?ind }
>         UNION
>           { # Empty BGP
>
>           }
>       }
>   }
>
> which is OK.
> I just need to find out how to remove an ElementGroup which contains only one 
> element which is the EMPTY one.
> Of course, I need to do the same for the other case, e.g. OPTION, SUBquery, 
> etc.
>
> Many Thanks for your help one again.
> Best Regards,
> Carlo
>
>
>
> == Here the code
>
>
>     @Override
>     public Element transform(ElementPathBlock eltPB) {
>         if (eltPB.isEmpty()) {
>             
> System.out.println("[RemoveOpTransform::transform(ElementPathBlock arg0)] 
> ElementPathBlock IS EMPTY:: " + eltPB.toString());
>             return eltPB;
>         }
>         System.out.println("[RemoveOpTransform::transform(ElementPathBlock 
> arg0)] ElementPathBlock:: " + eltPB.toString());
>         Iterator<TriplePath> l = eltPB.patternElts();
>         while (l.hasNext()) {
>             TriplePath tp = l.next();
>             if (tp.asTriple().matches(this.triple)) {
>                 l.remove();
>                 
> System.out.println("[RemoveOpTransform::transform(ElementPathBlock arg0)] 
> ElementPathBlock:: " + tp.toString()+" TRIPLE JUST REMOVED!!!");
>                 
> //System.out.println("[RemoveOpTransform::transform(ElementPathBlock arg0)] 
> TRIPLE JUST REMOVED!!! ");
>                 System.out.println("");
>                 return this.transform(eltPB);//eltPB;
>             }
>         }
>         return eltPB;
>     }
>
>
>     @Override
>     public Element transform(ElementGroup arg0, List<Element> arg1) {
>         //ElementGroup arg0New = new ElementGroup();
>
>         List<Element> elemList = arg0.getElements();
>         Iterator<Element> itr = elemList.iterator();
>         while (itr.hasNext()) {
>             Element elem = itr.next();
>             if (elem instanceof ElementGroup) {
> //                if(((ElementGroup) elem).isEmpty()){
>                                 
> System.out.println("[RemoveOpTransform::visit(ElementGroup arg0)] 
> ElementGroup IS EMPTY!!! " +((ElementGroup) elem).toString());
>                                 
> System.out.println("[RemoveOpTransform::visit(ElementGroup arg0)] 
> List<Element>  arg1 IS EMPTY!!! " +arg1.toString());
> //                }
>             }
>
>             if (elem instanceof ElementFilter) {
>                 //... check if this filter is the one that we should remove
>                 //...get the variables of the triple pattern that we want to 
> delete
>                 Set<Var> tpVars = new HashSet();
>                 Node subj = this.triple.getSubject();
>                 if (subj.isVariable()) {
>                     tpVars.add((Var) subj);
>                 }
>                 Node pred = this.triple.getPredicate();
>                 if (pred.isVariable()) {
>                     tpVars.add((Var) pred);
>                 }
>                 Node obj = this.triple.getObject();
>                 if (obj.isVariable()) {
>                     tpVars.add((Var) obj);
>                 }
>                 //...get the variables of the FILTER expression
>                 Set<Var> expVars = ((ElementFilter) 
> elem).getExpr().getVarsMentioned();
>                 //...check whether the FILTER expression contains any of the 
> triple pattern variable
>                 for (Var var : expVars) {
>                     //..if it does then we have to delete the entire FILTER 
> expression
>                     if (tpVars.contains(var)) {
>                         
> System.out.println("[RemoveOpTransform::visit(ElementGroup arg0)] THE 
> "+((ElementFilter) elem).toString() +"IS GOING TO BE REMOVED!!!");
>                         //Expr e = new NodeValueBoolean(true);
>                         //ElementFilter newFilter = new ElementFilter(e);
>                         itr.remove();
>                         return this.transform(arg0, arg1);
>                     }
>                 }
>
>             }
>         }
> //        System.out.println("[RemoveOpTransform::transform(ElementGroup 
> arg0)] arg1 " + arg1.toString());
> //        System.out.println("");
>         //return arg0New;
>         return arg0;
>     }
>
>
>
>
>> On 31 Jan 2016, at 15:40, Carlo.Allocca <carlo.allo...@open.ac.uk> wrote:
>>
>> Dear Andy,
>>
>>
>>> On 31 Jan 2016, at 15:25, Andy Seaborne <a...@apache.org> wrote:
>>>
>>> Cleaning up is slightly easier in the syntax because BGPs and filters are 
>>> inside a group (nothing to do with GROUP - a syntax group is things between 
>>> {}.
>>>
>>> So when you want to delete something, have some custom Element class 
>>> 'ElementDeleteMe' to return from the ElementFilter or ElementPathBlock.  
>>> Something that can not appear in a legal query. it does not need to 
>>> implement anything.
>>>
>>> Then in
>>> transform(ElementGroup el, List<Element> members) ;
>>>
>>> rewrite 'members' to remove any ElementDeleteMe.
>>>
>>> if members.size == 0
>>>  return ElementDeleteMe
>>>
>>> so it recursive works.
>>>
>>> Take care at the top of syntax tree.
>>>
>> Thank you for the details.
>> It seems that I should be using org.apache.jena.sparql.syntax rather than 
>> org.apache.jena.sparql.algebra.
>> I will try to implement it as suggested above.
>>
>> Many Thanks,
>> Best Regards,
>> Carlo
>>
>>
>>>      Andy
>>>
>>> On 31/01/16 15:11, Carlo.Allocca wrote:
>>>> Hello Lorenz,
>>>>
>>>>
>>>> Sure no problem.
>>>> I can share it here. In case you have suggest any other place I will do so.
>>>>
>>>> Please, let me know.
>>>> Many Thanks,
>>>>
>>>> Best Regards,
>>>> Carlo
>>>>
>>>>> On 31 Jan 2016, at 15:07, Lorenz Bühmann 
>>>>> <buehm...@informatik.uni-leipzig.de> wrote:
>>>>>
>>>>> Hello Carlo,
>>>>>
>>>>> I'm sure you'll make it, but maybe you should also share the complete 
>>>>> code somehow? Maybe this makes it easier for people to help you.
>>>>>
>>>>> Lorenz
>>>>>
>>>>>> Hello Lorenz,
>>>>>>
>>>>>> Thank you very much for your help.
>>>>>> Some comments follow in line.
>>>>>>
>>>>>>
>>>>>>> On 31 Jan 2016, at 13:36, Lorenz Bühmann 
>>>>>>> <buehm...@informatik.uni-leipzig.de> wrote:
>>>>>>>
>>>>>>> Hello Carlo,
>>>>>>>
>>>>>>> there is usually no link from a child node to its parent in the JENA 
>>>>>>> data structures.
>>>>>> It is very good to confirm it as I don’t spend more time to look for it. 
>>>>>> I thought that I was missing some JENA data structure and packages.
>>>>>>
>>>>>>> That means you have to keep track of it when you're processing the 
>>>>>>> parents. Why not run some "clean up" after each child has been 
>>>>>>> processed? E.g. check if there is no BGP left and thus mark this 
>>>>>>> current parent as also "toBeRemoved”.
>>>>>> Sure. I have already started doing it by using some boolean variables. 
>>>>>> Let’s see if I can make it.
>>>>>> Otherwise I have to develop a module that transform the Jena Query 
>>>>>> Expression into a Tree based representation and then apply the triple 
>>>>>> remove operation.
>>>>>>
>>>>>> Thank you again for your support and answers.
>>>>>>
>>>>>> Best Regards,
>>>>>> Carlo
>>>>>>
>>>>>>> Lorenz
>>>>>>>
>>>>>>>> and of course, the below is for processing an BGP:
>>>>>>>>
>>>>>>>>    @Override
>>>>>>>>    public Op transform(OpBGP opBGP) {
>>>>>>>>
>>>>>>>>        System.out.println("[TransformRemoveOp::transform(OpBGP opBGP)] 
>>>>>>>> opBGPCounter " + opBGPCounter++);
>>>>>>>>        System.out.println("[TransformRemoveOp::transform(OpBGP opBGP)] 
>>>>>>>> " + opBGP.toString());
>>>>>>>>        System.out.println("");
>>>>>>>>        Op newOpBGP = opBGP.copy();
>>>>>>>>        BasicPattern newBP = ((OpBGP) newOpBGP).getPattern();
>>>>>>>>        List<Triple> tripleList = newBP.getList();
>>>>>>>>
>>>>>>>>        Iterator<Triple> itr = tripleList.iterator();
>>>>>>>>        while (itr.hasNext()) {
>>>>>>>>            Triple tp = itr.next();
>>>>>>>>            if (tp.matches(this.triple)) {
>>>>>>>>                itr.remove();
>>>>>>>>                isParent = true;
>>>>>>>>                isStarted = true;
>>>>>>>>            }
>>>>>>>>        }
>>>>>>>>        //...it can be empty
>>>>>>>>        if (((OpBGP) newOpBGP).getPattern().getList().isEmpty()) {
>>>>>>>>            System.out.println("[TransformRemoveOp::transform(OpBGP 
>>>>>>>> opBGP)] opBGP is empty " + opBGP.toString());
>>>>>>>>            //return subOp;
>>>>>>>>        }
>>>>>>>>        return newOpBGP;
>>>>>>>>    }
>>>>>>>>
>>>>>>>>
>>>>>>>> Many Thanks,
>>>>>>>> Carlo.
>>>>>>>>
>>>>>>>>
>>>>>>>>> On 31 Jan 2016, at 04:36, Carlo.Allocca <carlo.allo...@open.ac.uk> 
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Dear Andy,
>>>>>>>>>
>>>>>>>>> Thank you very much one more time.
>>>>>>>>>
>>>>>>>>> Please, some comments follow in line.
>>>>>>>>>
>>>>>>>>> On 30 Jan 2016, at 17:53, Andy Seaborne 
>>>>>>>>> <a...@apache.org<mailto:a...@apache.org>> wrote:
>>>>>>>>>
>>>>>>>>> On 30/01/16 15:52, Carlo.Allocca wrote:
>>>>>>>>> Hello Lorenz,
>>>>>>>>>
>>>>>>>>> Thank you for your help.
>>>>>>>>>
>>>>>>>>> It was clear to me that I have to remove from the parent expression 
>>>>>>>>> and such is that using a patter-based approach
>>>>>>>>> make it a bit difficult. I tried three of them and I got to the same 
>>>>>>>>> results.
>>>>>>>>>
>>>>>>>>> You need to process the parent, not just the ElementFilter.
>>>>>>>>>
>>>>>>>>> How can I process the parent?
>>>>>>>>> My understanding is:
>>>>>>>>>
>>>>>>>>> 1. Building the Abstract Query Tree:  Op op = Algebra.compile(q);
>>>>>>>>>
>>>>>>>>> For example, given the query
>>>>>>>>>
>>>>>>>>> PREFIX  rdfs: <http://www.w3.org/2000/01/rdf-schema#>
>>>>>>>>> PREFIX  ex:   <http://www.semanticweb.org/dataset1/>
>>>>>>>>> PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
>>>>>>>>>
>>>>>>>>> SELECT DISTINCT  ?ind ?boss ?g
>>>>>>>>> WHERE
>>>>>>>>> {   { ?ind  rdf:type  ?z }
>>>>>>>>>   UNION
>>>>>>>>>     { ?boss  ex:isBossOf  ?ind
>>>>>>>>>       FILTER ( ?boss = "mathieu" )
>>>>>>>>>     }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> I obtain
>>>>>>>>>
>>>>>>>>> (distinct
>>>>>>>>> (project (?ind ?boss ?g)
>>>>>>>>>   (union
>>>>>>>>>     (bgp (triple ?ind 
>>>>>>>>> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?z))
>>>>>>>>>     (filter (= ?boss "mathieu")
>>>>>>>>>       (bgp (triple ?boss 
>>>>>>>>> <http://www.semanticweb.org/dataset1/isBossOf> ?ind))))))
>>>>>>>>>
>>>>>>>>> 2) Travere the tree to modify its internal structure. In terms of 
>>>>>>>>> code, I can write:
>>>>>>>>>
>>>>>>>>>    (A)   Transform transform = new TransformRemoveOp(q,tp) ;
>>>>>>>>>    (B)  op = Transformer.transform(transform, op);
>>>>>>>>>
>>>>>>>>> where TransformRemoveOp implements Transform interface.
>>>>>>>>> It seems that there is no link between children  and parent that can 
>>>>>>>>> be used to figure out at which level  the process is and modify the 
>>>>>>>>> Tree structure, accordingly. Please correct me if I am wrong.
>>>>>>>>> In fact running it over the above example, I got the following:
>>>>>>>>>
>>>>>>>>> =========== DURING
>>>>>>>>> [TransformRemoveOp::transform(OpBGP opBGP)] opBGPCounter 1
>>>>>>>>> [TransformRemoveOp::transform(OpBGP opBGP)] (bgp (triple ?ind 
>>>>>>>>> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?z))
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpBGP opBGP)] opBGPCounter 2
>>>>>>>>> [TransformRemoveOp::transform(OpBGP opBGP)] (bgp (triple ?boss 
>>>>>>>>> <http://www.semanticweb.org/dataset1/isBossOf> ?ind))
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpBGP opBGP)] opBGP is empty (bgp
>>>>>>>>> )
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpFilter opFilter, Op subOp)] opFilter 
>>>>>>>>> (filter (= ?boss "mathieu")
>>>>>>>>> (bgp
>>>>>>>>> ))
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpFilter opFilter, Op subOp)] subOp 
>>>>>>>>> Name bgp
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpUnion opUnion, Op left, Op right)] 
>>>>>>>>> left: (bgp (triple ?ind 
>>>>>>>>> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?z))
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpUnion opUnion, Op left, Op right)] 
>>>>>>>>> right: (filter (exprlist (= ?boss "mathieu") true)
>>>>>>>>> (bgp
>>>>>>>>> ))
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpProject opProject, Op subOp)] 
>>>>>>>>> (project (?ind ?boss ?g)
>>>>>>>>> (union
>>>>>>>>>   (bgp (triple ?ind <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> 
>>>>>>>>> ?z))
>>>>>>>>>   (filter (exprlist (= ?boss "mathieu") true)
>>>>>>>>>     (bgp
>>>>>>>>>     ))))
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> [TransformRemoveOp::transform(OpDistinct opDistinct, Op subOp)] 
>>>>>>>>> (distinct
>>>>>>>>> (project (?ind ?boss ?g)
>>>>>>>>>   (union
>>>>>>>>>     (bgp (triple ?ind 
>>>>>>>>> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?z))
>>>>>>>>>     (filter (exprlist (= ?boss "mathieu") true)
>>>>>>>>>       (bgp
>>>>>>>>>       )))))
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Moreover, implementing a first version of the OpFilter as reported 
>>>>>>>>> below:
>>>>>>>>>
>>>>>>>>>   @Override
>>>>>>>>>   public Op transform(OpFilter opFilter, Op subOp) {
>>>>>>>>>       System.out.println("[TransformRemoveOp::transform(OpFilter 
>>>>>>>>> opFilter, Op subOp)] opFilter " + opFilter.toString());
>>>>>>>>>       System.out.println("[TransformRemoveOp::transform(OpFilter 
>>>>>>>>> opFilter, Op subOp)] subOp Name " + subOp.getName());
>>>>>>>>>       System.out.println("");
>>>>>>>>>
>>>>>>>>>       if (isParent == false) {
>>>>>>>>>           return opFilter;
>>>>>>>>>       }
>>>>>>>>>
>>>>>>>>>       //...get the variables of the triple pattern that we want to 
>>>>>>>>> delete
>>>>>>>>>       Set<Var> tpVars = new HashSet();
>>>>>>>>>       Node subj = this.triple.getSubject();
>>>>>>>>>       if (subj.isVariable()) {
>>>>>>>>>           tpVars.add((Var) subj);
>>>>>>>>>       }
>>>>>>>>>       Node pred = this.triple.getPredicate();
>>>>>>>>>       if (pred.isVariable()) {
>>>>>>>>>           tpVars.add((Var) pred);
>>>>>>>>>       }
>>>>>>>>>       Node obj = this.triple.getObject();
>>>>>>>>>       if (obj.isVariable()) {
>>>>>>>>>           tpVars.add((Var) obj);
>>>>>>>>>       }
>>>>>>>>>       //...get the variables of the FILTER expression
>>>>>>>>>       Op opNew = opFilter.copy(subOp);
>>>>>>>>>       Set<Var> expVars = ((OpFilter) 
>>>>>>>>> opNew).getExprs().getVarsMentioned();
>>>>>>>>>
>>>>>>>>>       //...check whether the FILTER expression contains any of the 
>>>>>>>>> triple pattern variable
>>>>>>>>>       boolean isContained = false;
>>>>>>>>>       for (Var var : expVars) {
>>>>>>>>>           //..if it does then we have to delete the entire FILTER 
>>>>>>>>> expression
>>>>>>>>>           if (tpVars.contains(var)) {
>>>>>>>>>               isContained = true;
>>>>>>>>>               break;
>>>>>>>>>           }
>>>>>>>>>       }
>>>>>>>>>       //... if the filter contains any variable of the triple that 
>>>>>>>>> has been removed, then....
>>>>>>>>>       if (isContained) {
>>>>>>>>>           Op newOP;
>>>>>>>>>           Expr e;
>>>>>>>>>           if (subOp instanceof OpBGP) {
>>>>>>>>>               if (((OpBGP) subOp).getPattern().getList().isEmpty()) {
>>>>>>>>>                   e = new NodeValueBoolean(true);
>>>>>>>>>                   newOP = OpFilter.filter(e, opFilter);//filter(e, );
>>>>>>>>>                   return newOP;
>>>>>>>>>               } else {
>>>>>>>>>                   e = new NodeValueBoolean(false);
>>>>>>>>>                   newOP = OpFilter.filter(e, opFilter);//filter(e, );
>>>>>>>>>                   return newOP;
>>>>>>>>>               }
>>>>>>>>>           }
>>>>>>>>>       }
>>>>>>>>>       return opFilter;
>>>>>>>>>   }
>>>>>>>>>
>>>>>>>>> It produces the following SPARQL query:
>>>>>>>>>
>>>>>>>>> SELECT DISTINCT  ?ind ?boss ?g
>>>>>>>>> WHERE
>>>>>>>>> {   { ?ind  a                     ?z }
>>>>>>>>>   UNION
>>>>>>>>>     { # Empty BGP
>>>>>>>>>
>>>>>>>>>       FILTER ( ?boss = "mathieu" )
>>>>>>>>>       FILTER ( true )
>>>>>>>>>     }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> It seems quite challenging even transform the expression of  "?boss = 
>>>>>>>>> “mathieu” into “true” (as reported above) does not work as It should.
>>>>>>>>>
>>>>>>>>> If anyone could help me who is more experienced with this kind of 
>>>>>>>>> task, I would be very very grateful.
>>>>>>>>> I would like to see something concrete in sense of line of code as I 
>>>>>>>>> am using.
>>>>>>>>>
>>>>>>>>> Many Thanks,
>>>>>>>>> Best Regards,
>>>>>>>>> Carlo
>>>>>>>>> On 30 Jan 2016, at 17:53, Andy Seaborne 
>>>>>>>>> <a...@apache.org<mailto:a...@apache.org>> wrote:
>>>>>>>>>
>>>>>>>>> element has active parts
>>>>>>>>>
>>>>>>>>> -- The Open University is incorporated by Royal Charter (RC 000391), 
>>>>>>>>> an exempt charity in England & Wales and a charity registered in 
>>>>>>>>> Scotland (SC 038302). The Open University is authorised and regulated 
>>>>>>>>> by the Financial Conduct Authority.
>>>>>>>>
>>>>>>> --
>>>>>>> Lorenz Bühmann
>>>>>>> AKSW group, University of Leipzig
>>>>>>> Group: http://aksw.org - semantic web research center
>>>>>>>
>>>>>>
>>>>>>
>>>>> --
>>>>> Lorenz Bühmann
>>>>> AKSW group, University of Leipzig
>>>>> Group: http://aksw.org - semantic web research center
>>>>>
>>>>
>>>
>>
>

Reply via email to