diff options
author | Joffrey BION <joffrey.bion@gmail.com> | 2017-08-13 04:16:18 +0200 |
---|---|---|
committer | Joffrey BION <joffrey.bion@gmail.com> | 2017-08-15 00:05:55 +0200 |
commit | 3f8daeffbb298df25307b3fd422fecf88acf3de5 (patch) | |
tree | 3ef44bedc32959aea25c87efa6d18d497b8c8a08 | |
parent | Remove obsolete routes.js (diff) | |
download | seven-wonders-3f8daeffbb298df25307b3fd422fecf88acf3de5.tar.gz seven-wonders-3f8daeffbb298df25307b3fd422fecf88acf3de5.tar.bz2 seven-wonders-3f8daeffbb298df25307b3fd422fecf88acf3de5.zip |
Move from JsonDoc to Livedoc
The Livedoc project, based on JsonDoc, implements the overrides that we
used to make in this project for websocket compatibility.
25 files changed, 26 insertions, 1070 deletions
@@ -26,7 +26,7 @@ Missing steps: - End of game event - Access scoring -A [live API documentation using JsonDoc](https://seven-wonders-online.herokuapp.com/jsondoc-ui.html?url=https://seven-wonders-online.herokuapp.com/doc) +A [live API documentation using JsonDoc](https://seven-wonders-online.herokuapp.com/jsondoc-ui.html?url=https://seven-wonders-online.herokuapp.com/jsondoc) is available. It is in construction as well because I'm adding wesocket support to the existing REST-API support. ### Client diff --git a/backend/build.gradle b/backend/build.gradle index 5193f0cb..6e728b12 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -18,8 +18,8 @@ repositories { dependencies { compile 'com.google.code.gson:gson:2.8.0' compile 'ch.qos.logback:logback-classic:1.1.8' - compile 'org.jsondoc:spring-boot-starter-jsondoc:1.2.17' - compile 'org.jsondoc:jsondoc-ui-webjar:1.2.17' + compile 'org.hildan.livedoc:livedoc-springboot:0.2.0' + compile 'org.hildan.livedoc:livedoc-ui-webjar:0.2.0' compile 'org.springframework.boot:spring-boot-starter-websocket' compile 'org.springframework.security:spring-security-core:4.2.0.RELEASE' diff --git a/backend/src/main/java/org/luxons/sevenwonders/SevenWonders.java b/backend/src/main/java/org/luxons/sevenwonders/SevenWonders.java index eba0c607..c656b2c3 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/SevenWonders.java +++ b/backend/src/main/java/org/luxons/sevenwonders/SevenWonders.java @@ -1,6 +1,6 @@ package org.luxons.sevenwonders; -import org.jsondoc.spring.boot.starter.EnableJSONDoc; +import org.hildan.livedoc.spring.boot.starter.EnableJSONDoc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/ChooseNameAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/ChooseNameAction.java index be5e97ea..e6ecaa17 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/ChooseNameAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/ChooseNameAction.java @@ -3,8 +3,8 @@ package org.luxons.sevenwonders.actions; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; @ApiObject(name = "Choose Name Action", description = "The action to choose the player's name. This is the first action that should be called.", diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/CreateGameAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/CreateGameAction.java index 4ad957b8..91984016 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/CreateGameAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/CreateGameAction.java @@ -3,8 +3,8 @@ package org.luxons.sevenwonders.actions; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; @ApiObject(name = "Create Game Action", description = "The action to create a game.", diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/JoinGameAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/JoinGameAction.java index a392378c..eeb3381a 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/JoinGameAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/JoinGameAction.java @@ -2,8 +2,8 @@ package org.luxons.sevenwonders.actions; import javax.validation.constraints.NotNull; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; @ApiObject(name = "Join Game Action", description = "The action to join a game.", diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/PrepareMoveAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/PrepareMoveAction.java index 02899eab..5fd32c4c 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/PrepareMoveAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/PrepareMoveAction.java @@ -2,8 +2,8 @@ package org.luxons.sevenwonders.actions; import javax.validation.constraints.NotNull; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; import org.luxons.sevenwonders.game.api.PlayerMove; @ApiObject(name = "Prepare Move Action", diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/ReorderPlayersAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/ReorderPlayersAction.java index e457caf4..ba819fe0 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/ReorderPlayersAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/ReorderPlayersAction.java @@ -4,8 +4,8 @@ import java.util.List; import javax.validation.constraints.NotNull; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; @ApiObject(name = "Reorder Players Action", description = "The action to update the order of the players around the table. Can only be called in the " diff --git a/backend/src/main/java/org/luxons/sevenwonders/actions/UpdateSettingsAction.java b/backend/src/main/java/org/luxons/sevenwonders/actions/UpdateSettingsAction.java index fa454995..410dd8ea 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/actions/UpdateSettingsAction.java +++ b/backend/src/main/java/org/luxons/sevenwonders/actions/UpdateSettingsAction.java @@ -2,8 +2,8 @@ package org.luxons.sevenwonders.actions; import javax.validation.constraints.NotNull; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; +import org.hildan.livedoc.core.annotation.ApiObject; +import org.hildan.livedoc.core.annotation.ApiObjectField; import org.luxons.sevenwonders.game.api.CustomizableSettings; @ApiObject(name = "Update Settings Action", diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameBrowserController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameBrowserController.java index b482407f..26250b8a 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameBrowserController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameBrowserController.java @@ -4,8 +4,8 @@ import java.security.Principal; import java.util.Collection; import java.util.Collections; -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; +import org.hildan.livedoc.core.annotation.Api; +import org.hildan.livedoc.core.annotation.ApiMethod; import org.luxons.sevenwonders.actions.CreateGameAction; import org.luxons.sevenwonders.actions.JoinGameAction; import org.luxons.sevenwonders.errors.ApiMisuseException; diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java index 513a7cdb..e33d2012 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java @@ -3,8 +3,8 @@ package org.luxons.sevenwonders.controllers; import java.security.Principal; import java.util.List; -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; +import org.hildan.livedoc.core.annotation.Api; +import org.hildan.livedoc.core.annotation.ApiMethod; import org.luxons.sevenwonders.actions.PrepareMoveAction; import org.luxons.sevenwonders.game.Game; import org.luxons.sevenwonders.game.api.PlayerTurnInfo; diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/HomeController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/HomeController.java index dd6cad7f..4e0c1083 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/HomeController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/HomeController.java @@ -2,8 +2,8 @@ package org.luxons.sevenwonders.controllers; import java.security.Principal; -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; +import org.hildan.livedoc.core.annotation.Api; +import org.hildan.livedoc.core.annotation.ApiMethod; import org.luxons.sevenwonders.actions.ChooseNameAction; import org.luxons.sevenwonders.lobby.Player; import org.luxons.sevenwonders.repositories.PlayerRepository; diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java index e907981b..ba4df70e 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java @@ -3,8 +3,8 @@ package org.luxons.sevenwonders.controllers; import java.security.Principal; import java.util.Collections; -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; +import org.hildan.livedoc.core.annotation.Api; +import org.hildan.livedoc.core.annotation.ApiMethod; import org.luxons.sevenwonders.actions.ReorderPlayersAction; import org.luxons.sevenwonders.actions.UpdateSettingsAction; import org.luxons.sevenwonders.errors.ApiMisuseException; diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/GlobalDocumentation.java b/backend/src/main/java/org/luxons/sevenwonders/doc/GlobalDocumentation.java index b925c1cf..b1d64cab 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/GlobalDocumentation.java +++ b/backend/src/main/java/org/luxons/sevenwonders/doc/GlobalDocumentation.java @@ -1,7 +1,7 @@ package org.luxons.sevenwonders.doc; -import org.jsondoc.core.annotation.global.ApiGlobal; -import org.jsondoc.core.annotation.global.ApiGlobalSection; +import org.hildan.livedoc.core.annotation.global.ApiGlobal; +import org.hildan.livedoc.core.annotation.global.ApiGlobalSection; @ApiGlobal(sections = { @ApiGlobalSection(title = "First steps", paragraphs = {"Welcome to JsonDoc."}) diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/JsonDocController.java b/backend/src/main/java/org/luxons/sevenwonders/doc/JsonDocController.java deleted file mode 100644 index e9edde3e..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/JsonDocController.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.luxons.sevenwonders.doc; - -import java.util.Arrays; -import java.util.List; - -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; -import org.jsondoc.core.pojo.JSONDoc; -import org.jsondoc.core.pojo.JSONDoc.MethodDisplay; -import org.jsondoc.core.scanner.JSONDocScanner; -import org.luxons.sevenwonders.doc.scanner.JsonDocWebSocketScanner; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -@Api(name = "SevenWonders API Documentation", - description = "This controller provides a JSON description of this documentation") -@Controller -public class JsonDocController { - - private String version; - - private String basePath; - - private List<String> packages; - - private JSONDocScanner jsondocScanner; - - private boolean playgroundEnabled = true; - - private MethodDisplay displayMethodAs = MethodDisplay.URI; - - public JsonDocController() { - this.version = "1.0.0"; - this.basePath = "http://localhost:8080"; - this.packages = Arrays.asList("org.luxons.sevenwonders.controllers", "org.luxons.sevenwonders.doc", - "org.luxons.sevenwonders.actions", "org.luxons.sevenwonders.game", "org.luxons.sevenwonders.lobby"); - this.jsondocScanner = new JsonDocWebSocketScanner(); - } - - @ApiMethod(description = "Get the Websocket API documentation for this game") - @RequestMapping(value = "/doc", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public JSONDoc getApi() { - return jsondocScanner.getJSONDoc(version, basePath, packages, playgroundEnabled, displayMethodAs); - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectDocBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectDocBuilder.java deleted file mode 100644 index 8a59451f..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectDocBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.Field; -import java.util.Set; -import java.util.TreeSet; - -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.annotation.ApiObjectField; -import org.jsondoc.core.pojo.ApiObjectDoc; -import org.jsondoc.core.pojo.ApiObjectFieldDoc; -import org.jsondoc.core.scanner.DefaultJSONDocScanner; -import org.jsondoc.core.scanner.builder.JSONDocApiVersionDocBuilder; - -public class JSONDocApiObjectDocBuilder { - - public static ApiObjectDoc build(Class<?> clazz) { - ApiObject apiObject = clazz.getAnnotation(ApiObject.class); - ApiObjectDoc apiObjectDoc = new ApiObjectDoc(); - - Set<ApiObjectFieldDoc> fieldDocs = new TreeSet<ApiObjectFieldDoc>(); - for (Field field : clazz.getDeclaredFields()) { - if (field.getAnnotation(ApiObjectField.class) != null) { - ApiObjectFieldDoc fieldDoc = - JSONDocApiObjectFieldDocBuilder.build(field.getAnnotation(ApiObjectField.class), field); - fieldDoc.setSupportedversions(JSONDocApiVersionDocBuilder.build(field)); - fieldDocs.add(fieldDoc); - } - } - - Class<?> c = clazz.getSuperclass(); - if (c != null) { - if (c.isAnnotationPresent(ApiObject.class)) { - ApiObjectDoc objDoc = build(c); - fieldDocs.addAll(objDoc.getFields()); - } - } - - if (clazz.isEnum()) { - apiObjectDoc.setAllowedvalues(DefaultJSONDocScanner.enumConstantsToStringArray(clazz.getEnumConstants())); - } - - if (apiObject.name().trim().isEmpty()) { - apiObjectDoc.setName(clazz.getSimpleName()); - } else { - apiObjectDoc.setName(apiObject.name()); - } - - apiObjectDoc.setDescription(apiObject.description()); - apiObjectDoc.setFields(fieldDocs); - apiObjectDoc.setGroup(apiObject.group()); - apiObjectDoc.setVisibility(apiObject.visibility()); - apiObjectDoc.setStage(apiObject.stage()); - apiObjectDoc.setShow(apiObject.show()); - - return apiObjectDoc; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectFieldDocBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectFieldDocBuilder.java deleted file mode 100644 index a1c9d7c6..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocApiObjectFieldDocBuilder.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.Field; - -import org.jsondoc.core.annotation.ApiObjectField; -import org.jsondoc.core.pojo.ApiObjectFieldDoc; -import org.jsondoc.core.scanner.DefaultJSONDocScanner; -import org.jsondoc.core.util.JSONDocHibernateValidatorProcessor; -import org.jsondoc.core.util.JSONDocType; - -public class JSONDocApiObjectFieldDocBuilder { - - public static ApiObjectFieldDoc build(ApiObjectField annotation, Field field) { - ApiObjectFieldDoc apiPojoFieldDoc = new ApiObjectFieldDoc(); - if (!annotation.name().trim().isEmpty()) { - apiPojoFieldDoc.setName(annotation.name()); - } else { - apiPojoFieldDoc.setName(field.getName()); - } - apiPojoFieldDoc.setDescription(annotation.description()); - apiPojoFieldDoc.setJsondocType( - JSONDocTypeBuilder.build(new JSONDocType(), field.getType(), field.getGenericType())); - // if allowedvalues property is populated on an enum field, then the enum values are overridden with the - // allowedvalues ones - if (field.getType().isEnum() && annotation.allowedvalues().length == 0) { - apiPojoFieldDoc.setAllowedvalues( - DefaultJSONDocScanner.enumConstantsToStringArray(field.getType().getEnumConstants())); - } else { - apiPojoFieldDoc.setAllowedvalues(annotation.allowedvalues()); - } - apiPojoFieldDoc.setRequired(String.valueOf(annotation.required())); - apiPojoFieldDoc.setOrder(annotation.order()); - - if (!annotation.format().isEmpty()) { - apiPojoFieldDoc.addFormat(annotation.format()); - } - - JSONDocHibernateValidatorProcessor.processHibernateValidatorAnnotations(field, apiPojoFieldDoc); - - return apiPojoFieldDoc; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTemplateBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTemplateBuilder.java deleted file mode 100644 index f518f319..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTemplateBuilder.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import org.jsondoc.core.annotation.ApiObjectField; -import org.jsondoc.core.pojo.JSONDocTemplate; -import org.jsondoc.core.util.JSONDocFieldWrapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class JSONDocTemplateBuilder { - - private static final Logger log = LoggerFactory.getLogger(org.jsondoc.core.util.JSONDocTemplateBuilder.class); - - private static final Map<Class<?>, Class<?>> primitives = new HashMap<Class<?>, Class<?>>(); - - static { - primitives.put(boolean.class, Boolean.class); - primitives.put(byte.class, Byte.class); - primitives.put(char.class, String.class); - primitives.put(double.class, Double.class); - primitives.put(float.class, Float.class); - primitives.put(int.class, Integer.class); - primitives.put(long.class, Long.class); - primitives.put(short.class, Short.class); - primitives.put(void.class, Void.class); - } - - public static JSONDocTemplate build(Class<?> clazz, Set<Class<?>> jsondocObjects) { - final JSONDocTemplate jsonDocTemplate = new JSONDocTemplate(); - - if (jsondocObjects.contains(clazz)) { - try { - Set<JSONDocFieldWrapper> fields = getAllDeclaredFields(clazz); - - for (JSONDocFieldWrapper jsondocFieldWrapper : fields) { - Field field = jsondocFieldWrapper.getField(); - String fieldName = field.getName(); - ApiObjectField apiObjectField = field.getAnnotation(ApiObjectField.class); - if (apiObjectField != null && !apiObjectField.name().isEmpty()) { - fieldName = apiObjectField.name(); - } - - Object value; - // This condition is to avoid StackOverflow in case class "A" - // contains a field of type "A" - if (field.getType().equals(clazz) || (apiObjectField != null - && !apiObjectField.processtemplate())) { - value = getValue(Object.class, field.getGenericType(), fieldName, jsondocObjects); - } else { - value = getValue(field.getType(), field.getGenericType(), fieldName, jsondocObjects); - } - - jsonDocTemplate.put(fieldName, value); - } - } catch (Exception e) { - log.error("Error in JSONDocTemplate creation for class [" + clazz.getCanonicalName() + "]", e); - } - } - - return jsonDocTemplate; - } - - private static Object getValue(Class<?> fieldClass, Type fieldGenericType, String fieldName, - Set<Class<?>> jsondocObjects) { - - if (fieldClass.isPrimitive()) { - return getValue(wrap(fieldClass), null, fieldName, jsondocObjects); - } else if (Map.class.isAssignableFrom(fieldClass)) { - return new HashMap<Object, Object>(); - } else if (Number.class.isAssignableFrom(fieldClass)) { - return new Integer(0); - } else if (String.class.isAssignableFrom(fieldClass) || fieldClass.isEnum()) { - return new String(""); - } else if (Boolean.class.isAssignableFrom(fieldClass)) { - return new Boolean("true"); - } else if (fieldClass.isArray() || Collection.class.isAssignableFrom(fieldClass)) { - return new ArrayList<Object>(); - } else { - return build(fieldClass, jsondocObjects); - } - } - - private static Set<JSONDocFieldWrapper> getAllDeclaredFields(Class<?> clazz) { - Set<JSONDocFieldWrapper> fields = new TreeSet<JSONDocFieldWrapper>(); - - List<Field> declaredFields = new ArrayList<Field>(); - if (clazz.isEnum()) { - return fields; - } else { - declaredFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - } - - for (Field field : declaredFields) { - if (!shouldBeSerialized(field)) { - continue; - } - if (field.isAnnotationPresent(ApiObjectField.class)) { - ApiObjectField annotation = field.getAnnotation(ApiObjectField.class); - fields.add(new JSONDocFieldWrapper(field, annotation.order())); - } else { - fields.add(new JSONDocFieldWrapper(field, Integer.MAX_VALUE)); - } - } - - if (clazz.getSuperclass() != null) { - fields.addAll(getAllDeclaredFields(clazz.getSuperclass())); - } - - return fields; - } - - private static boolean shouldBeSerialized(Field field) { - return !field.isSynthetic() && !Modifier.isTransient(field.getModifiers()); - } - - @SuppressWarnings("unchecked") - private static <T> Class<T> wrap(Class<T> clazz) { - return clazz.isPrimitive() ? (Class<T>) primitives.get(clazz) : clazz; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTypeBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTypeBuilder.java deleted file mode 100644 index 4584e7cf..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/JSONDocTypeBuilder.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.Collection; -import java.util.Map; - -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.util.JSONDocDefaultType; -import org.jsondoc.core.util.JSONDocType; - -public class JSONDocTypeBuilder { - - private static final String WILDCARD = "wildcard"; - - private static final String UNDEFINED = "undefined"; - - private static final String ARRAY = "array"; - - public static JSONDocType build(JSONDocType jsondocType, Class<?> clazz, Type type) { - if (clazz.isAssignableFrom(JSONDocDefaultType.class)) { - jsondocType.addItemToType(UNDEFINED); - return jsondocType; - } - - if (Map.class.isAssignableFrom(clazz)) { - jsondocType.addItemToType(getCustomClassName(clazz)); - - if (type instanceof ParameterizedType) { - Type mapKeyType = ((ParameterizedType) type).getActualTypeArguments()[0]; - Type mapValueType = ((ParameterizedType) type).getActualTypeArguments()[1]; - - jsondocType.setMapKey(new JSONDocType()); - jsondocType.setMapValue(new JSONDocType()); - - if (mapKeyType instanceof Class) { - jsondocType.setMapKey(new JSONDocType(((Class<?>) mapKeyType).getSimpleName())); - } else if (mapKeyType instanceof WildcardType) { - jsondocType.setMapKey(new JSONDocType(WILDCARD)); - } else if (mapKeyType instanceof TypeVariable<?>) { - jsondocType.setMapKey(new JSONDocType(((TypeVariable<?>) mapKeyType).getName())); - } else { - jsondocType.setMapKey( - build(jsondocType.getMapKey(), (Class<?>) ((ParameterizedType) mapKeyType).getRawType(), - mapKeyType)); - } - - if (mapValueType instanceof Class) { - jsondocType.setMapValue(new JSONDocType(((Class<?>) mapValueType).getSimpleName())); - } else if (mapValueType instanceof WildcardType) { - jsondocType.setMapValue(new JSONDocType(WILDCARD)); - } else if (mapValueType instanceof TypeVariable<?>) { - jsondocType.setMapValue(new JSONDocType(((TypeVariable<?>) mapValueType).getName())); - } else { - jsondocType.setMapValue( - build(jsondocType.getMapValue(), (Class<?>) ((ParameterizedType) mapValueType).getRawType(), - mapValueType)); - } - } - } else if (Collection.class.isAssignableFrom(clazz)) { - if (type instanceof ParameterizedType) { - Type parametrizedType = ((ParameterizedType) type).getActualTypeArguments()[0]; - jsondocType.addItemToType(getCustomClassName(clazz)); - - if (parametrizedType instanceof Class) { - jsondocType.addItemToType(getCustomClassName((Class<?>) parametrizedType)); - } else if (parametrizedType instanceof WildcardType) { - jsondocType.addItemToType(WILDCARD); - } else if (parametrizedType instanceof TypeVariable<?>) { - jsondocType.addItemToType(((TypeVariable<?>) parametrizedType).getName()); - } else { - return build(jsondocType, (Class<?>) ((ParameterizedType) parametrizedType).getRawType(), - parametrizedType); - } - } else if (type instanceof GenericArrayType) { - return build(jsondocType, clazz, ((GenericArrayType) type).getGenericComponentType()); - } else { - jsondocType.addItemToType(getCustomClassName(clazz)); - } - } else if (clazz.isArray()) { - jsondocType.addItemToType(ARRAY); - Class<?> componentType = clazz.getComponentType(); - return build(jsondocType, componentType, type); - } else { - jsondocType.addItemToType(getCustomClassName(clazz)); - if (type instanceof ParameterizedType) { - Type parametrizedType = ((ParameterizedType) type).getActualTypeArguments()[0]; - - if (parametrizedType instanceof Class) { - jsondocType.addItemToType(getCustomClassName((Class<?>) parametrizedType)); - } else if (parametrizedType instanceof WildcardType) { - jsondocType.addItemToType(WILDCARD); - } else if (parametrizedType instanceof TypeVariable<?>) { - jsondocType.addItemToType(((TypeVariable<?>) parametrizedType).getName()); - } else { - return build(jsondocType, (Class<?>) ((ParameterizedType) parametrizedType).getRawType(), - parametrizedType); - } - } - } - - return jsondocType; - } - - private static String getCustomClassName(Class<?> clazz) { - if (clazz.isAnnotationPresent(ApiObject.class)) { - ApiObject annotation = clazz.getAnnotation(ApiObject.class); - if (annotation.name().isEmpty()) { - return clazz.getSimpleName().toLowerCase(); - } else { - return annotation.name(); - } - } else { - return clazz.getSimpleName(); - } - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringObjectBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringObjectBuilder.java deleted file mode 100644 index 46f38e8b..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringObjectBuilder.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Set; -import java.util.TreeSet; - -import org.jsondoc.core.pojo.ApiObjectDoc; -import org.jsondoc.core.pojo.ApiObjectFieldDoc; -import org.jsondoc.core.scanner.DefaultJSONDocScanner; -import org.jsondoc.core.util.JSONDocHibernateValidatorProcessor; -import org.jsondoc.core.util.JSONDocType; - -public class SpringObjectBuilder { - - public static ApiObjectDoc buildObject(Class<?> clazz) { - ApiObjectDoc apiObjectDoc = new ApiObjectDoc(); - apiObjectDoc.setName(clazz.getSimpleName()); - - Set<ApiObjectFieldDoc> fieldDocs = new TreeSet<ApiObjectFieldDoc>(); - - for (Field field : clazz.getDeclaredFields()) { - ApiObjectFieldDoc fieldDoc = new ApiObjectFieldDoc(); - fieldDoc.setName(field.getName()); - fieldDoc.setOrder(Integer.MAX_VALUE); - fieldDoc.setRequired(DefaultJSONDocScanner.UNDEFINED.toUpperCase()); - fieldDoc.setJsondocType( - JSONDocTypeBuilder.build(new JSONDocType(), field.getType(), field.getGenericType())); - - JSONDocHibernateValidatorProcessor.processHibernateValidatorAnnotations(field, fieldDoc); - - fieldDocs.add(fieldDoc); - } - - Class<?> superclass = clazz.getSuperclass(); - if (superclass != null) { - ApiObjectDoc parentObjectDoc = buildObject(superclass); - fieldDocs.addAll(parentObjectDoc.getFields()); - } - - if (clazz.isEnum()) { - apiObjectDoc.setAllowedvalues(DefaultJSONDocScanner.enumConstantsToStringArray(clazz.getEnumConstants())); - } - - apiObjectDoc.setFields(fieldDocs); - if (Modifier.isAbstract(clazz.getModifiers())) { - apiObjectDoc.setShow(false); - } - - return apiObjectDoc; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringPathBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringPathBuilder.java deleted file mode 100644 index ca97fb41..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringPathBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.simp.annotation.SubscribeMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -public class SpringPathBuilder { - - public static Set<String> buildPath(Method method) { - Set<String> paths = new HashSet<String>(); - - if (method.isAnnotationPresent(MessageMapping.class)) { - paths.addAll(getMappings(method, MessageMapping.class)); - } - if (method.isAnnotationPresent(SubscribeMapping.class)) { - paths.addAll(getMappings(method, SubscribeMapping.class)); - } - if (method.isAnnotationPresent(RequestMapping.class)) { - paths.addAll(getMappings(method, RequestMapping.class)); - } - - return paths; - } - - private static Set<String> getMappings(Method method, Class<? extends Annotation> annotationClass) { - Set<String> controllerMappings = getControllerMappings(method, annotationClass); - Set<String> methodMappings = getMappedPaths(method.getAnnotation(annotationClass)); - - Set<String> mappings = new HashSet<>(); - for (String controllerPath : controllerMappings) { - for (String methodPath : methodMappings) { - mappings.add(join(controllerPath, methodPath)); - } - } - return mappings; - } - - private static String join(String path1, String path2) { - boolean path1HasSep = path1.endsWith("/"); - boolean path2HasSep = path2.startsWith("/"); - if (path1HasSep && path2HasSep) { - return path1 + path2.substring(1); - } - if (!path1HasSep && !path2HasSep && (path1.isEmpty() || !path2.isEmpty())) { - return path1 + '/' + path2; - } - return path1 + path2; - } - - private static Set<String> getControllerMappings(Method method, Class<? extends Annotation> annotationClass) { - Class<?> controller = method.getDeclaringClass(); - if (controller.isAnnotationPresent(annotationClass)) { - return getMappedPaths(controller.getAnnotation(annotationClass)); - } - return Collections.singleton(""); - } - - private static Set<String> getMappedPaths(Annotation mapping) { - Set<String> paths = new HashSet<>(); - paths.addAll(Arrays.asList(valueMapping(mapping))); - paths.addAll(Arrays.asList(pathMapping(mapping))); - if (paths.isEmpty()) { - paths.add(""); - } - return paths; - } - - private static String[] pathMapping(Annotation mapping) { - try { - if (mapping instanceof RequestMapping) { - return ((RequestMapping) mapping).path(); - } - return new String[0]; - } catch (NoSuchMethodError e) { - //Handle the fact that this method is only in Spring 4, not available in Spring 3 - return new String[0]; - } - } - - private static String[] valueMapping(Annotation mapping) { - if (mapping instanceof RequestMapping) { - return ((RequestMapping) mapping).value(); - } - if (mapping instanceof MessageMapping) { - return ((MessageMapping) mapping).value(); - } - if (mapping instanceof SubscribeMapping) { - return ((SubscribeMapping) mapping).value(); - } - return new String[0]; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringRequestBodyBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringRequestBodyBuilder.java deleted file mode 100644 index e3b20a81..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringRequestBodyBuilder.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.security.Principal; -import java.util.Arrays; -import java.util.List; - -import org.jsondoc.core.pojo.ApiBodyObjectDoc; -import org.jsondoc.core.util.JSONDocType; -import org.jsondoc.core.util.JSONDocTypeBuilder; -import org.jsondoc.core.util.JSONDocUtils; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.handler.annotation.DestinationVariable; -import org.springframework.messaging.handler.annotation.Header; -import org.springframework.messaging.handler.annotation.Headers; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.support.MessageHeaderAccessor; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; - -public class SpringRequestBodyBuilder { - - private static final List<Class<?>> NON_BODY_PARAM_TYPES = - Arrays.asList(MessageHeaders.class, MessageHeaderAccessor.class, Principal.class); - - private static final List<Class<? extends Annotation>> NON_BODY_PARAM_ANNOTATIONS = - Arrays.asList(Header.class, Headers.class, DestinationVariable.class); - - public static ApiBodyObjectDoc buildRequestBody(Method method) { - int index = getIndexOfBodyParam(method); - if (index < 0) { - return null; - } - final Class<?> bodyParamClass = method.getParameterTypes()[index]; - final Type bodyParamType = method.getGenericParameterTypes()[index]; - return new ApiBodyObjectDoc(JSONDocTypeBuilder.build(new JSONDocType(), bodyParamClass, bodyParamType)); - } - - public static int getIndexOfBodyParam(Method method) { - if (method.isAnnotationPresent(RequestMapping.class)) { - return getIndexOfBodyParamForRequestMapping(method); - } - if (method.isAnnotationPresent(MessageMapping.class)) { - return getIndexOfBodyParamForMessageMapping(method); - } - return -1; - } - - private static int getIndexOfBodyParamForRequestMapping(Method method) { - return JSONDocUtils.getIndexOfParameterWithAnnotation(method, RequestBody.class); - } - - private static int getIndexOfBodyParamForMessageMapping(Method method) { - Class<?>[] paramTypes = method.getParameterTypes(); - Annotation[][] paramAnnotations = method.getParameterAnnotations(); - for (int i = 0; i < paramTypes.length; i++) { - if (isBodyParam(paramTypes[i], paramAnnotations[i])) { - return i; - } - } - // no body param found - return -1; - } - - private static boolean isBodyParam(Class<?> paramType, Annotation[] paramAnnotations) { - if (paramType.equals(Message.class)) { - // it is too generic to be useful in the API doc even if it is indeed the body param - return false; - } - if (NON_BODY_PARAM_TYPES.contains(paramType)) { - return false; - } - for (Annotation paramAnnotation : paramAnnotations) { - // guarantees this param is the payload - if (paramAnnotation instanceof Payload) { - return true; - } - // guarantees this param is NOT the payload by definition of the annotation - if (isNonBodyParamAnnotation(paramAnnotation)) { - return false; - } - } - return true; - } - - private static boolean isNonBodyParamAnnotation(Annotation paramAnnotation) { - for (Class<? extends Annotation> annotation : NON_BODY_PARAM_ANNOTATIONS) { - if (annotation.isInstance(paramAnnotation)) { - return true; - } - } - return false; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringResponseBuilder.java b/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringResponseBuilder.java deleted file mode 100644 index 4d8c0ed9..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/builders/SpringResponseBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.luxons.sevenwonders.doc.builders; - -import java.lang.reflect.Method; - -import org.jsondoc.core.pojo.ApiResponseObjectDoc; -import org.jsondoc.core.util.JSONDocType; -import org.springframework.http.ResponseEntity; - -public class SpringResponseBuilder { - - /** - * Builds the ApiResponseObjectDoc from the method's return type and checks if the first type corresponds to a - * ResponseEntity class. In that case removes the "responseentity" string from the final list because it's not - * important to the documentation user. - * - * @param method - * the method to create the response object for - * - * @return the created {@link ApiResponseObjectDoc} - */ - public static ApiResponseObjectDoc buildResponse(Method method) { - ApiResponseObjectDoc apiResponseObjectDoc = new ApiResponseObjectDoc( - JSONDocTypeBuilder.build(new JSONDocType(), method.getReturnType(), method.getGenericReturnType())); - - if (method.getReturnType().isAssignableFrom(ResponseEntity.class)) { - apiResponseObjectDoc.getJsondocType().getType().remove(0); - } - - return apiResponseObjectDoc; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/JsonDocWebSocketScanner.java b/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/JsonDocWebSocketScanner.java deleted file mode 100644 index d7523577..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/JsonDocWebSocketScanner.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.luxons.sevenwonders.doc.scanner; - -import java.lang.reflect.Method; -import java.net.URL; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.jsondoc.core.annotation.Api; -import org.jsondoc.core.annotation.ApiMethod; -import org.jsondoc.core.annotation.ApiObject; -import org.jsondoc.core.pojo.ApiMethodDoc; -import org.jsondoc.core.pojo.ApiObjectDoc; -import org.jsondoc.core.pojo.JSONDoc; -import org.jsondoc.core.pojo.JSONDoc.MethodDisplay; -import org.jsondoc.core.pojo.JSONDocTemplate; -import org.jsondoc.core.scanner.builder.JSONDocApiMethodDocBuilder; -import org.jsondoc.core.util.JSONDocUtils; -import org.jsondoc.springmvc.scanner.Spring4JSONDocScanner; -import org.jsondoc.springmvc.scanner.builder.SpringConsumesBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringHeaderBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringPathVariableBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringProducesBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringQueryParamBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringResponseStatusBuilder; -import org.jsondoc.springmvc.scanner.builder.SpringVerbBuilder; -import org.luxons.sevenwonders.doc.builders.JSONDocApiObjectDocBuilder; -import org.luxons.sevenwonders.doc.builders.JSONDocTemplateBuilder; -import org.luxons.sevenwonders.doc.builders.SpringObjectBuilder; -import org.luxons.sevenwonders.doc.builders.SpringPathBuilder; -import org.luxons.sevenwonders.doc.builders.SpringRequestBodyBuilder; -import org.luxons.sevenwonders.doc.builders.SpringResponseBuilder; -import org.reflections.Reflections; -import org.reflections.scanners.MethodAnnotationsScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; -import org.reflections.util.FilterBuilder; -import org.springframework.beans.BeanUtils; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.simp.annotation.SubscribeMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; - -public class JsonDocWebSocketScanner extends Spring4JSONDocScanner { - - @Override - public JSONDoc getJSONDoc(String version, String basePath, List<String> packages, boolean playgroundEnabled, - MethodDisplay displayMethodAs) { - Set<URL> urls = new HashSet<URL>(); - FilterBuilder filter = new FilterBuilder(); - - log.debug("Found " + packages.size() + " package(s) to scan..."); - for (String pkg : packages) { - log.debug("Adding package to JSONDoc recursive scan: " + pkg); - urls.addAll(ClasspathHelper.forPackage(pkg)); - filter.includePackage(pkg); - } - - reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(filter) - .setUrls(urls) - .addScanners(new MethodAnnotationsScanner())); - - JSONDoc jsondocDoc = new JSONDoc(version, basePath); - jsondocDoc.setPlaygroundEnabled(playgroundEnabled); - jsondocDoc.setDisplayMethodAs(displayMethodAs); - - jsondocControllers = jsondocControllers(); - jsondocObjects = jsondocObjects(packages); - jsondocFlows = jsondocFlows(); - jsondocGlobal = jsondocGlobal(); - jsondocChangelogs = jsondocChangelogs(); - jsondocMigrations = jsondocMigrations(); - - for (Class<?> clazz : jsondocObjects) { - jsondocTemplates.put(clazz, JSONDocTemplateBuilder.build(clazz, jsondocObjects)); - } - - jsondocDoc.setApis(getApiDocsMap(jsondocControllers, displayMethodAs)); - jsondocDoc.setObjects(getApiObjectsMap(jsondocObjects)); - jsondocDoc.setFlows(getApiFlowDocsMap(jsondocFlows, allApiMethodDocs)); - jsondocDoc.setGlobal(getApiGlobalDoc(jsondocGlobal, jsondocChangelogs, jsondocMigrations)); - - return jsondocDoc; - } - - @Override - public Set<Method> jsondocMethods(Class<?> controller) { - Set<Method> annotatedMethods = new LinkedHashSet<Method>(); - for (Method method : controller.getDeclaredMethods()) { - if (shouldDocument(method)) { - annotatedMethods.add(method); - } - } - return annotatedMethods; - } - - private boolean shouldDocument(Method method) { - return method.isAnnotationPresent(RequestMapping.class) || method.isAnnotationPresent(MessageMapping.class) - || method.isAnnotationPresent(SubscribeMapping.class); - } - - @Override - public ApiMethodDoc initApiMethodDoc(Method method, Map<Class<?>, JSONDocTemplate> jsondocTemplates) { - ApiMethodDoc apiMethodDoc = new ApiMethodDoc(); - apiMethodDoc.setPath(SpringPathBuilder.buildPath(method)); - apiMethodDoc.setMethod(method.getName()); - apiMethodDoc.setVerb(SpringVerbBuilder.buildVerb(method)); - apiMethodDoc.setProduces(SpringProducesBuilder.buildProduces(method)); - apiMethodDoc.setConsumes(SpringConsumesBuilder.buildConsumes(method)); - apiMethodDoc.setHeaders(SpringHeaderBuilder.buildHeaders(method)); - apiMethodDoc.setPathparameters(SpringPathVariableBuilder.buildPathVariable(method)); - apiMethodDoc.setQueryparameters(SpringQueryParamBuilder.buildQueryParams(method)); - apiMethodDoc.setBodyobject(SpringRequestBodyBuilder.buildRequestBody(method)); - apiMethodDoc.setResponse(SpringResponseBuilder.buildResponse(method)); - apiMethodDoc.setResponsestatuscode(SpringResponseStatusBuilder.buildResponseStatusCode(method)); - - Integer index = JSONDocUtils.getIndexOfParameterWithAnnotation(method, RequestBody.class); - if (index != -1) { - apiMethodDoc.getBodyobject().setJsondocTemplate(jsondocTemplates.get(method.getParameterTypes()[index])); - } - - return apiMethodDoc; - } - - @Override - public ApiMethodDoc mergeApiMethodDoc(Method method, ApiMethodDoc apiMethodDoc) { - if (method.isAnnotationPresent(ApiMethod.class) && method.getDeclaringClass().isAnnotationPresent(Api.class)) { - ApiMethodDoc jsondocApiMethodDoc = JSONDocApiMethodDocBuilder.build(method); - BeanUtils.copyProperties(jsondocApiMethodDoc, apiMethodDoc, "path", "verb", "produces", "consumes", - "headers", "pathparameters", "queryparameters", "bodyobject", "response", "responsestatuscode", - "apierrors", "supportedversions", "auth", "displayMethodAs"); - } - return apiMethodDoc; - } - - @Override - public Set<Class<?>> jsondocObjects(List<String> packages) { - return new ObjectsScanner(reflections).findJsondocObjects(packages); - } - - @Override - public ApiObjectDoc initApiObjectDoc(Class<?> clazz) { - return SpringObjectBuilder.buildObject(clazz); - } - - @Override - public ApiObjectDoc mergeApiObjectDoc(Class<?> clazz, ApiObjectDoc apiObjectDoc) { - if (clazz.isAnnotationPresent(ApiObject.class)) { - ApiObjectDoc jsondocApiObjectDoc = JSONDocApiObjectDocBuilder.build(clazz); - BeanUtils.copyProperties(jsondocApiObjectDoc, apiObjectDoc); - } - return apiObjectDoc; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/ObjectsScanner.java b/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/ObjectsScanner.java deleted file mode 100644 index e20406ef..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/doc/scanner/ObjectsScanner.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.luxons.sevenwonders.doc.scanner; - -import java.lang.reflect.Field; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import com.google.common.collect.Sets; -import org.jsondoc.core.pojo.JSONDoc; -import org.luxons.sevenwonders.doc.builders.SpringRequestBodyBuilder; -import org.reflections.Reflections; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.simp.annotation.SubscribeMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -public class ObjectsScanner { - - private final Reflections reflections; - - public ObjectsScanner(Reflections reflections) { - this.reflections = reflections; - } - - public Set<Class<?>> findJsondocObjects(List<String> packages) { - Set<Class<?>> candidates = getRootApiObjects(); - Set<Class<?>> subCandidates = Sets.newHashSet(); - - // This is to get objects' fields that are not returned nor part of the body request of a method, but that - // are a field of an object returned or a body of a request of a method - for (Class<?> clazz : candidates) { - appendSubCandidates(clazz, subCandidates); - } - candidates.addAll(subCandidates); - - return candidates.stream().filter(clazz -> inWhiteListedPackages(packages, clazz)).collect(Collectors.toSet()); - } - - private Set<Class<?>> getRootApiObjects() { - Set<Class<?>> candidates = Sets.newHashSet(); - Set<Method> methodsToDocument = getMethodsToDocument(); - for (Method method : methodsToDocument) { - addReturnType(candidates, method); - addBodyParam(candidates, method); - } - return candidates; - } - - private void addReturnType(Set<Class<?>> candidates, Method method) { - Class<?> returnValueClass = method.getReturnType(); - if (returnValueClass.isPrimitive() || returnValueClass.equals(JSONDoc.class)) { - return; - } - buildJSONDocObjectsCandidates(candidates, returnValueClass, method.getGenericReturnType(), reflections); - } - - private void addBodyParam(Set<Class<?>> candidates, Method method) { - int bodyParamIndex = SpringRequestBodyBuilder.getIndexOfBodyParam(method); - if (bodyParamIndex >= 0) { - Class<?> bodyParamClass = method.getParameterTypes()[bodyParamIndex]; - Type bodyParamType = method.getGenericParameterTypes()[bodyParamIndex]; - buildJSONDocObjectsCandidates(candidates, bodyParamClass, bodyParamType, reflections); - } - } - - private Set<Method> getMethodsToDocument() { - Set<Method> methodsAnnotatedWith = reflections.getMethodsAnnotatedWith(RequestMapping.class); - methodsAnnotatedWith.addAll(reflections.getMethodsAnnotatedWith(SubscribeMapping.class)); - methodsAnnotatedWith.addAll(reflections.getMethodsAnnotatedWith(MessageMapping.class)); - return methodsAnnotatedWith; - } - - private boolean inWhiteListedPackages(List<String> packages, Class<?> clazz) { - Package p = clazz.getPackage(); - return p != null && packages.stream().anyMatch(whiteListedPkg -> p.getName().startsWith(whiteListedPkg)); - } - - private void appendSubCandidates(Class<?> clazz, Set<Class<?>> subCandidates) { - if (clazz.isPrimitive() || clazz.equals(Class.class)) { - return; - } - - for (Field field : clazz.getDeclaredFields()) { - if (!isValidForRecursion(field)) { - continue; - } - - Class<?> fieldClass = field.getType(); - Set<Class<?>> fieldCandidates = new HashSet<>(); - buildJSONDocObjectsCandidates(fieldCandidates, fieldClass, field.getGenericType(), reflections); - - for (Class<?> candidate : fieldCandidates) { - if (!subCandidates.contains(candidate)) { - subCandidates.add(candidate); - - appendSubCandidates(candidate, subCandidates); - } - } - } - } - - private static boolean isValidForRecursion(Field field) { - // return !field.isSynthetic() && !field.getType().isPrimitive() && !Modifier.isTransient(field - // .getModifiers()); - return true; - } - - public static Set<Class<?>> buildJSONDocObjectsCandidates(Set<Class<?>> candidates, Class<?> clazz, Type type, - Reflections reflections) { - - if (Map.class.isAssignableFrom(clazz)) { - - if (type instanceof ParameterizedType) { - Type mapKeyType = ((ParameterizedType) type).getActualTypeArguments()[0]; - Type mapValueType = ((ParameterizedType) type).getActualTypeArguments()[1]; - - if (mapKeyType instanceof Class) { - candidates.add((Class<?>) mapKeyType); - } else if (mapKeyType instanceof WildcardType) { - candidates.add(Void.class); - } else { - if (mapKeyType instanceof ParameterizedType) { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) mapKeyType).getRawType(), mapKeyType, reflections)); - } - } - - if (mapValueType instanceof Class) { - candidates.add((Class<?>) mapValueType); - } else if (mapValueType instanceof WildcardType) { - candidates.add(Void.class); - } else { - if (mapValueType instanceof ParameterizedType) { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) mapValueType).getRawType(), mapValueType, reflections)); - } - } - } - } else if (Collection.class.isAssignableFrom(clazz)) { - if (type instanceof ParameterizedType) { - Type parametrizedType = ((ParameterizedType) type).getActualTypeArguments()[0]; - candidates.add(clazz); - - if (parametrizedType instanceof Class) { - candidates.add((Class<?>) parametrizedType); - } else if (parametrizedType instanceof WildcardType) { - candidates.add(Void.class); - } else { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) parametrizedType).getRawType(), parametrizedType, - reflections)); - } - } else if (type instanceof GenericArrayType) { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, clazz, - ((GenericArrayType) type).getGenericComponentType(), reflections)); - } else { - candidates.add(clazz); - } - } else if (clazz.isArray()) { - Class<?> componentType = clazz.getComponentType(); - candidates.addAll(buildJSONDocObjectsCandidates(candidates, componentType, type, reflections)); - } else { - if (type instanceof ParameterizedType) { - Type parametrizedType = ((ParameterizedType) type).getActualTypeArguments()[0]; - - if (parametrizedType instanceof Class) { - Class<?> candidate = (Class<?>) parametrizedType; - if (candidate.isInterface()) { - for (Class<?> implementation : reflections.getSubTypesOf(candidate)) { - buildJSONDocObjectsCandidates(candidates, implementation, parametrizedType, reflections); - } - } else { - candidates.add(candidate); - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) type).getRawType(), parametrizedType, reflections)); - } - } else if (parametrizedType instanceof WildcardType) { - candidates.add(Void.class); - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) type).getRawType(), parametrizedType, reflections)); - } else if (parametrizedType instanceof TypeVariable<?>) { - candidates.add(Void.class); - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) type).getRawType(), parametrizedType, reflections)); - } else { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, - (Class<?>) ((ParameterizedType) parametrizedType).getRawType(), parametrizedType, - reflections)); - } - } else if (clazz.isInterface()) { - for (Class<?> implementation : reflections.getSubTypesOf(clazz)) { - candidates.addAll(buildJSONDocObjectsCandidates(candidates, implementation, type, reflections)); - } - } else { - candidates.add(clazz); - } - } - - return candidates; - } -} |