package railo.transformer.library.function; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import railo.commons.lang.CFTypes; import railo.commons.lang.ClassException; import railo.commons.lang.ClassUtil; import railo.commons.lang.Md5; import railo.commons.lang.StringUtil; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageRuntimeException; import railo.runtime.exp.TemplateException; import railo.runtime.functions.BIF; import railo.runtime.functions.BIFProxy; import railo.runtime.reflection.Reflector; import railo.transformer.cfml.evaluator.FunctionEvaluator; import railo.transformer.library.tag.TagLib; /** * Eine FunctionLibFunction repraesentiert eine einzelne Funktion innerhalb einer FLD. */ public final class FunctionLibFunction { /** * Dynamischer Argument Typ */ public static final int ARG_DYNAMIC = 0; /** * statischer Argument Typ */ public static final int ARG_FIX = 1; private FunctionLib functionLib; private String name; private ArrayList<FunctionLibFunctionArg> argument=new ArrayList<FunctionLibFunctionArg>(); private int argMin=0; private int argMax=-1; private int argType=ARG_FIX; private String strReturnType; private String cls=""; private Class clazz; private String description; private boolean hasDefaultValues; private FunctionEvaluator eval; private String tteClass; private short status=TagLib.STATUS_IMPLEMENTED; private String memberName; private short memberType=CFTypes.TYPE_UNKNOW; private boolean memberChaining; private BIF bif; /** * Geschuetzer Konstruktor ohne Argumente. */ public FunctionLibFunction() { } public FunctionLibFunction(FunctionLib functionLib) { this.functionLib=functionLib; } /** * Gibt den Namen der Funktion zurueck. * @return name Name der Funktion. */ public String getName() { return name; } /** * Gibt alle Argumente einer Funktion als ArrayList zurueck. * @return Argumente der Funktion. */ public ArrayList<FunctionLibFunctionArg> getArg() { return argument; } /** * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss. * @return Minimale Anzahl Argumente der Funktion. */ public int getArgMin() { return argMin; } /** * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss. * @return Maximale Anzahl Argumente der Funktion. */ public int getArgMax() { return argMax; } /** * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) */ public short getStatus() { return status; } /** * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) */ public void setStatus(short status) { this.status = status; } /** * Gibt die argument art zurueck. * @return argument art */ public int getArgType() { return argType; } /** * Gibt die argument art als String zurueck. * @return argument art */ public String getArgTypeAsString() { if(argType==ARG_DYNAMIC) return "dynamic"; return "fixed"; } /** * Gibt zurueck von welchem Typ der Rueckgabewert dieser Funktion sein muss (query, string, struct, number usw.). * @return Typ des Rueckgabewert. */ public String getReturnTypeAsString() { return strReturnType; } /** * Gibt die Klassendefinition als Zeichenkette zurueck, welche diese Funktion implementiert. * @return Klassendefinition als Zeichenkette. */ public String getCls() { return cls; } /** * Gibt die Klasse zurueck, welche diese Funktion implementiert. * @return Klasse der Function. */ public Class getClazz() { if(clazz==null) { clazz=ClassUtil.loadClass(cls,(Class)null); } return clazz; } /** * Gibt die Beschreibung der Funktion zurueck. * @return String */ public String getDescription() { return description; } /** * Gibt die FunctionLib zurueck, zu der die Funktion gehoert. * @return Zugehoerige FunctionLib. */ public FunctionLib getFunctionLib() { return functionLib; } /** * Setzt den Namen der Funktion. * @param name Name der Funktion. */ public void setName(String name) { this.name = name.toLowerCase(); } /** * Fuegt der Funktion ein Argument hinzu. * @param arg Argument zur Funktion. */ public void addArg(FunctionLibFunctionArg arg) { arg.setFunction(this); argument.add(arg); if(arg.getDefaultValue()!=null) hasDefaultValues=true; } /** * Fuegt der Funktion ein Argument hinzu, alias fuer addArg. * @param arg Argument zur Funktion. */ public void setArg(FunctionLibFunctionArg arg) { addArg(arg); } /** * Setzt wieviele Argumente eine Funktion minimal haben muss. * @param argMin Minimale Anzahl Argumente der Funktion. */ public void setArgMin(int argMin) { this.argMin = argMin; } /** * Setzt wieviele Argumente eine Funktion minimal haben muss. * @param argMax Maximale Anzahl Argumente der Funktion. */ public void setArgMax(int argMax) { this.argMax = argMax; } /** * Setzt den Rueckgabewert der Funktion (query,array,string usw.) * @param value */ public void setReturn(String value) { strReturnType=value; } /** * Setzt die Klassendefinition als Zeichenkette, welche diese Funktion implementiert. * @param value Klassendefinition als Zeichenkette. */ public void setCls(String value) { cls+=value; } /** * Setzt die Beschreibung der Funktion. * @param description Beschreibung der Funktion. */ public void setDescription(String description) { this.description = description; } /** * Setzt die zugehoerige FunctionLib. * @param functionLib Zugehoerige FunctionLib. */ public void setFunctionLib(FunctionLib functionLib) { this.functionLib=functionLib; } /** * sets the argument type of the function * @param argType */ public void setArgType(int argType) { this.argType=argType; } public String getHash() { StringBuffer sb=new StringBuffer(); sb.append(this.getArgMax()); sb.append(this.getArgMin()); sb.append(this.getArgType()); sb.append(this.getArgTypeAsString()); sb.append(this.getCls()); sb.append(this.getName()); sb.append(this.getReturnTypeAsString()); Iterator it = this.getArg().iterator(); FunctionLibFunctionArg arg; while(it.hasNext()){ arg=(FunctionLibFunctionArg) it.next(); sb.append(arg.getHash()); } try { return Md5.getDigestAsString(sb.toString()); } catch (IOException e) { return ""; } } public boolean hasDefaultValues() { return hasDefaultValues; } public boolean hasTteClass() { return tteClass !=null && tteClass.length()>0; } public FunctionEvaluator getEvaluator() throws TemplateException { if(!hasTteClass()) return null; if(eval!=null) return eval; try { eval = (FunctionEvaluator) ClassUtil.loadInstance(tteClass); } catch (ClassException e) { throw new TemplateException(e.getMessage()); } return eval; } public void setTteClass(String tteClass) { this.tteClass=tteClass; } public void setMemberName(String memberName) { if(StringUtil.isEmpty(memberName,true)) return; this.memberName=memberName.trim(); } public String getMemberName() { return memberName; } public void setMemberChaining(boolean memberChaining) { this.memberChaining=memberChaining; } public boolean getMemberChaining() { return memberChaining; } public short getMemberType() { if(memberName!=null && memberType==CFTypes.TYPE_UNKNOW){ ArrayList<FunctionLibFunctionArg> args = getArg(); if(args.size()>=1){ memberType=CFTypes.toShortStrict(args.get(0).getTypeAsString(),CFTypes.TYPE_UNKNOW); } } return memberType; } public String getMemberTypeAsString() { return CFTypes.toString(getMemberType(),"any"); } public BIF getBIF() { if(bif!=null) return bif; Class clazz=getClazz(); if(clazz==null)throw new PageRuntimeException(new ExpressionException("class "+clazz+" not found")); if(Reflector.isInstaneOf(clazz, BIF.class)) { try { bif=(BIF)clazz.newInstance(); } catch (Throwable t) { throw new RuntimeException(t); } } else { return new BIFProxy(clazz); } return bif; } }