Package jfun.yan.xml

Source Code of jfun.yan.xml.NutsUtils

package jfun.yan.xml;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TimeZone;

import jfun.util.DateUtil;
import jfun.util.Misc;
import jfun.util.beans.BeanType;
import jfun.util.os.PathTokenizer;
import jfun.yan.Binder;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Creator;
import jfun.yan.Monad;
import jfun.yan.Mutation;
import jfun.yan.util.ReflectionUtil;
import jfun.yan.util.Utils;
import jfun.yan.util.deserializer.Deserializer;

/**
* A common utility class for various Nuts helper functions.
* <p>
* @author Ben Yu
*
*/
public class NutsUtils {

  /**
   * To split a string into an array of sub-strings.
   * @param str the string to split.
   * @param sep the separator characters.
   * @return an array of sub-strings who are seperated by
   * one or many of the characters in the sep string.
   */
  public static String[] split(String str, String sep){
    final StringTokenizer tok = new StringTokenizer(str, sep);
    final ArrayList buf = new ArrayList();
    while(tok.hasMoreTokens()){
      buf.add(tok.nextToken().trim());
    }
    final String[] result = new String[buf.size()];
    buf.toArray(result);
    return result;
  }
  private static final HashMap booleans = getBooleanMap();
  private static HashMap getBooleanMap(){
    final HashMap r = new HashMap();
    r.put("on", Boolean.valueOf(true));
    r.put("yes", Boolean.valueOf(true));
    r.put("true", Boolean.valueOf(true));
    r.put("off", Boolean.valueOf(false));
    r.put("no", Boolean.valueOf(false));
    r.put("false", Boolean.valueOf(false));
    return r;
  }
  /**
   * To convert a string literal to boolean.
   * @param str the string literal
   * @return Boolean object. null if the string is not recognized.
   */
  public static Boolean toBoolean(String str){
    return (Boolean)booleans.get(str);
  }
  /**
   * Convert a string to a File. if the string represents
   * a relative path, it is treated as relative to the basedir.
   * @param basedir the base directory.
   * @param path the string.
   * @return the File object.
   */
  public static File toFile(File basedir, String path){
    final File f = new File(path);
    if(f.isAbsolute() || f.getPath().startsWith("/")){
      return f;
    }
    else{
      return new File(basedir, path);
    }
  }
  /**
   * Convert a string to a URL. if the string represents
   * a relative path, it is treated as relative to the basedir.
   * @param basedir the base directory.
   * @param str the string.
   * @return the URL object.
   * @throws MalformedURLException if the string represents neither a file nor a URL.
   */
  public static URL toUrl(File basedir, String str)
  throws MalformedURLException{
    try{
      return new URL(str);
    }
    catch(MalformedURLException e){
      return toFile(basedir, str).toURL();
    }
  }
  /**
   * To convert a string literal to a URI object.
   * @param str the string literal.
   * @return the URI object.
   * @throws URISyntaxException if the uri syntax is wrong.
   */
  public static URI toUri(String str)
  throws URISyntaxException{
    return new URI(str);
  }
  private static void populate(Map m, Class t, Deserializer des){
    m.put(t, des);
    m.put(ReflectionUtil.toObjectType(t), des);
  }


  //private static HashMap deserializers = getDeserializers();
 
