diff --git a/pom.xml b/pom.xml
index 2b99875..153001e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,7 @@
spring-rest2ts-generator
spring-rest2ts-jackson
spring-rest2ts-spring
+ spring-rest2ts-jax-rs
spring-rest2ts-spring-data
diff --git a/spring-rest2ts-jax-rs/pom.xml b/spring-rest2ts-jax-rs/pom.xml
new file mode 100644
index 0000000..e6d6091
--- /dev/null
+++ b/spring-rest2ts-jax-rs/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+
+ com.blue-veery
+ spring-rest2ts
+ 1.2.2
+
+
+ spring-rest2ts-jax-rs
+ 1.2.2
+
+
+
+ com.blue-veery
+ spring-rest2ts-spring
+ 1.2.2
+
+
+ javax
+ javaee-api
+ 8.0.1
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/spring-rest2ts-jax-rs/src/main/java/com/blueveery/springrest2ts/converters/JaxRsRestToTsConverter.java b/spring-rest2ts-jax-rs/src/main/java/com/blueveery/springrest2ts/converters/JaxRsRestToTsConverter.java
new file mode 100644
index 0000000..69510c9
--- /dev/null
+++ b/spring-rest2ts-jax-rs/src/main/java/com/blueveery/springrest2ts/converters/JaxRsRestToTsConverter.java
@@ -0,0 +1,138 @@
+package com.blueveery.springrest2ts.converters;
+
+import com.blueveery.springrest2ts.implgens.ImplementationGenerator;
+import com.blueveery.springrest2ts.naming.ClassNameMapper;
+import com.blueveery.springrest2ts.spring.PathVariableEntity;
+import com.blueveery.springrest2ts.spring.RequestBodyEntity;
+import com.blueveery.springrest2ts.spring.RequestMappingEntity;
+import com.blueveery.springrest2ts.spring.RequestParamEntity;
+import com.blueveery.springrest2ts.tsmodel.TSClass;
+import com.blueveery.springrest2ts.tsmodel.TSMethod;
+import com.blueveery.springrest2ts.tsmodel.TSParameter;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.ws.rs.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class JaxRsRestToTsConverter extends SpringAnnotationsBasedRestClassConverter {
+ protected JaxRsRestToTsConverter(ImplementationGenerator implementationGenerator) {
+ super(implementationGenerator);
+ }
+
+ public JaxRsRestToTsConverter(ImplementationGenerator implementationGenerator, ClassNameMapper classNameMapper) {
+ super(implementationGenerator, classNameMapper);
+ }
+
+ @Override
+ protected void addClassAnnotations(Class javaClass, TSClass tsClass) {
+ RequestMappingEntity requestMapping = null;
+ Annotation[] annotationsByType = javaClass.getAnnotationsByType(Path.class);
+ if (annotationsByType != null) {
+ Path path = (Path) annotationsByType[0];
+ requestMapping = new RequestMappingEntity();
+ requestMapping.setPath(new String[]{path.value()});
+ tsClass.addAllAnnotations(new Annotation[]{requestMapping});
+ }
+
+ }
+
+ @Override
+ protected void addMethodAnnotations(Method method, TSMethod tsMethod) {
+ RequestMappingEntity requestMapping = new RequestMappingEntity();
+ Set requestMethodSet = new HashSet<>();
+ for (Annotation annotation : method.getAnnotations()) {
+ if(annotation instanceof Path){
+ Path path = (Path) annotation;
+ requestMapping.setPath(new String[]{path.value()});
+ }
+ if(annotation instanceof GET){
+ requestMethodSet.add(RequestMethod.GET);
+ }
+ if(annotation instanceof POST){
+ requestMethodSet.add(RequestMethod.POST);
+ }
+ if(annotation instanceof PUT){
+ requestMethodSet.add(RequestMethod.PUT);
+ }
+ if(annotation instanceof DELETE){
+ requestMethodSet.add(RequestMethod.DELETE);
+ }
+ if(annotation instanceof Produces){
+ Produces produces = (Produces) annotation;
+ requestMapping.setProduces(produces.value());
+ }
+ if(annotation instanceof Consumes){
+ Consumes consumes = (Consumes) annotation;
+ requestMapping.setConsumes(consumes.value());
+ }
+ }
+ if (!requestMethodSet.isEmpty()) {
+ requestMapping.setMethod(requestMethodSet.toArray(new RequestMethod[0]));
+ tsMethod.addAllAnnotations(new Annotation[]{requestMapping});
+ }
+
+ }
+
+ @Override
+ protected void addParameterAnnotations(Parameter parameter, TSParameter tsParameter) {
+ RequestParamEntity requestParam = null;
+ PathVariableEntity pathVariable = null;
+ DefaultValue defaultValue = null;
+ for (Annotation annotation : parameter.getAnnotations()) {
+ if(annotation instanceof PathParam){
+ PathParam pathParam = (PathParam) annotation;
+ pathVariable = new PathVariableEntity();
+ pathVariable.setName(pathParam.value());
+ }
+ if(annotation instanceof QueryParam){
+ QueryParam queryParam = (QueryParam) annotation;
+ requestParam = new RequestParamEntity();
+ requestParam.setName(queryParam.value());
+ }
+ if(annotation instanceof DefaultValue){
+ defaultValue = (DefaultValue) annotation;
+ }
+ }
+
+ if (requestParam != null) {
+ requestParam.setRequired(defaultValue == null);
+ tsParameter.addAllAnnotations(new Annotation[]{requestParam});
+ }
+ if (pathVariable != null) {
+ pathVariable.setRequired(defaultValue == null);
+ tsParameter.addAllAnnotations(new Annotation[]{pathVariable});
+ }
+ if (tsParameter.getAnnotationList().isEmpty()) {
+ boolean isPutOrPost = false;
+ List annotationList = tsParameter.getTsMethod().getAnnotationList();
+ RequestMapping requestMapping = (RequestMapping) annotationList.stream().filter(a -> a instanceof RequestMapping).findFirst().orElse(null);
+ if (requestMapping == null) {
+ List classAnnotationList = tsParameter.getTsMethod().getOwner().getAnnotationList();
+ requestMapping = (RequestMapping) classAnnotationList.stream().filter(a -> a instanceof RequestMapping).findFirst().orElse(null);
+ }
+ for (RequestMethod requestMethod : requestMapping.method()) {
+ switch (requestMethod){
+ case POST:
+ case PUT: isPutOrPost = true; break;
+ }
+ }
+ if (isPutOrPost) {
+ RequestBodyEntity requestBodyEntity = new RequestBodyEntity();
+ requestBodyEntity.setRequired(true);
+ tsParameter.getTsMethod().getAnnotationList().add(requestBodyEntity);
+ }
+ }
+ }
+
+ @Override
+ protected Type handleImplementationSpecificReturnTypes(Method method) {
+ return method.getGenericReturnType();
+ }
+}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringAnnotationsBasedRestClassConverter.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringAnnotationsBasedRestClassConverter.java
new file mode 100644
index 0000000..dac458a
--- /dev/null
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringAnnotationsBasedRestClassConverter.java
@@ -0,0 +1,299 @@
+package com.blueveery.springrest2ts.converters;
+
+import com.blueveery.springrest2ts.extensions.RestConversionExtension;
+import com.blueveery.springrest2ts.implgens.ImplementationGenerator;
+import com.blueveery.springrest2ts.naming.ClassNameMapper;
+import com.blueveery.springrest2ts.spring.RequestMappingUtility;
+import com.blueveery.springrest2ts.tsmodel.*;
+import com.blueveery.springrest2ts.tsmodel.generics.TSClassReference;
+import com.blueveery.springrest2ts.tsmodel.generics.TSInterfaceReference;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public abstract class SpringAnnotationsBasedRestClassConverter extends RestClassConverter {
+ protected SpringAnnotationsBasedRestClassConverter(ImplementationGenerator implementationGenerator) {
+ super(implementationGenerator);
+ }
+
+ public SpringAnnotationsBasedRestClassConverter(ImplementationGenerator implementationGenerator, ClassNameMapper classNameMapper) {
+ super(implementationGenerator, classNameMapper);
+ }
+
+ @Override
+ public boolean preConverted(JavaPackageToTsModuleConverter javaPackageToTsModuleConverter, Class javaClass){
+ if(TypeMapper.map(javaClass) == TypeMapper.tsAny && !javaClass.isInterface()){
+ TSModule tsModule = javaPackageToTsModuleConverter.getTsModule(javaClass);
+ String tsClassName = createTsClassName(javaClass);
+ TSClass tsClass = new TSClass(tsClassName, tsModule, implementationGenerator);
+ tsModule.addScopedType(tsClass);
+ TypeMapper.registerTsType(javaClass, tsClass);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void convert(Class javaClass, NullableTypesStrategy nullableTypesStrategy) {
+ TSClassReference tsClassReference = (TSClassReference) TypeMapper.map(javaClass);
+ TSClass tsClass = tsClassReference.getReferencedType();
+
+ convertFormalTypeParameters(javaClass.getTypeParameters(), tsClassReference);
+ setSupperClass(javaClass, tsClass);
+ addClassAnnotations(javaClass, tsClass);
+
+ TSMethod tsConstructorMethod = new TSMethod("constructor", tsClass, null, implementationGenerator, false, true);
+ tsClass.addTsMethod(tsConstructorMethod);
+ List restMethodList = filterRestMethods(javaClass);
+ Map methodNamesMap = new HashMap<>();
+
+ for (Method method: restMethodList) {
+
+ Map variableNameToJavaType = new HashMap<>();
+ Class> declaringClass = method.getDeclaringClass();
+ if(declaringClass != javaClass && method.getDeclaringClass().isInterface()){
+ variableNameToJavaType = fillVariableNameToJavaType(javaClass, declaringClass);
+ }
+
+ Type genericReturnType = handleImplementationSpecificReturnTypes(method);
+ String methodName = mapMethodName(restMethodList, methodNamesMap, method);
+ TSType methodReturnType = TypeMapper.map(resolveTypeVariable(genericReturnType, variableNameToJavaType));
+ tsClass.getModule().scopedTypeUsage(methodReturnType);
+ TSMethod tsMethod = new TSMethod(methodName, tsClass, methodReturnType, implementationGenerator, false, false);
+ for (Parameter parameter:method.getParameters()) {
+ Type parameterType = resolveTypeVariable(parameter.getParameterizedType(), variableNameToJavaType);
+ TSParameter tsParameter = new TSParameter(parameter.getName(), TypeMapper.map(parameterType), tsMethod, implementationGenerator);
+ addParameterAnnotations(parameter, tsParameter);
+ if (parameterIsMapped(tsParameter)) {
+ tsClass.getModule().scopedTypeUsage(tsParameter.getType());
+ setOptional(tsParameter);
+ nullableTypesStrategy.setAsNullableType(parameter.getParameterizedType(), parameter.getDeclaredAnnotations(), tsParameter);
+ tsMethod.getParameterList().add(tsParameter);
+ }
+ conversionListener.tsParameterCreated(parameter, tsParameter);
+ }
+ addMethodAnnotations(method, tsMethod);
+ tsClass.addTsMethod(tsMethod);
+ conversionListener.tsMethodCreated(method, tsMethod);
+ }
+
+ implementationGenerator.addComplexTypeUsage(tsClass);
+ conversionListener.tsScopedTypeCreated(javaClass, tsClass);
+ }
+
+ protected abstract void addClassAnnotations(Class javaClass, TSClass tsClass);
+
+ protected abstract void addMethodAnnotations(Method method, TSMethod tsMethod);
+
+ protected abstract void addParameterAnnotations(Parameter parameter, TSParameter tsParameter);
+
+ protected abstract Type handleImplementationSpecificReturnTypes(Method method);
+
+ private Type resolveTypeVariable(Type type, Map variableNameToJavaType) {
+ if (type instanceof TypeVariable) {
+ TypeVariable typeVariable = (TypeVariable) type;
+ Type resolvedType = variableNameToJavaType.get(typeVariable.getName());
+ if (resolvedType != null) {
+ return resolvedType;
+ }
+ }
+ return type;
+ }
+
+ private Map fillVariableNameToJavaType(Class javaClass, Class> declaringClass) {
+ Map typeParametersMap = new HashMap<>();
+ for (Type type:javaClass.getGenericInterfaces()){
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ if (parameterizedType.getRawType() == declaringClass) {
+ for (int i = 0; i < parameterizedType.getActualTypeArguments().length; i++) {
+ TypeVariable typeParameter = declaringClass.getTypeParameters()[i];
+ Type actualTypeArgument = parameterizedType.getActualTypeArguments()[i];
+ typeParametersMap.put(typeParameter.getName(), actualTypeArgument);
+ }
+ return typeParametersMap;
+ }
+ return fillVariableNameToJavaType((Class) type, declaringClass);
+ }
+ }
+ return typeParametersMap;
+ }
+
+ private List filterRestMethods(Class javaClass) {
+ List restMethodList = new ArrayList<>();
+ for (Method method : javaClass.getMethods()) {
+ if(method.getDeclaringClass() == javaClass || method.getDeclaringClass().isInterface()) {
+ for (Method nextMethod : javaClass.getSuperclass().getMethods()) {
+ if(nextMethod.equals(method)){
+ continue; // parent class contains method from interface
+ }
+ }
+ if (isRestMethod(method)) {
+ restMethodList.add(method);
+ }
+ }
+ }
+ return restMethodList;
+ }
+
+ private String mapMethodName(List restMethodList, Map methodNamesMap, Method currentMethod) {
+ StringBuilder methodName = methodNamesMap.get(currentMethod);
+ if (methodName != null) {
+ return methodName.toString();
+ }
+ List overloadedMethods = restMethodList.stream().filter(m -> m.getName().equals(currentMethod.getName())).collect(Collectors.toList());
+ if (overloadedMethods.size() == 1) {
+ return currentMethod.getName();
+ }
+ Map overloadedMethodNamesMap = new HashMap<>();
+ Map methodsRequestMappingsMap = new HashMap<>();
+ for (Method m : overloadedMethods) {
+ overloadedMethodNamesMap.put(m, new StringBuilder(m.getName()));
+ methodsRequestMappingsMap.put(m, RequestMappingUtility.getRequestMapping(Arrays.asList (m.getDeclaredAnnotations())));
+ }
+
+
+ appendHttpMethodToMethodName(overloadedMethodNamesMap, methodsRequestMappingsMap);
+ if(!methodNamesAreUnique(overloadedMethodNamesMap)){
+ appendHttpPathToMethodName(overloadedMethodNamesMap, methodsRequestMappingsMap);
+ }
+ if(!methodNamesAreUnique(overloadedMethodNamesMap)){
+ logger.error("There are overloaded REST methods which names are not unique after appending http method and http path : " + currentMethod);
+ }
+ overloadedMethodNamesMap.forEach((method, name) -> methodNamesMap.put(method, name));
+ return overloadedMethodNamesMap.get(currentMethod).toString();
+ }
+
+ private void appendHttpMethodToMethodName(Map overloadedMethodNamesMap, Map methodsRequestMappingsMap) {
+ Map httpMethodsValuesMap = new HashMap<>();
+
+ for (Map.Entry entry : methodsRequestMappingsMap.entrySet()) {
+ Method key = entry.getKey();
+ RequestMapping value = entry.getValue();
+ SortedSet httpMethodsSet = new TreeSet<>();
+ for (RequestMethod requestMethod : value.method()) {
+ httpMethodsSet.add(requestMethod.name());
+ }
+ httpMethodsValuesMap.put(key, String.join("_", httpMethodsSet));
+ }
+
+ Set allDifferentHttpMethods = new HashSet<>(httpMethodsValuesMap.values());
+ if (allDifferentHttpMethods.size() <= 1) {
+ return;
+ }
+ overloadedMethodNamesMap.forEach((method, methodName) -> methodName.append(httpMethodsValuesMap.get(method)));
+ }
+
+ private void appendHttpPathToMethodName(Map overloadedMethodNamesMap, Map methodsRequestMappingsMap) {
+ Map methodsHttpPaths = new HashMap<>();
+ for (Map.Entry entry : methodsRequestMappingsMap.entrySet()) {
+ Method method = entry.getKey();
+ RequestMapping requestMapping = entry.getValue();
+ if (requestMapping.path().length > 0) {
+ methodsHttpPaths.put(method, requestMapping.path()[0].split("/"));
+ }else{
+ methodsHttpPaths.put(method, new String[]{""});
+ }
+ }
+
+ int startIndex = findPathCommonPrefixIndex(methodsHttpPaths);
+
+ for (Method method : overloadedMethodNamesMap.keySet()) {
+ StringBuilder methodName = overloadedMethodNamesMap.get(method);
+ String[] pathComponents = methodsHttpPaths.get(method);
+ for (int i = startIndex; i < pathComponents.length; i++) {
+ String pathComponent = pathComponents[i];
+ if(!pathComponent.contains("{") && !"".equals(pathComponent)) {
+ methodName.append("_");
+ methodName.append(pathComponent.toUpperCase().replace("-", "_"));
+ }
+ }
+ }
+
+ }
+
+ int findPathCommonPrefixIndex(Map methodsHttpPaths) {
+ return 0;
+ }
+
+ private boolean methodNamesAreUnique(Map overloadedMethodNamesMap) {
+ Set methodNames = new HashSet<>();
+ overloadedMethodNamesMap.forEach((k, v) -> methodNames.add(v.toString()));
+ return overloadedMethodNamesMap.size() == methodNames.size();
+ }
+
+ private void setOptional(TSParameter tsParameter) {
+ for (Annotation annotation : tsParameter.getAnnotationList()) {
+ if(annotation instanceof PathVariable){
+ PathVariable pathVariable = (PathVariable) annotation;
+ tsParameter.setOptional(!pathVariable.required());
+ return;
+ }
+ if(annotation instanceof RequestParam){
+ RequestParam requestParam = (RequestParam) annotation;
+ tsParameter.setOptional(!requestParam.required());
+ if(!ValueConstants.DEFAULT_NONE.equals(requestParam.defaultValue())) {
+ tsParameter.setDefaultValue(requestParam.defaultValue());
+ }
+ return;
+ }
+ if(annotation instanceof RequestBody) {
+ RequestBody requestBody = (RequestBody) annotation;
+ tsParameter.setOptional(!requestBody.required());
+ return;
+ }
+ }
+ }
+
+ private boolean parameterIsMapped(TSParameter tsParameter) {
+ for (Annotation annotation : tsParameter.getAnnotationList()) {
+ if(annotation instanceof PathVariable){
+ return true;
+ }
+ if(annotation instanceof RequestParam){
+ return true;
+ }
+ if(annotation instanceof RequestBody) {
+ return true;
+ }
+ }
+
+ if (tsParameter.getType() instanceof TSInterfaceReference) {
+ TSInterfaceReference tsInterfaceReference = (TSInterfaceReference) tsParameter.getType();
+ for (Class nextClass : tsInterfaceReference.getReferencedType().getMappedFromJavaTypeSet()) {
+ for (RestConversionExtension extension : getConversionExtensionList()) {
+ if (extension.isMappedRestParam(nextClass)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean isRestMethod(Method method) {
+ if (method.isAnnotationPresent(RequestMapping.class)) {
+ return true;
+ }
+ for (Annotation annotation : method.getAnnotations()) {
+ if (annotation.annotationType().isAnnotationPresent(RequestMapping.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void setSupperClass(Class javaType, TSClass tsClass) {
+ TSType tsSupperClass = TypeMapper.map(javaType.getAnnotatedSuperclass().getType());
+ if(tsSupperClass instanceof TSClassReference){
+ TSClassReference tsClassReference = (TSClassReference) tsSupperClass;
+ convertFormalTypeParameters(javaType.getTypeParameters(), tsClassReference);
+ tsClass.setExtendsClass(tsClassReference);
+ tsClass.addScopedTypeUsage(tsClassReference);
+ }
+ }
+}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringRestToTsConverter.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringRestToTsConverter.java
index 6b65fef..9a244e0 100644
--- a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringRestToTsConverter.java
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/converters/SpringRestToTsConverter.java
@@ -1,22 +1,13 @@
package com.blueveery.springrest2ts.converters;
-import static com.blueveery.springrest2ts.spring.RequestMappingUtility.getRequestMapping;
-
-import com.blueveery.springrest2ts.extensions.RestConversionExtension;
import com.blueveery.springrest2ts.implgens.ImplementationGenerator;
import com.blueveery.springrest2ts.naming.ClassNameMapper;
import com.blueveery.springrest2ts.tsmodel.*;
-import com.blueveery.springrest2ts.tsmodel.generics.TSClassReference;
-import com.blueveery.springrest2ts.tsmodel.generics.TSInterfaceReference;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import java.lang.annotation.Annotation;
import java.lang.reflect.*;
-import java.util.*;
-import java.util.stream.Collectors;
-public class SpringRestToTsConverter extends RestClassConverter{
+public class SpringRestToTsConverter extends SpringAnnotationsBasedRestClassConverter{
public SpringRestToTsConverter(ImplementationGenerator implementationGenerator) {
super(implementationGenerator);
@@ -27,273 +18,29 @@ public SpringRestToTsConverter(ImplementationGenerator implementationGenerator,
}
@Override
- public boolean preConverted(JavaPackageToTsModuleConverter javaPackageToTsModuleConverter, Class javaClass){
- if(TypeMapper.map(javaClass) == TypeMapper.tsAny && !javaClass.isInterface()){
- TSModule tsModule = javaPackageToTsModuleConverter.getTsModule(javaClass);
- String tsClassName = createTsClassName(javaClass);
- TSClass tsClass = new TSClass(tsClassName, tsModule, implementationGenerator);
- tsModule.addScopedType(tsClass);
- TypeMapper.registerTsType(javaClass, tsClass);
- return true;
- }
- return false;
- }
-
- @Override
- public void convert(Class javaClass, NullableTypesStrategy nullableTypesStrategy) {
- TSClassReference tsClassReference = (TSClassReference) TypeMapper.map(javaClass);
- TSClass tsClass = tsClassReference.getReferencedType();
-
- convertFormalTypeParameters(javaClass.getTypeParameters(), tsClassReference);
- setSupperClass(javaClass, tsClass);
+ protected void addClassAnnotations(Class javaClass, TSClass tsClass) {
tsClass.addAllAnnotations(javaClass.getAnnotations());
-
- TSMethod tsConstructorMethod = new TSMethod("constructor", tsClass, null, implementationGenerator, false, true);
- tsClass.addTsMethod(tsConstructorMethod);
- List restMethodList = filterRestMethods(javaClass);
- Map methodNamesMap = new HashMap<>();
-
- for (Method method: restMethodList) {
-
- Map variableNameToJavaType = new HashMap<>();
- Class> declaringClass = method.getDeclaringClass();
- if(declaringClass != javaClass && method.getDeclaringClass().isInterface()){
- variableNameToJavaType = fillVariableNameToJavaType(javaClass, declaringClass);
- }
-
- Type genericReturnType = method.getGenericReturnType();
- if (genericReturnType instanceof ParameterizedType) {// handling ResponseEntity
- ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
- if (parameterizedType.getRawType() == ResponseEntity.class) {
- genericReturnType = parameterizedType.getActualTypeArguments()[0];
- }
- }
- String methodName = mapMethodName(restMethodList, methodNamesMap, method);
- TSType methodReturnType = TypeMapper.map(resolveTypeVariable(genericReturnType, variableNameToJavaType));
- tsClass.getModule().scopedTypeUsage(methodReturnType);
- TSMethod tsMethod = new TSMethod(methodName, tsClass, methodReturnType, implementationGenerator, false, false);
- for (Parameter parameter:method.getParameters()) {
- Type parameterType = resolveTypeVariable(parameter.getParameterizedType(), variableNameToJavaType);
- TSParameter tsParameter = new TSParameter(parameter.getName(), TypeMapper.map(parameterType), tsMethod, implementationGenerator);
- tsParameter.addAllAnnotations(parameter.getAnnotations());
- if (parameterIsMapped(tsParameter)) {
- tsClass.getModule().scopedTypeUsage(tsParameter.getType());
- setOptional(tsParameter);
- nullableTypesStrategy.setAsNullableType(parameter.getParameterizedType(), parameter.getDeclaredAnnotations(), tsParameter);
- tsMethod.getParameterList().add(tsParameter);
- }
- conversionListener.tsParameterCreated(parameter, tsParameter);
- }
- tsMethod.addAllAnnotations(method.getAnnotations());
- tsClass.addTsMethod(tsMethod);
- conversionListener.tsMethodCreated(method, tsMethod);
- }
-
- implementationGenerator.addComplexTypeUsage(tsClass);
- conversionListener.tsScopedTypeCreated(javaClass, tsClass);
- }
-
- private Type resolveTypeVariable(Type type, Map variableNameToJavaType) {
- if (type instanceof TypeVariable) {
- TypeVariable typeVariable = (TypeVariable) type;
- Type resolvedType = variableNameToJavaType.get(typeVariable.getName());
- if (resolvedType != null) {
- return resolvedType;
- }
- }
- return type;
}
- private Map fillVariableNameToJavaType(Class javaClass, Class> declaringClass) {
- Map typeParametersMap = new HashMap<>();
- for (Type type:javaClass.getGenericInterfaces()){
- if (type instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) type;
- if (parameterizedType.getRawType() == declaringClass) {
- for (int i = 0; i < parameterizedType.getActualTypeArguments().length; i++) {
- TypeVariable typeParameter = declaringClass.getTypeParameters()[i];
- Type actualTypeArgument = parameterizedType.getActualTypeArguments()[i];
- typeParametersMap.put(typeParameter.getName(), actualTypeArgument);
- }
- return typeParametersMap;
- }
- return fillVariableNameToJavaType((Class) type, declaringClass);
- }
- }
- return typeParametersMap;
- }
-
- private List filterRestMethods(Class javaClass) {
- List restMethodList = new ArrayList<>();
- for (Method method : javaClass.getMethods()) {
- if(method.getDeclaringClass() == javaClass || method.getDeclaringClass().isInterface()) {
- for (Method nextMethod : javaClass.getSuperclass().getMethods()) {
- if(nextMethod.equals(method)){
- continue; // parent class contains method from interface
- }
- }
- if (isRestMethod(method)) {
- restMethodList.add(method);
- }
- }
- }
- return restMethodList;
- }
-
- private String mapMethodName(List restMethodList, Map methodNamesMap, Method currentMethod) {
- StringBuilder methodName = methodNamesMap.get(currentMethod);
- if (methodName != null) {
- return methodName.toString();
- }
- List overloadedMethods = restMethodList.stream().filter(m -> m.getName().equals(currentMethod.getName())).collect(Collectors.toList());
- if (overloadedMethods.size() == 1) {
- return currentMethod.getName();
- }
- Map overloadedMethodNamesMap = new HashMap<>();
- Map methodsRequestMappingsMap = new HashMap<>();
- for (Method m : overloadedMethods) {
- overloadedMethodNamesMap.put(m, new StringBuilder(m.getName()));
- methodsRequestMappingsMap.put(m, getRequestMapping(Arrays.asList (m.getDeclaredAnnotations())));
- }
-
-
- appendHttpMethodToMethodName(overloadedMethodNamesMap, methodsRequestMappingsMap);
- if(!methodNamesAreUnique(overloadedMethodNamesMap)){
- appendHttpPathToMethodName(overloadedMethodNamesMap, methodsRequestMappingsMap);
- }
- if(!methodNamesAreUnique(overloadedMethodNamesMap)){
- logger.error("There are overloaded REST methods which names are not unique after appending http method and http path : " + currentMethod);
- }
- overloadedMethodNamesMap.forEach((method, name) -> methodNamesMap.put(method, name));
- return overloadedMethodNamesMap.get(currentMethod).toString();
- }
-
- private void appendHttpMethodToMethodName(Map overloadedMethodNamesMap, Map methodsRequestMappingsMap) {
- Map httpMethodsValuesMap = new HashMap<>();
-
- for (Map.Entry entry : methodsRequestMappingsMap.entrySet()) {
- Method key = entry.getKey();
- RequestMapping value = entry.getValue();
- SortedSet httpMethodsSet = new TreeSet<>();
- for (RequestMethod requestMethod : value.method()) {
- httpMethodsSet.add(requestMethod.name());
- }
- httpMethodsValuesMap.put(key, String.join("_", httpMethodsSet));
- }
-
- Set allDifferentHttpMethods = new HashSet<>(httpMethodsValuesMap.values());
- if (allDifferentHttpMethods.size() <= 1) {
- return;
- }
- overloadedMethodNamesMap.forEach((method, methodName) -> methodName.append(httpMethodsValuesMap.get(method)));
- }
-
- private void appendHttpPathToMethodName(Map overloadedMethodNamesMap, Map methodsRequestMappingsMap) {
- Map methodsHttpPaths = new HashMap<>();
- for (Map.Entry entry : methodsRequestMappingsMap.entrySet()) {
- Method method = entry.getKey();
- RequestMapping requestMapping = entry.getValue();
- if (requestMapping.path().length > 0) {
- methodsHttpPaths.put(method, requestMapping.path()[0].split("/"));
- }else{
- methodsHttpPaths.put(method, new String[]{""});
- }
- }
-
- int startIndex = findPathCommonPrefixIndex(methodsHttpPaths);
-
- for (Method method : overloadedMethodNamesMap.keySet()) {
- StringBuilder methodName = overloadedMethodNamesMap.get(method);
- String[] pathComponents = methodsHttpPaths.get(method);
- for (int i = startIndex; i < pathComponents.length; i++) {
- String pathComponent = pathComponents[i];
- if(!pathComponent.contains("{") && !"".equals(pathComponent)) {
- methodName.append("_");
- methodName.append(pathComponent.toUpperCase().replace("-", "_"));
- }
- }
- }
-
- }
-
- private int findPathCommonPrefixIndex(Map methodsHttpPaths) {
- return 0;
- }
-
- private boolean methodNamesAreUnique(Map overloadedMethodNamesMap) {
- Set methodNames = new HashSet<>();
- overloadedMethodNamesMap.forEach((k, v) -> methodNames.add(v.toString()));
- return overloadedMethodNamesMap.size() == methodNames.size();
- }
-
- private void setOptional(TSParameter tsParameter) {
- for (Annotation annotation : tsParameter.getAnnotationList()) {
- if(annotation instanceof PathVariable){
- PathVariable pathVariable = (PathVariable) annotation;
- tsParameter.setOptional(!pathVariable.required());
- return;
- }
- if(annotation instanceof RequestParam){
- RequestParam requestParam = (RequestParam) annotation;
- tsParameter.setOptional(!requestParam.required());
- if(!ValueConstants.DEFAULT_NONE.equals(requestParam.defaultValue())) {
- tsParameter.setDefaultValue(requestParam.defaultValue());
- }
- return;
- }
- if(annotation instanceof RequestBody) {
- RequestBody requestBody = (RequestBody) annotation;
- tsParameter.setOptional(!requestBody.required());
- return;
- }
- }
+ @Override
+ protected void addMethodAnnotations(Method method, TSMethod tsMethod) {
+ tsMethod.addAllAnnotations(method.getAnnotations());
}
- private boolean parameterIsMapped(TSParameter tsParameter) {
- for (Annotation annotation : tsParameter.getAnnotationList()) {
- if(annotation instanceof PathVariable){
- return true;
- }
- if(annotation instanceof RequestParam){
- return true;
- }
- if(annotation instanceof RequestBody) {
- return true;
- }
- }
-
- if (tsParameter.getType() instanceof TSInterfaceReference) {
- TSInterfaceReference tsInterfaceReference = (TSInterfaceReference) tsParameter.getType();
- for (Class nextClass : tsInterfaceReference.getReferencedType().getMappedFromJavaTypeSet()) {
- for (RestConversionExtension extension : getConversionExtensionList()) {
- if (extension.isMappedRestParam(nextClass)) {
- return true;
- }
- }
- }
- }
- return false;
+ @Override
+ protected void addParameterAnnotations(Parameter parameter, TSParameter tsParameter) {
+ tsParameter.addAllAnnotations(parameter.getAnnotations());
}
- private boolean isRestMethod(Method method) {
- if (method.isAnnotationPresent(RequestMapping.class)) {
- return true;
- }
- for (Annotation annotation : method.getAnnotations()) {
- if (annotation.annotationType().isAnnotationPresent(RequestMapping.class)) {
- return true;
+ @Override
+ protected Type handleImplementationSpecificReturnTypes(Method method) {
+ Type genericReturnType = method.getGenericReturnType();
+ if (genericReturnType instanceof ParameterizedType) {// handling ResponseEntity
+ ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
+ if (parameterizedType.getRawType() == ResponseEntity.class) {
+ genericReturnType = parameterizedType.getActualTypeArguments()[findPathCommonPrefixIndex(null)];
}
}
- return false;
- }
-
- private void setSupperClass(Class javaType, TSClass tsClass) {
- TSType tsSupperClass = TypeMapper.map(javaType.getAnnotatedSuperclass().getType());
- if(tsSupperClass instanceof TSClassReference){
- TSClassReference tsClassReference = (TSClassReference) tsSupperClass;
- convertFormalTypeParameters(javaType.getTypeParameters(), tsClassReference);
- tsClass.setExtendsClass(tsClassReference);
- tsClass.addScopedTypeUsage(tsClassReference);
- }
+ return genericReturnType;
}
}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/MethodParameterEntity.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/MethodParameterEntity.java
new file mode 100644
index 0000000..3a071b4
--- /dev/null
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/MethodParameterEntity.java
@@ -0,0 +1,31 @@
+package com.blueveery.springrest2ts.spring;
+
+public class MethodParameterEntity {
+ private String value;
+ private String name;
+ private boolean required;
+
+ public String value() {
+ return value;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public boolean required() {
+ return required;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/PathVariableEntity.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/PathVariableEntity.java
new file mode 100644
index 0000000..dc83320
--- /dev/null
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/PathVariableEntity.java
@@ -0,0 +1,14 @@
+package com.blueveery.springrest2ts.spring;
+
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.lang.annotation.Annotation;
+
+public class PathVariableEntity extends MethodParameterEntity implements PathVariable {
+
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return PathVariable.class;
+ }
+}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestBodyEntity.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestBodyEntity.java
new file mode 100644
index 0000000..d82a484
--- /dev/null
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestBodyEntity.java
@@ -0,0 +1,23 @@
+package com.blueveery.springrest2ts.spring;
+
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.lang.annotation.Annotation;
+
+public class RequestBodyEntity implements RequestBody {
+ private boolean required;
+
+ @Override
+ public boolean required() {
+ return required;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return RequestBody.class;
+ }
+}
diff --git a/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestParamEntity.java b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestParamEntity.java
new file mode 100644
index 0000000..b636c8d
--- /dev/null
+++ b/spring-rest2ts-spring/src/main/java/com/blueveery/springrest2ts/spring/RequestParamEntity.java
@@ -0,0 +1,24 @@
+package com.blueveery.springrest2ts.spring;
+
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.lang.annotation.Annotation;
+
+public class RequestParamEntity extends MethodParameterEntity implements RequestParam {
+
+ private String defaultValue;
+
+ @Override
+ public String defaultValue() {
+ return defaultValue;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return RequestParam.class;
+ }
+}