Package railo.runtime.type.util

Source Code of railo.runtime.type.util.UDFUtil

package railo.runtime.type.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import railo.commons.digest.HashUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.Page;
import railo.runtime.PageContext;
import railo.runtime.PagePlus;
import railo.runtime.PageSource;
import railo.runtime.dump.DumpData;
import railo.runtime.dump.DumpProperties;
import railo.runtime.dump.DumpRow;
import railo.runtime.dump.DumpTable;
import railo.runtime.dump.SimpleDumpData;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.exp.PageExceptionImpl;
import railo.runtime.op.Caster;
import railo.runtime.op.Decision;
import railo.runtime.type.Collection;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.FunctionArgument;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.UDF;
import railo.runtime.type.UDFGSProperty;
import railo.runtime.type.UDFPlus;
import railo.runtime.type.scope.Argument;
import railo.runtime.type.scope.ArgumentIntKey;
import railo.transformer.library.function.FunctionLibFunction;
import railo.transformer.library.function.FunctionLibFunctionArg;

public class UDFUtil {

  private static final char CACHE_DEL = ';';
  private static final char CACHE_DEL2 = ':';

  private static final FunctionArgument[] EMPTY = new FunctionArgument[0];
 
  /**
   * add detailed function documentation to the exception
   * @param pe
   * @param flf
   */
  public static void addFunctionDoc(PageExceptionImpl pe,FunctionLibFunction flf) {
    ArrayList<FunctionLibFunctionArg> args=flf.getArg();
    Iterator<FunctionLibFunctionArg> it = args.iterator();
   
    // Pattern
    StringBuilder pattern=new StringBuilder(flf.getName());
    StringBuilder end=new StringBuilder();
    pattern.append("(");
    FunctionLibFunctionArg arg;
    int c=0;
    while(it.hasNext()){
      arg = it.next();
      if(!arg.isRequired()) {
        pattern.append(" [");
        end.append("]");
      }
      if(c++>0)pattern.append(", ");
      pattern.append(arg.getName());
      pattern.append(":");
      pattern.append(arg.getTypeAsString());
     
    }
    pattern.append(end);
    pattern.append("):");
    pattern.append(flf.getReturnTypeAsString());
   
    pe.setAdditional(KeyConstants._Pattern, pattern);
   
    // Documentation
    StringBuilder doc=new StringBuilder(flf.getDescription());
    StringBuilder req=new StringBuilder();
    StringBuilder opt=new StringBuilder();
    StringBuilder tmp;
    doc.append("\n");
   
    it = args.iterator();
    while(it.hasNext()){
      arg = it.next();
      tmp=arg.isRequired()?req:opt;
     
      tmp.append("- ");
      tmp.append(arg.getName());
      tmp.append(" (");
      tmp.append(arg.getTypeAsString());
      tmp.append("): ");
      tmp.append(arg.getDescription());
      tmp.append("\n");
    }

    if(req.length()>0)doc.append("\nRequired:\n").append(req);
    if(opt.length()>0)doc.append("\nOptional:\n").append(opt);
   
   
    pe.setAdditional(KeyImpl.init("Documentation"), doc);
   
  }

  public static String callerHash(UDF udf, Object[] args, Struct values) throws ApplicationException {
    StringBuilder sb=new StringBuilder()
      .append(HashUtil.create64BitHash(udf.getPageSource().getDisplayPath()))
      .append(CACHE_DEL)
      .append(HashUtil.create64BitHash(udf.getFunctionName()))
      .append(CACHE_DEL);
   
   
    if(values!=null) {
      Iterator<Entry<Key, Object>> it = values.entryIterator();
      Entry<Key, Object> e;
      while(it.hasNext()){
        e = it.next();
        if(!Decision.isSimpleValue(e.getValue())) throw new ApplicationException("only simple values are allowed as parameter for a function with cachedWithin");
        sb.append(((KeyImpl)e.getKey()).hash()).append(CACHE_DEL2).append(HashUtil.create64BitHash(e.getValue().toString())).append(CACHE_DEL);
       
      }
    }
    else if(args!=null){
      for(int i=0;i<args.length;i++){
        if(!Decision.isSimpleValue(args[i])) throw new ApplicationException("only simple values are allowed as parameter for a function with cachedWithin");
        sb.append(HashUtil.create64BitHash(args[i].toString())).append(CACHE_DEL);
       
      }
    }
    return HashUtil.create64BitHashAsString(sb, Character.MAX_RADIX);
  }

  public static Object getDefaultValue(PageContext pc, PageSource ps, int udfIndex, int index, Object defaultValue) throws PageException {
    Page p=ComponentUtil.getPage(pc,ps);
      if(p instanceof PagePlus) return ((PagePlus)p).udfDefaultValue(pc,udfIndex,index,defaultValue);
      Object rtn = p.udfDefaultValue(pc,udfIndex,index);
      if(rtn==null) return defaultValue;// in that case it can make no diff between null and not existing, but this only happens with data from old ra files
      return rtn;
  }
 

