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 >>>> >>> >> >