public static String getGenericsSignature(ClassNode node) {
   if (!usesGenericsInClassSignature(node)) return null;
   GenericsType[] genericsTypes = node.getGenericsTypes();
   StringBuffer ret = new StringBuffer(100);
   getGenericsTypeSpec(ret, genericsTypes);
   GenericsType extendsPart = new GenericsType(node.getUnresolvedSuperClass(false));
   writeGenericsBounds(ret, extendsPart, true);
   ClassNode[] interfaces = node.getInterfaces();
   for (int i = 0; i < interfaces.length; i++) {
     GenericsType interfacePart = new GenericsType(interfaces[i]);
     writeGenericsBounds(ret, interfacePart, false);
   }
   return ret.toString();
 }
  public static String getGenericsMethodSignature(MethodNode node) {
    GenericsType[] generics = node.getGenericsTypes();
    Parameter[] param = node.getParameters();
    ClassNode returnType = node.getReturnType();

    if (generics == null && !hasGenerics(param) && !hasGenerics(returnType)) return null;

    StringBuffer ret = new StringBuffer(100);
    getGenericsTypeSpec(ret, generics);

    GenericsType[] paramTypes = new GenericsType[param.length];
    for (int i = 0; i < param.length; i++) {
      ClassNode pType = param[i].getType();
      if (pType.getGenericsTypes() == null || !pType.isGenericsPlaceHolder()) {
        paramTypes[i] = new GenericsType(pType);
      } else {
        paramTypes[i] = pType.getGenericsTypes()[0];
      }
    }
    addSubTypes(ret, paramTypes, "(", ")");
    addSubTypes(ret, new GenericsType[] {new GenericsType(returnType)}, "", "");
    return ret.toString();
  }