  public static Object getDefaultValue(PageContext pc, UDFPlus udf, int index, Object defaultValue) throws PageException {
    Page p=ComponentUtil.getPage(pc,udf.getPageSource());
    if(p instanceof PagePlus) return ((PagePlus)p).udfDefaultValue(pc,udf.getIndex(),index,defaultValue);
    Object rtn = p.udfDefaultValue(pc,udf.getIndex(),index);
      if(rtn==null) return defaultValue;// in that case it can make no diff between null and not existing, but this only happens with data from old ra files
      return rtn;
  }

  public static void argumentCollection(Struct values) {
    argumentCollection(values,EMPTY);
  }

  public static void argumentCollection(Struct values, FunctionArgument[] funcArgs) {
    Object value=values.removeEL(KeyConstants._argumentCollection);
    if(value !=null) {
      value=Caster.unwrap(value,value);
     
      if(value instanceof Argument) {
        Argument argColl=(Argument) value;
        Iterator<Key> it = argColl.keyIterator();
        Key k;
        int i=-1;
          while(it.hasNext()) {
            i++;
            k = it.next();
            if(funcArgs.length>i && k instanceof ArgumentIntKey) {
                  if(!values.containsKey(funcArgs[i].getName()))
                    values.setEL(funcArgs[i].getName(),argColl.get(k,Argument.NULL));
                  else
                    values.setEL(k,argColl.get(k,Argument.NULL));
            }
                else if(!values.containsKey(k)){
                  values.setEL(k,argColl.get(k,Argument.NULL));
                }
              }
        }
      else if(value instanceof Collection) {
            Collection argColl=(Collection) value;
          //Collection.Key[] keys = argColl.keys();
        Iterator<Key> it = argColl.keyIterator();
        Key k;
        while(it.hasNext()) {
            k = it.next();
            if(!values.containsKey(k)){
                  values.setEL(k,argColl.get(k,Argument.NULL));
                }
              }
        }
      else if(value instanceof Map) {
        Map map=(Map) value;
          Iterator it = map.entrySet().iterator();
          Map.Entry entry;
          Key key;
          while(it.hasNext()) {
            entry=(Entry) it.next();
            key = Caster.toKey(entry.getKey(),null);
            if(!values.containsKey(key)){
                  values.setEL(key,entry.getValue());
                }
              }
        }
      else if(value instanceof java.util.List) {
        java.util.List list=(java.util.List) value;
          Iterator it = list.iterator();
          Object v;
          int index=0;
          Key k;
          while(it.hasNext()) {
            v= it.next();
            k=ArgumentIntKey.init(++index);
            if(!values.containsKey(k)){
                  values.setEL(k,v);
                }
              }
        }
        else {
            values.setEL(KeyConstants._argumentCollection,value);
        }
    }
  }
 
