You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2013/08/03 15:20:20 UTC

svn commit: r1509984 - /jena/Scratch/AFS/Jena-Dev/trunk/src/element/

Author: andy
Date: Sat Aug  3 13:20:20 2013
New Revision: 1509984

URL: http://svn.apache.org/r1509984
Log:
Rewrite query abstract syntax by transformation.

Added:
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransform.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformCopyBase.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformSubst.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformer.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/ExprTransformNodeElement.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/MainElt.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/NodeTransformSubst.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/QueryOps.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestQueryOps.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestSubstitution.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/TransEltLib.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/element/UpdateOps.java

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransform.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransform.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransform.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransform.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element;
+
+import java.util.List ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.syntax.* ;
+
+/** Transformation function on an Element
+ *  @see ElementTransformer
+ */
+public interface ElementTransform
+{
+    public Element transform(ElementTriplesBlock el) ;
+    public Element transform(ElementPathBlock el) ;
+    public Element transform(ElementFilter el, Expr expr2) ;
+    public Element transform(ElementAssign el, Var v, Expr expr2) ;
+    public Element transform(ElementBind el, Var v, Expr expr2) ;
+    public Element transform(ElementData el) ;
+    public Element transform(ElementUnion el, List<Element> elements) ;
+    public Element transform(ElementOptional el, Element opElt) ;
+    public Element transform(ElementGroup el, List<Element> members) ;
+    public Element transform(ElementDataset el, Element subElt) ;
+    public Element transform(ElementNamedGraph el, Node gn, Element subElt) ;
+    public Element transform(ElementExists el, Element subElt) ;
+    public Element transform(ElementNotExists el, Element subElt) ;
+    public Element transform(ElementMinus el, Element eltRHS) ;
+    public Element transform(ElementService el, Node service, Element subElt) ;
+    public Element transform(ElementSubQuery el, Query query) ;
+}
+

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformCopyBase.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformCopyBase.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformCopyBase.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformCopyBase.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.List ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.syntax.* ;
+
+/** Create a copy if the Element(s) below have chanaged */
+public class ElementTransformCopyBase implements ElementTransform {
+    // Note the use of == as object pointer equality.
+
+    @Override
+    public Element transform(ElementTriplesBlock el) {
+        return el ;
+    }
+
+    @Override
+    public Element transform(ElementPathBlock el) {
+        return el ;
+    }
+
+    @Override
+    public Element transform(ElementFilter el, Expr expr2) {
+        if ( el.getExpr() == expr2 )
+            return el ;
+        return new ElementFilter(expr2) ;
+    }
+
+    @Override
+    public Element transform(ElementAssign el, Var v, Expr expr2) {
+        if ( el.getVar() == v && el.getExpr() == expr2 )
+            return el ;
+        return new ElementAssign(v, expr2) ;
+    }
+
+    @Override
+    public Element transform(ElementBind el, Var v, Expr expr2) {
+        if ( el.getVar() == v && el.getExpr() == expr2 )
+            return el ;
+        return new ElementAssign(v, expr2) ;
+    }
+
+    @Override
+    public Element transform(ElementData el) {
+        return el ;
+    }
+
+    @Override
+    public Element transform(ElementUnion el, List<Element> elts) {
+        if ( el.getElements() == elts )
+            return el ;
+        ElementUnion el2 = new ElementUnion() ;
+        el2.getElements().addAll(elts) ;
+        return el2 ;
+    }
+
+    @Override
+    public Element transform(ElementOptional el, Element elt1) {
+        if ( el.getOptionalElement() == elt1 )
+            return el ;
+        return new ElementOptional(elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementGroup el, List<Element> elts) {
+        if ( el.getElements() == elts )
+            return el ;
+        ElementGroup el2 = new ElementGroup() ;
+        el2.getElements().addAll(elts) ;
+        return el2 ;
+    }
+
+    @Override
+    public Element transform(ElementDataset el, Element elt1) {
+        if ( el.getPatternElement() == elt1 )
+            return el ;
+        return new ElementDataset(el.getDataset(), elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementNamedGraph el, Node gn, Element elt1) {
+        if ( el.getGraphNameNode() == gn && el.getElement() == elt1 )
+            return el ;
+        return new ElementNamedGraph(gn, elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementExists el, Element elt1) {
+        if ( el.getElement() == elt1 )
+            return el ;
+        return new ElementExists(elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementNotExists el, Element elt1) {
+        if ( el.getElement() == elt1 )
+            return el ;
+        return new ElementNotExists(elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementMinus el, Element elt1) {
+        if ( el.getMinusElement() == elt1 )
+            return el ;
+        return new ElementMinus(elt1) ;
+    }
+
+    @Override
+    public Element transform(ElementService el, Node service, Element elt1) {
+        if ( el.getServiceNode() == service && el.getElement() == elt1 )
+            return el ;
+        return new ElementService(service, elt1, el.getSilent()) ;
+    }
+
+    @Override
+    public Element transform(ElementSubQuery el, Query query) {
+        if ( el.getQuery() == query )
+            return el ;
+        return new ElementSubQuery(query) ;
+    }
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformSubst.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformSubst.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformSubst.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformSubst.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.Map ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.TriplePath ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.syntax.Element ;
+import com.hp.hpl.jena.sparql.syntax.ElementPathBlock ;
+import com.hp.hpl.jena.sparql.syntax.ElementTriplesBlock ;
+
+public class ElementTransformSubst extends ElementTransformCopyBase {
+    // NodeTransform
+
+    private final NodeTransform nodeTransform ;
+
+    public ElementTransformSubst(Map<Var, Node> mapping) {
+        this.nodeTransform = new NodeTransformSubst(mapping) ;
+    }
+
+    @Override
+    public Element transform(ElementTriplesBlock el) {
+        ElementTriplesBlock etb = new ElementTriplesBlock() ;
+        boolean changed = false ;
+        for (Triple t : el.getPattern()) {
+            Triple t2 = transform(t) ;
+            changed = changed || t != t2 ;
+            etb.addTriple(t2) ;
+        }
+        if ( changed )
+            return etb ;
+        return el ;
+    }
+
+    @Override
+    public Element transform(ElementPathBlock el) {
+        ElementPathBlock epb = new ElementPathBlock() ;
+        boolean changed = false ;
+        for (TriplePath p : el.getPattern()) {
+            TriplePath p2 = transform(p) ;
+            changed = changed || p != p2 ;
+            epb.addTriplePath(p2) ;
+        }
+        if ( changed )
+            return epb ;
+        return el ;
+    }
+
+    private TriplePath transform(TriplePath path) {
+        Node s = path.getSubject() ;
+        Node s1 = transform(s) ;
+        Node o = path.getObject() ;
+        Node o1 = transform(o) ;
+
+        if ( path.isTriple() ) {
+            Node p = path.getPredicate() ;
+            Node p1 = transform(p) ;
+            if ( s == s1 && p == p1 && o == o1 )
+                return path ;
+            return new TriplePath(Triple.create(s1, p1, o1)) ;
+        }
+        if ( s == s1 && o == o1 )
+            return path ;
+        return new TriplePath(s1, path.getPath(), o1) ;
+    }
+
+    private Triple transform(Triple triple) {
+        Node s = triple.getSubject() ;
+        Node s1 = transform(s) ;
+        Node p = triple.getPredicate() ;
+        Node p1 = transform(p) ;
+        Node o = triple.getObject() ;
+        Node o1 = transform(o) ;
+
+        if ( s == s1 && p == p1 && o == o1 )
+            return triple ;
+        return Triple.create(s1, p1, o1) ;
+    }
+
+    private Node transform(Node n) {
+        return nodeTransform.convert(n) ;
+    }
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformer.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformer.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformer.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/ElementTransformer.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.ArrayDeque ;
+import java.util.Deque ;
+import java.util.List ;
+
+import org.apache.jena.atlas.logging.Log ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
+import com.hp.hpl.jena.sparql.expr.ExprTransform ;
+import com.hp.hpl.jena.sparql.expr.ExprTransformer ;
+import com.hp.hpl.jena.sparql.syntax.* ;
+
+/** A bottom-top application of a transformation of SPARQL syntax */
+public class ElementTransformer {
+    private static ElementTransformer singleton = new ElementTransformer() ;
+
+    /** Get the current transformer */
+    public static ElementTransformer get() {
+        return singleton ;
+    }
+
+    /** Set the current transformer - use with care */
+    public static void set(ElementTransformer value) {
+        ElementTransformer.singleton = value ;
+    }
+
+    /** Transform an algebra expression */
+    public static Element transform(Element element, ElementTransform transform) {
+        return transform(element, transform, null, null, null) ;
+    }
+
+    /** Transformation with specific ElementTransform and ExprTransform */
+    public static Element transform(Element element, ElementTransform transform, ExprTransform exprTransform) {
+        return get().transformation(element, transform, exprTransform, null, null) ;
+    }
+
+    public static Element transform(Element element, ElementTransform transform, ExprTransform exprTransform,
+                                    ElementVisitor beforeVisitor, ElementVisitor afterVisitor) {
+        return get().transformation(element, transform, exprTransform, beforeVisitor, afterVisitor) ;
+    }
+
+    // To allow subclassing this class, we use a singleton pattern
+    // and these protected methods.
+    protected Element transformation(Element element, ElementTransform transform, ExprTransform exprTransform,
+                                     ElementVisitor beforeVisitor, ElementVisitor afterVisitor) {
+        ApplyTransformVisitor v = new ApplyTransformVisitor(transform, exprTransform) ;
+        return transformation(v, element, beforeVisitor, afterVisitor) ;
+    }
+
+    protected Element transformation(ApplyTransformVisitor transformApply, Element element,
+                                     ElementVisitor beforeVisitor, ElementVisitor afterVisitor) {
+        if ( element == null ) {
+            Log.warn(this, "Attempt to transform a null element - ignored") ;
+            return element ;
+        }
+        return applyTransformation(transformApply, element, beforeVisitor, afterVisitor) ;
+    }
+
+    /** The primitive operation to apply a transformation to an Op */
+    protected Element applyTransformation(ApplyTransformVisitor transformApply, Element element,
+                                          ElementVisitor beforeVisitor, ElementVisitor afterVisitor) {
+        ElementWalker.walk(element, transformApply) ; // , beforeVisitor,
+                                                      // afterVisitor) ;
+        Element r = transformApply.result() ;
+        return r ;
+    }
+
+    protected ElementTransformer() {}
+
+    static class ApplyTransformVisitor implements ElementVisitor {
+        protected final ElementTransform transform ;
+        private final ExprTransform      exprTransform ;
+
+        private final Deque<Element>     stack = new ArrayDeque<Element>() ;
+
+        protected final Element pop() {
+            return stack.pop() ;
+        }
+
+        protected final void push(Element elt) {
+            stack.push(elt) ;
+        }
+
+        protected final void pushChanged(Element elt, Element elt2) {
+            if ( elt == elt2 )
+                stack.push(elt) ;
+            else
+                stack.push(elt2) ;
+        }
+
+        public ApplyTransformVisitor(ElementTransform transform, ExprTransform exprTransform) {
+            this.transform = transform ;
+            this.exprTransform = exprTransform ;
+        }
+
+        final Element result() {
+            if ( stack.size() != 1 )
+                Log.warn(this, "Stack is not aligned") ;
+            return pop() ;
+        }
+
+        @Override
+        public void visit(ElementTriplesBlock el) {
+            Element el2 = transform.transform(el) ;
+            pushChanged(el, el2) ;
+        }
+
+        @Override
+        public void visit(ElementPathBlock el) {
+            Element el2 = transform.transform(el) ;
+            pushChanged(el, el2) ;
+        }
+
+        @Override
+        public void visit(ElementFilter el) {
+            Expr expr = el.getExpr() ;
+            Expr expr2 = transform(expr, exprTransform) ;
+            Element el2 = transform.transform(el, expr2) ;
+            pushChanged(el, el2) ;
+        }
+
+        @Override
+        public void visit(ElementAssign el) {
+            Var v = el.getVar() ;
+            Var v1 = TransEltLib.applyVar(v, exprTransform) ;
+            Expr expr = el.getExpr() ;
+            Expr expr1 = ExprTransformer.transform(exprTransform, expr) ;
+            if ( v == v1 && expr == expr1 ) {
+                push(el) ;
+                return ;
+            }
+            push(new ElementAssign(v1, expr1)) ;
+        }
+
+        @Override
+        public void visit(ElementBind el) {
+            Var v = el.getVar() ;
+            Var v1 = TransEltLib.applyVar(v, exprTransform) ;
+            Expr expr = el.getExpr() ;
+            Expr expr1 = ExprTransformer.transform(exprTransform, expr) ;
+            if ( v == v1 && expr == expr1 ) {
+                push(el) ;
+                return ;
+            }
+            push(new ElementBind(v1, expr1)) ;
+        }
+
+        @Override
+        public void visit(ElementData el) {
+            push(el) ;
+        }
+
+        @Override
+        public void visit(ElementOptional el) {
+            Element elSub = el.getOptionalElement() ;
+            Element elSub2 = pop() ;
+            Element el2 = (elSub == elSub2) ? el : new ElementOptional(elSub2) ;
+            pushChanged(el, el2) ;
+        }
+
+        @Override
+        public void visit(ElementGroup el) {
+            ElementGroup newElt = new ElementGroup() ;
+            boolean b = transformFromTo(el.getElements(), newElt.getElements()) ;
+            if ( b )
+                push(newElt) ;
+            else
+                push(el) ;
+        }
+
+        @Override
+        public void visit(ElementUnion el) {
+            ElementUnion newElt = new ElementUnion() ;
+            boolean b = transformFromTo(el.getElements(), newElt.getElements()) ;
+            if ( b )
+                push(newElt) ;
+            else
+                push(el) ;
+        }
+
+        private boolean transformFromTo(List<Element> elts, List<Element> elts2) {
+            boolean changed = false ;
+            for (Element elt : elts) {
+                Element elt2 = pop() ;
+                changed = (changed || (elt != elt2)) ;
+                // Add reversed.
+                elts2.add(0, elt2) ;
+            }
+            return changed ;
+        }
+
+        @Override
+        public void visit(ElementDataset el) {
+            push(el) ;
+            // TODO
+            // el.getPatternElement() ;
+        }
+
+        @Override
+        public void visit(ElementNamedGraph el) {
+            Node n = el.getGraphNameNode() ;
+            Node n1 = TransEltLib.apply(n, exprTransform) ;
+            Element elt = el.getElement() ;
+            Element elt1 = pop() ;
+            if ( n == n1 && elt == elt1 )
+                push(el) ;
+            else
+                push(new ElementNamedGraph(n1, elt1)) ;
+        }
+
+        @Override
+        public void visit(ElementExists el) {
+            Element elt = el.getElement() ;
+            Element elt1 = subElement(elt) ;
+            if ( elt == elt1 )
+                push(el) ;
+            else
+                push(new ElementExists(elt1)) ;
+        }
+
+        @Override
+        public void visit(ElementNotExists el) {
+            Element elt = el.getElement() ;
+            Element elt1 = subElement(elt) ;
+            if ( elt == elt1 )
+                push(el) ;
+            else
+                push(new ElementNotExists(elt1)) ;
+        }
+
+        // When you need to force the walking of the tree ... EXISTS / NOT
+        // EXISTS
+        private Element subElement(Element elt) {
+            ElementWalker.walk(elt, this) ;
+            Element elt1 = pop() ;
+            return elt1 ;
+        }
+
+        @Override
+        public void visit(ElementMinus el) {
+            Element elt = el.getMinusElement() ;
+            Element elt1 = pop() ;
+            if ( elt == elt1 )
+                push(el) ;
+            else
+                push(new ElementMinus(elt1)) ;
+        }
+
+        @Override
+        public void visit(ElementService el) {
+            boolean b = el.getSilent() ;
+            Node n = el.getServiceNode() ;
+            Node n1 = TransEltLib.apply(n, exprTransform) ;
+            Element elt = el.getElement() ;
+            Element elt1 = pop() ;
+            if ( n == n1 && elt == elt1 )
+                push(el) ;
+            else
+                push(new ElementService(n1, elt1, b)) ;
+        }
+
+        @Override
+        public void visit(ElementSubQuery el) {
+            Query newQuery = QueryOps.transform(el.getQuery(), transform, exprTransform) ;
+            push(new ElementSubQuery(newQuery)) ;
+        }
+
+        // private Element transform(Element el)
+        // {
+        // el.visit(this) ;
+        // return pop() ;
+        // }
+
+        private ExprList transform(ExprList exprList, ExprTransform exprTransform) {
+            if ( exprList == null || exprTransform == null )
+                return exprList ;
+            return ExprTransformer.transform(exprTransform, exprList) ;
+        }
+
+        private Expr transform(Expr expr, ExprTransform exprTransform) {
+            if ( expr == null || exprTransform == null )
+                return expr ;
+            return ExprTransformer.transform(exprTransform, expr) ;
+        }
+    }
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/ExprTransformNodeElement.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/ExprTransformNodeElement.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/ExprTransformNodeElement.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/ExprTransformNodeElement.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import org.apache.jena.atlas.lib.InternalErrorException ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.* ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.syntax.Element ;
+
+/**
+ * Special version of ExprTransform for applying a node transform on syntax
+ * (Elements) only
+ */
+public class ExprTransformNodeElement extends ExprTransformCopy {
+    private final NodeTransform    nodeTransform ;
+    private final ElementTransform elementTransform ;
+
+    public ExprTransformNodeElement(NodeTransform nodeTransform, ElementTransform eltrans) {
+        this.nodeTransform = nodeTransform ;
+        this.elementTransform = eltrans ;
+    }
+
+    @Override
+    public Expr transform(ExprVar nv) {
+        Node n = nodeTransform.convert(nv.getAsNode()) ;
+        if ( n == nv.getAsNode() )
+            return nv ;
+        if ( n instanceof Var ) {
+            Var v = Var.alloc(n) ;
+            return new ExprVar(v) ;
+        }
+        return NodeValue.makeNode(n) ;
+    }
+
+    @Override
+    public Expr transform(NodeValue nv) {
+        Node n = nodeTransform.convert(nv.asNode()) ;
+        if ( n == nv.asNode() )
+            return nv ;
+        return NodeValue.makeNode(n) ;
+    }
+
+    @Override
+    public Expr transform(ExprFunctionOp funcOp, ExprList args, Op opArg) {
+        // Syntax phased only - ignore args and opArg
+        Element elt = funcOp.getElement() ;
+        Element elt1 = ElementTransformer.transform(elt, elementTransform) ;
+        if ( elt == elt1 )
+            return funcOp ;
+        else {
+            if ( funcOp instanceof E_Exists )
+                return new E_Exists(elt1) ;
+            if ( funcOp instanceof E_NotExists )
+                return new E_NotExists(elt1) ;
+            throw new InternalErrorException("Unknown ExprFunctionOp: " + funcOp.getFunctionSymbol()) ;
+        }
+    }
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/MainElt.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/MainElt.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/MainElt.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/MainElt.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element;
+
+
+import java.util.HashMap ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.lib.StrUtils ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryFactory ;
+import com.hp.hpl.jena.query.Syntax ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+public class MainElt
+{
+    public static void main(String[] args)
+    {
+        String x = StrUtils.strjoinNL
+            ( "PREFIX : <http://example/>"
+              //, "SELECT * { ?s :p ?x . NOT EXISTS { ?x :r ?x }  FILTER NOT EXISTS { ?x :r ?x } FILTER ( ?x > ?y ) OPTIONAL { ?x :q ?y } }"
+            , "SELECT ?x { ?s :p ?x . FILTER NOT EXISTS { ?x :r ?x }} GROUP BY ?x ORDER BY ?x"
+            );
+        
+        Query q = QueryFactory.create(x, Syntax.syntaxARQ) ;
+
+        Map<Var, Node> map = new HashMap<Var, Node>() ;
+        map.put(Var.alloc("x"), NodeFactory.createURI("X")) ; 
+        
+        Query q2 = QueryOps.transform(q, map) ;
+        System.out.print(q) ;
+        System.out.println("-------------");
+        System.out.print(q2) ;
+        System.out.println("-------------");
+        
+        String z = StrUtils.strjoinNL
+            ( "PREFIX : <http://example/>"
+            , "DELETE { ?s :p ?x } WHERE {}" 
+            );
+        UpdateRequest req = UpdateFactory.create(z) ;
+        UpdateRequest req2 = UpdateOps.transform(req, map) ;
+        System.out.print(req) ;
+        System.out.println("-------------");
+        System.out.print(req2) ;
+        System.out.println("-------------");
+        
+        
+    }
+    
+}
+

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/NodeTransformSubst.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/NodeTransformSubst.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/NodeTransformSubst.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/NodeTransformSubst.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.Map ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+
+public class NodeTransformSubst implements NodeTransform {
+    private final Map<Var, Node> map ;
+
+    NodeTransformSubst(Map<Var, Node> map) {
+        this.map = map ;
+    }
+
+    @Override
+    public Node convert(Node node) {
+        Node n = map.get(node) ;
+        if ( n == null )
+            return node ;
+        return n ;
+    }
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/QueryOps.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/QueryOps.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/QueryOps.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/QueryOps.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,227 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.Map ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryVisitor ;
+import com.hp.hpl.jena.query.SortCondition ;
+import com.hp.hpl.jena.shared.PrefixMapping ;
+import com.hp.hpl.jena.shared.impl.PrefixMappingImpl ;
+import com.hp.hpl.jena.sparql.ARQException ;
+import com.hp.hpl.jena.sparql.core.* ;
+import com.hp.hpl.jena.sparql.expr.* ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.syntax.Element ;
+
+public class QueryOps {
+    public static Query transform(Query query, Map<Var, Node> substitutions) {
+        ElementTransform eltrans = new ElementTransformSubst(substitutions) ;
+        NodeTransform nodeTransform = new NodeTransformSubst(substitutions) ;
+        ExprTransform exprTrans = new ExprTransformNodeElement(nodeTransform, eltrans) ;
+        return transform(query, eltrans, exprTrans) ;
+    }
+
+    public static Query transform(Query query, ElementTransform transform, ExprTransform exprTransform) {
+        Query q2 = QueryOps.shallowCopy(query) ;
+
+        transformVarExprList(q2.getProject(), exprTransform) ;
+        transformVarExprList(q2.getGroupBy(), exprTransform) ;
+        // Nothing to do about ORDER BY - leave to sort by that variable.
+
+        Element el = q2.getQueryPattern() ;
+        Element el2 = ElementTransformer.transform(el, transform, exprTransform) ;
+        q2.setQueryPattern(el2) ;
+        return q2 ;
+    }
+
+    // Mutates the VarExprList
+    private static void transformVarExprList(VarExprList varExprList, ExprTransform exprTransform)
+    // , final Map<Var, Node> substitutions)
+    {
+        Map<Var, Expr> map = varExprList.getExprs() ;
+
+        for (Var v : varExprList.getVars()) {
+            Expr e = varExprList.getExpr(v) ;
+            ExprVar ev = new ExprVar(v) ;
+            Expr ev2 = exprTransform.transform(ev) ;
+            if ( ev != ev2 ) {
+                if ( e != null )
+                    throw new ARQException("Can't substitute " + v + " because it's used as an AS variable") ;
+                if ( ev2 instanceof NodeValue ) {
+                    // Convert to (substit value AS ?var)
+                    map.put(v, ev2) ;
+                    continue ;
+                } else
+                    throw new ARQException("Can't substitute " + v + " because it's not a simple value: " + ev2) ;
+            }
+            if ( e == null )
+                continue ;
+
+            // Didn't change the variable.
+            Expr e2 = ExprTransformer.transform(exprTransform, e) ;
+            if ( e != e2 )
+                // replace
+                map.put(v, e2) ;
+        }
+    }
+
+    static class QueryShallowCopy implements QueryVisitor {
+        final Query newQuery = new Query() ;
+
+        QueryShallowCopy() {}
+
+        @Override
+        public void startVisit(Query query) {
+            newQuery.setSyntax(query.getSyntax()) ;
+
+            if ( query.explicitlySetBaseURI() )
+                newQuery.setBaseURI(query.getPrologue().getResolver()) ;
+
+            newQuery.setQueryResultStar(query.isQueryResultStar()) ;
+
+            if ( query.hasDatasetDescription() ) {
+                DatasetDescription desc = query.getDatasetDescription() ;
+                for (String x : desc.getDefaultGraphURIs())
+                    newQuery.addGraphURI(x) ;
+                for (String x : desc.getDefaultGraphURIs())
+                    newQuery.addNamedGraphURI(x) ;
+            }
+            // Not needed in a shallow copy?
+            // for ( ExprAggregator agg : query.getAggregators() )
+            // {
+            // // Hooks for
+            // //aggregatorsAllocated.put(key, v) ;
+            // //aggregatorsMap.put(v, aggExpr) ;
+            // //aggregators.add(aggExpr) ;
+            // }
+
+        }
+
+        @Override
+        public void visitPrologue(Prologue prologue) {
+            // newQuery.setBaseURI(prologue.getResolver()) ;
+            PrefixMapping pmap = new PrefixMappingImpl().setNsPrefixes(prologue.getPrefixMapping()) ;
+            newQuery.setPrefixMapping(pmap) ;
+        }
+
+        @Override
+        public void visitResultForm(Query q) {}
+
+        @Override
+        public void visitSelectResultForm(Query query) {
+            newQuery.setQuerySelectType() ;
+            newQuery.setDistinct(query.isDistinct()) ;
+            VarExprList x = query.getProject() ;
+            for (Var v : x.getVars()) {
+                Expr expr = x.getExpr(v) ;
+                if ( expr == null )
+                    newQuery.addResultVar(v) ;
+                else
+                    newQuery.addResultVar(v, expr) ;
+            }
+        }
+
+        @Override
+        public void visitConstructResultForm(Query query) {
+            newQuery.setQueryConstructType() ;
+            newQuery.setConstructTemplate(query.getConstructTemplate()) ;
+        }
+
+        @Override
+        public void visitDescribeResultForm(Query query) {
+            newQuery.setQueryDescribeType() ;
+            for (Node x : query.getResultURIs())
+                newQuery.addDescribeNode(x) ;
+        }
+
+        @Override
+        public void visitAskResultForm(Query query) {
+            newQuery.setQueryAskType() ;
+        }
+
+        @Override
+        public void visitDatasetDecl(Query query) {}
+
+        @Override
+        public void visitQueryPattern(Query query) {
+            newQuery.setQueryPattern(query.getQueryPattern()) ;
+        }
+
+        @Override
+        public void visitGroupBy(Query query) {
+            if ( query.hasGroupBy() ) {
+                VarExprList x = query.getGroupBy() ;
+
+                for (Var v : x.getVars()) {
+                    Expr expr = x.getExpr(v) ;
+                    if ( expr == null )
+                        newQuery.addGroupBy(v) ;
+                    else
+                        newQuery.addGroupBy(v, expr) ;
+                }
+            }
+        }
+
+        @Override
+        public void visitHaving(Query query) {
+            if ( query.hasHaving() ) {
+                for (Expr expr : query.getHavingExprs())
+                    newQuery.addHavingCondition(expr) ;
+            }
+        }
+
+        @Override
+        public void visitOrderBy(Query query) {
+            if ( query.hasOrderBy() ) {
+                for (SortCondition sc : query.getOrderBy())
+                    newQuery.addOrderBy(sc) ;
+            }
+        }
+
+        @Override
+        public void visitLimit(Query query) {
+            newQuery.setLimit(query.getLimit()) ;
+        }
+
+        @Override
+        public void visitOffset(Query query) {
+            newQuery.setOffset(query.getOffset()) ;
+        }
+
+        @Override
+        public void visitValues(Query query) {
+            if ( query.hasValues() )
+                newQuery.setValuesDataBlock(query.getValuesVariables(), query.getValuesData()) ;
+        }
+
+        @Override
+        public void finishVisit(Query query) {}
+    }
+
+    public static Query shallowCopy(Query query) {
+        QueryShallowCopy copy = new QueryShallowCopy() ;
+        query.visit(copy) ;
+        Query q2 = copy.newQuery ;
+        return q2 ;
+    }
+
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestQueryOps.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestQueryOps.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestQueryOps.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestQueryOps.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryFactory ;
+
+public class TestQueryOps  extends BaseTest
+{
+    @Test public void queryOp_01() { testShallowCopy("SELECT * { }") ; }
+    
+    @Test public void queryOp_02() { testShallowCopy("SELECT ?x { }") ; }
+    
+    @Test public void queryOp_03() { testShallowCopy("SELECT * { ?s ?p ?o }") ; }
+
+    @Test public void queryOp_04() { testShallowCopy("SELECT ?x { ?s ?p ?o }") ; }
+
+    @Test public void queryOp_05() { testShallowCopy("SELECT (?x+1 AS ?z) ?y { }") ; }
+    
+    @Test public void queryOp_06() { testShallowCopy("SELECT DISTINCT (?x+1 AS ?z) ?y { }") ; }
+
+    @Test public void queryOp_07() { testShallowCopy("SELECT REDUCED (?x+1 AS ?z) ?y { }") ; }
+
+    @Test public void queryOp_10() { testShallowCopy("SELECT ?s { ?s ?p ?o } GROUP BY ?s") ; }
+
+    @Test public void queryOp_11() { testShallowCopy("SELECT ?s { ?s ?p ?o } ORDER BY ?o") ; }
+
+    @Test public void queryOp_12() { testShallowCopy("SELECT ?s { ?s ?p ?o } LIMIT 10") ; }
+
+    @Test public void queryOp_13() { testShallowCopy("SELECT ?s { ?s ?p ?o } OFFSET 5 LIMIT 10") ; }
+
+    private static void testShallowCopy(String queryString)
+    {
+        Query q1 = QueryFactory.create(queryString) ;
+        Query q2 = QueryOps.shallowCopy(q1) ;
+        assertEquals(q1, q2) ;
+    }
+
+}
+

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestSubstitution.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestSubstitution.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestSubstitution.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/TestSubstitution.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element;
+
+import java.util.HashMap ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryFactory ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+public class TestSubstitution extends BaseTest
+{
+    @Test public void subst_01() { testQuery("SELECT * { }", "SELECT * {}", "o", "1") ; }
+    
+    @Test public void subst_02() { testQuery("SELECT ?x { }", "SELECT ?x {}", "o", "1") ; }
+
+    @Test public void subst_03() { testQuery("SELECT ?o { }", "SELECT (1 as ?o) {}", "o", "1") ; }
+
+    @Test public void subst_04() { testQuery("SELECT (?o AS ?z) { }", "SELECT (1 AS ?z) {}", "o", "1") ; }
+
+    @Test public void subst_05() { testQuery("SELECT (?o+2 AS ?z) { }", "SELECT (1+2 AS ?z) {}", "o", "1") ; }
+
+    @Test public void subst_09() { testQuery("SELECT * {?s ?p ?o}", "SELECT * {?s ?p 1}", "o", "1") ; }  
+    
+    @Test public void subst_10() { testQuery("SELECT * { SELECT ?o {} }", "SELECT * {SELECT (1 as ?o) {}}", "o", "1") ; }
+
+    //static final String PREFIX = "PREFIX : <http://example/>\n" ;
+    static final String PREFIX = "" ;
+
+    private void testQuery(String input, String output, String varStr, String valStr)
+    {
+        Query q1 = QueryFactory.create(PREFIX+input) ;
+        Query qExpected = QueryFactory.create(PREFIX+output) ;
+        
+        Map<Var, Node> map = new HashMap<Var, Node>() ;
+        map.put(Var.alloc(varStr), SSE.parseNode(valStr)) ;
+        
+        Query qTrans = QueryOps.transform(q1, map) ;
+        assertEquals(qExpected, qTrans) ;
+    }
+
+    
+}
+

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/TransEltLib.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/TransEltLib.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/TransEltLib.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/TransEltLib.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import org.apache.jena.atlas.lib.InternalErrorException ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprTransform ;
+import com.hp.hpl.jena.sparql.expr.ExprVar ;
+import com.hp.hpl.jena.sparql.expr.NodeValue ;
+
+public class TransEltLib {
+    public static Var applyVar(Var v, ExprTransform exprTransform) {
+        ExprVar expr = new ExprVar(v) ;
+        Expr e = exprTransform.transform(expr) ;
+        if ( e instanceof ExprVar )
+            return ((ExprVar)e).asVar() ;
+        throw new InternalErrorException("Managed to turn a variable " + v + " into " + e) ;
+    }
+
+    public static Node apply(Node n, ExprTransform exprTransform) {
+        Expr e = null ;
+        if ( Var.isVar(n) ) {
+            Var v = Var.alloc(n) ;
+            ExprVar expr = new ExprVar(v) ;
+            e = exprTransform.transform(expr) ;
+        } else {
+            NodeValue nv = NodeValue.makeNode(n) ;
+            e = exprTransform.transform(nv) ;
+        }
+
+        if ( e instanceof ExprVar )
+            return ((ExprVar)e).asVar() ;
+        if ( e instanceof NodeValue )
+            return ((NodeValue)e).asNode() ;
+        throw new InternalErrorException("Managed to turn a node " + n + " into " + e) ;
+    }
+
+}

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/element/UpdateOps.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/element/UpdateOps.java?rev=1509984&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/element/UpdateOps.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/element/UpdateOps.java Sat Aug  3 13:20:20 2013
@@ -0,0 +1,206 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package element ;
+
+import java.util.ArrayList ;
+import java.util.List ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.lib.Sink ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.ExprTransform ;
+import com.hp.hpl.jena.sparql.graph.NodeTransform ;
+import com.hp.hpl.jena.sparql.modify.request.* ;
+import com.hp.hpl.jena.sparql.syntax.Element ;
+import com.hp.hpl.jena.update.Update ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+public class UpdateOps {
+    
+    public static Update transform(Update update, Map<Var, Node> substitutions) {
+        ElementTransform eltrans = new ElementTransformSubst(substitutions) ;
+        NodeTransform nodeTransform = new NodeTransformSubst(substitutions) ;
+        ExprTransform exprTrans = new ExprTransformNodeElement(nodeTransform, eltrans) ;
+        return transform(update, eltrans, exprTrans) ;
+    }
+
+    public static UpdateRequest transform(UpdateRequest update, Map<Var, Node> substitutions) {
+        ElementTransform eltrans = new ElementTransformSubst(substitutions) ;
+        NodeTransform nodeTransform = new NodeTransformSubst(substitutions) ;
+        ExprTransform exprTrans = new ExprTransformNodeElement(nodeTransform, eltrans) ;
+        return transform(update, eltrans, exprTrans) ;
+    }
+
+    public static Update transform(Update update, ElementTransform transform, ExprTransform exprTransform) {
+        UpdateTransform upParam = new UpdateTransform(transform, exprTransform) ;
+        update.visit(upParam) ;
+        Update update1 = upParam.result ;
+        return update1 ;
+    }
+
+    public static UpdateRequest transform(UpdateRequest update, ElementTransform transform, ExprTransform exprTransform) {
+        UpdateRequest req = new UpdateRequest() ;
+        for (Update up : update.getOperations()) {
+            up = transform(up, transform, exprTransform) ;
+            req.add(up) ;
+        }
+
+        return req ;
+    }
+
+    static class UpdateTransform implements UpdateVisitor {
+        ElementTransform elTransform ;
+        ExprTransform    exprTransform ;
+        Update           result = null ;
+
+        public UpdateTransform(ElementTransform transform, ExprTransform exprTransform) {
+            this.elTransform = transform ;
+            this.exprTransform = exprTransform ;
+        }
+
+        @Override
+        public void visit(UpdateDrop update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateClear update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateCreate update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateLoad update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateAdd update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateCopy update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateMove update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateDataInsert update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateDataDelete update) {
+            result = update ;
+        }
+
+        @Override
+        public void visit(UpdateDeleteWhere update) {
+            List<Quad> quads = update.getQuads() ;
+            List<Quad> quads2 = transform(quads) ;
+            if ( quads == quads2 )
+                result = update ;
+            else {
+                QuadAcc acc = new QuadAcc() ;
+                addAll(acc, quads2) ;
+                result = new UpdateDeleteWhere(acc) ;
+            }
+        }
+
+        @Override
+        public void visit(UpdateModify update) {
+            Element el = update.getWherePattern() ;
+            Element el2 = ElementTransformer.transform(el, elTransform, exprTransform) ;
+
+            List<Quad> del = update.getDeleteQuads() ;
+            List<Quad> del1 = transform(del) ;
+            List<Quad> ins = update.getInsertQuads() ;
+            List<Quad> ins1 = transform(ins) ;
+
+            UpdateModify mod = new UpdateModify() ;
+
+            addAll(mod.getDeleteAcc(), del1) ;
+            addAll(mod.getInsertAcc(), ins1) ;
+            result = mod ;
+        }
+
+        private void addAll(QuadAcc acc, List<Quad> quads) {
+            for (Quad q : quads)
+                acc.addQuad(q) ;
+        }
+
+        public List<Quad> transform(List<Quad> quads) {
+            List<Quad> x = new ArrayList<Quad>() ;
+            boolean changed = false ;
+            for (Quad q : quads) {
+                Quad q1 = transform(q) ;
+                changed = changed || q1 != q ;
+                x.add(q1) ;
+            }
+            if ( changed )
+                return x ;
+            return quads ;
+        }
+
+        private Quad transform(Quad q) {
+            Node g = q.getGraph() ;
+            Node g1 = transform(g) ;
+            Node s = q.getSubject() ;
+            Node s1 = transform(s) ;
+            Node p = q.getPredicate() ;
+            Node p1 = transform(p) ;
+            Node o = q.getObject() ;
+            Node o1 = transform(o) ;
+            if ( g == g1 && s == s1 && p == p1 && o == o1 )
+                return q ;
+            return Quad.create(g1, s1, p1, o1) ;
+        }
+
+        private Node transform(Node n) {
+            if ( Var.isVar(n) )
+                return TransEltLib.apply(Var.alloc(n), exprTransform) ;
+            else
+                return TransEltLib.apply(n, exprTransform) ;
+        }
+
+        @Override
+        public Sink<Quad> createInsertDataSink() {
+            return null ;
+        }
+
+        @Override
+        public Sink<Quad> createDeleteDataSink() {
+            return null ;
+        }
+
+    }
+
+}