/*
* 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.arq.querybuilder.rewriters;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.jena.graph.Node ;
import org.apache.jena.query.SortCondition ;
import org.apache.jena.sparql.algebra.Op ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.expr.* ;
import org.apache.jena.sparql.syntax.Element ;
/**
* A rewriter that implements an ExprVisitor
*
*/
public class ExprRewriter extends AbstractRewriter<Expr> implements ExprVisitor {
/**
* Constructor.
* @param values the values to replace.
*/
public ExprRewriter(Map<Var, Node> values) {
super(values);
}
@Override
public void visit(ExprFunction0 func) {
push(func);
}
@Override
public void visit(ExprFunction1 func) {
func.getArg().visit(this);
push(func.copy(pop()));
}
@Override
public void visit(ExprFunction2 func) {
// reverse order so they pop in the right order
func.getArg2().visit(this);
func.getArg1().visit(this);
push(func.copy(pop(), pop()));
}
@Override
public void visit(ExprFunction3 func) {
func.getArg3().visit(this);
func.getArg2().visit(this);
func.getArg1().visit(this);
push(func.copy(pop(), pop(), pop()));
}
@Override
public void visit(ExprFunctionN func) {
ExprList exprList = rewrite(new ExprList(func.getArgs()));
ExprFunctionN retval = (ExprFunctionN) func.deepCopy();
setExprList(retval, exprList);
push(retval);
}
private void setExprList(ExprFunctionN n, ExprList exprList) {
try {
Field f = ExprFunctionN.class.getDeclaredField("args");
f.setAccessible(true);
f.set(n, exprList);
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
} catch (SecurityException e) {
throw new IllegalStateException(e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
@Override
public void visit(ExprFunctionOp funcOp) {
ElementRewriter elementRewriter = new ElementRewriter(values);
funcOp.getElement().visit(elementRewriter);
OpRewriter opRewriter = new OpRewriter(values);
funcOp.getGraphPattern().visit(opRewriter);
try {
Constructor<? extends ExprFunctionOp> con = funcOp.getClass()
.getConstructor(Element.class, Op.class);
push(con.newInstance(elementRewriter.pop(), opRewriter.pop()));
} catch (NoSuchMethodException e) {
throw new IllegalStateException(e);
} catch (SecurityException e) {
throw new IllegalStateException(e);
} catch (InstantiationException e) {
throw new IllegalStateException(e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} catch (InvocationTargetException e) {
throw new IllegalStateException(e);
}
}
@Override
public void visit(NodeValue nv) {
NodeValueRewriter rewriter = new NodeValueRewriter(values);
nv.visit(rewriter);
push(rewriter.pop());
}
@Override
public void visit(ExprVar nv) {
Node n = changeNode(nv.asVar());
if (n.isVariable()) {
push(new ExprVar(n));
} else {
push(NodeValue.makeNode(n));
}
}
@Override
public void visit(ExprAggregator eAgg) {
Node n = changeNode(eAgg.getVar());
if (n.equals(eAgg.getVar())) {
push(eAgg);
} else {
push(NodeValue.makeNode(n));
}
}
public final List<SortCondition> rewriteSortConditionList(
List<SortCondition> lst) {
if (lst == null) {
return null;
}
List<SortCondition> retval = new ArrayList<SortCondition>();
for (SortCondition sc : lst) {
retval.add(rewrite(sc));
}
return retval;
}
public final SortCondition rewrite(SortCondition sortCondition) {
sortCondition.getExpression().visit(this);
return new SortCondition(pop(), sortCondition.getDirection());
}
public final ExprList rewrite(ExprList lst) {
if (lst == null) {
return null;
}
ExprList exprList = new ExprList();
int limit = lst.size();
for (int i = 0; i < limit; i++) {
lst.get(i).visit(this);
exprList.add(pop());
}
return exprList;
}
}