net.gdface.codegen.generic.GenericInterface Maven / Gradle / Ivy
package net.gdface.codegen.generic;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.gdface.annotation.AnnotationException;
import net.gdface.annotation.AnnotationRuntimeException;
import net.gdface.annotation.DefaultGenericTypes;
import net.gdface.annotation.DeriveMethod;
import net.gdface.annotation.Generic;
import net.gdface.annotation.GenericNameException;
import net.gdface.annotation.GenericParam;
import net.gdface.annotation.GenericParamException;
import net.gdface.codegen.AnnotationUtils;
import net.gdface.codegen.CodeGenUtils;
import net.gdface.codegen.InvalidAnnotationDefineException;
import net.gdface.codegen.InvalidNameException;
import net.gdface.codegen.Method;
import net.gdface.codegen.Method.Parameter;
import net.gdface.codegen.NewSourceInfoAbstract;
import net.gdface.codegen.ServiceInfo;
import net.gdface.utils.Assert;
public class GenericInterface extends NewSourceInfoAbstract implements GenericInterfaceConstants {
private static final Logger logger = LoggerFactory.getLogger(NewSourceInfoAbstract.class);
private DefaultParameterGenericTypes defaultGenericTypes;
private Class> shellInterface;
private ServiceInfo serviceInfo;
private boolean hasRemoteResolveType;
public GenericInterface(Class interfaceClass, Class extends T> refClass, Class> shellInterface) {
super(interfaceClass, refClass, null);
Assert.notNull(shellInterface, "shellInterface");
this.shellInterface=shellInterface;
if(!shellInterface.isInterface())
throw new IllegalArgumentException(String.format("shellInterface must be a interface(必须是接口)"));
if (!interfaceClass.isAssignableFrom(shellInterface))
throw new IllegalArgumentException(String.format(
"shellInterface must extends from [%s] (必须实现接口)", interfaceClass.getName()));
}
@Override
public boolean compile() {
boolean compileOk=false;
try {
defaultGenericTypes = new DefaultParameterGenericTypes(interfaceClass);
serviceInfo=new ServiceInfo(AnnotationUtils.getServiceAnnotation(shellInterface));
super.compile();
importedList.remove(refClass.getSimpleName());
importedList.remove(interfaceClass.getSimpleName());
// 检查是否有同名的泛型名称
for (String name : defaultGenericTypes.names()) {
if (hasInClassGenericTypes(name))
try {
throw new GenericNameConflictException(name, DefaultGenericTypes.class.getSimpleName(),
defaultGenericTypes.toString());
} catch (GenericNameConflictException e) {
throw new DefaultGenericTypesExceptoin(e);
}
}
for (Method method : methodsNeedGenerated) {
compile(method);
}
compileOk=true;
} catch (AnnotationException e) {
logger.error(e.toString());
}catch(AnnotationRuntimeException e){
logger.error(e.toString());
}
return compileOk;
}
private final void compile(Method method) throws GenericParamException, GenericNameException, GenericNameConflictException {
for (Parameter param : method.getParameters()) {
try {
compile(param);
} catch (GenericParamRedefineException e) {
logger.warn("{} is generic type({}) defined by class,can't be redefined in method:\n{}", param.name,
param.genericType.toString(), method.toGenericString());
} catch (GenericNameException e) {
throw new GenericNameException(String.format(
"the name of annotation %s of parameter [%s] must not have space char in method %s",
Generic.class.getSimpleName(), param.name, method.toGenericString()));
}
}
DeriveMethod deriveMethodAnnotation = getDeriveMethodAnnotation(method);
if(deriveMethodAnnotation!=null){
this.addImportedClass(deriveMethodAnnotation.localResolvedTypes());
if(deriveMethodAnnotation.remoteResolveTypes().length>0){
hasRemoteResolveType=true;
this.addImportedClass(deriveMethodAnnotation.remoteResolveTypes());
}
}
}
private final void compile(Parameter param) throws GenericParamRedefineException, GenericNameConflictException,
GenericNameException {
GenericParam genericParam = param.getAnnotation(GenericParam.class);
if (null != genericParam && genericParam.value() && (param.genericType instanceof TypeVariable)) {
throw new GenericParamRedefineException();
}
if (null != genericParam && !genericParam.name().isEmpty()) {
if (!Pattern.compile("^[A-Z]\\w*$").matcher(genericParam.name()).matches())
throw new GenericNameException();
if (hasInClassGenericTypes(genericParam.name()))
throw new GenericNameConflictException(genericParam.name(), GenericParam.class.getSimpleName(),
genericParam.toString());
}
}
@Override
protected void createMethodsNeedGenerated() {
ArrayList interfaceMethods = new ArrayList(
Arrays.asList(interfaceClass.getMethods()));
Iterator it = interfaceMethods.iterator();
try {
Method cm;
while (it.hasNext()) {
java.lang.reflect.Method im = it.next();
// cm = new Method(refClass.getMethod(im.getName(), im.getParameterTypes()),
// this.paramTable.getParameterNames(im.getName(), im.getParameterTypes()));
cm = new Method(im,
this.paramTable.getParameterNames(im.getName(), im.getParameterTypes()));
if (needGeneric(cm))
this.methodsNeedGenerated.add(cm);
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
/**
* @return defaultGenericTypes
*/
public DefaultParameterGenericTypes getDefaultGenericTypes() {
return defaultGenericTypes;
}
private boolean hasInClassGenericTypes(String name) {
for (TypeVariable> type : interfaceClass.getTypeParameters()) {
if (type.getName().equals(name))
return true;
}
return false;
}
private final boolean hasNeedGenericParameter(Method method) {
for (Parameter param : method.getParameters()) {
if (needGeneric(param)) {
return true;
}
}
return false;
}
public boolean needGeneric(Method method) {
Generic generic = method.getAnnotation(Generic.class);
return (null == generic || generic.value()) && hasNeedGenericParameter(method);
}
public final boolean needGeneric(Parameter param){
GenericParam genericParam = param.getAnnotation(GenericParam.class);
return (null == genericParam || genericParam.value()) && defaultGenericTypes.hasType(param.type);
}
public final GenericParam getGenericParam(Parameter param){
return param.getAnnotation(GenericParam.class);
}
public final Set getGenericNames(Method method) {
GenericParam genericParam;
Set names=new HashSet();
for (Parameter param : method.getParameters()) {
if (needGeneric(param)) {
if(null==(genericParam = getGenericParam(param))){
names.add(defaultGenericTypes.getName(param.getType()));
}else
names.add(genericParam.name());
}
}
return names;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
int c = 0;
builder.append("//classes need imported in new Class:\n");
for (Class> clazz : importedList.values()) {
builder.append("//[" + (++c) + "]\nimported ").append(clazz.getName()).append(";\n");
}
builder.append("public interface NewClass{\n");
c = 0;
builder.append("//methods thad need generated in new Class:\n");
for (Method m : methodsNeedGenerated) {
builder.append("//[" + (++c) + "]\n").append(m.toGenericString()).append(";\n");
}
builder.append("}\n");
return builder.toString();
}
/**
* @return shellInterface
*/
public Class> getShellInterface() {
return shellInterface;
}
public DeriveMethod getDeriveMethodAnnotation(Method method) {
try {
return AnnotationUtils.getDeriveMethodAnnotation(method, serviceInfo);
} catch (InvalidNameException e) {
throw new RuntimeException(e);
} catch (InvalidAnnotationDefineException e) {
throw new RuntimeException(e);
}
}
/**
* @return serviceInfo
*/
public ServiceInfo getServiceInfo() {
return serviceInfo;
}
public boolean isTargetType(Class> type){
return serviceInfo.getTargetType()==type;
}
public boolean needDeriveParam(Method method,Parameter param){
DeriveMethod deriveMethod =getDeriveMethodAnnotation(method);
if(deriveMethod!=null){
Set set = CodeGenUtils.toSet(deriveMethod.genericParam());
return needGeneric(param)&&(set.isEmpty()||set.contains(param.name));
}
return false;
}
public ArrayList getDeriveParameterNames(Method method){
ArrayList list = new ArrayList();
for(Parameter parameter:method.getParameters()){
if(needDeriveParam(method,parameter)){
list.add(parameter.name);
}
}
return list;
}
/**
* @return hasRemoteResolveType
*/
public boolean isHasRemoteResolveType() {
return hasRemoteResolveType;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy