Monday, January 29, 2018

How to use reflect.Type.Implements

see: https://stackoverflow.com/questions/18570391/check-if-struct-implements-a-given-interface

ou've unfortunately left out the essential parts (please always post complete programs), so I can only guess that the problem is in a method defined on a pointer receiver, in which case the behavior of your code is expected. Check this example and its output:

package main
import (
        "fmt"
        "reflect"
)
type Model interface {
        m()
}
func HasModels(m Model) {
        s := reflect.ValueOf(m).Elem()
        t := s.Type()
        modelType := reflect.TypeOf((*Model)(nil)).Elem()
        for i := 0; i < s.NumField(); i++ {
                f := t.Field(i)
                fmt.Printf("%d: %s %s -> %t\n", i, f.Name, f.Type, f.Type.Implements(modelType))
        }
}
type Company struct{}
func (Company) m() {}
type Department struct{}
func (*Department) m() {}
type User struct {
        CompanyA    Company
        CompanyB    *Company
        DepartmentA Department
        DepartmentB *Department
}

Tuesday, January 23, 2018

docker file. jre and libfontconfig resolve jdk graph2d problem.

# jre-libfontconfig
docker file. jre and libfontconfig resolve jdk graph2d problem.

# why

because china get Get:2 http://cdn-fastly.deb.debian.org/debian sid/main amd64 Packages [10.5 MB]
is very slow, so create one docker image, that no need fetch libfontconfig each time.

blogs: https://blogs.pkstate.com

Dockerfile:
FROM openjdk:9-jre-slim
RUN apt-get update -y && apt-get install -y libfontconfig

# Last

thanks!
now, your can used docker image: pkrss/jre-libfontconfig:latest

# other tutorial draft

build dockerfile (ex: pkrss/jre-libfontconfig):
docker build -t pkrss/jre-libfontconfig:latest .

publish image from local to docker.io:
docker tag pkrss/jre-libfontconfig:latest docker.io/pkrss/jre-libfontconfig:latest
docker login --username="your user name" --password="your password" docker.io
docker push docker.io/pkrss/jre-libfontconfig:latest
docker logout docker.io

above content, "pkrss/jre-libfontconfig" is sample name, your must change to your owner dockerfile image name in your project.

Wednesday, January 17, 2018

go lang get struct field value by field name through reflect method

What
i want to used go lang reflect method to get struct field value by dynamic reflect.

How
func getStructFieldSimple(v interface{}, field string) interface{} {

    if v == nil || field == "" {
        return nil
    }

    val := reflect.ValueOf(v)

    if val.Kind() == reflect.Ptr {
        val = val.Elem()
    }

    field = strings.ToLower(field)

    c := val.NumField()
    for i := 0; i < c; i++ {
        valueField := val.Field(i)
        typeField := val.Type().Field(i)

        if strings.ToLower(typeField.Name) == field {
            return valueField.Interface()
        }

        // tag := typeField.Tag
        // fmt.Printf("Field Name: %s,\t Field Value: %v,\t Tag Value: %s\n", typeField.Name, valueField.Interface(), tag.Get("tag_name"))
    }
    return nil
}
Last
Thanks!

Tuesday, January 16, 2018

how to get generic class method return type and parameters class type by dynamic java reflect.

1.What

i want to get generic class method return type and method parameters and parameters class type by dynamic java reflect.

For example code:
////////////////////////////////////////////////////////////

class UserDomain {}

public interface BaseService<T> {
    T selectOne(T record); 
}

public interface UserService extends BaseService<UserDomain> { }

public interface MyMapper<T> { }

public interface UserDomainMapper extends MyMapper<UserDomain> { }

public abstract class BaseServiceImpl<MAP extends MyMapper<T>,T extends Object> implements BaseService<T> { 
    @Override
    public T selectOne(T record){
    return ...;
    }
}

@Service("userService")
public class UserServiceImpl extends BaseServiceImpl<UserDomainMapper,UserDomain> implements UserService { }

////////////////////////////////////////////////////////////


now, i have one UserService instance, and have it's selectOne method of java.lang.reflect.Method, by rpc proxy, i have the T result json string. how i unmarsher it to UserDomain?

2. how

Thanks google search one reference result, i have GenericClassHelper(make small change from GenericClass):

package com.myzc98.server.helper;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * A wrapper around reflection to resolve generics.
 *
 * @author Simone Gianni <simoneg@apache.org>
 */
// TODO there is vast space for caching and optimizations here!
public class GenericClassHelper {

  private Class<?> myclass = null;

  private Map<String, Class<?>> genericMap = new HashMap<String, Class<?>>();

