package org.aksw.jena_sparql_api.views;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aksw.commons.util.reflect.MultiMethod;
import org.apache.commons.lang.NotImplementedException;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprAggregator;
import org.apache.jena.sparql.expr.ExprFunction;
import org.apache.jena.sparql.expr.ExprFunction0;
import org.apache.jena.sparql.expr.ExprFunction1;
import org.apache.jena.sparql.expr.ExprFunction2;
import org.apache.jena.sparql.expr.ExprFunction3;
import org.apache.jena.sparql.expr.ExprFunctionN;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.ExprVar;
import org.apache.jena.sparql.expr.NodeValue;
class ExprCopySlow {
private static ExprCopy instance;
public static ExprCopy getInstance()
{
if(instance == null) {
instance = new ExprCopy();
}
return instance;
}
public Expr deepCopy(Expr proto)
{
return deepCopy(proto, ExprArgs.getArgs(proto));
}
public Expr deepCopy(Expr proto, ExprList args)
{
return copy(proto, deepCopy(args));
}
public ExprList deepCopy(ExprList exprs) {
ExprList result = new ExprList();
for(Expr expr : exprs) {
result.add(deepCopy(expr));
}
return result;
}
/**
* Creates a copy of an expression, with different arguments.
*
*
* @param proto
* @param args
*/
public Expr copy(Expr proto, Expr ...args)
{
@SuppressWarnings("unchecked")
ExprList list = new ExprList(Arrays.asList(args));
return (Expr)MultiMethod.invoke(this, "_copy", proto, list);
}
public Expr copy(Expr proto, ExprList args)
{
return (Expr)MultiMethod.invoke(this, "_copy", proto, args);
}
public Expr copy(Expr proto, List<Expr> args)
{
return (Expr)MultiMethod.invoke(this, "_copy", proto, new ExprList(args));
}
public Expr copy(Expr expr) {
return copy(expr, ExprArgs.getArgs(expr));
}
public Expr _copy(ExprFunction0 func, ExprList args) {
return func;
}
public Expr _copy(ExprFunction1 func, ExprList args) {
return func.copy(args.get(0));
}
public Expr _copy(ExprFunction2 func, ExprList args) {
return func.copy(args.get(0), args.get(1));
}
public Expr _copy(ExprFunction3 func, ExprList args) {
return func.copy(args.get(0), args.get(1), args.get(2));
}
public List<String> classNameList(Iterable<Class<?>> classes) {
List<String> result = new ArrayList<String>();
for(Class<?> clazz : classes) {
result.add(clazz.getName());
}
return result;
}
public Expr _copy(ExprFunctionN func, ExprList args) {
return (Expr)MultiMethod.invoke(func, "copy", args);
}
/*
public Expr _copy(ExprFunctionOp funcOp, ExprList args, Op opArg) {
throw new NotImplementedException();
}*/
public Expr _copy(NodeValue nv, ExprList args) {
return nv;
}
public Expr _copy(ExprVar nv, ExprList args) {
return nv;
}
public Expr _copy(ExprAggregator eAgg, ExprList args) {
throw new NotImplementedException();
}
}
public class ExprCopy {
private static ExprCopy instance;
public static ExprCopy getInstance()
{
if(instance == null) {
instance = new ExprCopy();
}
return instance;
}
public Expr deepCopy(Expr proto)
{
Expr result;
if(proto == null) {
throw new NullPointerException();
}
if(proto.isConstant()) {
result = deepCopy(proto.getConstant());
}
else if(proto.isFunction()) {
result = deepCopy(proto.getFunction());
}
else if(proto.isVariable()) {
result = deepCopy(proto.getExprVar());
}
else {
throw new RuntimeException("Don't know how to copy " + proto + " of type " + proto.getClass());
}
return result;
//return deepCopy(proto, ExprArgs.getArgs(proto));
}
public Expr deepCopy(NodeValue expr) {
return expr;
}
public Expr deepCopy(ExprVar expr) {
return expr;
}
public Expr deepCopy(ExprFunction fn) {
List<Expr> args = fn.getArgs();
List<Expr> newArgs = new ArrayList<Expr>(args.size());
for(Expr arg : args) {
Expr newArg = deepCopy(arg);
newArgs.add(newArg);
}
Expr result = deepCopy(fn, newArgs);
return result;
}
/**
* This method is intended to be overridden to e.g. substitute functions
*
* In the overriding method, call "super.deepCopy(proto, args)" for the default handling.
*
* @param proto
* @param args
* @return
*/
public Expr deepCopy(ExprFunction proto, List<Expr> args) {
Expr result = copy(proto, args);
return result;
}
public Expr deepCopy(Expr proto, ExprList args)
{
return copy(proto, deepCopy(args));
}
public ExprList deepCopy(ExprList exprs) {
ExprList result = new ExprList();
for(Expr expr : exprs) {
result.add(deepCopy(expr));
}
return result;
}
/**
* Creates a copy of an expression, with different arguments.
*
*
* @param proto
* @param args
*/
public Expr copy(Expr proto, Expr ...args)
{
@SuppressWarnings("unchecked")
List<Expr> list = Arrays.asList(args);
return copy(proto, list);
}
public Expr copy(Expr proto, ExprList args)
{
return copy(proto, args.getList());
}
public Expr copy(Expr proto, List<Expr> args)
{
Expr result;
if(!proto.isFunction()) {
throw new RuntimeException("Must not be called on non-functions");
}
ExprFunction fn = proto.getFunction();
result = copy(fn, args);
return result;
}
public Expr copy(ExprFunction proto, List<Expr> args) {
Expr result;
if(proto == null) {
throw new NullPointerException();
}
if(proto instanceof ExprFunction0) {
result = copy((ExprFunction0)proto, args);
}
else if(proto instanceof ExprFunction1) {
result = copy((ExprFunction1)proto, args);
}
else if(proto instanceof ExprFunction2) {
result = copy((ExprFunction2)proto, args);
}
else if(proto instanceof ExprFunction3) {
result = copy((ExprFunction3)proto, args);
}
else if(proto instanceof ExprFunctionN) {
result = copy((ExprFunctionN)proto, args);
}
else {
throw new RuntimeException("Don't know how to handle " + proto + " with type " + proto.getClass());
}
return result;
}
public Expr copy(Expr expr) {
return copy(expr, ExprArgs.getArgs(expr));
}
public Expr copy(ExprFunction0 func, List<Expr> args) {
return func;
}
public Expr copy(ExprFunction1 func, List<Expr> args) {
return func.copy(args.get(0));
}
public Expr copy(ExprFunction2 func, List<Expr> args) {
return func.copy(args.get(0), args.get(1));
}
public Expr copy(ExprFunction3 func, List<Expr> args) {
return func.copy(args.get(0), args.get(1), args.get(2));
}
public List<String> classNameList(Iterable<Class<?>> classes) {
List<String> result = new ArrayList<String>();
for(Class<?> clazz : classes) {
result.add(clazz.getName());
}
return result;
}
public Expr copy(ExprFunctionN func, List<Expr> args) {
ExprList exprList = new ExprList(args);
try {
Method m = func.getClass().getDeclaredMethod("copy", ExprList.class);
//boolean isOriginallyAccessible = m.isAccessible();
m.setAccessible(true);
Expr result = (Expr)m.invoke(func, exprList);
//m.setAccessible(isOriginallyAccessible);
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/*
public Expr _copy(ExprFunctionOp funcOp, ExprList args, Op opArg) {
throw new NotImplementedException();
}*/
// public Expr _copy(NodeValue nv, List<Expr> args) {
// return nv;
// }
//
// public Expr _copy(ExprVar nv, List<Expr> args) {
// return nv;
// }
//
// public Expr _copy(ExprAggregator eAgg, List<Expr> args) {
// throw new NotImplementedException();
// }
}