  static HashMap getDeserializers(){
    final HashMap hmap = new HashMap();
    populate(hmap, boolean.class, new Deserializer(){
      public Object deserialize(String str){
        return toBoolean(str);
      }
    });
    populate(hmap, char.class, new Deserializer(){
      public Object deserialize(String str){
        if(str.length()!=1){
          throw new IllegalArgumentException("cannot convert string to character");
        }
        return new Character(str.charAt(0));
      }
    });
    populate(hmap, byte.class, new Deserializer(){
      public Object deserialize(String str){
        return Byte.valueOf(str);
      }
    });
    populate(hmap, short.class, new Deserializer(){
      public Object deserialize(String str){
        return Short.valueOf(str);
      }
    });
    final Deserializer int_des = new Deserializer(){
      public Object deserialize(String str){
        return Integer.valueOf(str);
      }
    };
    populate(hmap, int.class, int_des);
    populate(hmap, Number.class, int_des);
    populate(hmap, long.class, new Deserializer(){
      public Object deserialize(String str){
        return Long.valueOf(str);
      }
    });
    populate(hmap, float.class, new Deserializer(){
      public Object deserialize(String str){
        return Float.valueOf(str);
      }
    });
    populate(hmap, double.class, new Deserializer(){
      public Object deserialize(String str){
        return Double.valueOf(str);
      }
    });
    populate(hmap, BigInteger.class, new Deserializer(){
      public Object deserialize(String str){
        return new BigInteger(str);
      }     
    });
    populate(hmap, BigDecimal.class, new Deserializer(){
      public Object deserialize(String str){
        return new BigDecimal(str);
      }
    });
    final Deserializer component_des = new Deserializer(){
      public Object deserialize(String str){
        return asComponent(str);
      }
    };
    populate(hmap, Creator.class, component_des);
    populate(hmap, Component.class, component_des);
    populate(hmap, URL.class, new Deserializer(){
      public Object deserialize(String str)
      throws MalformedURLException{
        return new URL(str);
      }
    });
    populate(hmap, URI.class, new Deserializer(){
      public Object deserialize(String str)
      throws URISyntaxException{
        return toUri(str);
      }
    });
    populate(hmap, Date.class, new Deserializer(){
      public Object deserialize(String str)
      throws ParseException{
        return DateFormat.getInstance().parseObject(str);
      }
    });
    populate(hmap, Locale.class, new Deserializer(){
      public Object deserialize(String str){
        return DateUtil.parseLocale(str);
      }
    });
    populate(hmap, TimeZone.class, new Deserializer(){
      public Object deserialize(String str){
        return TimeZone.getTimeZone(str);
      }
    });
    populate(hmap, Class.class, new Deserializer(){
      public Object deserialize(String str)
      throws ClassNotFoundException{
        return Class.forName(str);
      }
    });
    populate(hmap, File.class, new Deserializer(){
      public Object deserialize(String str){
        return new File(str);
      }
    });
    return hmap;
  }
  /**
   * Convert a string to an array of URL. The
   * string contains a series of sub-string seperated by whitespaces
   * or "," or ";"
   * @param basedir the base directory to resolve relative path.
   * @param str the string.
   * @return the array of URL
   * @throws MalformedURLException if any sub-string is not convertible to URL.
   */
  public static URL[] toUrls(File basedir, String str)
  throws MalformedURLException{
    final List result = new ArrayList();
    PathTokenizer tok = new PathTokenizer(str);
    while (tok.hasMoreTokens()) {
      final String element = tok.nextToken();
      result.add(toUrl(basedir, element));
    }
    final URL[] ret = new URL[result.size()];
    result.toArray(ret);
    return ret;
  }
  private static boolean isIdentifierStart(char c){
    return c=='/' || c!='$' && Character.isJavaIdentifierStart(c);
  }
  private static boolean isIdentifierPart(char c){
    return c=='_' || c=='.' || c==' ' || c=='-' || c=='/' ||
    Character.isLetter(c)||Character.isDigit(c);
  }
  /**
   * To determine if a string is a valid id in yan xml config file.
   * @param str the string.
   * @return true if valid.
   */
  public static boolean isValidId(String str){
    final int len = str.length();
    if(str==null || len==0) return false;
    if(!isIdentifierStart(str.charAt(0)))
      return false;
    int i=1;
    for(; i<len; i++){
      final char c = str.charAt(i);
      if(c=='\'')break;
      if(!isIdentifierPart(c))
        return false;
    }
    for(++i;i<len;i++){
      final char c = str.charAt(i);
      if(c!='\''){
        return false;
      }
    }
    return true;
  }
 
