package codeStatistics.xpathfunctions;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.sf.saxon.s9api.ExtensionFunction;
import net.sf.saxon.s9api.ItemType;
import net.sf.saxon.s9api.ItemTypeFactory;
import net.sf.saxon.s9api.OccurrenceIndicator;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.SequenceType;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.XdmEmptySequence;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmValue;
import net.sf.saxon.value.ObjectValue;
import org.eclipse.jdt.core.dom.ASTNode;
import codeStatistics.AnalysisPluginsManager;
import codeStatistics.extension.IAnalysisFunction;
public class ExtensionFunctions {
private static class AnalysisFunction implements ExtensionFunction {
private final ItemTypeFactory typeFactory;
private final IAnalysisFunction func;
private Map<ASTNode, Object> analysisContext;
public AnalysisFunction(IAnalysisFunction func, ItemTypeFactory typeFactory) {
this.typeFactory = typeFactory;
this.func = func;
}
@Override
public XdmValue call(XdmValue[] arguments) throws SaxonApiException {
Object[] funcArguments = new Object[arguments.length];
Class<?>[] argTypes = func.getArgumentType();
for(int i=0; i< arguments.length; i++) {
XdmItem item = arguments[i].itemAt(0);
funcArguments[i] = translateValue(argTypes[i], item);
}
Object result = func.execute(funcArguments, analysisContext);
if (func.getResultType() == Boolean.class)
return new XdmAtomicValue((Boolean)result);
if (result == null)
return XdmEmptySequence.getInstance();
return new ObjValue(result);
}
private ItemType translateType(Class<?> clazz) {
if (clazz == String.class)
return ItemType.STRING;
return typeFactory.getExternalObjectType(clazz);
}
private Object translateValue(Class<?> clazz, XdmItem item){
if (clazz == String.class)
return ((net.sf.saxon.value.StringValue)item.getUnderlyingValue()).getStringValue();
return ((ObjectValue) item.getUnderlyingValue()).getObject();
}
@Override
public SequenceType[] getArgumentTypes() {
Class<?>[] args = func.getArgumentType();
SequenceType[] result = new SequenceType[args.length];
for(int i=0; i< args.length; i++)
result[i] = SequenceType.makeSequenceType(translateType(args[i]), OccurrenceIndicator.ONE);
return result;
}
@Override
public QName getName() {
return FunctionUtils.getName(func.getName());
}
@Override
public SequenceType getResultType() {
if (func.getResultType() == Boolean.class)
return SequenceType.makeSequenceType(ItemType.BOOLEAN, OccurrenceIndicator.ZERO_OR_ONE);
return FunctionUtils.createZeroOrOneResultType(typeFactory, func.getResultType());
}
public void setAnalysisContext(Map<ASTNode, Object> analysisContext) {
this.analysisContext = analysisContext;
}
}
// private static abstract class ExtensionFunctionBase extends
// CodeStatisticsNodeFunction{
//
// private Map<ASTNode, Object> analysisResult;
//
// public ExtensionFunctionBase(String name) {
// super(name);
// this.analysisResult = null;
// }
//
// protected abstract XdmValue getResult(Object result);
// protected abstract ItemType getResType();
//
// @Override
// protected final XdmValue getResult(ASTNode nodeOrNull) {
// return getResult(nodeOrNull == null ? null :
// analysisResult.get(nodeOrNull));
// }
//
//
// public void setAnalysisResult(Map<ASTNode, Object> analysisResult){
// this.analysisResult = analysisResult;
// }
//
// @Override
// public final SequenceType getResultType() {
// return SequenceType.makeSequenceType(getResType(),
// OccurrenceIndicator.ONE);
// }
// }
//
// public class ObjValue extends XdmValue {
// public ObjValue(Object o) {
// super(new ObjectValue(o));
// }
// }
//
// private class GenericFunction extends ExtensionFunctionBase {
//
// private final IGenericAnalysisFunction func;
// private final ItemTypeFactory typeFactory;
//
// public GenericFunction(IGenericAnalysisFunction func, ItemTypeFactory
// typeFactory) {
// super(func.getName());
// this.func = func;
// this.typeFactory = typeFactory;
// }
//
// @Override
// protected XdmValue getResult(Object nodeAnalysisResultOrNull) {
// Object res = func.execute(nodeAnalysisResultOrNull);
// return new ObjValue(res);
// }
//
// @Override
// protected ItemType getResType() {
// return typeFactory.getExternalObjectType(func.getResultType());
// }
//
// }
//
// private static class BooleanFunction extends ExtensionFunctionBase {
//
// private final IBooleanAnalysisFunction func;
//
// public BooleanFunction(IBooleanAnalysisFunction func) {
// super(func.getName());
// this.func = func;
// }
//
// @Override
// protected XdmValue getResult(Object nodeAnalysisResultOrNull) {
// boolean res = func.execute(nodeAnalysisResultOrNull);
// return new XdmAtomicValue(res);
// }
//
// @Override
// protected ItemType getResType() {
// return ItemType.BOOLEAN;
// }
//
// }
private ArrayList<List<AnalysisFunction>> allFunctions = new ArrayList<List<AnalysisFunction>>();
public ExtensionFunctions(ItemTypeFactory typeFactory, Processor proc) {
// generate functions
for (List<IAnalysisFunction> gFuncs : AnalysisPluginsManager.getFunctionDefinitions()) {
List<AnalysisFunction> funcs = new LinkedList<AnalysisFunction>();
allFunctions.add(funcs);
for (IAnalysisFunction gFunc : gFuncs) {
AnalysisFunction func = new AnalysisFunction(gFunc, typeFactory);
proc.registerExtensionFunction(func);
funcs.add(func);
}
}
}
public void setAnalysisResult(int idx, Map<ASTNode, Object> result) {
for (AnalysisFunction func : allFunctions.get(idx))
func.setAnalysisContext(result);
}
// public static void initialiseFunctions(Processor proc) {
// // Processor proc = new Processor(false);
// // AstTextExtensionFunction func = new AstTextExtensionFunction();
// for(IBooleanAnalysisFunction bFunc:
// AnalysisPluginsManager.getBooleanFunctionDefinitions()){
// System.out.println(bFunc);
// }
// // proc.registerExtensionFunction(func);
// // AnalysisPluginsManager.initialiseExtensions();
// //
// // XPathCompiler xpath = proc.newXPathCompiler();
// // xpath.declareNamespace("cs", XPathConstants.NAMESPACE);
// //
// // return xpath;
// }
}