001    package railo.transformer.library.function;
002    
003    import java.io.IOException;
004    import java.util.ArrayList;
005    import java.util.Iterator;
006    
007    import railo.commons.lang.CFTypes;
008    import railo.commons.lang.ClassException;
009    import railo.commons.lang.ClassUtil;
010    import railo.commons.lang.Md5;
011    import railo.commons.lang.StringUtil;
012    import railo.runtime.exp.ExpressionException;
013    import railo.runtime.exp.PageRuntimeException;
014    import railo.runtime.exp.TemplateException;
015    import railo.runtime.functions.BIF;
016    import railo.runtime.functions.BIFProxy;
017    import railo.runtime.reflection.Reflector;
018    import railo.transformer.cfml.evaluator.FunctionEvaluator;
019    import railo.transformer.library.tag.TagLib;
020    
021    
022    
023    /**
024     * Eine FunctionLibFunction repraesentiert eine einzelne Funktion innerhalb einer FLD.
025     */
026    public final class FunctionLibFunction {
027            
028            /**
029             * Dynamischer Argument Typ
030             */
031            public static final int ARG_DYNAMIC = 0;
032            /**
033             * statischer Argument Typ
034             */
035            public static final int ARG_FIX = 1;
036    
037             
038            private FunctionLib functionLib;
039            private String name;
040            private ArrayList<FunctionLibFunctionArg> argument=new ArrayList<FunctionLibFunctionArg>();
041            
042            private int argMin=0;
043            private int argMax=-1;
044            private int argType=ARG_FIX;
045            
046    
047            private String strReturnType;
048    
049            private String cls="";
050            private Class clazz;
051            private String description;
052            private boolean hasDefaultValues;
053            private FunctionEvaluator eval;
054            private String tteClass;        
055            private short status=TagLib.STATUS_IMPLEMENTED;
056            private String memberName;
057            private short memberType=CFTypes.TYPE_UNKNOW;
058            private boolean memberChaining;
059            private BIF bif;
060    
061            
062            /**
063             * Geschuetzer Konstruktor ohne Argumente.
064             */
065            public FunctionLibFunction() {
066            }
067            public FunctionLibFunction(FunctionLib functionLib) {
068                            this.functionLib=functionLib;
069            }
070            
071            /**
072             * Gibt den Namen der Funktion zurueck.
073             * @return name Name der Funktion.
074             */
075            public String getName() {
076                    return name;
077            }
078            
079            /**
080            * Gibt alle Argumente einer Funktion als ArrayList zurueck.
081            * @return Argumente der Funktion.
082            */
083       public ArrayList<FunctionLibFunctionArg> getArg() {
084               return argument;
085       }
086    
087            /**
088             * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss.
089             * @return Minimale Anzahl Argumente der Funktion.
090             */
091            public int getArgMin() {
092                    return argMin;
093            }
094            
095            /**
096             * Gibt zurueck wieviele Argumente eine Funktion minimal haben muss.
097             * @return Maximale Anzahl Argumente der Funktion.
098             */
099            public int getArgMax() {
100                    return argMax;
101            }
102            
103            /**
104             * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED)
105             */
106            public short getStatus() {
107                    return status;
108            }
109    
110    
111            /**
112             * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED)
113             */
114            public void setStatus(short status) {
115                    this.status = status;
116            }
117            
118            
119            /**
120             * Gibt die argument art zurueck.
121             * @return argument art
122             */
123            public int getArgType() {
124                    return argType;
125            }
126            
127            /**
128             * Gibt die argument art als String zurueck.
129             * @return argument art
130             */
131            public String getArgTypeAsString() {
132                    if(argType==ARG_DYNAMIC) return "dynamic";
133                    return "fixed";
134            }
135    
136            /**
137             * Gibt zurueck von welchem Typ der Rueckgabewert dieser Funktion sein muss (query, string, struct, number usw.).
138             * @return Typ des Rueckgabewert.
139             */
140            public String getReturnTypeAsString() {
141                    return strReturnType;
142            }
143    
144            /**
145             * Gibt die Klassendefinition als Zeichenkette zurueck, welche diese Funktion implementiert.
146             * @return Klassendefinition als Zeichenkette.
147             */
148            public String getCls() {
149                    return cls;
150            }
151    
152            /**
153             * Gibt die Klasse zurueck, welche diese Funktion implementiert.
154             * @return Klasse der Function.
155             */
156            public Class getClazz() {
157                    if(clazz==null) {
158                            clazz=ClassUtil.loadClass(cls,(Class)null);
159                    }
160                    return clazz;
161            }
162    
163            /**
164             * Gibt die Beschreibung der Funktion zurueck.
165             * @return String
166             */
167            public String getDescription() {
168                    return description;
169            }
170    
171            /**
172             * Gibt die FunctionLib zurueck, zu der die Funktion gehoert.
173             * @return Zugehoerige FunctionLib.
174             */
175            public FunctionLib getFunctionLib() {
176                    return functionLib;
177            }
178    
179            /**
180             * Setzt den Namen der Funktion.
181             * @param name Name der Funktion.
182             */
183            public void setName(String name) {
184                    this.name = name.toLowerCase();
185            }       
186    
187            /**
188             * Fuegt der Funktion ein Argument hinzu.
189             * @param arg Argument zur Funktion.
190             */
191            public void addArg(FunctionLibFunctionArg arg) {
192                    arg.setFunction(this);
193                    argument.add(arg); 
194                    if(arg.getDefaultValue()!=null)
195                            hasDefaultValues=true;
196            }
197    
198            /**
199             * Fuegt der Funktion ein Argument hinzu, alias fuer addArg.
200             * @param arg Argument zur Funktion.
201             */
202            public void setArg(FunctionLibFunctionArg arg) {
203                    addArg(arg);
204            }
205    
206    
207            /**
208             * Setzt wieviele Argumente eine Funktion minimal haben muss.
209             * @param argMin Minimale Anzahl Argumente der Funktion.
210             */
211            public void setArgMin(int argMin) {
212                    this.argMin = argMin;
213            }
214            
215            /**
216             * Setzt wieviele Argumente eine Funktion minimal haben muss.
217             * @param argMax Maximale Anzahl Argumente der Funktion.
218             */
219            public void setArgMax(int argMax) {
220                    this.argMax = argMax;
221            }
222    
223            /**
224             * Setzt den Rueckgabewert der Funktion (query,array,string usw.)
225             * @param value
226             */
227            public void setReturn(String value) {
228                    strReturnType=value;
229            }
230    
231            /**
232             * Setzt die Klassendefinition als Zeichenkette, welche diese Funktion implementiert.
233             * @param value Klassendefinition als Zeichenkette.
234             */
235            public void setCls(String value) {
236                    cls+=value;
237                    
238            }
239    
240            /**
241             * Setzt die Beschreibung der Funktion.
242             * @param description Beschreibung der Funktion.
243             */
244            public void setDescription(String description) {
245                    this.description = description;
246            }
247    
248            /**
249             * Setzt die zugehoerige FunctionLib.
250             * @param functionLib Zugehoerige FunctionLib.
251             */
252            public void setFunctionLib(FunctionLib functionLib) {
253                    this.functionLib=functionLib;
254            }
255    
256            /**
257             * sets the argument type of the function
258             * @param argType
259             */
260            public void setArgType(int argType) {
261                    this.argType=argType;
262            }
263            
264    
265            public String getHash() {
266                    StringBuffer sb=new StringBuffer();
267                    sb.append(this.getArgMax());
268                    sb.append(this.getArgMin());
269                    sb.append(this.getArgType());
270                    sb.append(this.getArgTypeAsString());
271                    sb.append(this.getCls());
272                    sb.append(this.getName());
273                    sb.append(this.getReturnTypeAsString());
274                    
275                    Iterator it = this.getArg().iterator();
276                    FunctionLibFunctionArg arg;
277                    while(it.hasNext()){
278                            arg=(FunctionLibFunctionArg) it.next();
279                            sb.append(arg.getHash());
280                    }
281                    
282                    try {
283                            return Md5.getDigestAsString(sb.toString());
284                    } catch (IOException e) {
285                            return "";
286                    }
287            }
288            public boolean hasDefaultValues() {
289                    return hasDefaultValues;
290            }
291    
292            public boolean hasTteClass() {
293                    return tteClass !=null && tteClass.length()>0;
294            }
295            
296            public FunctionEvaluator getEvaluator() throws TemplateException {
297                    if(!hasTteClass()) return null;
298                    if(eval!=null) return eval;
299                    try {
300                            eval = (FunctionEvaluator) ClassUtil.loadInstance(tteClass);
301                    } 
302                    catch (ClassException e) {
303                            throw new TemplateException(e.getMessage());
304                    } 
305                    return eval;
306            }
307            public void setTteClass(String tteClass) {
308                    this.tteClass=tteClass;
309            }
310            public void setMemberName(String memberName) {
311                    if(StringUtil.isEmpty(memberName,true)) return;
312                    this.memberName=memberName.trim();      
313            }
314            public String getMemberName() {
315                    return memberName;
316            }
317            public void setMemberChaining(boolean memberChaining) {
318                    this.memberChaining=memberChaining;     
319            }
320            public boolean getMemberChaining() {
321                    return memberChaining;
322            }
323            
324            public short getMemberType() {
325                    if(memberName!=null && memberType==CFTypes.TYPE_UNKNOW){
326                            ArrayList<FunctionLibFunctionArg> args = getArg();
327                            if(args.size()>=1){
328                                    memberType=CFTypes.toShortStrict(args.get(0).getTypeAsString(),CFTypes.TYPE_UNKNOW);
329                            }
330                    }
331                    return memberType;
332            }
333            public String getMemberTypeAsString() {
334                    return CFTypes.toString(getMemberType(),"any");
335            }
336            public BIF getBIF() {
337                    if(bif!=null) return bif;
338                    
339                    Class clazz=getClazz();
340            if(clazz==null)throw new PageRuntimeException(new ExpressionException("class "+clazz+" not found"));
341            
342                    if(Reflector.isInstaneOf(clazz, BIF.class)) {
343                            try {
344                                    bif=(BIF)clazz.newInstance();
345                            }
346                            catch (Throwable t) {
347                                    throw new RuntimeException(t);
348                            }
349                    }
350                    else {
351                            return new BIFProxy(clazz);
352                    }
353                    return bif;
354            }
355    }