  public static String toReturnFormat(int returnFormat,String defaultValue) {
    if(UDF.RETURN_FORMAT_WDDX==returnFormat)    return "wddx";
    else if(UDF.RETURN_FORMAT_JSON==returnFormatreturn "json";
    else if(UDF.RETURN_FORMAT_PLAIN==returnFormatreturn "plain";
    else if(UDF.RETURN_FORMAT_SERIALIZE==returnFormatreturn "cfml";
    else if(UDFPlus.RETURN_FORMAT_JAVA==returnFormatreturn "java";
    // NO XML else if(UDFPlus.RETURN_FORMAT_XML==returnFormat)  return "xml";
    else return defaultValue;
  }
 

  public static boolean isValidReturnFormat(int returnFormat) {
    return toReturnFormat(returnFormat,null)!=null;
  }
 

  public static int toReturnFormat(String[] returnFormats, int defaultValue) {
    if(ArrayUtil.isEmpty(returnFormats)) return defaultValue;
    int rf;
    for(int i=0;i<returnFormats.length;i++){
      rf=toReturnFormat(returnFormats[i].trim(), -1);
      if(rf!=-1) return rf;
    }
    return defaultValue;
  }
  public static int toReturnFormat(String returnFormat, int defaultValue) {
    if(StringUtil.isEmpty(returnFormat,true)) return defaultValue;
   
    returnFormat=returnFormat.trim().toLowerCase();
    if("wddx".equals(returnFormat))        return UDF.RETURN_FORMAT_WDDX;
    else if("json".equals(returnFormat))    return UDF.RETURN_FORMAT_JSON;
    else if("plain".equals(returnFormat))    return UDF.RETURN_FORMAT_PLAIN;
    else if("text".equals(returnFormat))    return UDF.RETURN_FORMAT_PLAIN;
    else if("serialize".equals(returnFormat))  return UDF.RETURN_FORMAT_SERIALIZE;
    else if("cfml".equals(returnFormat))  return UDF.RETURN_FORMAT_SERIALIZE;
    else if("cfm".equals(returnFormat))  return UDF.RETURN_FORMAT_SERIALIZE;
    else if("xml".equals(returnFormat))  return UDF.RETURN_FORMAT_XML;
    else if("java".equals(returnFormat))  return UDFPlus.RETURN_FORMAT_JAVA;
    return defaultValue;
  }
 

  public static int toReturnFormat(String returnFormat) throws ExpressionException {
    int rf = toReturnFormat(returnFormat,-1);
    if(rf!=-1) return rf;
    throw new ExpressionException("invalid returnFormat definition ["+returnFormat+"], valid values are [wddx,plain,json,cfml]");
  }

  public static String toReturnFormat(int returnFormat) throws ExpressionException {
    if(UDF.RETURN_FORMAT_WDDX==returnFormat)    return "wddx";
    else if(UDF.RETURN_FORMAT_JSON==returnFormatreturn "json";
    else if(UDF.RETURN_FORMAT_PLAIN==returnFormatreturn "plain";
    else if(UDF.RETURN_FORMAT_SERIALIZE==returnFormatreturn "cfml";
    else if(UDFPlus.RETURN_FORMAT_JAVA==returnFormatreturn "java";
    else throw new ExpressionException("invalid returnFormat definition, valid values are [wddx,plain,json,cfml]");
  }
 

  public static DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp,UDF udf, boolean closure) {
 
    if(!dp.getShowUDFs())
      return new SimpleDumpData(closure?"<Closure>":"<UDF>");
   
    // arguments
    FunctionArgument[] args = udf.getFunctionArguments();
       
        DumpTable atts = closure?new DumpTable("udf","#ff00ff","#ffccff","#000000"):new DumpTable("udf","#cc66ff","#ffccff","#000000");
       
    atts.appendRow(new DumpRow(63,new DumpData[]{new SimpleDumpData("label"),new SimpleDumpData("name"),new SimpleDumpData("required"),new SimpleDumpData("type"),new SimpleDumpData("default"),new SimpleDumpData("hint")}));
    for(int i=0;i<args.length;i++) {
      FunctionArgument arg=args[i];
      DumpData def;
      try {
        Object oa=null;
                try {
                    oa = UDFUtil.getDefaultValue(pageContext, (UDFPlus)udf, i, null);//udf.getDefaultValue(pageContext,i,null);
                } catch (PageException e1) {
                }
                if(oa==null)oa="null";
        def=new SimpleDumpData(Caster.toString(oa));
      } catch (PageException e) {
        def=new SimpleDumpData("");
      }
      atts.appendRow(new DumpRow(0,new DumpData[]{
          new SimpleDumpData(arg.getDisplayName()),
          new SimpleDumpData(arg.getName().getString()),
          new SimpleDumpData(arg.isRequired()),
          new SimpleDumpData(arg.getTypeAsString()),
          def,
          new SimpleDumpData(arg.getHint())}));
      //atts.setRow(0,arg.getHint());
     
    }
   
    DumpTable func = closure?new DumpTable("#ff00ff","#ffccff","#000000"):new DumpTable("#cc66ff","#ffccff","#000000");
    if(closure) func.setTitle("Closure");
    else {
      String f="Function ";
      try {
        f=StringUtil.ucFirst(ComponentUtil.toStringAccess(udf.getAccess()).toLowerCase())+" "+f;
      }
      catch (ExpressionException e) {}
      f+=udf.getFunctionName();
      if(udf instanceof UDFGSProperty) f+=" (generated)";
      func.setTitle(f);
    }

    if(udf instanceof UDFPlus)func.setComment("source:"+((UDFPlus)udf).getPageSource().getDisplayPath());

    if(!StringUtil.isEmpty(udf.getDescription()))func.setComment(udf.getDescription());
   
    func.appendRow(1,new SimpleDumpData("arguments"),atts);
    func.appendRow(1,new SimpleDumpData("return type"),new SimpleDumpData(udf.getReturnTypeAsString()));
   
    boolean hasLabel=!StringUtil.isEmpty(udf.getDisplayName());//displayName!=null && !displayName.equals("");
    boolean hasHint=!StringUtil.isEmpty(udf.getHint());//hint!=null && !hint.equals("");
   
    if(hasLabel || hasHint) {
      DumpTable box = new DumpTable("#ffffff","#cccccc","#000000");
      box.setTitle(hasLabel?udf.getDisplayName():udf.getFunctionName());
      if(hasHint)box.appendRow(0,new SimpleDumpData(udf.getHint()));
      box.appendRow(0,func);
      return box;
    }
    return func;
  }


}
TOP

Related Classes of railo.runtime.type.util.UDFUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.