  private Map<String, String> reverseIntermediate = new HashMap<String, String>();

  private static void warnMsg(String msg) {
//   String msg = "Impossible situation, it's a bug : {0} generic is both {1} and bound to {2}" + target + genericMap.get(target) + search;
//  System.out.println(msg);
//  throw new RuntimeException(msg);
  }

  public static GenericClassHelper forClass(Class<?> concrete) {
    return new GenericClassHelper(concrete);
  }

  public static GenericClassHelper forField(Field field) {
    return forGenericType(field.getGenericType());
  }

  public static GenericClassHelper forReturnType(Method method) {
    return forGenericType(method.getGenericReturnType());
  }

  public static GenericClassHelper forParameter(Method method, int index) {
    return forGenericType(method.getGenericParameterTypes()[index]);
  }

  public static GenericClassHelper forGenericType(Type type) {
    if (type instanceof Class) {
      return forClass((Class<?>) type);
    } else if (type instanceof ParameterizedType) {
      return new GenericClassHelper((ParameterizedType) type);
    } else {
      return forClass(Object.class);
      // throw new MagmaException("Dont know how to build a GenericClassHelper out of
      // {0}", type.getClass());
    }
  }

  private GenericClassHelper(Class<?> concrete) {
//    TypeVariable<?>[] parameters = concrete.getTypeParameters();
    // if (parameters.length > 0) throw new MagmaException("Cannot parse {0}, it
    // is a generic class, use a concrete class instead", concrete);
    myclass = concrete;
    recurse(concrete);
    coalesceMap();
  }

  private GenericClassHelper(ParameterizedType type) {
    myclass = (Class<?>) type.getRawType();
    recurse(myclass, myclass, type);
    coalesceMap();
  }

  private void coalesceMap() {
    int cnt = reverseIntermediate.size();
    while (reverseIntermediate.size() > 0 && cnt > 0) {
      for (Iterator<Map.Entry<String, String>> iterator = this.reverseIntermediate.entrySet()
          .iterator(); iterator.hasNext();) {
        Map.Entry<String, String> entry = iterator.next();
        String target = entry.getValue();
        String search = entry.getKey();
        Class<?> clazz = genericMap.get(search);
        if (clazz == null)
          continue;
        if (genericMap.containsKey(target))
        warnMsg("Impossible situation, it's a bug : {0} generic is both {1} and bound to {2}" + target + genericMap.get(target) + search);
       
        genericMap.put(target, clazz);
        iterator.remove();
      }
      cnt--;
    }
    if (reverseIntermediate.size() > 0) {
      for (Iterator<Map.Entry<String, String>> iterator = this.reverseIntermediate.entrySet()
          .iterator(); iterator.hasNext();) {
        Map.Entry<String, String> entry = iterator.next();
        String target = entry.getValue();
        String search = entry.getKey();
        Class<?> clazz = genericMap.get(search);
        if (clazz == null)
          clazz = Object.class;
        if (genericMap.containsKey(target))
        warnMsg("Impossible situation, it's a bug : {0} generic is both {1} and bound to {2}"+ target+ genericMap.get(target)+ search);
        genericMap.put(target, clazz);
      }
    }
  }

  public Class<?> getBaseClass() {
    return this.myclass;
  }

  private void recurse(Class<?> clazz, Class<?> simplesup, ParameterizedType partype) {
    Type[] typeArguments = partype.getActualTypeArguments();
    TypeVariable<?>[] parameters = simplesup.getTypeParameters();

    for (int i = 0; i < typeArguments.length; i++) {
      if (typeArguments[i] instanceof Class) {
      String target = clazz.getName() + "--" + simplesup.getName() + "--" + parameters[i].getName();
      if (genericMap.containsKey(target))
          warnMsg("Impossible situation, it's a bug : {0} generic is both {1}"+ target+ genericMap.get(target));
   
        genericMap.put(target, (Class<?>) typeArguments[i]);
      } else if (typeArguments[i] instanceof TypeVariable) {
      String target = clazz.getName() + "--" + ((TypeVariable<?>) typeArguments[i]).getName();
      if (reverseIntermediate.containsKey(target))
            warnMsg("Impossible situation, it's a bug : {0} generic is both {1}"+ target+ reverseIntermediate.get(target));
        reverseIntermediate.put(target, simplesup.getName() + "--"
            + parameters[i].getName());
      }
    }

    recurse(simplesup);
  }

  private void recurse(Class<?> clazz) {
  recurse(clazz, null);
  }

