Functions.java
package eu.javaexperience.functional.saac;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import eu.javaexperience.annotation.FunctionDescription;
import eu.javaexperience.annotation.FunctionVariableDescription;
import eu.javaexperience.arrays.ArrayTools;
import eu.javaexperience.datareprez.DataObject;
import eu.javaexperience.datareprez.DataReprezTools;
import eu.javaexperience.datareprez.convertFrom.DataWrapper;
import eu.javaexperience.datareprez.jsonImpl.DataObjectJsonImpl;
import eu.javaexperience.generic.annotations.Ignore;
import eu.javaexperience.interfaces.ObjectWithProperty;
import eu.javaexperience.interfaces.ObjectWithPropertyStorage;
import eu.javaexperience.interfaces.simple.SimpleCall;
import eu.javaexperience.interfaces.simple.SimpleGet;
import eu.javaexperience.interfaces.simple.getBy.GetBy1;
import eu.javaexperience.interfaces.simple.getBy.GetBy2;
import eu.javaexperience.interfaces.simple.getBy.GetBy3;
import eu.javaexperience.interfaces.simple.publish.SimplePublish1;
import eu.javaexperience.reflect.Mirror;
import eu.javaexperience.rpc.bidirectional.BidirectionalRpcDefaultProtocol;
import eu.javaexperience.saac.SaacIgnore;
import eu.javaexperience.saac.SaacServerUnit;
import eu.javaexperience.saac.exceptions.SaacFunctionCreationException;
import eu.javaexperience.text.StringTools;
public class Functions
{
public static class Param implements ObjectWithProperty
{
protected String name;
protected Type type;
protected String description;
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
public Type getType()
{
return type;
}
public Param(Parameter at, FunctionDescription d, int i)
{
name = at.getName();
type = at.getParameterizedType();
description = name;
if(null != d)
{
try
{
FunctionVariableDescription[] pds = d.parameters();
if(null != pds)
{
FunctionVariableDescription pd = ArrayTools.accessIndexSafe(pds, i);
if(null != pd)
{
name = pd.paramName();
description = pd.description();
}
}
}
catch(Exception e)
{
throw new RuntimeException("Error in FunctionVariableDescription at parameter index: "+i);
}
}
}
public Param
(
AnnotatedType annotatedReturnType,
FunctionDescription d
)
{
//ret type
name = "ret";
type = annotatedReturnType.getType();
description = "return";
if(null != d)
{
FunctionVariableDescription f = d.returning();
name = f.paramName();
description = f.description();
}
}
public static final Param[] emptyParamArray = new Param[0];
public static Param[] wrap(Parameter[] params, FunctionDescription d)
{
ArrayList<Param> ret = new ArrayList<>();
int i=0;
for(Parameter p:params)
{
ret.add(new Param(p, d, i++));
}
return ret.toArray(emptyParamArray);
}
public AutocompleteProvider getAutocompleteProvider()
{
return null;
}
@Override
public Object get(String key)
{
return PROPS.get(this, key);
}
@Override
public String[] keys()
{
return PROPS.keys();
}
protected static ObjectWithPropertyStorage<Param> PROPS = new ObjectWithPropertyStorage<>();
static
{
PROPS.addExaminer("name", (e)-> e.name);
PROPS.addExaminer("description", (e)-> e.description);
PROPS.addExaminer("type", (e)-> serializeType(e.type));
}
}
public static final DataWrapper TYPE_SERIALIZER = DataReprezTools.combineWrappers
(
SaacServerUnit.reflectTypeDataWrapper,
BidirectionalRpcDefaultProtocol.DEFAULT_RPC_DATA_WRAPPER_WITH_CLASS
);
protected static DataObject serializeType(Type t)
{
return (DataObject) TYPE_SERIALIZER.wrap
(
TYPE_SERIALIZER,
DataObjectJsonImpl.instane,
t
);
}
/*
@FunctionDescription
(
functionDescription = "A küldő nevének vizsgálata.",
parameters = {@FunctionVariableDescription(description = "Vizsgáló függvény", mayNull = false, paramName = "functionName", type = GetBy1.class)},
returning = @FunctionVariableDescription(description="Megállapító függvény",mayNull=false,paramName="",type=GetBy1.class)
)
*/
public static class PreparedFunction
{
protected Method m;
public PreparedFunction(Method m)
{
try
{
this.m = m;
id = m.getDeclaringClass().getName()+"."+m.getName();
name = StringTools.getSubstringAfterLastString(m.getName(), ".");
description = name;
FunctionDescription d = m.getAnnotation(FunctionDescription.class);
if(null != d)
{
description = d.functionDescription();
}
returning = new Param(m.getAnnotatedReturnType(), d);
args = Param.wrap(m.getParameters(), d);
}
catch(Exception e)
{
throw new RuntimeException("Error in FunctionDescription: "+m+"");
}
}
protected String id;
protected String name;
protected String description;
protected Param returning;
protected Param[] args;
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
public Param getReturning()
{
return returning;
}
public Param[] getArgs()
{
return ArrayTools.copy(args);
}
public Method getMethod()
{
return m;
}
public Object create(Object... arguments)
{
try
{
return m.invoke(null, arguments);
}
catch (Exception e)
{
SaacFunctionCreationException ex = new SaacFunctionCreationException("Can't create function", e);
ex.function = this;
ex.functionName = id;
ex.arguments = arguments;
throw ex;
}
}
public String getId()
{
return id;
}
@Override
public String toString()
{
return "PreparedFunction: "+m;
}
}
protected static final Collection<Class<?>> FUNCTION_CLASS = new ArrayList<>();
static
{
FUNCTION_CLASS.add(SimpleGet.class);
FUNCTION_CLASS.add(SimplePublish1.class);
FUNCTION_CLASS.add(SimpleCall.class);
FUNCTION_CLASS.add(GetBy1.class);
FUNCTION_CLASS.add(GetBy2.class);
FUNCTION_CLASS.add(GetBy3.class);
}
public static void collectFunctions
(
Collection<PreparedFunction> funcs,
Class cls
)
{
final int req_mod = Modifier.STATIC | Modifier.PUBLIC;
for(Method m:cls.getMethods())
{
if(0 != m.getAnnotationsByType(SaacIgnore.class).length || 0 != m.getAnnotationsByType(Ignore.class).length)
{
continue;
}
int mod = m.getModifiers();
if((mod & req_mod) == req_mod)
//if(FUNCTION_CLASS.contains(m.getReturnType()))
{
funcs.add(new PreparedFunction(m));
}
}
}
}