| /* |
| * 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 org.apache.jena.sparql.algebra; |
| |
| import org.apache.jena.sparql.algebra.op.OpService ; |
| import org.apache.jena.sparql.algebra.walker.ApplyTransformVisitor ; |
| import org.apache.jena.sparql.algebra.walker.Walker ; |
| import org.apache.jena.sparql.expr.ExprTransform ; |
| import org.apache.jena.sparql.expr.ExprTransformCopy ; |
| |
| /** A bottom-top application of a transformation of SPARQL algebra */ |
| public class Transformer |
| { |
| // XXX XXX Clean me! |
| |
| private static Transformer singleton = new Transformer(); |
| |
| /** Get the current transformer */ |
| public static Transformer get() { return singleton; } |
| |
| /** Set the current transformer - use with care */ |
| public static void set(Transformer value) { Transformer.singleton = value; } |
| |
| /** Transform an algebra expression */ |
| public static Op transform(Transform transform, Op op) |
| { return get().transformation(transform, op, null, null) ; } |
| |
| /** Transform an algebra expression and the expressions */ |
| public static Op transform(Transform transform, ExprTransform exprTransform, Op op) |
| { return get().transformation(transform, exprTransform, op, null, null) ; } |
| |
| /** |
| * Transformation with specific Transform and default ExprTransform (apply transform |
| * inside pattern expressions like NOT EXISTS) |
| */ |
| public static Op transform(Transform transform, Op op, OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| return get().transformation(transform, op, beforeVisitor, afterVisitor) ; |
| } |
| |
| /** Transformation with specific Transform and ExprTransform applied */ |
| public static Op transform(Transform transform, ExprTransform exprTransform, Op op, OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| return get().transformation(transform, exprTransform, op, beforeVisitor, afterVisitor) ; |
| } |
| |
| /** Transform an algebra expression except skip (leave alone) any OpService nodes */ |
| public static Op transformSkipService(Transform transform, Op op) { |
| return transformSkipService(transform, null, op, null, null) ; |
| } |
| |
| /** Transform an algebra expression except skip (leave alone) any OpService nodes */ |
| public static Op transformSkipService(Transform transform, ExprTransform exprTransform, Op op) { |
| return transformSkipService(transform, exprTransform, op, null, null) ; |
| } |
| |
| /** Transform an algebra expression except skip (leave alone) any OpService nodes */ |
| public static Op transformSkipService(Transform opTransform, ExprTransform exprTransform, Op op, |
| OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| |
| if ( true ) { |
| // XXX XXX Better work with Walker. |
| if ( opTransform == null ) |
| opTransform = new TransformCopy() ; |
| if ( exprTransform == null ) |
| exprTransform = new ExprTransformCopy() ; |
| Transform transform2 = new TransformSkipService(opTransform) ; |
| transform2 = opTransform ; |
| ApplyTransformVisitor atv = new ApplyTransformVisitor(transform2, exprTransform, false, beforeVisitor, afterVisitor) ; |
| return Walker.transformSkipService(op, atv, beforeVisitor, afterVisitor) ; |
| } |
| |
| Transform transform = new TransformSkipService(opTransform) ; |
| return Transformer.transform(transform, exprTransform, op, beforeVisitor, afterVisitor) ; |
| // // OLD |
| // // Simplest way but still walks the OpService subtree (and throws away the |
| // // transformation). |
| // Transform transform = new TransformSkipService(opTransform) ; |
| // return Transformer.transform(transform, exprTransform, op, beforeVisitor, afterVisitor) ; |
| } |
| |
| // To allow subclassing this class, we use a singleton pattern |
| // and theses protected methods. |
| protected Op transformation(Transform transform, Op op, OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| return transformation(transform, null, op, beforeVisitor, afterVisitor) ; |
| } |
| |
| protected Op transformation(Transform transform, ExprTransform exprTransform, Op op, OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| return transformation$(transform, exprTransform, op, beforeVisitor, afterVisitor) ; |
| } |
| |
| private Op transformation$(Transform transform, ExprTransform exprTransform, Op op, OpVisitor beforeVisitor, OpVisitor afterVisitor) { |
| return Walker.transform(op, transform, exprTransform, beforeVisitor, afterVisitor) ; |
| } |
| |
| // -------------------------------- |
| // Safe: ignore transformation of OpService and return the original. |
| // Still walks the sub-op of OpService unless combined with a walker that does not go |
| // down SERVICE |
| static class TransformSkipService extends TransformWrapper |
| { |
| public TransformSkipService(Transform transform) |
| { |
| super(transform) ; |
| } |
| |
| @Override |
| public Op transform(OpService opService, Op subOp) |
| { return opService ; } |
| } |
| } |