  private void recurse(Class<?> clazz, Class<?> parent) {
  if(parent == null) {
  parent = clazz;
  }
  Type[] types = clazz.getGenericInterfaces();
  for(Type t : types) {
  if(t instanceof ParameterizedType ) {
  recurse(clazz, (Class<?>)((ParameterizedType) t).getRawType(), (ParameterizedType) t);
  if(!parent.equals(clazz))
  recurse(parent, (Class<?>)((ParameterizedType) t).getRawType(), (ParameterizedType) t);
  }else if(t instanceof TypeVariable ) {
  recurse(clazz, (Class<?>)t, (ParameterizedType) t);
  if(!parent.equals(clazz))
  recurse(parent, (Class<?>)t, (ParameterizedType) t);
  }else {
  recurse((Class<?>)t, clazz);
  }
  }

    Type supclass = clazz.getGenericSuperclass();
    Class<?> simplesup = clazz.getSuperclass();
    if (supclass == null)
      return;
    if (supclass instanceof ParameterizedType) {
      recurse(clazz, simplesup, (ParameterizedType) supclass);
  if(!parent.equals(clazz))
  recurse(parent, simplesup, (ParameterizedType) supclass);
    } else {
        recurse(parent, simplesup);
        if(!parent.equals(simplesup))
        recurse(simplesup);
    } 
  }

  /**
   * Return real, "generics dereferenced", parameter types for the given method.
   *
   * @param method
   *          The method to analyze
   * @return The real classes, dereferencing generics
   */
  public GenericClassHelper[] getParameterTypes(Method method) {
    Class<?> declaring = method.getDeclaringClass();
    String declname = declaring.getName();

    Type[] parameterTypes = method.getGenericParameterTypes();
    GenericClassHelper[] ret = new GenericClassHelper[parameterTypes.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      Type type = parameterTypes[i];
      if (type instanceof Class) {
        ret[i] = forClass((Class<?>) type);
      } else if (type instanceof TypeVariable) {
        String name = ((TypeVariable<?>) type).getName();
        Class<?> sub = genericMap.get(declname + "--" + name);
        if (sub == null)
          sub = Object.class;
        ret[i] = forClass(sub);
      } else {
        ret[i] = forGenericType(type);
      }
    }
    return ret;
  }

  public GenericClassHelper resolveType(Class<?> cls, Type type) {
    if (type instanceof Class) {
      return forClass((Class<?>) type);
    } else if (type instanceof TypeVariable) {
      GenericDeclaration gd = ((TypeVariable<?>) type).getGenericDeclaration();
      Class<?> acclass = null;
      if (gd instanceof Class) {
        acclass = (Class<?>) gd;
      } else if (gd instanceof Method) {
        acclass = ((Method) gd).getDeclaringClass();
      } else if (gd instanceof Constructor) {
        acclass = ((Constructor<?>) gd).getDeclaringClass();
      }
      String name = ((TypeVariable<?>) type).getName();
      Class<?> objClass = genericMap.get(cls.getName() + "--" + acclass.getName() + "--" + name);
      if(objClass != null)
      return forClass(objClass);
      objClass = genericMap.get(cls.getName() + "--" + name);
      if(objClass != null)
      return forClass(objClass);
      objClass = genericMap.get(acclass.getName() + "--" + name);
      return forClass(objClass);
    } else {
      return forGenericType(type);
    }
  }

  /**
   * Search for all occurrencies of a specific method.
   * <p>
   * The type parameters passed in may be Class or null. If they are null, that
   * means that we don't know which class they should be, if they are a class,
   * that means we are searching for that class, and the comparison is made on
   * dereferenced generics.
   * </p>
   * <p>
   * Specifying no parameter types explicitly means "a method without
   * parameters".
   * </p>
   *
   * @param name
   *          The name of the method
   * @param parameterTypes
   *          The types of the parameters
   * @return A list of {@link MethodDef}, ordered with methods from current
   *         class first, then method from superclass and so on.
   */
  public List<MethodDef> findMethods(String name, Class<?>... parameterTypes) {
    List<MethodDef> founds = new ArrayList<MethodDef>();
    findMethods(founds, myclass, name, parameterTypes);
    return founds;
  }

  private void findMethods(List<MethodDef> founds, Class<?> current, String name, Class<?>... parameterTypes) {
    while (current != null) {
      Method[] methods = current.getDeclaredMethods();
      for (Method method : methods) {
        if (!method.isBridge() && !method.isSynthetic() && method.getName().equals(name)) {
          Type[] types = method.getGenericParameterTypes();
          if (types.length == parameterTypes.length) {
            GenericClassHelper[] GenericClassHelperes = getParameterTypes(method);
            Class<?>[] classes = toRawClasses(GenericClassHelperes);
            boolean good = true;
            for (int i = 0; i < types.length; i++) {
              if (parameterTypes[i] != null) {
                if (!classes[i].equals(parameterTypes[i])) {
                if (!Object.class.equals(parameterTypes[i])) {
                  good = false;
                  break;
                }
                }
              }
            }
            if (good) {
              MethodDef def = new MethodDef(method, GenericClassHelperes);
              if (!founds.contains(def))
                founds.add(def);
            }
          }
        }
      }
   
      Class<?>[] classes = current.getInterfaces();
      for(Class<?> cls : classes) {
      findMethods(founds, cls, name, parameterTypes);
      }
   
      current = current.getSuperclass();
    }
  }