  static String getTypeName(Object v){
    if(v==null) return null;
    else return Misc.getTypeName(v.getClass());
  }
  /**
   * Call a NutsFunction object with an array of arguments.
   * @param nfun the NutsFunction object.
   * @param args the arguments.
   * @return the result.
   */
  public static Object callFunction(NutsFunction nfun, Object[] args) {
    final int params = nfun.getParameterCount();
    if(params!=args.length){
      throw new IllegalArgumentException(""+params+" parameter expected by function "+nfun.getName()
          + ", while "+args.length+" arguments provided.");
    }
    return nfun.call(args);
  }
  /**
   * Call a NutsFunction object with a map of parameter name to argument value.
   * @param nfun the function.
   * @param arg_map the map of the argument values.
   * @return the result.
   */
  public static Object callFunction(NutsFunction nfun,
      final Map arg_map){
    final String[] params = nfun.getParameterNames();
    if(params.length!=arg_map.size()){
      throw new IllegalArgumentException(""+params.length
          +" parameter expected by function "+nfun.getName()
          + ", while "+arg_map.size()+" arguments provided.");
    }
    final Object[] args = new Object[params.length];
    for(int i=0; i<params.length; i++){
      final String name = params[i];
      if(!arg_map.containsKey(name)){
        throw new IllegalArgumentException("missing parameter "
            + name + " for function "+nfun.getName());
      }
      args[i] = arg_map.get(name);
    }
    return nfun.call(args);
  }
  /**
   * Convert an object to Component.
   * Conversion is automatically done if necessary.
   * @param val the value to be converted to Component.
   * @return the Component.
   */
  public static Component asComponent(Object val){
    if(val==null) return Components.value(null);
    else if(val instanceof Creator)
      return Components.adapt((Creator)val);
    else if(val instanceof NutsFunction){
      return Components.fun(new NutsFunction2Function((NutsFunction)val))
        .bind(Monad.instantiator());
    }
    else if(val instanceof Binder){
      return Utils.asComponent((Binder)val);
    }
    else{
      return Components.value(val);
    }
  }
  /**
   * Canonicalize an attribute name by replacing "-" with "_".
   * @param name the attribute name.
   * @return the new attribute name, or null if the attribute name is null.
   */
  public static String canonicalizeAttributeName(String name){
    if(name==null) return name;
    return name.replace('-', '_');
  }
  /**
   * To get a ClassLoader object that uses a base ClassLoader object
   * as parent and alternatively searches a classpath if the class
   * or resource is not found in parent.
   * @param baseloader the base class loader.
   * @param classpath the alternative classpath.
   * @param basedir the base directory used in the classpath.
   * @return the ClassLoader object.
   * @throws MalformedURLException if the classpath is invalid.
   */
  public static ClassLoader getClassLoader(ClassLoader baseloader,
      String classpath, File basedir)
  throws MalformedURLException{
    if(classpath != null){
      return new URLClassLoader(
          NutsUtils.toUrls(basedir, classpath)
          , baseloader);
    }
    else return baseloader;
  }
 
  /**
   * Add named state to a Component object.
   * @param c the Component object.
   * @param key the key of the state.
   * @param val the value of the state.
   * @return the new Component object with this state.
   */
  public static Component setState(Component c, Object key, Object val){
    java.util.Map carrier = (java.util.Map)c.getState();
    if(carrier==null){
      //to save space, we don't leave a lot of empty space in the map.
      carrier = new HashMap(4);
      c = c.withState(carrier);
    }
    carrier.put(key, val);
    return c;
  }
  /**
   * Get a state value by name.
   * @param c the Component object to get state from.
   * @param key the state key.
   * @return the state value.
   */
  public static Object getState(Component c, Object key){
    final java.util.Map carrier = (java.util.Map)c.getState();
    if(carrier==null) return null;
    else return carrier.get(key);
  }
 
  /**
   * If a property of the component type exists and the property type is
   * compatible with the property value, the property is set when
   * the component is instantiated.
   * @param c the component.
   * @param name the property name.
   * @param val the property value.
   * @return the result Component.
   * @throws IntrospectionException
   */
  public static Component setPossiblePropertyValue(Component c, String name, Object val)
  throws IntrospectionException{
    final Method mtd = getPossiblePropertySetter(c, name);
    if(mtd==null) return c;
    final Class[] param_types = mtd.getParameterTypes();
    if(param_types.length!=1){
      return c;
    }
    final Class param_type = param_types[0];
    if(ReflectionUtil.isInstance(param_type, val)){
      final Object[] args = {val};
      return c.mutate(new Mutation(){
        public void mutate(Object obj)
        throws Exception{
          mtd.invoke(obj, args);
        }
      });
    }
    return c;
  }
  public static Component setPossibleProperty(Component c, String name,
      final Component valc)
  throws IntrospectionException{
    final Method mtd = getPossiblePropertySetter(c, name);
    if(mtd==null) return c;
    final Class[] param_types = mtd.getParameterTypes();
    if(param_types.length!=1){
      return c;
    }
    final Class param_type = param_types[0];
    final Class argtype = valc.getType();
    if(argtype!=null && !ReflectionUtil.isAssignableFrom(param_type, argtype)){
      return c;
    }
    return c.followedBy(new Binder(){
      public Creator bind(final Object obj){
        return valc.mutate(new Mutation(){
          public void mutate(Object arg) throws Exception {
            if(ReflectionUtil.isInstance(param_type, arg)){
              mtd.invoke(obj, new Object[]{arg});
            }
          }
        });
      }
    });
  }
  private static Method getPossiblePropertySetter(Component c, String name)
  throws IntrospectionException{
    if(name==null||name.length()==0) return null;
    final Class type = c.getType();
    if(type==null){
      //unknown type, do not set property.
      return null;
    }
    final BeanType beantype = BeanType.instance(type);
    final PropertyDescriptor prop = beantype.getPropertyDescriptor(name);
    if(prop == null) return null;
    final Method mtd = prop.getWriteMethod();
    return mtd;
  }
}
TOP

Related Classes of jfun.yan.xml.NutsUtils

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.