  public static Class<?>[] toRawClasses(GenericClassHelper[] genclasses) {
    Class<?>[] ret = new Class<?>[genclasses.length];
    for (int i = 0; i < genclasses.length; i++) {
      ret[i] = genclasses[i].getBaseClass();
    }
    return ret;
  }

  /**
   * Search for all methods having that name, no matter which parameter they
   * take.
   *
   * @param name
   *          The name of the methods
   * @return A list of {@link MethodDef}, ordered with methods from current
   *         class first, then method from superclass and so on.
   */
  public List<MethodDef> findAllMethods(String name) {
    List<MethodDef> founds = new ArrayList<MethodDef>();
    findAllMethods(founds, myclass, name);
    return founds;
  }

  private void findAllMethods(List<MethodDef> founds, Class<?> current, String name) {
    while (current != null) {
      Method[] methods = current.getDeclaredMethods();
      for (Method method : methods) {
        if (!method.isBridge() && !method.isSynthetic() && method.getName().equals(name)) {
          MethodDef def = new MethodDef(method);
          if (!founds.contains(def))
            founds.add(def);
        }
      }

      Class<?>[] classes = current.getInterfaces();
      for(Class<?> cls : classes) {
      findAllMethods(founds, cls, name);
      }
   
      current = current.getSuperclass();
   
    }
  }

  public List<MethodDef> getMethods() {
    List<MethodDef> founds = new ArrayList<MethodDef>();
    Class<?> current = myclass;
    while (current != null) {
      Method[] methods = current.getDeclaredMethods();
      for (Method method : methods) {
        if (!method.isBridge() && !method.isSynthetic()) {
          MethodDef def = new MethodDef(method);
          if (!founds.contains(def))
            founds.add(def);
        }
      }
      current = current.getSuperclass();
    }
    return founds;
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof GenericClassHelper))
      return false;
    GenericClassHelper oth = (GenericClassHelper) obj;
    return this.getBaseClass().equals(oth.getBaseClass());
  }

  public class MethodDef {
    private Method method = null;

    private GenericClassHelper[] params = null;

    MethodDef(Method m) {
      this.method = m;
    }

    MethodDef(Method m, GenericClassHelper[] params) {
      this.method = m;
      this.params = params;
    }

    public String getName() {
      return this.method.getName();
    }

    public Method getBaseMethod() {
      return this.method;
    }

    public GenericClassHelper[] getParameterTypes() {
      if (this.params == null) {
        this.params = GenericClassHelper.this.getParameterTypes(method);
      }
      return this.params;
    }

    public GenericClassHelper getReturnType() {
      return getReturnType(myclass);
    }

    public GenericClassHelper getReturnType(Class<?> instanceClass) {
      return resolveType(instanceClass, method.getGenericReturnType());
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof MethodDef))
        return false;
      MethodDef oth = (MethodDef) other;
      return (method.getName().equals(oth.method.getName()))
          && (Arrays.equals(getParameterTypes(), oth.getParameterTypes()));
    }

    public Class<?> getDeclaringClass() {
      return this.method.getDeclaringClass();
    }
  }

}

How to used it:

static void testGeneric(Class<?> beanCls, String methodName) {
GenericClassHelper v1 = GenericClassHelper.forClass(beanCls);
java.util.List<GenericClassHelper.MethodDef> methods = v1.findAllMethods(methodName);
GenericClassHelper.MethodDef method = methods.get(0);
GenericClassHelper ret = method.getReturnType();
Class<?> cls = ret.getBaseClass();
System.out.println(beanCls.getName() + " " + methodName);
System.out.println("  ret:" + cls);

GenericClassHelper[] params = method.getParameterTypes();
for(int i=0,c=params.length;i<c;++i) {
System.out.println("   p" + (i+1) + ":" + params[i].getBaseClass() + "\n");
}
}

    testGeneric(UserServiceImpl.class, "selectOne");
    testGeneric(UserService.class, "selectOne");

Last:
Thanks for your readed

Reference:
A wrapper around reflection to resolve generics. : Generic « Reflection « Java